diff --git a/.github/workflows/linter.yml b/.github/workflows/linter.yml
index 7a89735..7cdc563 100644
--- a/.github/workflows/linter.yml
+++ b/.github/workflows/linter.yml
@@ -66,5 +66,4 @@ jobs:
- name: Install and run pip-audit
run: |
pip install pip-audit
- cd ${GITHUB_WORKSPACE}
- pip-audit --desc on .
+ pip-audit -r requirements.txt --desc on
diff --git a/vsd_fleet_ms/patches.txt b/vsd_fleet_ms/patches.txt
index e8fc603..e3aba9d 100644
--- a/vsd_fleet_ms/patches.txt
+++ b/vsd_fleet_ms/patches.txt
@@ -1,8 +1,10 @@
[pre_model_sync]
+vsd_fleet_ms.patches.workspace.rename_fleet_ms_workspace
[post_model_sync]
vsd_fleet_ms.patches.custom_fields.add_cargo_id_custom_field_on_sales_invoice_item
vsd_fleet_ms.patches.custom_fields.add_bill_uom_field_in_cargo_detail
vsd_fleet_ms.patches.custom_fields.add_allow_bill_on_weight
vsd_fleet_ms.patches.property_setters.create_property_setter_cargo_details
-
+vsd_fleet_ms.patches.reports.remove_legacy_invoice_reports
+vsd_fleet_ms.patches.workspace.sync_fleet_management_workspace
diff --git a/vsd_fleet_ms/patches/reports/__init__.py b/vsd_fleet_ms/patches/reports/__init__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/vsd_fleet_ms/patches/reports/__init__.py
@@ -0,0 +1 @@
+
diff --git a/vsd_fleet_ms/patches/reports/remove_legacy_invoice_reports.py b/vsd_fleet_ms/patches/reports/remove_legacy_invoice_reports.py
new file mode 100644
index 0000000..1da5bc3
--- /dev/null
+++ b/vsd_fleet_ms/patches/reports/remove_legacy_invoice_reports.py
@@ -0,0 +1,7 @@
+import frappe
+
+
+def execute():
+ for report in ("Unpaid Invoices Report", "Overdue Invoices Report"):
+ if frappe.db.exists("Report", report):
+ frappe.delete_doc("Report", report, force=True, ignore_permissions=True)
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/fuel_expense_by_trip/__init__.py b/vsd_fleet_ms/patches/workspace/__init__.py
similarity index 100%
rename from vsd_fleet_ms/vsd_fleet_ms/report/fuel_expense_by_trip/__init__.py
rename to vsd_fleet_ms/patches/workspace/__init__.py
diff --git a/vsd_fleet_ms/patches/workspace/rename_fleet_ms_workspace.py b/vsd_fleet_ms/patches/workspace/rename_fleet_ms_workspace.py
new file mode 100644
index 0000000..3b673fb
--- /dev/null
+++ b/vsd_fleet_ms/patches/workspace/rename_fleet_ms_workspace.py
@@ -0,0 +1,32 @@
+import glob
+import os
+
+import frappe
+from frappe.modules.import_file import import_file_by_path
+
+
+def execute():
+ """Bring any site's Fleet MS workspace in line with the new Fleet Management layout.
+
+ Runs in pre_model_sync so the rename happens before the standard fixture sync
+ tries to import the "Fleet Management" workspace file - otherwise a site that
+ still has the old "Fleet MS" doc would end up with both, side by side.
+ """
+ if frappe.db.exists("Workspace", "Fleet MS") and not frappe.db.exists("Workspace", "Fleet Management"):
+ frappe.rename_doc("Workspace", "Fleet MS", "Fleet Management", ignore_permissions=True)
+ frappe.db.set_value("Workspace", "Fleet Management", "label", "Fleet Management")
+
+ frappe.flags.in_migrate = True
+ for old_report in ("Fuel Expense By Trip", "Truck Status Report"):
+ if frappe.db.exists("Report", old_report):
+ frappe.delete_doc("Report", old_report, force=True, ignore_permissions=True)
+
+ # Number Card fixtures for this app are not picked up by the generic module sync
+ # (frappe.model.sync only scans a fixed doctype list that excludes "number_card"
+ # for non-core apps), so import them explicitly here - before the workspace
+ # fixture syncs and tries to link to them.
+ app_path = frappe.get_app_path("vsd_fleet_ms", "vsd_fleet_ms")
+ for path in sorted(glob.glob(os.path.join(app_path, "number_card", "*", "*.json"))):
+ import_file_by_path(path, force=True)
+
+ frappe.db.commit()
diff --git a/vsd_fleet_ms/patches/workspace/sync_fleet_management_workspace.py b/vsd_fleet_ms/patches/workspace/sync_fleet_management_workspace.py
new file mode 100644
index 0000000..f9b599f
--- /dev/null
+++ b/vsd_fleet_ms/patches/workspace/sync_fleet_management_workspace.py
@@ -0,0 +1,7 @@
+import frappe
+from frappe.modules.import_file import import_file_by_path
+
+
+def execute():
+ path = frappe.get_app_path("vsd_fleet_ms", "vsd_fleet_ms", "workspace", "fleet_management", "fleet_management.json")
+ import_file_by_path(path, force=True)
diff --git a/vsd_fleet_ms/vsd_fleet_ms/number_card/__init__.py b/vsd_fleet_ms/vsd_fleet_ms/number_card/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/vsd_fleet_ms/vsd_fleet_ms/number_card/available_truck/available_truck.json b/vsd_fleet_ms/vsd_fleet_ms/number_card/available_truck/available_truck.json
new file mode 100644
index 0000000..92e47ec
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/number_card/available_truck/available_truck.json
@@ -0,0 +1,22 @@
+{
+ "background_color": "#e6f6ea",
+ "color": "#2e9e4f",
+ "creation": "2026-09-17 09:00:00.000000",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Truck",
+ "filters_json": "[[\"Truck\", \"status\", \"=\", \"Idle\", false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Available Truck",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Available Truck",
+ "owner": "Administrator",
+ "show_percentage_stats": 0,
+ "stats_time_interval": "Weekly",
+ "type": "Document Type"
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/number_card/cargo_registrations/cargo_registrations.json b/vsd_fleet_ms/vsd_fleet_ms/number_card/cargo_registrations/cargo_registrations.json
new file mode 100644
index 0000000..6b03291
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/number_card/cargo_registrations/cargo_registrations.json
@@ -0,0 +1,22 @@
+{
+ "background_color": "#e0f7f7",
+ "color": "#16a3a3",
+ "creation": "2026-09-17 09:00:00.000000",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Cargo Registration",
+ "filters_json": "[]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Cargo Registrations",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Cargo Registrations",
+ "owner": "Administrator",
+ "show_percentage_stats": 0,
+ "stats_time_interval": "Weekly",
+ "type": "Document Type"
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/number_card/completed_trips/completed_trips.json b/vsd_fleet_ms/vsd_fleet_ms/number_card/completed_trips/completed_trips.json
new file mode 100644
index 0000000..ba2f2be
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/number_card/completed_trips/completed_trips.json
@@ -0,0 +1,22 @@
+{
+ "background_color": "#e6f6ea",
+ "color": "#2e9e4f",
+ "creation": "2026-09-17 09:00:00.000000",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Trips",
+ "filters_json": "[[\"Trips\", \"trip_status\", \"=\", \"Completed\", false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Completed Trips",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Completed Trips",
+ "owner": "Administrator",
+ "show_percentage_stats": 0,
+ "stats_time_interval": "Weekly",
+ "type": "Document Type"
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/number_card/fuel_requests/fuel_requests.json b/vsd_fleet_ms/vsd_fleet_ms/number_card/fuel_requests/fuel_requests.json
new file mode 100644
index 0000000..2009497
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/number_card/fuel_requests/fuel_requests.json
@@ -0,0 +1,22 @@
+{
+ "background_color": "#fdf1df",
+ "color": "#e0891e",
+ "creation": "2026-09-17 09:00:00.000000",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Fuel Requests",
+ "filters_json": "[[\"Fuel Requests\", \"status\", \"!=\", \"Fully Processed\", false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Fuel Requests",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Fuel Requests",
+ "owner": "Administrator",
+ "show_percentage_stats": 0,
+ "stats_time_interval": "Weekly",
+ "type": "Document Type"
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/number_card/manifest/manifest.json b/vsd_fleet_ms/vsd_fleet_ms/number_card/manifest/manifest.json
new file mode 100644
index 0000000..7e1ee36
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/number_card/manifest/manifest.json
@@ -0,0 +1,22 @@
+{
+ "background_color": "#f1e9fb",
+ "color": "#8258d1",
+ "creation": "2026-09-17 09:00:00.000000",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Manifest",
+ "filters_json": "[]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Manifest",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Manifest",
+ "owner": "Administrator",
+ "show_percentage_stats": 0,
+ "stats_time_interval": "Weekly",
+ "type": "Document Type"
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/number_card/ongoing_trips/ongoing_trips.json b/vsd_fleet_ms/vsd_fleet_ms/number_card/ongoing_trips/ongoing_trips.json
new file mode 100644
index 0000000..430e178
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/number_card/ongoing_trips/ongoing_trips.json
@@ -0,0 +1,22 @@
+{
+ "background_color": "#e5f0fd",
+ "color": "#2f6fed",
+ "creation": "2026-09-17 09:00:00.000000",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Trips",
+ "filters_json": "[[\"Trips\", \"trip_status\", \"=\", \"Pending\", false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Ongoing Trips",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Ongoing Trips",
+ "owner": "Administrator",
+ "show_percentage_stats": 0,
+ "stats_time_interval": "Weekly",
+ "type": "Document Type"
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/number_card/overdue_sales_invoices/overdue_sales_invoices.json b/vsd_fleet_ms/vsd_fleet_ms/number_card/overdue_sales_invoices/overdue_sales_invoices.json
new file mode 100644
index 0000000..20891a9
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/number_card/overdue_sales_invoices/overdue_sales_invoices.json
@@ -0,0 +1,23 @@
+{
+ "background_color": "#fbe7ea",
+ "color": "#c0293f",
+ "creation": "2026-09-17 09:00:00.000000",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Sales Invoice",
+ "dynamic_filters_json": "[[\"Sales Invoice\", \"due_date\", \"<\", \"frappe.datetime.get_today()\"]]",
+ "filters_json": "[[\"Sales Invoice\", \"docstatus\", \"=\", \"1\", false], [\"Sales Invoice\", \"outstanding_amount\", \">\", \"0\", false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Overdue Sales Invoices",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Overdue Sales Invoices",
+ "owner": "Administrator",
+ "show_percentage_stats": 0,
+ "stats_time_interval": "Weekly",
+ "type": "Document Type"
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/number_card/requested_payments_in_trip/requested_payments_in_trip.json b/vsd_fleet_ms/vsd_fleet_ms/number_card/requested_payments_in_trip/requested_payments_in_trip.json
new file mode 100644
index 0000000..e868117
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/number_card/requested_payments_in_trip/requested_payments_in_trip.json
@@ -0,0 +1,22 @@
+{
+ "background_color": "#fbe7ea",
+ "color": "#c0293f",
+ "creation": "2026-09-17 09:00:00.000000",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Requested Payment",
+ "filters_json": "[[\"Requested Payment\", \"payment_status\", \"!=\", \"Paid\", false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Requested Payments In Trip",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Requested Payments In Trip",
+ "owner": "Administrator",
+ "show_percentage_stats": 0,
+ "stats_time_interval": "Weekly",
+ "type": "Document Type"
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/number_card/total_trips/total_trips.json b/vsd_fleet_ms/vsd_fleet_ms/number_card/total_trips/total_trips.json
new file mode 100644
index 0000000..222236c
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/number_card/total_trips/total_trips.json
@@ -0,0 +1,22 @@
+{
+ "background_color": "#e6e9f5",
+ "color": "#3f51b5",
+ "creation": "2026-09-17 09:00:00.000000",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Trips",
+ "filters_json": "[]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Trips",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Total Trips",
+ "owner": "Administrator",
+ "show_percentage_stats": 0,
+ "stats_time_interval": "Weekly",
+ "type": "Document Type"
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/number_card/total_trucks/total_trucks.json b/vsd_fleet_ms/vsd_fleet_ms/number_card/total_trucks/total_trucks.json
new file mode 100644
index 0000000..91a0689
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/number_card/total_trucks/total_trucks.json
@@ -0,0 +1,22 @@
+{
+ "background_color": "#e6e9f5",
+ "color": "#3f51b5",
+ "creation": "2026-09-17 09:00:00.000000",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Truck",
+ "filters_json": "[]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Total Trucks",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Total Trucks",
+ "owner": "Administrator",
+ "show_percentage_stats": 0,
+ "stats_time_interval": "Weekly",
+ "type": "Document Type"
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/number_card/truck_on_trip/truck_on_trip.json b/vsd_fleet_ms/vsd_fleet_ms/number_card/truck_on_trip/truck_on_trip.json
new file mode 100644
index 0000000..2a0b273
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/number_card/truck_on_trip/truck_on_trip.json
@@ -0,0 +1,22 @@
+{
+ "background_color": "#e5f0fd",
+ "color": "#2f6fed",
+ "creation": "2026-09-17 09:00:00.000000",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Truck",
+ "filters_json": "[[\"Truck\", \"status\", \"=\", \"On Trip\", false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Truck On Trip",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Truck On Trip",
+ "owner": "Administrator",
+ "show_percentage_stats": 0,
+ "stats_time_interval": "Weekly",
+ "type": "Document Type"
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/number_card/unpaid_sales_invoices/unpaid_sales_invoices.json b/vsd_fleet_ms/vsd_fleet_ms/number_card/unpaid_sales_invoices/unpaid_sales_invoices.json
new file mode 100644
index 0000000..2705e50
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/number_card/unpaid_sales_invoices/unpaid_sales_invoices.json
@@ -0,0 +1,22 @@
+{
+ "background_color": "#fdf1df",
+ "color": "#c0293f",
+ "creation": "2026-09-17 09:00:00.000000",
+ "docstatus": 0,
+ "doctype": "Number Card",
+ "document_type": "Sales Invoice",
+ "filters_json": "[[\"Sales Invoice\", \"docstatus\", \"=\", \"1\", false], [\"Sales Invoice\", \"outstanding_amount\", \">\", \"0\", false]]",
+ "function": "Count",
+ "idx": 0,
+ "is_public": 1,
+ "is_standard": 1,
+ "label": "Unpaid Sales Invoices",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Unpaid Sales Invoices",
+ "owner": "Administrator",
+ "show_percentage_stats": 0,
+ "stats_time_interval": "Weekly",
+ "type": "Document Type"
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/completed_trips_report/__init__.py b/vsd_fleet_ms/vsd_fleet_ms/report/completed_trips_report/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/completed_trips_report/completed_trips_report.js b/vsd_fleet_ms/vsd_fleet_ms/report/completed_trips_report/completed_trips_report.js
new file mode 100644
index 0000000..bca6f95
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/completed_trips_report/completed_trips_report.js
@@ -0,0 +1,26 @@
+// Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Completed Trips Report"] = {
+ "filters": [
+ {
+ "fieldname": "truck_number",
+ "label": __("Truck"),
+ "fieldtype": "Link",
+ "options": "Truck"
+ },
+ {
+ "fieldname": "from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.month_start()
+ },
+ {
+ "fieldname": "to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.now_date()
+ }
+ ]
+};
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/completed_trips_report/completed_trips_report.json b/vsd_fleet_ms/vsd_fleet_ms/report/completed_trips_report/completed_trips_report.json
new file mode 100644
index 0000000..0f5f480
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/completed_trips_report/completed_trips_report.json
@@ -0,0 +1,30 @@
+{
+ "add_total_row": 1,
+ "columns": [],
+ "creation": "2026-09-17 09:00:00.000000",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Completed Trips Report",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Trips",
+ "report_name": "Completed Trips Report",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "System Manager"
+ },
+ {
+ "role": "All"
+ }
+ ]
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/completed_trips_report/completed_trips_report.py b/vsd_fleet_ms/vsd_fleet_ms/report/completed_trips_report/completed_trips_report.py
new file mode 100644
index 0000000..1770f20
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/completed_trips_report/completed_trips_report.py
@@ -0,0 +1,58 @@
+# Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe import _
+
+
+def execute(filters=None):
+ filters = filters or {}
+ columns = get_columns()
+ data = get_data(filters)
+ return columns, data, None, None
+
+
+def get_columns():
+ return [
+ {"fieldname": "name", "label": _("Trip"), "fieldtype": "Link", "options": "Trips", "width": 130},
+ {"fieldname": "date", "label": _("Trip Date"), "fieldtype": "Date", "width": 100},
+ {"fieldname": "trip_completed_date", "label": _("Completed Date"), "fieldtype": "Date", "width": 120},
+ {"fieldname": "truck_number", "label": _("Truck"), "fieldtype": "Link", "options": "Truck", "width": 110},
+ {"fieldname": "truck_licence_plate", "label": _("Plate Number"), "fieldtype": "Data", "width": 110},
+ {"fieldname": "driver_name", "label": _("Driver"), "fieldtype": "Data", "width": 150},
+ {"fieldname": "route", "label": _("Route"), "fieldtype": "Link", "options": "Trip Routes", "width": 150},
+ ]
+
+
+def get_data(filters):
+ conditions, values = get_conditions(filters)
+
+ return frappe.db.sql(
+ """
+ SELECT name, date, trip_completed_date, truck_number, truck_licence_plate, driver_name, route
+ FROM `tabTrips`
+ WHERE trip_status = 'Completed' """ + conditions + """
+ ORDER BY trip_completed_date DESC
+ """,
+ values,
+ as_dict=1,
+ )
+
+
+def get_conditions(filters):
+ conditions = ""
+ values = {}
+
+ if filters.get("truck_number"):
+ conditions += " AND truck_number = %(truck_number)s"
+ values["truck_number"] = filters.get("truck_number")
+
+ if filters.get("from_date"):
+ conditions += " AND trip_completed_date >= %(from_date)s"
+ values["from_date"] = filters.get("from_date")
+
+ if filters.get("to_date"):
+ conditions += " AND trip_completed_date <= %(to_date)s"
+ values["to_date"] = filters.get("to_date")
+
+ return conditions, values
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/driver_activity_report/__init__.py b/vsd_fleet_ms/vsd_fleet_ms/report/driver_activity_report/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/driver_activity_report/driver_activity_report.js b/vsd_fleet_ms/vsd_fleet_ms/report/driver_activity_report/driver_activity_report.js
new file mode 100644
index 0000000..9507d8f
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/driver_activity_report/driver_activity_report.js
@@ -0,0 +1,14 @@
+// Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Driver Activity Report"] = {
+ "filters": [
+ {
+ "fieldname": "status",
+ "label": __("Status"),
+ "fieldtype": "Select",
+ "options": "\nActive\nSuspended\nLeft"
+ }
+ ]
+};
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/driver_activity_report/driver_activity_report.json b/vsd_fleet_ms/vsd_fleet_ms/report/driver_activity_report/driver_activity_report.json
new file mode 100644
index 0000000..2c3543f
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/driver_activity_report/driver_activity_report.json
@@ -0,0 +1,30 @@
+{
+ "add_total_row": 1,
+ "columns": [],
+ "creation": "2026-09-17 09:00:00.000000",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Driver Activity Report",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Truck Driver",
+ "report_name": "Driver Activity Report",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "System Manager"
+ },
+ {
+ "role": "All"
+ }
+ ]
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/driver_activity_report/driver_activity_report.py b/vsd_fleet_ms/vsd_fleet_ms/report/driver_activity_report/driver_activity_report.py
new file mode 100644
index 0000000..99caef2
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/driver_activity_report/driver_activity_report.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe import _
+
+
+def execute(filters=None):
+ filters = filters or {}
+ columns = get_columns()
+ data = get_data(filters)
+ return columns, data, None, None
+
+
+def get_columns():
+ return [
+ {"fieldname": "driver", "label": _("Driver"), "fieldtype": "Link", "options": "Truck Driver", "width": 130},
+ {"fieldname": "full_name", "label": _("Full Name"), "fieldtype": "Data", "width": 150},
+ {"fieldname": "status", "label": _("Status"), "fieldtype": "Select", "width": 100},
+ {"fieldname": "current_truck", "label": _("Current Truck"), "fieldtype": "Link", "options": "Truck", "width": 120},
+ {"fieldname": "total_trips", "label": _("Total Trips"), "fieldtype": "Int", "width": 100},
+ {"fieldname": "completed_trips", "label": _("Completed Trips"), "fieldtype": "Int", "width": 130},
+ {"fieldname": "pending_trips", "label": _("Pending Trips"), "fieldtype": "Int", "width": 110},
+ ]
+
+
+def get_data(filters):
+ conditions, values = get_conditions(filters)
+
+ return frappe.db.sql(
+ """
+ SELECT
+ d.name AS driver,
+ d.full_name,
+ d.status,
+ (SELECT tr.name FROM `tabTruck` tr WHERE tr.trans_ms_driver = d.name LIMIT 1) AS current_truck,
+ (SELECT COUNT(*) FROM `tabTrips` WHERE assigned_driver = d.name) AS total_trips,
+ (SELECT COUNT(*) FROM `tabTrips` WHERE assigned_driver = d.name AND trip_status = 'Completed') AS completed_trips,
+ (SELECT COUNT(*) FROM `tabTrips` WHERE assigned_driver = d.name AND trip_status = 'Pending') AS pending_trips
+ FROM `tabTruck Driver` d
+ WHERE 1 = 1 """ + conditions + """
+ ORDER BY total_trips DESC
+ """,
+ values,
+ as_dict=1,
+ )
+
+
+def get_conditions(filters):
+ conditions = ""
+ values = {}
+
+ if filters.get("status"):
+ conditions += " AND d.status = %(status)s"
+ values["status"] = filters.get("status")
+
+ return conditions, values
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/fixed_expenses_report/__init__.py b/vsd_fleet_ms/vsd_fleet_ms/report/fixed_expenses_report/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/fixed_expenses_report/fixed_expenses_report.js b/vsd_fleet_ms/vsd_fleet_ms/report/fixed_expenses_report/fixed_expenses_report.js
new file mode 100644
index 0000000..6663990
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/fixed_expenses_report/fixed_expenses_report.js
@@ -0,0 +1,26 @@
+// Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Fixed Expenses Report"] = {
+ "filters": [
+ {
+ "fieldname": "expense_type",
+ "label": __("Expense"),
+ "fieldtype": "Link",
+ "options": "Fixed Expenses"
+ },
+ {
+ "fieldname": "from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.month_start()
+ },
+ {
+ "fieldname": "to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.now_date()
+ }
+ ]
+};
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/fixed_expenses_report/fixed_expenses_report.json b/vsd_fleet_ms/vsd_fleet_ms/report/fixed_expenses_report/fixed_expenses_report.json
new file mode 100644
index 0000000..4a21c51
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/fixed_expenses_report/fixed_expenses_report.json
@@ -0,0 +1,30 @@
+{
+ "add_total_row": 1,
+ "columns": [],
+ "creation": "2026-09-17 09:00:00.000000",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2026-09-18 12:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Fixed Expenses Report",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Fixed Expenses",
+ "report_name": "Fixed Expenses Report",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "System Manager"
+ },
+ {
+ "role": "All"
+ }
+ ]
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/fixed_expenses_report/fixed_expenses_report.py b/vsd_fleet_ms/vsd_fleet_ms/report/fixed_expenses_report/fixed_expenses_report.py
new file mode 100644
index 0000000..d33f5db
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/fixed_expenses_report/fixed_expenses_report.py
@@ -0,0 +1,60 @@
+# Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe import _
+
+
+def execute(filters=None):
+ filters = filters or {}
+ columns = get_columns()
+ data = get_data(filters)
+ return columns, data, None, None
+
+
+def get_columns():
+ return [
+ {"fieldname": "expense_type", "label": _("Expense"), "fieldtype": "Link", "options": "Fixed Expenses", "width": 200},
+ {"fieldname": "request_count", "label": _("Number of Requests"), "fieldtype": "Int", "width": 140},
+ {"fieldname": "total_tzs", "label": _("Total (TZS)"), "fieldtype": "Currency", "options": "TZS", "width": 130},
+ {"fieldname": "total_usd", "label": _("Total (USD)"), "fieldtype": "Currency", "options": "USD", "width": 130},
+ ]
+
+
+def get_data(filters):
+ conditions, values = get_conditions(filters)
+
+ return frappe.db.sql(
+ """
+ SELECT
+ expense_type,
+ COUNT(*) AS request_count,
+ SUM(CASE WHEN request_currency = 'TZS' THEN request_amount ELSE 0 END) AS total_tzs,
+ SUM(CASE WHEN request_currency = 'USD' THEN request_amount ELSE 0 END) AS total_usd
+ FROM `tabRequested Fund Details`
+ WHERE expense_type IS NOT NULL AND expense_type != '' """ + conditions + """
+ GROUP BY expense_type
+ ORDER BY total_tzs DESC
+ """,
+ values,
+ as_dict=1,
+ )
+
+
+def get_conditions(filters):
+ conditions = ""
+ values = {}
+
+ if filters.get("expense_type"):
+ conditions += " AND expense_type = %(expense_type)s"
+ values["expense_type"] = filters.get("expense_type")
+
+ if filters.get("from_date"):
+ conditions += " AND requested_date >= %(from_date)s"
+ values["from_date"] = filters.get("from_date")
+
+ if filters.get("to_date"):
+ conditions += " AND requested_date <= %(to_date)s"
+ values["to_date"] = filters.get("to_date")
+
+ return conditions, values
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/fleet_availability/__init__.py b/vsd_fleet_ms/vsd_fleet_ms/report/fleet_availability/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/fleet_availability/fleet_availability.js b/vsd_fleet_ms/vsd_fleet_ms/report/fleet_availability/fleet_availability.js
new file mode 100644
index 0000000..0ea653a
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/fleet_availability/fleet_availability.js
@@ -0,0 +1,7 @@
+// Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Fleet Availability"] = {
+ "filters": []
+};
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/fleet_availability/fleet_availability.json b/vsd_fleet_ms/vsd_fleet_ms/report/fleet_availability/fleet_availability.json
new file mode 100644
index 0000000..9ec0d6d
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/fleet_availability/fleet_availability.json
@@ -0,0 +1,30 @@
+{
+ "add_total_row": 1,
+ "columns": [],
+ "creation": "2026-09-17 09:00:00.000000",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Fleet Availability",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Truck",
+ "report_name": "Fleet Availability",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "System Manager"
+ },
+ {
+ "role": "All"
+ }
+ ]
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/fleet_availability/fleet_availability.py b/vsd_fleet_ms/vsd_fleet_ms/report/fleet_availability/fleet_availability.py
new file mode 100644
index 0000000..7472f3c
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/fleet_availability/fleet_availability.py
@@ -0,0 +1,30 @@
+# Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe import _
+
+
+def execute(filters=None):
+ columns = get_columns()
+ data = get_data()
+ return columns, data, None, None
+
+
+def get_columns():
+ return [
+ {"fieldname": "status", "label": _("Status"), "fieldtype": "Select", "width": 150},
+ {"fieldname": "truck_count", "label": _("Number of Trucks"), "fieldtype": "Int", "width": 150},
+ ]
+
+
+def get_data():
+ return frappe.db.sql(
+ """
+ SELECT status, COUNT(*) AS truck_count
+ FROM `tabTruck`
+ GROUP BY status
+ ORDER BY truck_count DESC
+ """,
+ as_dict=1,
+ )
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/fuel_consumption_report/__init__.py b/vsd_fleet_ms/vsd_fleet_ms/report/fuel_consumption_report/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/fuel_consumption_report/fuel_consumption_report.js b/vsd_fleet_ms/vsd_fleet_ms/report/fuel_consumption_report/fuel_consumption_report.js
new file mode 100644
index 0000000..b46bef7
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/fuel_consumption_report/fuel_consumption_report.js
@@ -0,0 +1,26 @@
+// Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Fuel Consumption Report"] = {
+ "filters": [
+ {
+ "fieldname": "truck_number",
+ "label": __("Truck"),
+ "fieldtype": "Link",
+ "options": "Truck"
+ },
+ {
+ "fieldname": "from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.month_start()
+ },
+ {
+ "fieldname": "to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.now_date()
+ }
+ ]
+};
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/fuel_consumption_report/fuel_consumption_report.json b/vsd_fleet_ms/vsd_fleet_ms/report/fuel_consumption_report/fuel_consumption_report.json
new file mode 100644
index 0000000..b00f761
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/fuel_consumption_report/fuel_consumption_report.json
@@ -0,0 +1,30 @@
+{
+ "add_total_row": 1,
+ "columns": [],
+ "creation": "2026-09-17 09:00:00.000000",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Fuel Consumption Report",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Trips",
+ "report_name": "Fuel Consumption Report",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "System Manager"
+ },
+ {
+ "role": "All"
+ }
+ ]
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/fuel_consumption_report/fuel_consumption_report.py b/vsd_fleet_ms/vsd_fleet_ms/report/fuel_consumption_report/fuel_consumption_report.py
new file mode 100644
index 0000000..cfb8b10
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/fuel_consumption_report/fuel_consumption_report.py
@@ -0,0 +1,64 @@
+# Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe import _
+
+
+def execute(filters=None):
+ filters = filters or {}
+ columns = get_columns()
+ data = get_data(filters)
+ return columns, data, None, None
+
+
+def get_columns():
+ return [
+ {"fieldname": "truck_number", "label": _("Truck"), "fieldtype": "Link", "options": "Truck", "width": 120},
+ {"fieldname": "trip_count", "label": _("Trips"), "fieldtype": "Int", "width": 90},
+ {"fieldname": "total_quantity", "label": _("Total Fuel (Ltr)"), "fieldtype": "Float", "width": 130},
+ {"fieldname": "total_cost_tzs", "label": _("Total Cost (TZS)"), "fieldtype": "Currency", "options": "TZS", "width": 140},
+ {"fieldname": "total_cost_usd", "label": _("Total Cost (USD)"), "fieldtype": "Currency", "options": "USD", "width": 140},
+ ]
+
+
+def get_data(filters):
+ conditions, values = get_conditions(filters)
+
+ return frappe.db.sql(
+ """
+ SELECT
+ t.truck_number,
+ COUNT(DISTINCT t.name) AS trip_count,
+ SUM(f.quantity) AS total_quantity,
+ SUM(CASE WHEN f.currency = 'TZS' THEN f.total_cost ELSE 0 END) AS total_cost_tzs,
+ SUM(CASE WHEN f.currency = 'USD' THEN f.total_cost ELSE 0 END) AS total_cost_usd
+ FROM `tabTrips` t
+ INNER JOIN `tabFuel Requests Table` f
+ ON f.parent = t.name AND f.parentfield = 'fuel_request_history'
+ WHERE t.truck_number IS NOT NULL AND t.truck_number != '' """ + conditions + """
+ GROUP BY t.truck_number
+ ORDER BY total_quantity DESC
+ """,
+ values,
+ as_dict=1,
+ )
+
+
+def get_conditions(filters):
+ conditions = ""
+ values = {}
+
+ if filters.get("truck_number"):
+ conditions += " AND t.truck_number = %(truck_number)s"
+ values["truck_number"] = filters.get("truck_number")
+
+ if filters.get("from_date"):
+ conditions += " AND t.date >= %(from_date)s"
+ values["from_date"] = filters.get("from_date")
+
+ if filters.get("to_date"):
+ conditions += " AND t.date <= %(to_date)s"
+ values["to_date"] = filters.get("to_date")
+
+ return conditions, values
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/fuel_expense_by_trip/fuel_expense_by_trip.js b/vsd_fleet_ms/vsd_fleet_ms/report/fuel_expense_by_trip/fuel_expense_by_trip.js
deleted file mode 100644
index af490a4..0000000
--- a/vsd_fleet_ms/vsd_fleet_ms/report/fuel_expense_by_trip/fuel_expense_by_trip.js
+++ /dev/null
@@ -1,9 +0,0 @@
-// Copyright (c) 2024, VV SYSTEMS DEVELOPER LTD and contributors
-// For license information, please see license.txt
-/* eslint-disable */
-
-frappe.query_reports["Fuel Expense By Trip"] = {
- "filters": [
-
- ]
-};
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/fuel_expense_by_trip/fuel_expense_by_trip.py b/vsd_fleet_ms/vsd_fleet_ms/report/fuel_expense_by_trip/fuel_expense_by_trip.py
deleted file mode 100644
index e1c834e..0000000
--- a/vsd_fleet_ms/vsd_fleet_ms/report/fuel_expense_by_trip/fuel_expense_by_trip.py
+++ /dev/null
@@ -1,71 +0,0 @@
-# Copyright (c) 2024, VV SYSTEMS DEVELOPER LTD and contributors
-# For license information, please see license.txt
-
-import frappe
-from frappe import _
-
-
-def execute(filters=None):
- columns, data = [], []
- columns = get_columns()
- data = get_data(filters)
- return columns, data, None
-
-def get_columns():
- # Define the columns to be displayed in the report
- return [
- {"fieldname": "vehicle_trip", "fieldtype": "Link", "label": "Vehicle Trip", "options": "Trips"},
- {"fieldname": "date", "fieldtype": "Date", "label": "Trip Date"},
- {"fieldname": "driver_name", "fieldtype": "Data", "label": "Driver Name"},
- {"fieldname": "truck_number", "fieldtype": "Data", "label": "Truck Number"},
- {"fieldname": "transporter_type", "fieldtype": "Data", "label": "Transporter Type"},
- {"fieldname": "trip_status", "fieldtype": "Data", "label": "Trip Status"},
- {"fieldname": "truck_licence_plate", "fieldtype": "Data", "label": "Truck Licence Plate"},
- {"fieldname": "route", "fieldtype": "Link", "label": "Route","options":"Trip Routes"},
- {"fieldname": "item_name", "fieldtype": "Data", "label": "Item Name"},
- {"fieldname": "uom", "fieldtype": "Data", "label": "UOM"},
- {"fieldname": "quantity", "fieldtype": "Float", "label": "Quantity"},
- {"fieldname": "cost_per_litre", "fieldtype": "Float", "label": "Cost Per Litre"},
- {"fieldname": "currency", "fieldtype": "Link", "label": "Currency","options":"Currency"},
- {"fieldname": "total_cost", "fieldtype": "Currency", "label": "Total Cost","options":""},
- {"fieldname": "disbursement_type", "fieldtype": "Data", "label": "Disbursement Type"},
- {"fieldname": "supplier", "fieldtype": "Link", "label": "Supplier", "options": "Supplier"},
- {"fieldname": "status", "fieldtype": "Data", "label": "Status"},
- {"fieldname": "approved_by", "fieldtype": "Data", "label": "Approved By"},
- {"fieldname": "approved_date", "fieldtype": "Date", "label": "Approved Date"},
- {"fieldname": "round_trip", "fieldtype": "Check", "label": "Round Trip"},
- {"fieldname": "trip_complited", "fieldtype": "Check", "label": "Trip Completed"}
-
- ]
-
-def get_data(filters):
- data = []
- vehicle_trips = frappe.db.sql("SELECT * FROM tabTrips T INNER JOIN `tabFuel Requests Table` FL ON FL.parent = T.name",as_dict=True)
- for trip in vehicle_trips:
- data.append({
- "round_trip": trip.round_trip,
- "driver_name": trip.driver_name,
- "trip_complited": trip.trip_complited,
- "truck_number": trip.truck_number,
- "transporter_type": trip.transporter_type,
- "trip_status": trip.trip_status,
- "truck_number": trip.truck_number,
- "truck_licence_plate": trip.truck_licence_plate,
- "route": trip.route,
- "vehicle_trip": trip.parent,
- "item_code": trip.item_code,
- "item_name": trip.item_name,
- "uom": trip.uom,
- "quantity": trip.quantity,
- "cost_per_litre": trip.cost_per_litre,
- "currency": trip.currency,
- "total_cost": trip.total_cost,
- "disbursement_type": trip.disbursement_type,
- "supplier": trip.supplier,
- "status": trip.status,
- "approved_by": trip.approved_by,
- "date": trip.date,
- "approved_date": trip.approved_date
-
- })
- return data
\ No newline at end of file
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/ongoing_trips_report/__init__.py b/vsd_fleet_ms/vsd_fleet_ms/report/ongoing_trips_report/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/ongoing_trips_report/ongoing_trips_report.js b/vsd_fleet_ms/vsd_fleet_ms/report/ongoing_trips_report/ongoing_trips_report.js
new file mode 100644
index 0000000..4cfb759
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/ongoing_trips_report/ongoing_trips_report.js
@@ -0,0 +1,24 @@
+// Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Ongoing Trips Report"] = {
+ "filters": [
+ {
+ "fieldname": "truck_number",
+ "label": __("Truck"),
+ "fieldtype": "Link",
+ "options": "Truck"
+ },
+ {
+ "fieldname": "from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date"
+ },
+ {
+ "fieldname": "to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date"
+ }
+ ]
+};
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/ongoing_trips_report/ongoing_trips_report.json b/vsd_fleet_ms/vsd_fleet_ms/report/ongoing_trips_report/ongoing_trips_report.json
new file mode 100644
index 0000000..82191b3
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/ongoing_trips_report/ongoing_trips_report.json
@@ -0,0 +1,30 @@
+{
+ "add_total_row": 1,
+ "columns": [],
+ "creation": "2026-09-17 09:00:00.000000",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Ongoing Trips Report",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Trips",
+ "report_name": "Ongoing Trips Report",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "System Manager"
+ },
+ {
+ "role": "All"
+ }
+ ]
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/ongoing_trips_report/ongoing_trips_report.py b/vsd_fleet_ms/vsd_fleet_ms/report/ongoing_trips_report/ongoing_trips_report.py
new file mode 100644
index 0000000..6ffbcf0
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/ongoing_trips_report/ongoing_trips_report.py
@@ -0,0 +1,58 @@
+# Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe import _
+
+
+def execute(filters=None):
+ filters = filters or {}
+ columns = get_columns()
+ data = get_data(filters)
+ return columns, data, None, None
+
+
+def get_columns():
+ return [
+ {"fieldname": "name", "label": _("Trip"), "fieldtype": "Link", "options": "Trips", "width": 130},
+ {"fieldname": "date", "label": _("Trip Date"), "fieldtype": "Date", "width": 100},
+ {"fieldname": "truck_number", "label": _("Truck"), "fieldtype": "Link", "options": "Truck", "width": 110},
+ {"fieldname": "truck_licence_plate", "label": _("Plate Number"), "fieldtype": "Data", "width": 110},
+ {"fieldname": "driver_name", "label": _("Driver"), "fieldtype": "Data", "width": 150},
+ {"fieldname": "route", "label": _("Route"), "fieldtype": "Link", "options": "Trip Routes", "width": 150},
+ {"fieldname": "transporter_type", "label": _("Transporter"), "fieldtype": "Data", "width": 110},
+ ]
+
+
+def get_data(filters):
+ conditions, values = get_conditions(filters)
+
+ return frappe.db.sql(
+ """
+ SELECT name, date, truck_number, truck_licence_plate, driver_name, route, transporter_type
+ FROM `tabTrips`
+ WHERE trip_status = 'Pending' """ + conditions + """
+ ORDER BY date DESC
+ """,
+ values,
+ as_dict=1,
+ )
+
+
+def get_conditions(filters):
+ conditions = ""
+ values = {}
+
+ if filters.get("truck_number"):
+ conditions += " AND truck_number = %(truck_number)s"
+ values["truck_number"] = filters.get("truck_number")
+
+ if filters.get("from_date"):
+ conditions += " AND date >= %(from_date)s"
+ values["from_date"] = filters.get("from_date")
+
+ if filters.get("to_date"):
+ conditions += " AND date <= %(to_date)s"
+ values["to_date"] = filters.get("to_date")
+
+ return conditions, values
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/pending_fuel_requests_report/__init__.py b/vsd_fleet_ms/vsd_fleet_ms/report/pending_fuel_requests_report/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/pending_fuel_requests_report/pending_fuel_requests_report.js b/vsd_fleet_ms/vsd_fleet_ms/report/pending_fuel_requests_report/pending_fuel_requests_report.js
new file mode 100644
index 0000000..c961330
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/pending_fuel_requests_report/pending_fuel_requests_report.js
@@ -0,0 +1,30 @@
+// Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Pending Fuel Requests Report"] = {
+ "filters": [
+ {
+ "fieldname": "from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date"
+ },
+ {
+ "fieldname": "to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date"
+ },
+ {
+ "fieldname": "truck",
+ "label": __("Truck"),
+ "fieldtype": "Link",
+ "options": "Truck"
+ },
+ {
+ "fieldname": "status",
+ "label": __("Status"),
+ "fieldtype": "Select",
+ "options": "\nWaiting Approval\nPartially Processed"
+ }
+ ]
+};
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/pending_fuel_requests_report/pending_fuel_requests_report.json b/vsd_fleet_ms/vsd_fleet_ms/report/pending_fuel_requests_report/pending_fuel_requests_report.json
new file mode 100644
index 0000000..213c835
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/pending_fuel_requests_report/pending_fuel_requests_report.json
@@ -0,0 +1,30 @@
+{
+ "add_total_row": 1,
+ "columns": [],
+ "creation": "2026-09-17 09:00:00.000000",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Pending Fuel Requests Report",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Fuel Requests",
+ "report_name": "Pending Fuel Requests Report",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "System Manager"
+ },
+ {
+ "role": "All"
+ }
+ ]
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/pending_fuel_requests_report/pending_fuel_requests_report.py b/vsd_fleet_ms/vsd_fleet_ms/report/pending_fuel_requests_report/pending_fuel_requests_report.py
new file mode 100644
index 0000000..7a4495f
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/pending_fuel_requests_report/pending_fuel_requests_report.py
@@ -0,0 +1,104 @@
+# Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe import _
+
+
+def execute(filters=None):
+ filters = filters or {}
+ columns = get_columns()
+ data = get_data(filters)
+ return columns, data, None, None
+
+
+def get_columns():
+ return [
+ {"fieldname": "name", "label": _("Fuel Request"), "fieldtype": "Link", "options": "Fuel Requests", "width": 150},
+ {"fieldname": "transaction_date", "label": _("Transaction Date"), "fieldtype": "Date", "width": 110},
+ {"fieldname": "truck", "label": _("Truck"), "fieldtype": "Link", "options": "Truck", "width": 110},
+ {"fieldname": "driver_name", "label": _("Driver"), "fieldtype": "Data", "width": 150},
+ {"fieldname": "main_route", "label": _("Main Route"), "fieldtype": "Link", "options": "Trip Routes", "width": 150},
+ {"fieldname": "return_route", "label": _("Return Route"), "fieldtype": "Link", "options": "Trip Routes", "width": 150},
+ {"fieldname": "status", "label": _("Status"), "fieldtype": "Data", "width": 130},
+ {"fieldname": "requested_quantity", "label": _("Requested Quantity (Ltr)"), "fieldtype": "Float", "width": 160},
+ {"fieldname": "requested_cost_tzs", "label": _("Requested Cost (TZS)"), "fieldtype": "Currency", "options": "TZS", "width": 150},
+ {"fieldname": "requested_cost_usd", "label": _("Requested Cost (USD)"), "fieldtype": "Currency", "options": "USD", "width": 150},
+ {"fieldname": "reference_doctype", "label": _("Reference Doctype"), "fieldtype": "Link", "options": "DocType", "width": 130},
+ {"fieldname": "reference_docname", "label": _("Reference"), "fieldtype": "Dynamic Link", "options": "reference_doctype", "width": 150},
+ ]
+
+
+def get_data(filters):
+ conditions, values = get_conditions(filters)
+
+ return frappe.db.sql(
+ """
+ SELECT
+ fr.name AS name,
+ COALESCE(fr.transaction_date, t.date) AS transaction_date,
+ COALESCE(fr.truck, t.truck_number) AS truck,
+ COALESCE(fr.driver_name, t.driver_name) AS driver_name,
+ COALESCE(fr.main_route, t.route) AS main_route,
+ fr.return_route,
+ fr.status,
+ fr.reference_doctype,
+ fr.reference_docname,
+ COALESCE((
+ SELECT SUM(quantity)
+ FROM `tabFuel Requests Table`
+ WHERE parenttype = 'Fuel Requests' AND parentfield = 'requested_fuel' AND parent = fr.name
+ ), 0) + COALESCE((
+ SELECT SUM(quantity)
+ FROM `tabFuel Requests Table`
+ WHERE parenttype = 'Trips' AND parentfield = 'fuel_request_history' AND parent = t.name
+ ), 0) AS requested_quantity,
+ COALESCE((
+ SELECT SUM(total_cost)
+ FROM `tabFuel Requests Table`
+ WHERE parenttype = 'Fuel Requests' AND parentfield = 'requested_fuel' AND parent = fr.name AND currency = 'TZS'
+ ), 0) + COALESCE((
+ SELECT SUM(total_cost)
+ FROM `tabFuel Requests Table`
+ WHERE parenttype = 'Trips' AND parentfield = 'fuel_request_history' AND parent = t.name AND currency = 'TZS'
+ ), 0) AS requested_cost_tzs,
+ COALESCE((
+ SELECT SUM(total_cost)
+ FROM `tabFuel Requests Table`
+ WHERE parenttype = 'Fuel Requests' AND parentfield = 'requested_fuel' AND parent = fr.name AND currency = 'USD'
+ ), 0) + COALESCE((
+ SELECT SUM(total_cost)
+ FROM `tabFuel Requests Table`
+ WHERE parenttype = 'Trips' AND parentfield = 'fuel_request_history' AND parent = t.name AND currency = 'USD'
+ ), 0) AS requested_cost_usd
+ FROM `tabFuel Requests` fr
+ LEFT JOIN `tabTrips` t ON fr.reference_doctype = 'Trips' AND fr.reference_docname = t.name
+ WHERE fr.status != 'Fully Processed' """ + conditions + """
+ ORDER BY transaction_date DESC
+ """,
+ values,
+ as_dict=1,
+ )
+
+
+def get_conditions(filters):
+ conditions = ""
+ values = {}
+
+ if filters.get("status"):
+ conditions += " AND fr.status = %(status)s"
+ values["status"] = filters.get("status")
+
+ if filters.get("truck"):
+ conditions += " AND fr.truck = %(truck)s"
+ values["truck"] = filters.get("truck")
+
+ if filters.get("from_date"):
+ conditions += " AND (COALESCE(fr.transaction_date, t.date) >= %(from_date)s OR COALESCE(fr.transaction_date, t.date) IS NULL)"
+ values["from_date"] = filters.get("from_date")
+
+ if filters.get("to_date"):
+ conditions += " AND (COALESCE(fr.transaction_date, t.date) <= %(to_date)s OR COALESCE(fr.transaction_date, t.date) IS NULL)"
+ values["to_date"] = filters.get("to_date")
+
+ return conditions, values
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/pending_requested_payments_report/__init__.py b/vsd_fleet_ms/vsd_fleet_ms/report/pending_requested_payments_report/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/pending_requested_payments_report/pending_requested_payments_report.js b/vsd_fleet_ms/vsd_fleet_ms/report/pending_requested_payments_report/pending_requested_payments_report.js
new file mode 100644
index 0000000..6fc45cc
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/pending_requested_payments_report/pending_requested_payments_report.js
@@ -0,0 +1,38 @@
+// Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Pending Requested Payments Report"] = {
+ "filters": [
+ {
+ "fieldname": "from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.month_start()
+ },
+ {
+ "fieldname": "to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.now_date()
+ },
+ {
+ "fieldname": "truck_no",
+ "label": __("Truck"),
+ "fieldtype": "Link",
+ "options": "Truck"
+ },
+ {
+ "fieldname": "approval_status",
+ "label": __("Approval Status"),
+ "fieldtype": "Select",
+ "options": "\nWaiting Approval\nProcessed"
+ },
+ {
+ "fieldname": "payment_status",
+ "label": __("Payment Status"),
+ "fieldtype": "Select",
+ "options": "\nWaiting Approval\nWaiting Payment\nPaid"
+ }
+ ]
+};
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/pending_requested_payments_report/pending_requested_payments_report.json b/vsd_fleet_ms/vsd_fleet_ms/report/pending_requested_payments_report/pending_requested_payments_report.json
new file mode 100644
index 0000000..715680f
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/pending_requested_payments_report/pending_requested_payments_report.json
@@ -0,0 +1,30 @@
+{
+ "add_total_row": 1,
+ "columns": [],
+ "creation": "2026-09-17 09:00:00.000000",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Pending Requested Payments Report",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Requested Payment",
+ "report_name": "Pending Requested Payments Report",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "System Manager"
+ },
+ {
+ "role": "All"
+ }
+ ]
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/pending_requested_payments_report/pending_requested_payments_report.py b/vsd_fleet_ms/vsd_fleet_ms/report/pending_requested_payments_report/pending_requested_payments_report.py
new file mode 100644
index 0000000..d2450c9
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/pending_requested_payments_report/pending_requested_payments_report.py
@@ -0,0 +1,87 @@
+# Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe import _
+
+
+def execute(filters=None):
+ filters = filters or {}
+ columns = get_columns()
+ data = get_data(filters)
+ return columns, data, None, None
+
+
+def get_columns():
+ return [
+ {"fieldname": "reference", "label": _("Requested Payment"), "fieldtype": "Link", "options": "Requested Payment", "width": 160},
+ {"fieldname": "request_date", "label": _("Request Date"), "fieldtype": "Date", "width": 110},
+ {"fieldname": "truck_no", "label": _("Truck"), "fieldtype": "Link", "options": "Truck", "width": 110},
+ {"fieldname": "driver_name", "label": _("Driver"), "fieldtype": "Data", "width": 150},
+ {"fieldname": "trip_route", "label": _("Route"), "fieldtype": "Link", "options": "Trip Routes", "width": 150},
+ {"fieldname": "manifest", "label": _("Manifest"), "fieldtype": "Link", "options": "Manifest", "width": 130},
+ {"fieldname": "approval_status", "label": _("Approval Status"), "fieldtype": "Data", "width": 130},
+ {"fieldname": "payment_status", "label": _("Payment Status"), "fieldtype": "Data", "width": 130},
+ {"fieldname": "requested_usd", "label": _("Requested (USD)"), "fieldtype": "Currency", "options": "USD", "width": 130},
+ {"fieldname": "requested_tzs", "label": _("Requested (TZS)"), "fieldtype": "Currency", "options": "TZS", "width": 130},
+ ]
+
+
+def get_data(filters):
+ conditions, values = get_conditions(filters)
+
+ return frappe.db.sql(
+ """
+ SELECT
+ rp.name AS reference,
+ rp.request_date,
+ rp.truck_no,
+ rp.driver_name,
+ rp.trip_route,
+ rp.manifest,
+ rp.approval_status,
+ rp.payment_status,
+ (
+ SELECT SUM(request_amount)
+ FROM `tabRequested Fund Details`
+ WHERE parenttype = rp.reference_doctype AND parent = rp.reference_docname AND request_currency = 'USD'
+ ) AS requested_usd,
+ (
+ SELECT SUM(request_amount)
+ FROM `tabRequested Fund Details`
+ WHERE parenttype = rp.reference_doctype AND parent = rp.reference_docname AND request_currency = 'TZS'
+ ) AS requested_tzs
+ FROM `tabRequested Payment` rp
+ WHERE rp.payment_status != 'Paid' """ + conditions + """
+ ORDER BY rp.request_date DESC
+ """,
+ values,
+ as_dict=1,
+ )
+
+
+def get_conditions(filters):
+ conditions = ""
+ values = {}
+
+ if filters.get("approval_status"):
+ conditions += " AND rp.approval_status = %(approval_status)s"
+ values["approval_status"] = filters.get("approval_status")
+
+ if filters.get("payment_status"):
+ conditions += " AND rp.payment_status = %(payment_status)s"
+ values["payment_status"] = filters.get("payment_status")
+
+ if filters.get("truck_no"):
+ conditions += " AND rp.truck_no = %(truck_no)s"
+ values["truck_no"] = filters.get("truck_no")
+
+ if filters.get("from_date"):
+ conditions += " AND rp.request_date >= %(from_date)s"
+ values["from_date"] = filters.get("from_date")
+
+ if filters.get("to_date"):
+ conditions += " AND rp.request_date <= %(to_date)s"
+ values["to_date"] = filters.get("to_date")
+
+ return conditions, values
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_fuel_cost/__init__.py b/vsd_fleet_ms/vsd_fleet_ms/report/trip_fuel_cost/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_fuel_cost/trip_fuel_cost.js b/vsd_fleet_ms/vsd_fleet_ms/report/trip_fuel_cost/trip_fuel_cost.js
new file mode 100644
index 0000000..3575121
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/trip_fuel_cost/trip_fuel_cost.js
@@ -0,0 +1,26 @@
+// Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Trip Fuel Cost"] = {
+ "filters": [
+ {
+ "fieldname": "from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.month_start()
+ },
+ {
+ "fieldname": "to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.now_date()
+ },
+ {
+ "fieldname": "truck_number",
+ "label": __("Truck"),
+ "fieldtype": "Link",
+ "options": "Truck"
+ }
+ ]
+};
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/fuel_expense_by_trip/fuel_expense_by_trip.json b/vsd_fleet_ms/vsd_fleet_ms/report/trip_fuel_cost/trip_fuel_cost.json
similarity index 72%
rename from vsd_fleet_ms/vsd_fleet_ms/report/fuel_expense_by_trip/fuel_expense_by_trip.json
rename to vsd_fleet_ms/vsd_fleet_ms/report/trip_fuel_cost/trip_fuel_cost.json
index 9521bde..f203053 100644
--- a/vsd_fleet_ms/vsd_fleet_ms/report/fuel_expense_by_trip/fuel_expense_by_trip.json
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/trip_fuel_cost/trip_fuel_cost.json
@@ -9,21 +9,24 @@
"filters": [],
"idx": 0,
"is_standard": "Yes",
- "modified": "2024-05-06 09:52:06.596618",
+ "modified": "2026-09-17 09:00:00.000000",
"modified_by": "Administrator",
"module": "VSD Fleet MS",
- "name": "Fuel Expense By Trip",
+ "name": "Trip Fuel Cost",
"owner": "Administrator",
"prepared_report": 0,
"ref_doctype": "Trips",
- "report_name": "Fuel Expense By Trip",
+ "report_name": "Trip Fuel Cost",
"report_type": "Script Report",
"roles": [
{
"role": "System Manager"
},
{
- "role": "All"
+ "role": "Fleet Manager"
+ },
+ {
+ "role": "Accounts User"
}
]
-}
\ No newline at end of file
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_fuel_cost/trip_fuel_cost.py b/vsd_fleet_ms/vsd_fleet_ms/report/trip_fuel_cost/trip_fuel_cost.py
new file mode 100644
index 0000000..11d34f2
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/trip_fuel_cost/trip_fuel_cost.py
@@ -0,0 +1,75 @@
+# Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe import _
+
+
+def execute(filters=None):
+ filters = filters or {}
+ columns = get_columns()
+ data = get_data(filters)
+ return columns, data, None
+
+
+def get_columns():
+ return [
+ {"fieldname": "vehicle_trip", "fieldtype": "Link", "label": _("Vehicle Trip"), "options": "Trips"},
+ {"fieldname": "date", "fieldtype": "Date", "label": _("Trip Date")},
+ {"fieldname": "driver_name", "fieldtype": "Data", "label": _("Driver Name")},
+ {"fieldname": "truck_number", "fieldtype": "Data", "label": _("Truck Number")},
+ {"fieldname": "transporter_type", "fieldtype": "Data", "label": _("Transporter Type")},
+ {"fieldname": "trip_status", "fieldtype": "Data", "label": _("Trip Status")},
+ {"fieldname": "route", "fieldtype": "Link", "label": _("Route"), "options": "Trip Routes"},
+ {"fieldname": "item_name", "fieldtype": "Data", "label": _("Item Name")},
+ {"fieldname": "uom", "fieldtype": "Data", "label": _("UOM")},
+ {"fieldname": "quantity", "fieldtype": "Float", "label": _("Quantity")},
+ {"fieldname": "cost_per_litre", "fieldtype": "Float", "label": _("Cost Per Litre")},
+ {"fieldname": "currency", "fieldtype": "Link", "label": _("Currency"), "options": "Currency"},
+ {"fieldname": "total_cost", "fieldtype": "Currency", "label": _("Total Cost"), "options": "currency"},
+ {"fieldname": "disbursement_type", "fieldtype": "Data", "label": _("Disbursement Type")},
+ {"fieldname": "supplier", "fieldtype": "Link", "label": _("Supplier"), "options": "Supplier"},
+ {"fieldname": "status", "fieldtype": "Data", "label": _("Status")},
+ {"fieldname": "approved_by", "fieldtype": "Data", "label": _("Approved By")},
+ {"fieldname": "approved_date", "fieldtype": "Date", "label": _("Approved Date")},
+ ]
+
+
+def get_data(filters):
+ conditions, values = get_conditions(filters)
+
+ rows = frappe.db.sql(
+ """
+ SELECT
+ T.name AS vehicle_trip, T.date, T.driver_name, T.truck_number, T.transporter_type,
+ T.trip_status, T.route,
+ FL.item_name, FL.uom, FL.quantity, FL.cost_per_litre, FL.currency, FL.total_cost,
+ FL.disbursement_type, FL.supplier, FL.status, FL.approved_by, FL.approved_date
+ FROM `tabTrips` T
+ INNER JOIN `tabFuel Requests Table` FL ON FL.parent = T.name AND FL.parentfield = 'fuel_request_history'
+ WHERE 1 = 1 """ + conditions + """
+ ORDER BY T.date DESC
+ """,
+ values,
+ as_dict=True,
+ )
+ return rows
+
+
+def get_conditions(filters):
+ conditions = ""
+ values = {}
+
+ if filters.get("truck_number"):
+ conditions += " AND T.truck_number = %(truck_number)s"
+ values["truck_number"] = filters.get("truck_number")
+
+ if filters.get("from_date"):
+ conditions += " AND T.date >= %(from_date)s"
+ values["from_date"] = filters.get("from_date")
+
+ if filters.get("to_date"):
+ conditions += " AND T.date <= %(to_date)s"
+ values["to_date"] = filters.get("to_date")
+
+ return conditions, values
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_invoices_report/__init__.py b/vsd_fleet_ms/vsd_fleet_ms/report/trip_invoices_report/__init__.py
new file mode 100644
index 0000000..8b13789
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/trip_invoices_report/__init__.py
@@ -0,0 +1 @@
+
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_invoices_report/trip_invoices_report.js b/vsd_fleet_ms/vsd_fleet_ms/report/trip_invoices_report/trip_invoices_report.js
new file mode 100644
index 0000000..eb60055
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/trip_invoices_report/trip_invoices_report.js
@@ -0,0 +1,45 @@
+// Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Trip Invoices Report"] = {
+ filters: [
+ {
+ fieldname: "invoice_status",
+ label: __("Invoice Status"),
+ fieldtype: "Select",
+ options: "All\nPending\nOverdue\nPaid",
+ default: "All"
+ },
+ {
+ fieldname: "customer",
+ label: __("Customer"),
+ fieldtype: "Link",
+ options: "Customer"
+ },
+ {
+ fieldname: "trip",
+ label: __("Trip"),
+ fieldtype: "Link",
+ options: "Trips"
+ },
+ {
+ fieldname: "cargo_registration",
+ label: __("Cargo Registration"),
+ fieldtype: "Link",
+ options: "Cargo Registration"
+ },
+ {
+ fieldname: "from_date",
+ label: __("From Date"),
+ fieldtype: "Date",
+ default: frappe.datetime.month_start()
+ },
+ {
+ fieldname: "to_date",
+ label: __("To Date"),
+ fieldtype: "Date",
+ default: frappe.datetime.now_date()
+ }
+ ]
+};
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_invoices_report/trip_invoices_report.json b/vsd_fleet_ms/vsd_fleet_ms/report/trip_invoices_report/trip_invoices_report.json
new file mode 100644
index 0000000..a87d18e
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/trip_invoices_report/trip_invoices_report.json
@@ -0,0 +1,33 @@
+{
+ "add_total_row": 1,
+ "columns": [],
+ "creation": "2026-09-18 12:00:00.000000",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2026-09-18 12:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Trip Invoices Report",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Sales Invoice",
+ "report_name": "Trip Invoices Report",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "System Manager"
+ },
+ {
+ "role": "Fleet Manager"
+ },
+ {
+ "role": "Accounts User"
+ }
+ ]
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_invoices_report/trip_invoices_report.py b/vsd_fleet_ms/vsd_fleet_ms/report/trip_invoices_report/trip_invoices_report.py
new file mode 100644
index 0000000..ea93d1a
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/trip_invoices_report/trip_invoices_report.py
@@ -0,0 +1,86 @@
+import frappe
+from frappe import _
+from frappe.utils import nowdate
+
+
+def execute(filters=None):
+ filters = filters or {}
+ return get_columns(), get_data(filters)
+
+
+def get_columns():
+ return [
+ {"fieldname": "name", "label": _("Sales Invoice"), "fieldtype": "Link", "options": "Sales Invoice", "width": 130},
+ {"fieldname": "invoice_status", "label": _("Status"), "fieldtype": "Data", "width": 100},
+ {"fieldname": "trip", "label": _("Trip"), "fieldtype": "Link", "options": "Trips", "width": 120},
+ {"fieldname": "cargo_registration", "label": _("Cargo Registration"), "fieldtype": "Link", "options": "Cargo Registration", "width": 150},
+ {"fieldname": "customer", "label": _("Customer"), "fieldtype": "Link", "options": "Customer", "width": 160},
+ {"fieldname": "posting_date", "label": _("Posting Date"), "fieldtype": "Date", "width": 110},
+ {"fieldname": "due_date", "label": _("Due Date"), "fieldtype": "Date", "width": 110},
+ {"fieldname": "days_overdue", "label": _("Days Overdue"), "fieldtype": "Int", "width": 110},
+ {"fieldname": "grand_total", "label": _("Grand Total"), "fieldtype": "Currency", "options": "currency", "width": 130},
+ {"fieldname": "outstanding_amount", "label": _("Outstanding Amount"), "fieldtype": "Currency", "options": "currency", "width": 150},
+ {"fieldname": "currency", "label": _("Currency"), "fieldtype": "Link", "options": "Currency", "width": 90},
+ ]
+
+
+def get_data(filters):
+ conditions, values = get_conditions(filters)
+ values["today"] = nowdate()
+
+ return frappe.db.sql(
+ """
+ SELECT DISTINCT
+ si.name,
+ CASE
+ WHEN si.outstanding_amount = 0 THEN 'Paid'
+ WHEN si.due_date < %(today)s THEN 'Overdue'
+ ELSE 'Pending'
+ END AS invoice_status,
+ cr.trip,
+ cr.name AS cargo_registration,
+ si.customer, si.posting_date, si.due_date,
+ GREATEST(DATEDIFF(%(today)s, si.due_date), 0) AS days_overdue,
+ si.grand_total, si.outstanding_amount, si.currency
+ FROM `tabSales Invoice` si
+ INNER JOIN `tabCargo Detail` cd ON cd.invoice = si.name
+ INNER JOIN `tabCargo Registration` cr ON cr.name = cd.parent
+ WHERE si.docstatus = 1
+ """
+ + conditions
+ + """
+ ORDER BY si.due_date ASC
+ """,
+ values,
+ as_dict=1,
+ )
+
+
+def get_conditions(filters):
+ conditions = ""
+ values = {}
+
+ if filters.get("invoice_status") == "Pending":
+ conditions += " AND si.outstanding_amount > 0 AND si.due_date >= %(today)s"
+ elif filters.get("invoice_status") == "Overdue":
+ conditions += " AND si.outstanding_amount > 0 AND si.due_date < %(today)s"
+ elif filters.get("invoice_status") == "Paid":
+ conditions += " AND si.outstanding_amount = 0"
+
+ for field, condition in (
+ ("customer", " AND si.customer = %(customer)s"),
+ ("trip", " AND cr.trip = %(trip)s"),
+ ("cargo_registration", " AND cr.name = %(cargo_registration)s"),
+ ):
+ if filters.get(field):
+ conditions += condition
+ values[field] = filters[field]
+
+ if filters.get("from_date"):
+ conditions += " AND si.posting_date >= %(from_date)s"
+ values["from_date"] = filters["from_date"]
+ if filters.get("to_date"):
+ conditions += " AND si.posting_date <= %(to_date)s"
+ values["to_date"] = filters["to_date"]
+
+ return conditions, values
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_profit_and_loss_statement/__init__.py b/vsd_fleet_ms/vsd_fleet_ms/report/trip_profit_and_loss_statement/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_profit_and_loss_statement/trip_profit_and_loss_statement.js b/vsd_fleet_ms/vsd_fleet_ms/report/trip_profit_and_loss_statement/trip_profit_and_loss_statement.js
new file mode 100644
index 0000000..2215f82
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/trip_profit_and_loss_statement/trip_profit_and_loss_statement.js
@@ -0,0 +1,26 @@
+// Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Trip Profit and Loss Statement"] = {
+ "filters": [
+ {
+ "fieldname": "from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.month_start()
+ },
+ {
+ "fieldname": "to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.now_date()
+ },
+ {
+ "fieldname": "status",
+ "label": __("Trip Status"),
+ "fieldtype": "Select",
+ "options": "\nPending\nCompleted\nBreakdown"
+ }
+ ]
+};
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_profit_and_loss_statement/trip_profit_and_loss_statement.json b/vsd_fleet_ms/vsd_fleet_ms/report/trip_profit_and_loss_statement/trip_profit_and_loss_statement.json
new file mode 100644
index 0000000..ab4457b
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/trip_profit_and_loss_statement/trip_profit_and_loss_statement.json
@@ -0,0 +1,30 @@
+{
+ "add_total_row": 1,
+ "columns": [],
+ "creation": "2026-09-17 09:00:00.000000",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Trip Profit and Loss Statement",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Trips",
+ "report_name": "Trip Profit and Loss Statement",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "System Manager"
+ },
+ {
+ "role": "All"
+ }
+ ]
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_profit_and_loss_statement/trip_profit_and_loss_statement.py b/vsd_fleet_ms/vsd_fleet_ms/report/trip_profit_and_loss_statement/trip_profit_and_loss_statement.py
new file mode 100644
index 0000000..2e94079
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/trip_profit_and_loss_statement/trip_profit_and_loss_statement.py
@@ -0,0 +1,131 @@
+# Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe import _
+
+
+def execute(filters=None):
+ filters = filters or {}
+
+ if filters.get("from_date") and filters.get("to_date") and filters.get("from_date") > filters.get("to_date"):
+ frappe.throw(_("From Date must be before To Date {0}").format(filters.get("to_date")))
+
+ columns = get_columns()
+ data = get_data(filters)
+ return columns, data, None, None
+
+
+def get_columns():
+ return [
+ {"fieldname": "reference", "label": _("Trip"), "fieldtype": "Link", "options": "Trips", "width": 130},
+ {"fieldname": "posting_date", "label": _("Trip Date"), "fieldtype": "Date", "width": 100},
+ {"fieldname": "transporter_name", "label": _("Transporter"), "fieldtype": "Data", "width": 160},
+ {"fieldname": "vehicle_plate_number", "label": _("Vehicle"), "fieldtype": "Data", "width": 110},
+ {"fieldname": "driver_name", "label": _("Driver"), "fieldtype": "Data", "width": 150},
+ {"fieldname": "route", "label": _("Route"), "fieldtype": "Data", "width": 150},
+ {"fieldname": "status", "label": _("Status"), "fieldtype": "Data", "width": 110},
+ {"fieldname": "revenue_usd", "label": _("Revenue (USD)"), "fieldtype": "Currency", "options": "USD", "width": 120},
+ {"fieldname": "expenses_usd", "label": _("Expenses (USD)"), "fieldtype": "Currency", "options": "USD", "width": 120},
+ {"fieldname": "profit_usd", "label": _("Profit (USD)"), "fieldtype": "Currency", "options": "USD", "width": 120},
+ {"fieldname": "revenue_tzs", "label": _("Revenue (TZS)"), "fieldtype": "Currency", "options": "TZS", "width": 130},
+ {"fieldname": "expenses_tzs", "label": _("Expenses (TZS)"), "fieldtype": "Currency", "options": "TZS", "width": 130},
+ {"fieldname": "profit_tzs", "label": _("Profit (TZS)"), "fieldtype": "Currency", "options": "TZS", "width": 130},
+ ]
+
+
+def get_data(filters):
+ conditions, values = get_conditions(filters)
+
+ rows = frappe.db.sql(
+ """
+ SELECT
+ `tabTrips`.name AS reference,
+ `tabTrips`.date AS posting_date,
+ `tabTrips`.trip_status AS status,
+ IF(`tabTrips`.transporter_type = 'In House', '', `tabTrips`.sub_contractor_name) AS transporter_name,
+ IF(`tabTrips`.transporter_type = 'In House', `tabTrips`.truck_licence_plate, `tabTrips`.sub_contactor_truck_license_plate_no) AS vehicle_plate_number,
+ IF(`tabTrips`.transporter_type = 'In House', `tabTrips`.driver_name, `tabTrips`.sub_contactor_driver_name) AS driver_name,
+ `tabTrips`.route AS route,
+ (
+ SELECT SUM(cd.rate)
+ FROM `tabCargo Detail` cd
+ INNER JOIN `tabCargo Registration` cr ON cd.parent = cr.name
+ WHERE cr.trip = `tabTrips`.name AND cd.currency = 'USD'
+ ) AS revenue_usd,
+ (
+ SELECT SUM(cd.rate)
+ FROM `tabCargo Detail` cd
+ INNER JOIN `tabCargo Registration` cr ON cd.parent = cr.name
+ WHERE cr.trip = `tabTrips`.name AND cd.currency = 'TZS'
+ ) AS revenue_tzs,
+ (
+ SELECT SUM(request_amount)
+ FROM `tabRequested Fund Details`
+ WHERE parenttype = 'Trips' AND parent = `tabTrips`.name AND request_currency = 'USD' AND request_status = 'Approved'
+ ) AS fund_expenses_usd,
+ (
+ SELECT SUM(request_amount)
+ FROM `tabRequested Fund Details`
+ WHERE parenttype = 'Trips' AND parent = `tabTrips`.name AND request_currency = 'TZS' AND request_status = 'Approved'
+ ) AS fund_expenses_tzs,
+ (
+ SELECT SUM(total_cost)
+ FROM `tabFuel Requests Table`
+ WHERE parenttype = 'Trips' AND parentfield = 'fuel_request_history' AND parent = `tabTrips`.name AND currency = 'USD'
+ ) AS fuel_expenses_usd,
+ (
+ SELECT SUM(total_cost)
+ FROM `tabFuel Requests Table`
+ WHERE parenttype = 'Trips' AND parentfield = 'fuel_request_history' AND parent = `tabTrips`.name AND currency = 'TZS'
+ ) AS fuel_expenses_tzs
+ FROM `tabTrips`
+ WHERE 1 = 1 """ + conditions + """
+ """,
+ values,
+ as_dict=1,
+ )
+
+ data = []
+ for row in rows:
+ revenue_usd = row.revenue_usd or 0
+ revenue_tzs = row.revenue_tzs or 0
+ expenses_usd = (row.fund_expenses_usd or 0) + (row.fuel_expenses_usd or 0)
+ expenses_tzs = (row.fund_expenses_tzs or 0) + (row.fuel_expenses_tzs or 0)
+
+ data.append({
+ "reference": row.reference,
+ "posting_date": row.posting_date,
+ "transporter_name": row.transporter_name,
+ "vehicle_plate_number": row.vehicle_plate_number,
+ "driver_name": row.driver_name,
+ "route": row.route,
+ "status": row.status,
+ "revenue_usd": revenue_usd,
+ "expenses_usd": expenses_usd,
+ "profit_usd": revenue_usd - expenses_usd,
+ "revenue_tzs": revenue_tzs,
+ "expenses_tzs": expenses_tzs,
+ "profit_tzs": revenue_tzs - expenses_tzs,
+ })
+
+ return data
+
+
+def get_conditions(filters):
+ conditions = ""
+ values = {}
+
+ if filters.get("status"):
+ conditions += " AND `tabTrips`.trip_status = %(status)s"
+ values["status"] = filters.get("status")
+
+ if filters.get("from_date"):
+ conditions += " AND `tabTrips`.date >= %(from_date)s"
+ values["from_date"] = filters.get("from_date")
+
+ if filters.get("to_date"):
+ conditions += " AND `tabTrips`.date <= %(to_date)s"
+ values["to_date"] = filters.get("to_date")
+
+ return conditions, values
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_revenue_report/__init__.py b/vsd_fleet_ms/vsd_fleet_ms/report/trip_revenue_report/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_revenue_report/trip_revenue_report.js b/vsd_fleet_ms/vsd_fleet_ms/report/trip_revenue_report/trip_revenue_report.js
new file mode 100644
index 0000000..d233232
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/trip_revenue_report/trip_revenue_report.js
@@ -0,0 +1,20 @@
+// Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Trip Revenue Report"] = {
+ "filters": [
+ {
+ "fieldname": "from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.month_start()
+ },
+ {
+ "fieldname": "to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.now_date()
+ }
+ ]
+};
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_revenue_report/trip_revenue_report.json b/vsd_fleet_ms/vsd_fleet_ms/report/trip_revenue_report/trip_revenue_report.json
new file mode 100644
index 0000000..efcc64a
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/trip_revenue_report/trip_revenue_report.json
@@ -0,0 +1,30 @@
+{
+ "add_total_row": 1,
+ "columns": [],
+ "creation": "2026-09-17 09:00:00.000000",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Trip Revenue Report",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Trips",
+ "report_name": "Trip Revenue Report",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "System Manager"
+ },
+ {
+ "role": "All"
+ }
+ ]
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_revenue_report/trip_revenue_report.py b/vsd_fleet_ms/vsd_fleet_ms/report/trip_revenue_report/trip_revenue_report.py
new file mode 100644
index 0000000..a9ba215
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/trip_revenue_report/trip_revenue_report.py
@@ -0,0 +1,64 @@
+# Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe import _
+
+
+def execute(filters=None):
+ filters = filters or {}
+ columns = get_columns()
+ data = get_data(filters)
+ return columns, data, None, None
+
+
+def get_columns():
+ return [
+ {"fieldname": "reference", "label": _("Trip"), "fieldtype": "Link", "options": "Trips", "width": 130},
+ {"fieldname": "date", "label": _("Trip Date"), "fieldtype": "Date", "width": 100},
+ {"fieldname": "route", "label": _("Route"), "fieldtype": "Link", "options": "Trip Routes", "width": 150},
+ {"fieldname": "invoice_count", "label": _("Invoices"), "fieldtype": "Int", "width": 90},
+ {"fieldname": "revenue_usd", "label": _("Revenue (USD)"), "fieldtype": "Currency", "options": "USD", "width": 130},
+ {"fieldname": "revenue_tzs", "label": _("Revenue (TZS)"), "fieldtype": "Currency", "options": "TZS", "width": 130},
+ ]
+
+
+def get_data(filters):
+ # Revenue is booked through Cargo Registration: Trip -> Cargo Registration -> Cargo Detail -> Sales Invoice
+ conditions, values = get_conditions(filters)
+
+ return frappe.db.sql(
+ """
+ SELECT
+ t.name AS reference,
+ t.date,
+ t.route,
+ COUNT(DISTINCT si.name) AS invoice_count,
+ SUM(CASE WHEN si.currency = 'USD' THEN si.grand_total ELSE 0 END) AS revenue_usd,
+ SUM(CASE WHEN si.currency = 'TZS' THEN si.grand_total ELSE 0 END) AS revenue_tzs
+ FROM `tabTrips` t
+ INNER JOIN `tabCargo Registration` cr ON cr.trip = t.name
+ INNER JOIN `tabCargo Detail` cd ON cd.parent = cr.name AND cd.invoice IS NOT NULL AND cd.invoice != ''
+ INNER JOIN `tabSales Invoice` si ON si.name = cd.invoice AND si.docstatus = 1
+ WHERE 1 = 1 """ + conditions + """
+ GROUP BY t.name
+ ORDER BY t.date DESC
+ """,
+ values,
+ as_dict=1,
+ )
+
+
+def get_conditions(filters):
+ conditions = ""
+ values = {}
+
+ if filters.get("from_date"):
+ conditions += " AND t.date >= %(from_date)s"
+ values["from_date"] = filters.get("from_date")
+
+ if filters.get("to_date"):
+ conditions += " AND t.date <= %(to_date)s"
+ values["to_date"] = filters.get("to_date")
+
+ return conditions, values
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_turnaround_time/__init__.py b/vsd_fleet_ms/vsd_fleet_ms/report/trip_turnaround_time/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_turnaround_time/trip_turnaround_time.js b/vsd_fleet_ms/vsd_fleet_ms/report/trip_turnaround_time/trip_turnaround_time.js
new file mode 100644
index 0000000..8d9b677
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/trip_turnaround_time/trip_turnaround_time.js
@@ -0,0 +1,26 @@
+// Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Trip Turnaround Time"] = {
+ "filters": [
+ {
+ "fieldname": "truck_number",
+ "label": __("Truck"),
+ "fieldtype": "Link",
+ "options": "Truck"
+ },
+ {
+ "fieldname": "from_date",
+ "label": __("From Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.month_start()
+ },
+ {
+ "fieldname": "to_date",
+ "label": __("To Date"),
+ "fieldtype": "Date",
+ "default": frappe.datetime.now_date()
+ }
+ ]
+};
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_turnaround_time/trip_turnaround_time.json b/vsd_fleet_ms/vsd_fleet_ms/report/trip_turnaround_time/trip_turnaround_time.json
new file mode 100644
index 0000000..92ceee4
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/trip_turnaround_time/trip_turnaround_time.json
@@ -0,0 +1,30 @@
+{
+ "add_total_row": 1,
+ "columns": [],
+ "creation": "2026-09-17 09:00:00.000000",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Trip Turnaround Time",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Trips",
+ "report_name": "Trip Turnaround Time",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "System Manager"
+ },
+ {
+ "role": "All"
+ }
+ ]
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/trip_turnaround_time/trip_turnaround_time.py b/vsd_fleet_ms/vsd_fleet_ms/report/trip_turnaround_time/trip_turnaround_time.py
new file mode 100644
index 0000000..d5d0c74
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/trip_turnaround_time/trip_turnaround_time.py
@@ -0,0 +1,60 @@
+# Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe import _
+
+
+def execute(filters=None):
+ filters = filters or {}
+ columns = get_columns()
+ data = get_data(filters)
+ return columns, data, None, None
+
+
+def get_columns():
+ return [
+ {"fieldname": "name", "label": _("Trip"), "fieldtype": "Link", "options": "Trips", "width": 130},
+ {"fieldname": "truck_number", "label": _("Truck"), "fieldtype": "Link", "options": "Truck", "width": 110},
+ {"fieldname": "driver_name", "label": _("Driver"), "fieldtype": "Data", "width": 150},
+ {"fieldname": "route", "label": _("Route"), "fieldtype": "Link", "options": "Trip Routes", "width": 150},
+ {"fieldname": "date", "label": _("Start Date"), "fieldtype": "Date", "width": 100},
+ {"fieldname": "trip_completed_date", "label": _("Completed Date"), "fieldtype": "Date", "width": 120},
+ {"fieldname": "days_taken", "label": _("Days Taken"), "fieldtype": "Int", "width": 100},
+ ]
+
+
+def get_data(filters):
+ conditions, values = get_conditions(filters)
+
+ return frappe.db.sql(
+ """
+ SELECT
+ name, truck_number, driver_name, route, date, trip_completed_date,
+ DATEDIFF(trip_completed_date, date) AS days_taken
+ FROM `tabTrips`
+ WHERE trip_status = 'Completed' AND date IS NOT NULL AND trip_completed_date IS NOT NULL """ + conditions + """
+ ORDER BY days_taken DESC
+ """,
+ values,
+ as_dict=1,
+ )
+
+
+def get_conditions(filters):
+ conditions = ""
+ values = {}
+
+ if filters.get("truck_number"):
+ conditions += " AND truck_number = %(truck_number)s"
+ values["truck_number"] = filters.get("truck_number")
+
+ if filters.get("from_date"):
+ conditions += " AND date >= %(from_date)s"
+ values["from_date"] = filters.get("from_date")
+
+ if filters.get("to_date"):
+ conditions += " AND date <= %(to_date)s"
+ values["to_date"] = filters.get("to_date")
+
+ return conditions, values
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/vehicle_utilization/__init__.py b/vsd_fleet_ms/vsd_fleet_ms/report/vehicle_utilization/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/vehicle_utilization/vehicle_utilization.js b/vsd_fleet_ms/vsd_fleet_ms/report/vehicle_utilization/vehicle_utilization.js
new file mode 100644
index 0000000..465c35c
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/vehicle_utilization/vehicle_utilization.js
@@ -0,0 +1,14 @@
+// Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+// For license information, please see license.txt
+/* eslint-disable */
+
+frappe.query_reports["Vehicle Utilization"] = {
+ "filters": [
+ {
+ "fieldname": "status",
+ "label": __("Status"),
+ "fieldtype": "Select",
+ "options": "\nIdle\nUnder Maintenance\nOn Trip\nDisabled"
+ }
+ ]
+};
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/vehicle_utilization/vehicle_utilization.json b/vsd_fleet_ms/vsd_fleet_ms/report/vehicle_utilization/vehicle_utilization.json
new file mode 100644
index 0000000..f39a712
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/vehicle_utilization/vehicle_utilization.json
@@ -0,0 +1,30 @@
+{
+ "add_total_row": 1,
+ "columns": [],
+ "creation": "2026-09-17 09:00:00.000000",
+ "disable_prepared_report": 0,
+ "disabled": 0,
+ "docstatus": 0,
+ "doctype": "Report",
+ "filters": [],
+ "idx": 0,
+ "is_standard": "Yes",
+ "json": "{}",
+ "modified": "2026-09-17 09:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Vehicle Utilization",
+ "owner": "Administrator",
+ "prepared_report": 0,
+ "ref_doctype": "Truck",
+ "report_name": "Vehicle Utilization",
+ "report_type": "Script Report",
+ "roles": [
+ {
+ "role": "System Manager"
+ },
+ {
+ "role": "All"
+ }
+ ]
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/report/vehicle_utilization/vehicle_utilization.py b/vsd_fleet_ms/vsd_fleet_ms/report/vehicle_utilization/vehicle_utilization.py
new file mode 100644
index 0000000..a622d42
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/report/vehicle_utilization/vehicle_utilization.py
@@ -0,0 +1,57 @@
+# Copyright (c) 2026, VV SYSTEMS DEVELOPER LTD and contributors
+# For license information, please see license.txt
+
+import frappe
+from frappe import _
+
+
+def execute(filters=None):
+ filters = filters or {}
+ columns = get_columns()
+ data = get_data(filters)
+ return columns, data, None, None
+
+
+def get_columns():
+ return [
+ {"fieldname": "truck", "label": _("Truck"), "fieldtype": "Link", "options": "Truck", "width": 120},
+ {"fieldname": "truck_number", "label": _("Truck Number"), "fieldtype": "Data", "width": 110},
+ {"fieldname": "status", "label": _("Current Status"), "fieldtype": "Select", "width": 120},
+ {"fieldname": "total_trips", "label": _("Total Trips"), "fieldtype": "Int", "width": 100},
+ {"fieldname": "completed_trips", "label": _("Completed Trips"), "fieldtype": "Int", "width": 130},
+ {"fieldname": "breakdown_trips", "label": _("Breakdown Trips"), "fieldtype": "Int", "width": 130},
+ {"fieldname": "last_trip_date", "label": _("Last Trip Date"), "fieldtype": "Date", "width": 120},
+ ]
+
+
+def get_data(filters):
+ conditions, values = get_conditions(filters)
+
+ return frappe.db.sql(
+ """
+ SELECT
+ t.name AS truck,
+ t.truck_number,
+ t.status,
+ (SELECT COUNT(*) FROM `tabTrips` WHERE truck_number = t.name) AS total_trips,
+ (SELECT COUNT(*) FROM `tabTrips` WHERE truck_number = t.name AND trip_status = 'Completed') AS completed_trips,
+ (SELECT COUNT(*) FROM `tabTrips` WHERE truck_number = t.name AND trip_status = 'Breakdown') AS breakdown_trips,
+ (SELECT MAX(date) FROM `tabTrips` WHERE truck_number = t.name) AS last_trip_date
+ FROM `tabTruck` t
+ WHERE 1 = 1 """ + conditions + """
+ ORDER BY total_trips DESC
+ """,
+ values,
+ as_dict=1,
+ )
+
+
+def get_conditions(filters):
+ conditions = ""
+ values = {}
+
+ if filters.get("status"):
+ conditions += " AND t.status = %(status)s"
+ values["status"] = filters.get("status")
+
+ return conditions, values
diff --git a/vsd_fleet_ms/vsd_fleet_ms/workspace/fleet_management/fleet_management.json b/vsd_fleet_ms/vsd_fleet_ms/workspace/fleet_management/fleet_management.json
new file mode 100644
index 0000000..a4736e6
--- /dev/null
+++ b/vsd_fleet_ms/vsd_fleet_ms/workspace/fleet_management/fleet_management.json
@@ -0,0 +1,634 @@
+{
+ "charts": [],
+ "content": "[{\"id\":\"fleet_head_1\",\"type\":\"header\",\"data\":{\"text\":\"Overview\",\"col\":12}},{\"id\":\"fleet_nc_1\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Trucks\",\"col\":3}},{\"id\":\"fleet_nc_2\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Available Truck\",\"col\":3}},{\"id\":\"fleet_nc_3\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Truck On Trip\",\"col\":3}},{\"id\":\"fleet_nc_4\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Trips\",\"col\":3}},{\"id\":\"fleet_head_2\",\"type\":\"header\",\"data\":{\"text\":\"Trip Operations\",\"col\":12}},{\"id\":\"fleet_nc_5\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Ongoing Trips\",\"col\":3}},{\"id\":\"fleet_nc_6\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Completed Trips\",\"col\":3}},{\"id\":\"fleet_nc_7\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Cargo Registrations\",\"col\":3}},{\"id\":\"fleet_nc_8\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Manifest\",\"col\":3}},{\"id\":\"fleet_head_3\",\"type\":\"header\",\"data\":{\"text\":\"Attention Required\",\"col\":12}},{\"id\":\"fleet_nc_9\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Fuel Requests\",\"col\":3}},{\"id\":\"fleet_nc_10\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Requested Payments In Trip\",\"col\":3}},{\"id\":\"fleet_nc_11\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Unpaid Sales Invoices\",\"col\":3}},{\"id\":\"fleet_nc_12\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Overdue Sales Invoices\",\"col\":3}},{\"id\":\"fleet_space_1\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"fleet_head_4\",\"type\":\"header\",\"data\":{\"text\":\"Fleet Management\",\"col\":12}},{\"id\":\"fleet_card_1\",\"type\":\"card\",\"data\":{\"card_name\":\"Fleet & Drivers\",\"col\":3}},{\"id\":\"fleet_card_2\",\"type\":\"card\",\"data\":{\"card_name\":\"Trip Operations\",\"col\":3}},{\"id\":\"fleet_card_3\",\"type\":\"card\",\"data\":{\"card_name\":\"Locations & Routes\",\"col\":3}},{\"id\":\"fleet_card_4\",\"type\":\"card\",\"data\":{\"card_name\":\"Fuel & Expenses\",\"col\":3}},{\"id\":\"fleet_card_5\",\"type\":\"card\",\"data\":{\"card_name\":\"Compliance & Logs\",\"col\":3}},{\"id\":\"fleet_space_2\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"fleet_head_5\",\"type\":\"header\",\"data\":{\"text\":\"Finance & Operations\",\"col\":12}},{\"id\":\"fleet_card_6\",\"type\":\"card\",\"data\":{\"card_name\":\"Finance & Billing\",\"col\":4}},{\"id\":\"fleet_card_7\",\"type\":\"card\",\"data\":{\"card_name\":\"Procurement & Stock\",\"col\":4}},{\"id\":\"fleet_card_8\",\"type\":\"card\",\"data\":{\"card_name\":\"Configuration\",\"col\":4}},{\"id\":\"fleet_space_4\",\"type\":\"spacer\",\"data\":{\"col\":12}},{\"id\":\"fleet_head_8\",\"type\":\"header\",\"data\":{\"text\":\"Reports & Analytics\",\"col\":12}},{\"id\":\"fleet_card_13\",\"type\":\"card\",\"data\":{\"card_name\":\"Fleet Operations\",\"col\":3}},{\"id\":\"fleet_card_14\",\"type\":\"card\",\"data\":{\"card_name\":\"Trip Performance\",\"col\":3}},{\"id\":\"fleet_card_15\",\"type\":\"card\",\"data\":{\"card_name\":\"Fuel & Cost Analysis\",\"col\":3}},{\"id\":\"fleet_card_16\",\"type\":\"card\",\"data\":{\"card_name\":\"Finance & Billing Reports\",\"col\":3}}]",
+ "creation": "2023-05-04 18:08:12.460715",
+ "custom_blocks": [],
+ "docstatus": 0,
+ "doctype": "Workspace",
+ "for_user": "",
+ "hide_custom": 0,
+ "icon": "map",
+ "idx": 0,
+ "is_hidden": 0,
+ "label": "Fleet Management",
+ "links": [
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Fleet & Drivers",
+ "link_count": 3,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Truck",
+ "link_count": 0,
+ "link_to": "Truck",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Truck Type",
+ "link_count": 0,
+ "link_to": "Truck Type",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Trailers",
+ "link_count": 0,
+ "link_to": "Trailers",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Truck Driver",
+ "link_count": 0,
+ "link_to": "Truck Driver",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Trip Operations",
+ "link_count": 5,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Cargo Registration",
+ "link_count": 0,
+ "link_to": "Cargo Registration",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Bulk Cargo",
+ "link_count": 0,
+ "link_to": "Bulk Cargo",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Trips",
+ "link_count": 0,
+ "link_to": "Trips",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Round Trip",
+ "link_count": 0,
+ "link_to": "Round Trip",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Manifest",
+ "link_count": 0,
+ "link_to": "Manifest",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Locations & Routes",
+ "link_count": 5,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Trip Routes",
+ "link_count": 0,
+ "link_to": "Trip Routes",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Trip Locations",
+ "link_count": 0,
+ "link_to": "Trip Locations",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Trip Locations Type",
+ "link_count": 0,
+ "link_to": "Trip Locations Type",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Transport Location",
+ "link_count": 0,
+ "link_to": "Transport Location",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Cargo Types",
+ "link_count": 0,
+ "link_to": "Cargo Types",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Fuel & Expenses",
+ "link_count": 3,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Fuel Requests",
+ "link_count": 0,
+ "link_to": "Fuel Requests",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Fuel UOM",
+ "link_count": 0,
+ "link_to": "Fuel UOM",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Fixed Expenses",
+ "link_count": 0,
+ "link_to": "Fixed Expenses",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Compliance & Logs",
+ "link_count": 3,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Truck and Trailer Inspection",
+ "link_count": 0,
+ "link_to": "Truck and Trailer Inspection",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Truck Log",
+ "link_count": 0,
+ "link_to": "Truck Log",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Trip Breakdown",
+ "link_count": 0,
+ "link_to": "Trip Breakdown",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Finance & Billing",
+ "link_count": 5,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Quotation",
+ "link_count": 0,
+ "link_to": "Quotation",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Sales Order",
+ "link_count": 0,
+ "link_to": "Sales Order",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Sales Invoice",
+ "link_count": 0,
+ "link_to": "Sales Invoice",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Journal Entry",
+ "link_count": 0,
+ "link_to": "Journal Entry",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Requested Payment",
+ "link_count": 0,
+ "link_to": "Requested Payment",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Procurement & Stock",
+ "link_count": 4,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Purchase Order",
+ "link_count": 0,
+ "link_to": "Purchase Order",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Purchase Receipt",
+ "link_count": 0,
+ "link_to": "Purchase Receipt",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Purchase Invoice",
+ "link_count": 0,
+ "link_to": "Purchase Invoice",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Stock Entry",
+ "link_count": 0,
+ "link_to": "Stock Entry",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Configuration",
+ "link_count": 3,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Transport Settings",
+ "link_count": 0,
+ "link_to": "Transport Settings",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Approval Workflows",
+ "link_count": 0,
+ "link_to": "Workflow",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Accounting Dimension",
+ "link_count": 0,
+ "link_to": "Transport Accounting Dimension",
+ "link_type": "DocType",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Fleet Operations",
+ "link_count": 3,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Vehicle Utilization",
+ "link_count": 0,
+ "link_to": "Vehicle Utilization",
+ "link_type": "Report",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Driver Assignment/Activity",
+ "link_count": 0,
+ "link_to": "Driver Activity Report",
+ "link_type": "Report",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Fleet Availability",
+ "link_count": 0,
+ "link_to": "Fleet Availability",
+ "link_type": "Report",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Trip Performance",
+ "link_count": 4,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Trip Summary",
+ "link_count": 0,
+ "link_to": "Trip Summary",
+ "link_type": "Report",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Ongoing Trips",
+ "link_count": 0,
+ "link_to": "Ongoing Trips Report",
+ "link_type": "Report",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Completed Trips",
+ "link_count": 0,
+ "link_to": "Completed Trips Report",
+ "link_type": "Report",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Trip Turnaround / Duration",
+ "link_count": 0,
+ "link_to": "Trip Turnaround Time",
+ "link_type": "Report",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Fuel & Cost Analysis",
+ "link_count": 4,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Fuel Consumption",
+ "link_count": 0,
+ "link_to": "Fuel Consumption Report",
+ "link_type": "Report",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Fuel Requests",
+ "link_count": 0,
+ "link_to": "Pending Fuel Requests Report",
+ "link_type": "Report",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Trip Fuel Cost",
+ "link_count": 0,
+ "link_to": "Trip Fuel Cost",
+ "link_type": "Report",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Fixed Expenses",
+ "link_count": 0,
+ "link_to": "Fixed Expenses Report",
+ "link_type": "Report",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Finance & Billing Reports",
+ "link_count": 4,
+ "onboard": 0,
+ "type": "Card Break"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Trip Revenue",
+ "link_count": 0,
+ "link_to": "Trip Revenue Report",
+ "link_type": "Report",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Requested Payments",
+ "link_count": 0,
+ "link_to": "Pending Requested Payments Report",
+ "link_type": "Report",
+ "onboard": 0,
+ "type": "Link"
+ },
+ {
+ "hidden": 0,
+ "is_query_report": 0,
+ "label": "Trip Invoices",
+ "link_count": 0,
+ "link_to": "Trip Invoices Report",
+ "link_type": "Report",
+ "onboard": 0,
+ "type": "Link"
+ }
+ ],
+ "modified": "2026-09-18 11:00:00.000000",
+ "modified_by": "Administrator",
+ "module": "VSD Fleet MS",
+ "name": "Fleet Management",
+ "number_cards": [
+ {
+ "label": "Total Trucks",
+ "number_card_name": "Total Trucks"
+ },
+ {
+ "label": "Available Truck",
+ "number_card_name": "Available Truck"
+ },
+ {
+ "label": "Truck On Trip",
+ "number_card_name": "Truck On Trip"
+ },
+ {
+ "label": "Total Trips",
+ "number_card_name": "Total Trips"
+ },
+ {
+ "label": "Ongoing Trips",
+ "number_card_name": "Ongoing Trips"
+ },
+ {
+ "label": "Completed Trips",
+ "number_card_name": "Completed Trips"
+ },
+ {
+ "label": "Cargo Registrations",
+ "number_card_name": "Cargo Registrations"
+ },
+ {
+ "label": "Manifest",
+ "number_card_name": "Manifest"
+ },
+ {
+ "label": "Fuel Requests",
+ "number_card_name": "Fuel Requests"
+ },
+ {
+ "label": "Requested Payments In Trip",
+ "number_card_name": "Requested Payments In Trip"
+ },
+ {
+ "label": "Unpaid Sales Invoices",
+ "number_card_name": "Unpaid Sales Invoices"
+ },
+ {
+ "label": "Overdue Sales Invoices",
+ "number_card_name": "Overdue Sales Invoices"
+ }
+ ],
+ "owner": "Administrator",
+ "parent_page": "",
+ "public": 1,
+ "quick_lists": [],
+ "roles": [],
+ "sequence_id": 1.0,
+ "shortcuts": [],
+ "title": "Fleet Management"
+}
diff --git a/vsd_fleet_ms/vsd_fleet_ms/workspace/fleet_ms/fleet_ms.json b/vsd_fleet_ms/vsd_fleet_ms/workspace/fleet_ms/fleet_ms.json
deleted file mode 100644
index d92d28f..0000000
--- a/vsd_fleet_ms/vsd_fleet_ms/workspace/fleet_ms/fleet_ms.json
+++ /dev/null
@@ -1,319 +0,0 @@
-{
- "charts": [],
- "content": "[{\"id\":\"jXwnsJvil0\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Active Trucks\",\"col\":4}},{\"id\":\"G8EkHN13E6\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Idle Trucks\",\"col\":3}},{\"id\":\"WQoT9AN7J1\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Completed Trips\",\"col\":4}},{\"id\":\"ClfVgiJBsi\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Active Trips\",\"col\":3}},{\"id\":\"q2QOU-UHg3\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Requested Payments\",\"col\":3}},{\"id\":\"zmWWdyEBaN\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Drivers\",\"col\":3}},{\"id\":\"x0AUY7DppD\",\"type\":\"number_card\",\"data\":{\"number_card_name\":\"Total Fuel Requested\",\"col\":3}},{\"id\":\"D_r2tq24Wk\",\"type\":\"header\",\"data\":{\"text\":\"VSD Fleet\",\"col\":12}},{\"id\":\"eEKQ_vxz6K\",\"type\":\"card\",\"data\":{\"card_name\":\"Masters\",\"col\":4}},{\"id\":\"_FHA1FtdB9\",\"type\":\"card\",\"data\":{\"card_name\":\"Trips\",\"col\":4}},{\"id\":\"tiOnXE60vg\",\"type\":\"card\",\"data\":{\"card_name\":\"Settings\",\"col\":4}},{\"id\":\"fgOY4518ML\",\"type\":\"card\",\"data\":{\"card_name\":\"Transactions\",\"col\":4}},{\"id\":\"RRWILp0x3t\",\"type\":\"card\",\"data\":{\"card_name\":\"Transport Records\",\"col\":4}},{\"id\":\"Fvhi34VUqU\",\"type\":\"card\",\"data\":{\"card_name\":\"Reports\",\"col\":4}}]",
- "creation": "2023-05-04 18:08:12.460715",
- "custom_blocks": [],
- "docstatus": 0,
- "doctype": "Workspace",
- "for_user": "",
- "hide_custom": 0,
- "icon": "map",
- "idx": 0,
- "is_hidden": 0,
- "label": "Fleet MS",
- "links": [
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Masters",
- "link_count": 4,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Truck",
- "link_count": 0,
- "link_to": "Truck",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Trailer",
- "link_count": 0,
- "link_to": "Trailers",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Driver",
- "link_count": 0,
- "link_to": "Truck Driver",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Fuel UOM",
- "link_count": 0,
- "link_to": "Fuel UOM",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Settings",
- "link_count": 1,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Transport Setting",
- "link_count": 0,
- "link_to": "Transport Settings",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Trips",
- "link_count": 5,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Trip Location",
- "link_count": 0,
- "link_to": "Trip Locations",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Trip Location Type",
- "link_count": 0,
- "link_to": "Trip Locations Type",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Cargo Type",
- "link_count": 0,
- "link_to": "Cargo Types",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Trip Fixed Expense",
- "link_count": 0,
- "link_to": "Fixed Expenses",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Truck & Trailer Inspection",
- "link_count": 0,
- "link_to": "Truck and Trailer Inspection",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Transport Records",
- "link_count": 2,
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Manifest",
- "link_count": 0,
- "link_to": "Manifest",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Truck Log",
- "link_count": 0,
- "link_to": "Truck Log",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Reports",
- "link_count": 2,
- "link_type": "DocType",
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Trip Report and Expenses",
- "link_count": 0,
- "link_to": "Trip Report and Expenses",
- "link_type": "Report",
- "onboard": 0,
- "report_ref_doctype": "Trips",
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 1,
- "label": "Fuel Expense By Trip",
- "link_count": 0,
- "link_to": "Fuel Expense By Trip",
- "link_type": "Report",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Transactions",
- "link_count": 7,
- "link_type": "DocType",
- "onboard": 0,
- "type": "Card Break"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Cargo Registration",
- "link_count": 0,
- "link_to": "Cargo Registration",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Vehicle Trips",
- "link_count": 0,
- "link_to": "Trips",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Fuel Requests",
- "link_count": 0,
- "link_to": "Fuel Requests",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Requested Payment",
- "link_count": 0,
- "link_to": "Requested Payment",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Round Trip Details",
- "link_count": 0,
- "link_to": "Round Trip",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Trip Breakdown",
- "link_count": 0,
- "link_to": "Trip Breakdown",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- },
- {
- "hidden": 0,
- "is_query_report": 0,
- "label": "Fixed Expenses",
- "link_count": 0,
- "link_to": "Fixed Expenses",
- "link_type": "DocType",
- "onboard": 0,
- "type": "Link"
- }
- ],
- "modified": "2025-09-03 10:49:31.306934",
- "modified_by": "Administrator",
- "module": "VSD Fleet MS",
- "name": "Fleet MS",
- "number_cards": [
- {
- "label": "Active Trucks",
- "number_card_name": "Active Trucks"
- },
- {
- "label": "Completed Trips",
- "number_card_name": "Completed Trips"
- },
- {
- "label": "Idle Trucks",
- "number_card_name": "Idle Trucks"
- },
- {
- "label": "Active Trips",
- "number_card_name": "Trucks with Pending Trips"
- },
- {
- "label": "Total Requested Payments",
- "number_card_name": "Total Requested Payments"
- },
- {
- "label": "Drivers",
- "number_card_name": "Active Drivers"
- },
- {
- "label": "Total Fuel Requested",
- "number_card_name": "Total Fuel Requested"
- }
- ],
- "owner": "arnold@vvsdtz.com",
- "parent_page": "",
- "public": 1,
- "quick_lists": [],
- "roles": [],
- "sequence_id": 1.0,
- "shortcuts": [],
- "title": "Fleet MS"
-}
\ No newline at end of file