From 1ef05996f5ed44845e458737cac2c1e6165b10d8 Mon Sep 17 00:00:00 2001 From: Luiz Costa Date: Fri, 12 Apr 2024 12:09:00 +0100 Subject: [PATCH] update changes --- .vs/slnx.sqlite | Bin 0 -> 90112 bytes .../fleet_management/doctype/__init__.py | 0 .../doctype/fleet_vehicle/__init__.py | 0 .../doctype/fleet_vehicle/fleet_vehicle.js | 8 + .../doctype/fleet_vehicle/fleet_vehicle.json | 84 +++++++++ .../doctype/fleet_vehicle/fleet_vehicle.py | 8 + .../fleet_vehicle/test_fleet_vehicle.py | 9 + .../doctype/traccar_settings/__init__.py | 0 .../traccar_settings/test_traccar_settings.py | 9 + .../traccar_settings/traccar_settings.js | 8 + .../traccar_settings/traccar_settings.json | 54 ++++++ .../traccar_settings/traccar_settings.py | 8 + .../doctype/tracker/__init__.py | 0 .../doctype/tracker/test_tracker.py | 9 + .../doctype/tracker/tracker.js | 8 + .../doctype/tracker/tracker.json | 121 +++++++++++++ .../doctype/tracker/tracker.py | 8 + .../fleet_management/doctype/trip/__init__.py | 0 .../doctype/trip/test_trip.py | 9 + .../fleet_management/doctype/trip/trip.js | 8 + .../fleet_management/doctype/trip/trip.json | 135 +++++++++++++++ .../fleet_management/doctype/trip/trip.py | 8 + fleet_management/hooks.py | 3 + fleet_management/traccar_api.py | 161 +++++++++++------- 24 files changed, 592 insertions(+), 66 deletions(-) create mode 100644 .vs/slnx.sqlite create mode 100644 fleet_management/fleet_management/doctype/__init__.py create mode 100644 fleet_management/fleet_management/doctype/fleet_vehicle/__init__.py create mode 100644 fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle.js create mode 100644 fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle.json create mode 100644 fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle.py create mode 100644 fleet_management/fleet_management/doctype/fleet_vehicle/test_fleet_vehicle.py create mode 100644 fleet_management/fleet_management/doctype/traccar_settings/__init__.py create mode 100644 fleet_management/fleet_management/doctype/traccar_settings/test_traccar_settings.py create mode 100644 fleet_management/fleet_management/doctype/traccar_settings/traccar_settings.js create mode 100644 fleet_management/fleet_management/doctype/traccar_settings/traccar_settings.json create mode 100644 fleet_management/fleet_management/doctype/traccar_settings/traccar_settings.py create mode 100644 fleet_management/fleet_management/doctype/tracker/__init__.py create mode 100644 fleet_management/fleet_management/doctype/tracker/test_tracker.py create mode 100644 fleet_management/fleet_management/doctype/tracker/tracker.js create mode 100644 fleet_management/fleet_management/doctype/tracker/tracker.json create mode 100644 fleet_management/fleet_management/doctype/tracker/tracker.py create mode 100644 fleet_management/fleet_management/doctype/trip/__init__.py create mode 100644 fleet_management/fleet_management/doctype/trip/test_trip.py create mode 100644 fleet_management/fleet_management/doctype/trip/trip.js create mode 100644 fleet_management/fleet_management/doctype/trip/trip.json create mode 100644 fleet_management/fleet_management/doctype/trip/trip.py diff --git a/.vs/slnx.sqlite b/.vs/slnx.sqlite new file mode 100644 index 0000000000000000000000000000000000000000..7b5c5000751193aa4129b8c1fc70694407187769 GIT binary patch literal 90112 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 literal 0 HcmV?d00001 diff --git a/fleet_management/fleet_management/doctype/__init__.py b/fleet_management/fleet_management/doctype/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fleet_management/fleet_management/doctype/fleet_vehicle/__init__.py b/fleet_management/fleet_management/doctype/fleet_vehicle/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle.js b/fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle.js new file mode 100644 index 0000000..8e572df --- /dev/null +++ b/fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle.js @@ -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) { + + // } +}); diff --git a/fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle.json b/fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle.json new file mode 100644 index 0000000..525472c --- /dev/null +++ b/fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle.json @@ -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": [] +} \ No newline at end of file diff --git a/fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle.py b/fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle.py new file mode 100644 index 0000000..4b6d21b --- /dev/null +++ b/fleet_management/fleet_management/doctype/fleet_vehicle/fleet_vehicle.py @@ -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 diff --git a/fleet_management/fleet_management/doctype/fleet_vehicle/test_fleet_vehicle.py b/fleet_management/fleet_management/doctype/fleet_vehicle/test_fleet_vehicle.py new file mode 100644 index 0000000..55b13ee --- /dev/null +++ b/fleet_management/fleet_management/doctype/fleet_vehicle/test_fleet_vehicle.py @@ -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 diff --git a/fleet_management/fleet_management/doctype/traccar_settings/__init__.py b/fleet_management/fleet_management/doctype/traccar_settings/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fleet_management/fleet_management/doctype/traccar_settings/test_traccar_settings.py b/fleet_management/fleet_management/doctype/traccar_settings/test_traccar_settings.py new file mode 100644 index 0000000..ed0a979 --- /dev/null +++ b/fleet_management/fleet_management/doctype/traccar_settings/test_traccar_settings.py @@ -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 diff --git a/fleet_management/fleet_management/doctype/traccar_settings/traccar_settings.js b/fleet_management/fleet_management/doctype/traccar_settings/traccar_settings.js new file mode 100644 index 0000000..aff942a --- /dev/null +++ b/fleet_management/fleet_management/doctype/traccar_settings/traccar_settings.js @@ -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) { + + // } +}); diff --git a/fleet_management/fleet_management/doctype/traccar_settings/traccar_settings.json b/fleet_management/fleet_management/doctype/traccar_settings/traccar_settings.json new file mode 100644 index 0000000..b2eb83d --- /dev/null +++ b/fleet_management/fleet_management/doctype/traccar_settings/traccar_settings.json @@ -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": [] +} \ No newline at end of file diff --git a/fleet_management/fleet_management/doctype/traccar_settings/traccar_settings.py b/fleet_management/fleet_management/doctype/traccar_settings/traccar_settings.py new file mode 100644 index 0000000..698282c --- /dev/null +++ b/fleet_management/fleet_management/doctype/traccar_settings/traccar_settings.py @@ -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 diff --git a/fleet_management/fleet_management/doctype/tracker/__init__.py b/fleet_management/fleet_management/doctype/tracker/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fleet_management/fleet_management/doctype/tracker/test_tracker.py b/fleet_management/fleet_management/doctype/tracker/test_tracker.py new file mode 100644 index 0000000..b547230 --- /dev/null +++ b/fleet_management/fleet_management/doctype/tracker/test_tracker.py @@ -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 diff --git a/fleet_management/fleet_management/doctype/tracker/tracker.js b/fleet_management/fleet_management/doctype/tracker/tracker.js new file mode 100644 index 0000000..5ea8e16 --- /dev/null +++ b/fleet_management/fleet_management/doctype/tracker/tracker.js @@ -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) { + + // } +}); diff --git a/fleet_management/fleet_management/doctype/tracker/tracker.json b/fleet_management/fleet_management/doctype/tracker/tracker.json new file mode 100644 index 0000000..7e021ca --- /dev/null +++ b/fleet_management/fleet_management/doctype/tracker/tracker.json @@ -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": [] +} \ No newline at end of file diff --git a/fleet_management/fleet_management/doctype/tracker/tracker.py b/fleet_management/fleet_management/doctype/tracker/tracker.py new file mode 100644 index 0000000..99091d1 --- /dev/null +++ b/fleet_management/fleet_management/doctype/tracker/tracker.py @@ -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 diff --git a/fleet_management/fleet_management/doctype/trip/__init__.py b/fleet_management/fleet_management/doctype/trip/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/fleet_management/fleet_management/doctype/trip/test_trip.py b/fleet_management/fleet_management/doctype/trip/test_trip.py new file mode 100644 index 0000000..f39d0c1 --- /dev/null +++ b/fleet_management/fleet_management/doctype/trip/test_trip.py @@ -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 diff --git a/fleet_management/fleet_management/doctype/trip/trip.js b/fleet_management/fleet_management/doctype/trip/trip.js new file mode 100644 index 0000000..89e0b08 --- /dev/null +++ b/fleet_management/fleet_management/doctype/trip/trip.js @@ -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) { + + // } +}); diff --git a/fleet_management/fleet_management/doctype/trip/trip.json b/fleet_management/fleet_management/doctype/trip/trip.json new file mode 100644 index 0000000..61fbdeb --- /dev/null +++ b/fleet_management/fleet_management/doctype/trip/trip.json @@ -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": [] +} \ No newline at end of file diff --git a/fleet_management/fleet_management/doctype/trip/trip.py b/fleet_management/fleet_management/doctype/trip/trip.py new file mode 100644 index 0000000..f856e71 --- /dev/null +++ b/fleet_management/fleet_management/doctype/trip/trip.py @@ -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 diff --git a/fleet_management/hooks.py b/fleet_management/hooks.py index 951985b..0ee443f 100644 --- a/fleet_management/hooks.py +++ b/fleet_management/hooks.py @@ -215,3 +215,6 @@ app_license = "GPLv3" # auth_hooks = [ # "fleet_management.auth.validate" # ] + +# hooks.py + diff --git a/fleet_management/traccar_api.py b/fleet_management/traccar_api.py index 3814d33..fe96f36 100644 --- a/fleet_management/traccar_api.py +++ b/fleet_management/traccar_api.py @@ -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() +