update changes

This commit is contained in:
Luiz Costa 2024-04-12 12:09:00 +01:00
parent 9e95b66928
commit 1ef05996f5
24 changed files with 592 additions and 66 deletions

BIN
.vs/slnx.sqlite Normal file

Binary file not shown.

View File

@ -0,0 +1,8 @@
// Copyright (c) 2024, itsdave GmbH and contributors
// For license information, please see license.txt
frappe.ui.form.on('Fleet Vehicle', {
// refresh: function(frm) {
// }
});

View File

@ -0,0 +1,84 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "FV-.#####",
"creation": "2024-04-10 12:44:32.374346",
"default_view": "List",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"caption",
"license_plate",
"manufacturer",
"model",
"vin",
"tracker"
],
"fields": [
{
"fieldname": "tracker",
"fieldtype": "Link",
"label": "Tracker",
"options": "Tracker"
},
{
"fieldname": "vin",
"fieldtype": "Data",
"label": "VIN"
},
{
"fieldname": "manufacturer",
"fieldtype": "Data",
"in_filter": 1,
"in_list_view": 1,
"label": "Manufacturer"
},
{
"fieldname": "model",
"fieldtype": "Data",
"in_filter": 1,
"in_list_view": 1,
"label": "Model"
},
{
"fieldname": "caption",
"fieldtype": "Data",
"in_filter": 1,
"in_list_view": 1,
"label": "Caption"
},
{
"fieldname": "license_plate",
"fieldtype": "Data",
"in_filter": 1,
"in_standard_filter": 1,
"label": "License Plate"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2024-04-11 15:29:47.121435",
"modified_by": "Administrator",
"module": "Fleet Management",
"name": "Fleet Vehicle",
"naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@ -0,0 +1,8 @@
# Copyright (c) 2024, itsdave GmbH and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class FleetVehicle(Document):
pass

View File

@ -0,0 +1,9 @@
# Copyright (c) 2024, itsdave GmbH and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestFleetVehicle(FrappeTestCase):
pass

View File

@ -0,0 +1,9 @@
# Copyright (c) 2024, itsdave GmbH and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestTraccarSettings(FrappeTestCase):
pass

View File

@ -0,0 +1,8 @@
// Copyright (c) 2024, itsdave GmbH and contributors
// For license information, please see license.txt
frappe.ui.form.on('Traccar Settings', {
// refresh: function(frm) {
// }
});

View File

@ -0,0 +1,54 @@
{
"actions": [],
"allow_rename": 1,
"creation": "2024-04-10 12:43:01.179708",
"default_view": "List",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"traccar_server",
"traccar_username",
"traccar_password"
],
"fields": [
{
"fieldname": "traccar_server",
"fieldtype": "Data",
"label": "URL Server"
},
{
"fieldname": "traccar_username",
"fieldtype": "Data",
"label": "Username"
},
{
"fieldname": "traccar_password",
"fieldtype": "Password",
"label": "Password"
}
],
"index_web_pages_for_search": 1,
"issingle": 1,
"links": [],
"modified": "2024-04-11 16:50:20.436522",
"modified_by": "Administrator",
"module": "Fleet Management",
"name": "Traccar Settings",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"print": 1,
"read": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@ -0,0 +1,8 @@
# Copyright (c) 2024, itsdave GmbH and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class TraccarSettings(Document):
pass

View File

@ -0,0 +1,9 @@
# Copyright (c) 2024, itsdave GmbH and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestTracker(FrappeTestCase):
pass

View File

@ -0,0 +1,8 @@
// Copyright (c) 2024, itsdave GmbH and contributors
// For license information, please see license.txt
frappe.ui.form.on('Tracker', {
// refresh: function(frm) {
// }
});

View File

@ -0,0 +1,121 @@
{
"actions": [],
"autoname": "field:portal_name",
"creation": "2024-04-10 12:41:13.026691",
"default_view": "List",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"portal_id",
"portal_name",
"unique_id",
"status",
"last_update",
"position_id",
"group_id",
"phone",
"model",
"contact",
"category",
"disabled",
"button_trips"
],
"fields": [
{
"fieldname": "portal_id",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Portal ID"
},
{
"fieldname": "portal_name",
"fieldtype": "Data",
"in_standard_filter": 1,
"label": "Portal Name",
"unique": 1
},
{
"fieldname": "unique_id",
"fieldtype": "Data",
"label": "Unique ID"
},
{
"fieldname": "status",
"fieldtype": "Data",
"label": "Status"
},
{
"fieldname": "last_update",
"fieldtype": "Data",
"in_list_view": 1,
"in_preview": 1,
"label": "Last Update"
},
{
"fieldname": "position_id",
"fieldtype": "Data",
"label": "Position ID"
},
{
"fieldname": "group_id",
"fieldtype": "Data",
"label": "Group ID"
},
{
"fieldname": "phone",
"fieldtype": "Data",
"label": "Phone"
},
{
"fieldname": "model",
"fieldtype": "Data",
"label": "Model"
},
{
"fieldname": "contact",
"fieldtype": "Data",
"label": "Contact"
},
{
"fieldname": "category",
"fieldtype": "Data",
"label": "Category"
},
{
"fieldname": "disabled",
"fieldtype": "Data",
"label": "Disabled"
},
{
"fieldname": "button_trips",
"fieldtype": "Button",
"label": "View Trips"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2024-04-11 12:52:37.199851",
"modified_by": "Administrator",
"module": "Fleet Management",
"name": "Tracker",
"naming_rule": "By fieldname",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "last_update",
"sort_order": "ASC",
"states": []
}

View File

@ -0,0 +1,8 @@
# Copyright (c) 2024, itsdave GmbH and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class Tracker(Document):
pass

View File

@ -0,0 +1,9 @@
# Copyright (c) 2024, itsdave GmbH and Contributors
# See license.txt
# import frappe
from frappe.tests.utils import FrappeTestCase
class TestTrip(FrappeTestCase):
pass

View File

@ -0,0 +1,8 @@
// Copyright (c) 2024, itsdave GmbH and contributors
// For license information, please see license.txt
frappe.ui.form.on('Trip', {
// refresh: function(frm) {
// }
});

View File

@ -0,0 +1,135 @@
{
"actions": [],
"allow_rename": 1,
"autoname": "TRIP-.######",
"creation": "2024-04-10 12:34:21.394534",
"default_view": "List",
"doctype": "DocType",
"editable_grid": 1,
"engine": "InnoDB",
"field_order": [
"portal_id",
"device_id",
"start",
"end",
"distance",
"average_speed",
"max_speed",
"spent_fuel",
"start_address",
"end_address",
"duration",
"driver_unique_id",
"fleet_vehicle",
"tracker"
],
"fields": [
{
"fieldname": "portal_id",
"fieldtype": "Data",
"hidden": 1,
"label": "Portal ID"
},
{
"fieldname": "device_id",
"fieldtype": "Data",
"label": "Device ID"
},
{
"fieldname": "start",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "Start"
},
{
"fieldname": "end",
"fieldtype": "Data",
"in_list_view": 1,
"in_standard_filter": 1,
"label": "End"
},
{
"fieldname": "distance",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Distance"
},
{
"fieldname": "average_speed",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Average Speed",
"precision": "1"
},
{
"fieldname": "max_speed",
"fieldtype": "Data",
"label": "Max Speed"
},
{
"fieldname": "spent_fuel",
"fieldtype": "Data",
"label": "Spent Fuel"
},
{
"fieldname": "start_address",
"fieldtype": "Data",
"in_list_view": 1,
"label": "Start Address"
},
{
"fieldname": "end_address",
"fieldtype": "Data",
"in_list_view": 1,
"label": "End Address"
},
{
"fieldname": "duration",
"fieldtype": "Data",
"label": "Duration"
},
{
"fieldname": "driver_unique_id",
"fieldtype": "Data",
"label": "Driver Unique ID"
},
{
"fieldname": "fleet_vehicle",
"fieldtype": "Link",
"label": "Fleet Vehicle",
"options": "Fleet Vehicle"
},
{
"fieldname": "tracker",
"fieldtype": "Link",
"label": "Tracker",
"options": "Tracker"
}
],
"index_web_pages_for_search": 1,
"links": [],
"modified": "2024-04-12 12:31:26.524755",
"modified_by": "Administrator",
"module": "Fleet Management",
"name": "Trip",
"naming_rule": "Expression (old style)",
"owner": "Administrator",
"permissions": [
{
"create": 1,
"delete": 1,
"email": 1,
"export": 1,
"print": 1,
"read": 1,
"report": 1,
"role": "System Manager",
"share": 1,
"write": 1
}
],
"sort_field": "modified",
"sort_order": "DESC",
"states": []
}

View File

@ -0,0 +1,8 @@
# Copyright (c) 2024, itsdave GmbH and contributors
# For license information, please see license.txt
# import frappe
from frappe.model.document import Document
class Trip(Document):
pass

View File

@ -215,3 +215,6 @@ app_license = "GPLv3"
# auth_hooks = [
# "fleet_management.auth.validate"
# ]
# hooks.py

View File

@ -1,4 +1,5 @@
from datetime import datetime
from datetime import datetime, timedelta
from frappe.utils.password import get_decrypted_password
import frappe
import requests
@ -6,16 +7,13 @@ import requests
def traccar_auth(ts):
"""authenticates on traccar server and returns cookies"""
response = requests.post(
f"http://{ts.traccar_server}:{ts.traccar_port}/api/session",
f"{ts.traccar_server}/api/session",
data = {
'email': ts.traccar_username,
'password': frappe.utils.password.get_decrypted_password(
'Traccar Settings',
ts.name,
'traccar_password'
)
'password': get_decrypted_password('Traccar Settings', ts.name, 'traccar_password')
}
)
if response.status_code == 200:
return response.cookies
else:
@ -24,8 +22,7 @@ def traccar_auth(ts):
@frappe.whitelist()
def get_devices(doc=None):
"""fetches all devices the user has access to and stores them in Tracker Doctype
should also be able to be called frequently to update the status"""
"""Fetches all devices the user has access to and stores or updates them in Tracker Doctype."""
# get informations for authentication on traccar server
ts = frappe.get_doc('Traccar Settings')
@ -33,88 +30,120 @@ def get_devices(doc=None):
# get all devices from traccar server
try:
devices = requests.get(
f"http://{ts.traccar_server}:{ts.traccar_port}/api/devices",
cookies = traccar_auth(ts)
f"{ts.traccar_server}/api/devices",
cookies = traccar_auth(ts) # Assuming traccar_auth is defined elsewhere
)
except:
frappe.throw("Could not fetch devices from traccar server")
except Exception as e:
frappe.throw(f"Could not fetch devices from Traccar server: {str(e)}")
# Insert devices into Tracker Doctype
# Process each device
for dev in devices.json():
if not frappe.db.exists('Tracker', int(dev['id'])):
frappe.get_doc({
'doctype': 'Tracker',
'portal_id': dev['id'],
'portal_name': dev['name'],
'unique_id': dev['uniqueId'],
'status': dev['status'],
'last_update': datetime.fromisoformat(dev['lastUpdate']).strftime('%Y-%m-%d %H:%M:%S'),
'position_id': dev['positionId'],
'group_id': dev['groupId'],
'phone': dev['phone'],
'model': dev['model'],
'contact': dev['contact'],
'categorie': dev['category'],
'disabled': dev['disabled'],
}).insert()
tracker_id = str(dev['id'])
# Check if the Tracker exists
existing_tracker = frappe.db.exists('Tracker', {'portal_id': tracker_id})
# update db frappe
if existing_tracker:
# If exists, get the document and update
tracker_doc = frappe.get_doc('Tracker', existing_tracker)
else:
# If not, create a new Tracker document
tracker_doc = frappe.get_doc({'doctype': 'Tracker', 'portal_id': tracker_id})
# Update or set fields
tracker_doc.portal_name = dev['name']
tracker_doc.unique_id = dev['uniqueId']
tracker_doc.status = dev['status']
tracker_doc.last_update = datetime.fromisoformat(dev['lastUpdate']).strftime('%Y-%m-%d %H:%M:%S')
tracker_doc.position_id = dev['positionId']
tracker_doc.group_id = dev['groupId']
tracker_doc.phone = dev.get('phone', '') # Using .get() in case some fields might be missing
tracker_doc.model = dev.get('model', '')
tracker_doc.contact = dev.get('contact', '')
tracker_doc.categorie = dev.get('category', '')
tracker_doc.disabled = dev['disabled']
# Save changes to the database
tracker_doc.save()
# Commit the transaction
frappe.db.commit()
@frappe.whitelist()
def get_trips_for_device(device_id, start=None, end=None):
"""
Fetches all trips for a device, stores them in Trip Doctype, and links them to the vehicle assigned to the device.
Fetches all trips for a device, stores or updates them in the Trip Doctype,
and links them to the vehicle assigned to the device.
"""
# get information for authentication on traccar server
ts = frappe.get_doc('Traccar Settings')
# Define default start and end datetime if not provided
if not start:
start = datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ') # Adjust format as required by your Traccar API
start = (datetime.now() - timedelta(days=30)).strftime('%Y-%m-%dT%H:%M:%SZ')
if not end:
end = datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ') # Adjust format as required by your Traccar API
end = datetime.now().strftime('%Y-%m-%dT%H:%M:%SZ')
# get all trips from traccar server
try:
trips_response = requests.get(
f"http://{ts.traccar_server}:{ts.traccar_port}/api/reports/trips",
f"{ts.traccar_server}/api/reports/trips",
cookies=traccar_auth(ts),
params={
'deviceId': device_id,
'from': start,
'to': end
}
params={'deviceId': device_id, 'from': start, 'to': end}
)
trips_response.raise_for_status() # This will raise an error for HTTP error codes
trips_response.raise_for_status()
except requests.HTTPError as e:
frappe.throw(f"HTTP error occurred: {e}")
except Exception as e:
frappe.throw(f"Error fetching trips: {e}")
# Insert trips into Trip Doctype
for trip in trips_response.json():
# Assuming 'id' is unique identifier for the trip from Traccar API response
if not frappe.db.exists('Trip', {'portal_id': trip['id']}):
trip_doc = frappe.get_doc({
'doctype': 'Trip',
'portal_id': trip['id'],
'device_id': trip['deviceId'],
'start': datetime.fromisoformat(trip['startTime']).strftime('%Y-%m-%d %H:%M:%S'),
'end': datetime.fromisoformat(trip['endTime']).strftime('%Y-%m-%d %H:%M:%S'),
'distance': trip['distance'],
'average_speed': trip['averageSpeed'],
'max_speed': trip['maxSpeed'],
'spent_fuel': trip['spentFuel'],
'start_address': trip['startAddress'],
'end_address': trip['endAddress'],
'duration': trip['duration'],
'driver_unique_id': trip['driverUniqueId'],
'vehicle': frappe.get_value('Tracker', trip['deviceId'], 'vehicle')
})
trip_doc.insert(ignore_permissions=True) # Use ignore_permissions if needed
# Remove all data from device (to renew)
existing_trips = frappe.get_all('Trip', filters={'device_id': device_id}, fields=['portal_id'])
for trip in existing_trips:
frappe.delete_doc('Trip', trip['portal_id'], force=1)
for trip in trips_response.json():
trip_doc = frappe.get_doc({'doctype': 'Trip'})
trip_doc.device_id = trip['deviceId']
trip_doc.start = datetime.fromisoformat(trip['startTime']).strftime('%Y-%m-%d %H:%M:%S')
trip_doc.end = datetime.fromisoformat(trip['endTime']).strftime('%Y-%m-%d %H:%M:%S')
trip_doc.distance = trip['distance']
trip_doc.average_speed = trip['averageSpeed']
trip_doc.max_speed = trip['maxSpeed']
trip_doc.spent_fuel = trip['spentFuel']
trip_doc.start_address = trip['startAddress']
trip_doc.end_address = trip['endAddress']
trip_doc.duration = trip['duration']
trip_doc.driver_unique_id = trip['driverUniqueId']
trip_doc.tracker = frappe.get_value('Tracker', {'portal_id': trip['deviceId']}, 'portal_name')
trip_doc.fleet_vehicle = frappe.get_value('Fleet Vehicle', {'tracker': trip_doc.tracker}, 'name')
trip_doc.save(ignore_permissions=True)
# commit the transaction
frappe.db.commit()
@frappe.whitelist()
def getroutes(name, start=None, end=None):
ts = frappe.get_doc('Traccar Settings')
device_id = frappe.get_value('Trip', {'name': name}, 'device_id')
startdate = datetime.strptime(start, "%Y-%m-%d %H:%M:%S").strftime("%Y-%m-%dT%H:%M:%S.000+00:00")
enddate = datetime.strptime(end, "%Y-%m-%d %H:%M:%S").strftime("%Y-%m-%dT%H:%M:%S.000+00:00")
print(f"startdate: {startdate}")
print(f"enddate: {enddate}")
# get route by filter from traccar server
try:
route_response = requests.get(
f"{ts.traccar_server}/api/reports/route",
cookies=traccar_auth(ts),
headers={'Accept': 'application/json'},
params={'deviceId': device_id, 'from': startdate, 'to': enddate}
)
route_response.raise_for_status() # This will raise an error for HTTP error codes
except requests.HTTPError as e:
frappe.throw(f"HTTP error occurred: {e}")
except Exception as e:
frappe.throw(f"Error fetching trips: {e}")
print(route_response)
return route_response.json()