From 1bb581cda7253f09c3ab2ed6ce4de5f291d60fcf Mon Sep 17 00:00:00 2001 From: MariamMabele Date: Fri, 6 Mar 2026 12:57:08 +0300 Subject: [PATCH] feat(vsd_fleet_ms): enforce fleet company defaults and strengthen trip submission/status controls --- vsd_fleet_ms/hooks.py | 52 ++++++- vsd_fleet_ms/utils/fleet_company_fields.py | 11 ++ .../utils/service_job_card_tyre_fields.py | 91 +++++++++++ .../doctype/bulk_cargo/bulk_cargo.py | 3 +- .../cargo_registration/cargo_registration.js | 12 ++ .../doctype/fuel_requests/fuel_requests.js | 12 ++ .../doctype/fuel_requests/fuel_requests.py | 5 + .../requested_payment/requested_payment.js | 13 +- .../requested_payment/requested_payment.py | 3 + .../transport_settings.json | 15 ++ .../transportation_order.js | 12 ++ .../vsd_fleet_ms/doctype/trips/trips.js | 15 ++ .../vsd_fleet_ms/doctype/trips/trips.py | 144 +++++++++++++++++- 13 files changed, 383 insertions(+), 5 deletions(-) create mode 100644 vsd_fleet_ms/utils/fleet_company_fields.py create mode 100644 vsd_fleet_ms/utils/service_job_card_tyre_fields.py diff --git a/vsd_fleet_ms/hooks.py b/vsd_fleet_ms/hooks.py index 953675d..4608ccc 100644 --- a/vsd_fleet_ms/hooks.py +++ b/vsd_fleet_ms/hooks.py @@ -64,7 +64,12 @@ # ------------ # before_install = "vsd_fleet_ms.install.before_install" -# after_install = "vsd_fleet_ms.install.after_install" +after_install = [ + "vsd_fleet_ms.utils.service_job_card_tyre_fields.ensure_service_job_card_tyre_fields", +] +after_migrate = [ + "vsd_fleet_ms.utils.service_job_card_tyre_fields.ensure_service_job_card_tyre_fields", +] # Uninstallation # ------------ @@ -110,6 +115,51 @@ # } # } doc_events = { + "Trips": { + "validate": "vsd_fleet_ms.utils.fleet_company_fields.set_company_from_transport_settings", + }, + "Fuel Requests": { + "validate": "vsd_fleet_ms.utils.fleet_company_fields.set_company_from_transport_settings", + }, + "Cargo Registration": { + "validate": "vsd_fleet_ms.utils.fleet_company_fields.set_company_from_transport_settings", + }, + "Transportation Order": { + "validate": "vsd_fleet_ms.utils.fleet_company_fields.set_company_from_transport_settings", + }, + "Requested Payment": { + "validate": "vsd_fleet_ms.utils.fleet_company_fields.set_company_from_transport_settings", + }, + "Sales Invoice": { + "validate": "vsd_fleet_ms.utils.fleet_company_fields.set_company_from_transport_settings", + }, + "Sales Order": { + "validate": "vsd_fleet_ms.utils.fleet_company_fields.set_company_from_transport_settings", + }, + "Purchase Invoice": { + "validate": "vsd_fleet_ms.utils.fleet_company_fields.set_company_from_transport_settings", + }, + "Purchase Order": { + "validate": "vsd_fleet_ms.utils.fleet_company_fields.set_company_from_transport_settings", + }, + "Purchase Receipt": { + "validate": "vsd_fleet_ms.utils.fleet_company_fields.set_company_from_transport_settings", + }, + "Delivery Note": { + "validate": "vsd_fleet_ms.utils.fleet_company_fields.set_company_from_transport_settings", + }, + "Stock Entry": { + "validate": "vsd_fleet_ms.utils.fleet_company_fields.set_company_from_transport_settings", + }, + "Journal Entry": { + "validate": "vsd_fleet_ms.utils.fleet_company_fields.set_company_from_transport_settings", + }, + "Payment Entry": { + "validate": "vsd_fleet_ms.utils.fleet_company_fields.set_company_from_transport_settings", + }, + "Quotation": { + "validate": "vsd_fleet_ms.utils.fleet_company_fields.set_company_from_transport_settings", + }, "Service Job Card": { "on_submit": "vsd_fleet_ms.utils.tyre_service_integration.create_tyre_movement_from_service_job_card" } diff --git a/vsd_fleet_ms/utils/fleet_company_fields.py b/vsd_fleet_ms/utils/fleet_company_fields.py new file mode 100644 index 0000000..0cdc823 --- /dev/null +++ b/vsd_fleet_ms/utils/fleet_company_fields.py @@ -0,0 +1,11 @@ +import frappe + + +def get_transport_company(fallback_company=None): + transport_company = frappe.db.get_single_value("Transport Settings", "company") + default_company = frappe.defaults.get_global_default("company") + return transport_company or default_company or fallback_company + + +def set_company_from_transport_settings(doc, method=None): + doc.company = get_transport_company(doc.get("company")) diff --git a/vsd_fleet_ms/utils/service_job_card_tyre_fields.py b/vsd_fleet_ms/utils/service_job_card_tyre_fields.py new file mode 100644 index 0000000..6fa022d --- /dev/null +++ b/vsd_fleet_ms/utils/service_job_card_tyre_fields.py @@ -0,0 +1,91 @@ +import frappe +from frappe.custom.doctype.custom_field.custom_field import create_custom_fields + + +def ensure_service_job_card_tyre_fields(): + """Create Fleet-specific tyre fields on Service Job Card. + + Safe to run repeatedly on migrate/install and on sites where either app is absent. + """ + if "servicems" not in frappe.get_installed_apps(): + return + + if not frappe.db.exists("DocType", "Service Job Card"): + return + + required_doctypes = ["Tyre Master", "Tyre Position", "Trailers"] + if not all(frappe.db.exists("DocType", dt) for dt in required_doctypes): + return + + create_custom_fields( + { + "Service Job Card": [ + { + "fieldname": "custom_trailer", + "label": "Trailer", + "fieldtype": "Link", + "options": "Trailers", + "insert_after": "service_item_name", + }, + { + "fieldname": "tyre_management_section", + "label": "Tyre Management", + "fieldtype": "Section Break", + "insert_after": "odometer_reading", + }, + { + "fieldname": "tyre_serial", + "label": "Tyre Serial", + "fieldtype": "Link", + "options": "Tyre Master", + "insert_after": "tyre_management_section", + }, + { + "fieldname": "tyre_movement_type", + "label": "Tyre Movement Type", + "fieldtype": "Select", + "options": "Installation\nRemoval\nPositional Change\nVehicle Transfer\nSend for Repair\nReturn from Repair\nScrap", + "default": "Installation", + "insert_after": "tyre_serial", + }, + { + "fieldname": "tyre_install_on", + "label": "Movement On", + "fieldtype": "Select", + "options": "Truck\nTrailers", + "depends_on": "eval:doc.tyre_movement_type", + "insert_after": "tyre_movement_type", + }, + { + "fieldname": "column_break_tyre_1", + "fieldtype": "Column Break", + "insert_after": "tyre_install_on", + }, + { + "fieldname": "tyre_from_position", + "label": "From Position", + "fieldtype": "Link", + "options": "Tyre Position", + "depends_on": "eval:doc.tyre_movement_type == 'Positional Change'", + "insert_after": "column_break_tyre_1", + }, + { + "fieldname": "tyre_to_position", + "label": "To Position", + "fieldtype": "Link", + "options": "Tyre Position", + "depends_on": "eval:doc.tyre_movement_type == 'Positional Change'", + "insert_after": "tyre_from_position", + }, + { + "fieldname": "tyre_position", + "label": "Tyre Position", + "fieldtype": "Link", + "options": "Tyre Position", + "depends_on": "eval:doc.tyre_movement_type != 'Positional Change'", + "insert_after": "tyre_to_position", + }, + ] + }, + update=True, + ) diff --git a/vsd_fleet_ms/vsd_fleet_ms/doctype/bulk_cargo/bulk_cargo.py b/vsd_fleet_ms/vsd_fleet_ms/doctype/bulk_cargo/bulk_cargo.py index 4962699..7fb750f 100644 --- a/vsd_fleet_ms/vsd_fleet_ms/doctype/bulk_cargo/bulk_cargo.py +++ b/vsd_fleet_ms/vsd_fleet_ms/doctype/bulk_cargo/bulk_cargo.py @@ -2,6 +2,7 @@ from frappe import _ from frappe.model.document import Document from frappe.utils import nowdate, flt +from vsd_fleet_ms.utils.fleet_company_fields import get_transport_company class BulkCargo(Document): def validate(self): @@ -149,7 +150,7 @@ def create_sales_invoice(name): "customer": bulk_cargo.customer_name, "currency": frappe.defaults.get_global_default("currency"), # <-- fixed here "posting_date": nowdate(), - "company": frappe.defaults.get_global_default("company"), + "company": get_transport_company(), "items": items }) diff --git a/vsd_fleet_ms/vsd_fleet_ms/doctype/cargo_registration/cargo_registration.js b/vsd_fleet_ms/vsd_fleet_ms/doctype/cargo_registration/cargo_registration.js index 1b646bc..db5ca68 100644 --- a/vsd_fleet_ms/vsd_fleet_ms/doctype/cargo_registration/cargo_registration.js +++ b/vsd_fleet_ms/vsd_fleet_ms/doctype/cargo_registration/cargo_registration.js @@ -3,6 +3,7 @@ frappe.ui.form.on('Cargo Registration', { onload: function(frm){ + setFleetCompanyDefault(frm); if(!frm.doc.posting_date) { frm.set_value('posting_date', frappe.datetime.nowdate()); } @@ -57,6 +58,17 @@ frappe.ui.form.on('Cargo Registration', { }, }); +const setFleetCompanyDefault = (frm) => { + if (!frm.is_new()) return; + frappe.db.get_single_value("Transport Settings", "company").then((company) => { + const fallback = (frappe.boot && frappe.boot.sysdefaults && frappe.boot.sysdefaults.company) || ""; + const target_company = company || fallback; + if (target_company) { + frm.set_value("company", target_company); + } + }); +}; + frappe.ui.form.on('Cargo Detail', { form_render: function (frm, cdt, cdn) { const container = document.querySelector('[data-fieldname="assign_manifest"]'); diff --git a/vsd_fleet_ms/vsd_fleet_ms/doctype/fuel_requests/fuel_requests.js b/vsd_fleet_ms/vsd_fleet_ms/doctype/fuel_requests/fuel_requests.js index 3c28922..626d6e8 100644 --- a/vsd_fleet_ms/vsd_fleet_ms/doctype/fuel_requests/fuel_requests.js +++ b/vsd_fleet_ms/vsd_fleet_ms/doctype/fuel_requests/fuel_requests.js @@ -3,6 +3,7 @@ frappe.ui.form.on('Fuel Requests', { onload: function (frm) { + setFleetCompanyDefault(frm); //Load the approve and reject buttons var html = ' '; html += ''; @@ -129,6 +130,17 @@ cur_frm.cscript.approve_request = function (frm) { } }; +const setFleetCompanyDefault = (frm) => { + if (!frm.is_new()) return; + frappe.db.get_single_value("Transport Settings", "company").then((company) => { + const fallback = (frappe.boot && frappe.boot.sysdefaults && frappe.boot.sysdefaults.company) || ""; + const target_company = company || fallback; + if (target_company) { + frm.set_value("company", target_company); + } + }); +}; + //For reject button cur_frm.cscript.reject_request = function (frm) { //cur_frm.cscript.populate_child(cur_frm.doc.reference_doctype, cur_frm.doc.reference_docname); diff --git a/vsd_fleet_ms/vsd_fleet_ms/doctype/fuel_requests/fuel_requests.py b/vsd_fleet_ms/vsd_fleet_ms/doctype/fuel_requests/fuel_requests.py index 82e4d29..9968324 100644 --- a/vsd_fleet_ms/vsd_fleet_ms/doctype/fuel_requests/fuel_requests.py +++ b/vsd_fleet_ms/vsd_fleet_ms/doctype/fuel_requests/fuel_requests.py @@ -10,9 +10,12 @@ from frappe import _, msgprint from frappe.model.mapper import get_mapped_doc from frappe.utils import nowdate +from vsd_fleet_ms.utils.fleet_company_fields import get_transport_company class FuelRequests(Document): def onload(self): + if not self.company: + self.company = get_transport_company(self.company) trip = frappe.get_doc(self.reference_doctype, self.reference_docname) if not self.main_route: self.set("main_route", trip.route) @@ -253,5 +256,7 @@ def make_stock_entry(source_name, target_doc=None): }, target_doc, ) + source_company = frappe.db.get_value("Fuel Requests", source_name, "company") + doc.company = get_transport_company(source_company) return doc diff --git a/vsd_fleet_ms/vsd_fleet_ms/doctype/requested_payment/requested_payment.js b/vsd_fleet_ms/vsd_fleet_ms/doctype/requested_payment/requested_payment.js index 6981a02..9824428 100644 --- a/vsd_fleet_ms/vsd_fleet_ms/doctype/requested_payment/requested_payment.js +++ b/vsd_fleet_ms/vsd_fleet_ms/doctype/requested_payment/requested_payment.js @@ -3,6 +3,7 @@ frappe.ui.form.on('Requested Payment', { onload: function(frm){ + setFleetCompanyDefault(frm); //Load the approve and reject buttons var html = ' '; html += '' @@ -189,6 +190,17 @@ frappe.ui.form.on('Requested Payment', { } } }); + +const setFleetCompanyDefault = (frm) => { + if (!frm.is_new()) return; + frappe.db.get_single_value("Transport Settings", "company").then((company) => { + const fallback = (frappe.boot && frappe.boot.sysdefaults && frappe.boot.sysdefaults.company) || ""; + const target_company = company || fallback; + if (target_company) { + frm.set_value("company", target_company); + } + }); +}; frappe.ui.form.on('Requested Fund Details', { form_render (frm, cdt, cdn) { @@ -636,4 +648,3 @@ cur_frm.cscript.populate_child = function(reference_doctype, reference_docname){ }); }; - diff --git a/vsd_fleet_ms/vsd_fleet_ms/doctype/requested_payment/requested_payment.py b/vsd_fleet_ms/vsd_fleet_ms/doctype/requested_payment/requested_payment.py index 157afeb..a4eea0b 100644 --- a/vsd_fleet_ms/vsd_fleet_ms/doctype/requested_payment/requested_payment.py +++ b/vsd_fleet_ms/vsd_fleet_ms/doctype/requested_payment/requested_payment.py @@ -17,6 +17,7 @@ ) from erpnext.controllers.accounts_controller import set_balance_in_account_currency from erpnext.accounts.doctype.budget.budget import validate_expense_against_budget +from vsd_fleet_ms.utils.fleet_company_fields import get_transport_company class RequestedPayment(Document): @@ -716,6 +717,8 @@ def make_payment(source_name, target_doc=None, ignore_permissions=False): pe.mode_of_payment = "Cash" pe.party_type = "Employee" pe.allocate_payment_amount = 1 + source_company = frappe.db.get_value("Requested Payment", source_name, "company") + pe.company = get_transport_company(source_company) return pe diff --git a/vsd_fleet_ms/vsd_fleet_ms/doctype/transport_settings/transport_settings.json b/vsd_fleet_ms/vsd_fleet_ms/doctype/transport_settings/transport_settings.json index ce84f97..28f15b9 100644 --- a/vsd_fleet_ms/vsd_fleet_ms/doctype/transport_settings/transport_settings.json +++ b/vsd_fleet_ms/vsd_fleet_ms/doctype/transport_settings/transport_settings.json @@ -7,6 +7,7 @@ "editable_grid": 1, "engine": "InnoDB", "field_order": [ + "company", "vehicle_fuel_parent_warehouse", "sales_item_group", "fuel_item_group", @@ -17,6 +18,7 @@ "default_compartment_capacity", "require_purchase_order_for_fuel", "require_journal_entry_for_funds", + "enforce_financial_booking_before_trip_submission", "servicems_tab", "servicems_section", "enable_service_ms", @@ -26,6 +28,12 @@ "accounting_dimension" ], "fields": [ + { + "fieldname": "company", + "fieldtype": "Link", + "label": "Company", + "options": "Company" + }, { "fieldname": "vehicle_fuel_parent_warehouse", "fieldtype": "Link", @@ -112,6 +120,13 @@ "default": 1, "description": "Require Journal Entry For Funds in Trip" }, + { + "fieldname": "enforce_financial_booking_before_trip_submission", + "fieldtype": "Check", + "label": "Enforce Financial Booking Before Trip Submission", + "default": 0, + "description": "Block trip submission until fund requests and fuel stockout are fully processed" + }, { "fieldname": "enable_service_ms", "fieldtype": "Check", diff --git a/vsd_fleet_ms/vsd_fleet_ms/doctype/transportation_order/transportation_order.js b/vsd_fleet_ms/vsd_fleet_ms/doctype/transportation_order/transportation_order.js index 77d461a..01757c6 100644 --- a/vsd_fleet_ms/vsd_fleet_ms/doctype/transportation_order/transportation_order.js +++ b/vsd_fleet_ms/vsd_fleet_ms/doctype/transportation_order/transportation_order.js @@ -3,6 +3,7 @@ frappe.ui.form.on('Transportation Order', { onload: function (frm) { + setFleetCompanyDefault(frm); frm.get_field("assign_transport").grid.cannot_add_rows = true; $("*[data-fieldname='assign_transport']").find(".grid-remove-rows").hide(); $("*[data-fieldname='assign_transport']").find(".grid-remove-all-rows").hide(); @@ -227,6 +228,17 @@ frappe.ui.form.on('Transportation Order', { }, }); +const setFleetCompanyDefault = (frm) => { + if (!frm.is_new()) return; + frappe.db.get_single_value("Transport Settings", "company").then((company) => { + const fallback = (frappe.boot && frappe.boot.sysdefaults && frappe.boot.sysdefaults.company) || ""; + const target_company = company || fallback; + if (target_company) { + frm.set_value("company", target_company); + } + }); +}; + frappe.ui.form.on("Transport Assignments", { form_render: function (frm, cdt, cdn) { diff --git a/vsd_fleet_ms/vsd_fleet_ms/doctype/trips/trips.js b/vsd_fleet_ms/vsd_fleet_ms/doctype/trips/trips.js index 5644154..8342dc8 100644 --- a/vsd_fleet_ms/vsd_fleet_ms/doctype/trips/trips.js +++ b/vsd_fleet_ms/vsd_fleet_ms/doctype/trips/trips.js @@ -2,6 +2,9 @@ // For license information, please see license.txt frappe.ui.form.on("Trips", { + onload: function (frm) { + setFleetCompanyDefault(frm); + }, refresh: function (frm) { approved_total(); requested_total(); @@ -14,6 +17,7 @@ frappe.ui.form.on("Trips", { function () { frm.set_value("trip_completed", 1); frm.set_value("trip_completed_date", frappe.datetime.nowdate()); + frm.set_value("trip_status", "Completed"); var truck = frm.doc.truck_number; frm.save(); if (frm.doc.transporter_type == "In House") { @@ -252,6 +256,17 @@ frappe.ui.form.on("Trips", { }, }); +const setFleetCompanyDefault = (frm) => { + if (!frm.is_new()) return; + frappe.db.get_single_value("Transport Settings", "company").then((company) => { + const fallback = (frappe.boot && frappe.boot.sysdefaults && frappe.boot.sysdefaults.company) || ""; + const target_company = company || fallback; + if (target_company) { + frm.set_value("company", target_company); + } + }); +}; + function set_service_ms_costing_visibility(frm) { frappe.db .get_single_value("Transport Settings", "enable_service_ms") diff --git a/vsd_fleet_ms/vsd_fleet_ms/doctype/trips/trips.py b/vsd_fleet_ms/vsd_fleet_ms/doctype/trips/trips.py index e41d2fa..8f759ce 100644 --- a/vsd_fleet_ms/vsd_fleet_ms/doctype/trips/trips.py +++ b/vsd_fleet_ms/vsd_fleet_ms/doctype/trips/trips.py @@ -9,9 +9,10 @@ import json from frappe.model.document import Document from frappe.model.mapper import get_mapped_doc -from frappe.utils import nowdate, now +from frappe.utils import nowdate, now, cint from frappe import _, msgprint from vsd_fleet_ms.utils.dimension import set_dimension +from vsd_fleet_ms.utils.fleet_company_fields import get_transport_company from erpnext.setup.utils import get_exchange_rate from vsd_fleet_ms.vsd_fleet_ms.doctype.requested_payment.requested_payment import request_funds @@ -28,7 +29,7 @@ def on_submit(self): def onload(self): if not self.company: - self.company = frappe.defaults.get_user_default("Company") or frappe.defaults.get_global_default("company") + self.company = get_transport_company(self.company) if not self.fuel_stock_out: self.fuel_stock_out = self.total_fuel @@ -41,6 +42,8 @@ def before_insert(self): self.requested_fund_accounts_table = [] def validate(self): + self.sync_trip_status() + self.validate_active_trip_for_truck() if self.transporter_type == "In House": self.validate_fuel_requests() # self.set_permits() @@ -112,6 +115,17 @@ def before_save(self): self.date = datetime.datetime.now() self.validate_main_route_inputs() + def after_insert(self): + self.sync_truck_status() + + def on_update(self): + self.sync_truck_status() + + def on_update_after_submit(self): + self.sync_trip_status() + self.validate_active_trip_for_truck() + self.sync_truck_status() + def validate_fuel_requests(self): make_request = False for request in self.get("fuel_request_history"): @@ -134,6 +148,7 @@ def validate_fuel_requests(self): else: fuel_request = frappe.new_doc("Fuel Requests") fuel_request.update({ + "company": get_transport_company(self.company), "truck_plate_number": self.get("vehicle_plate_number"), "customer": self.get("customer"), "truck": self.get("vehicle_plate_number"), @@ -178,6 +193,131 @@ def validate_request_status(self): if row.request_status == "Approved" and je_required and not row.journal_entry: frappe.throw("All approved fund requests must have a Journal Entry before submitting the trip") + enforce_financial_booking = ( + frappe.db.get_single_value( + "Transport Settings", + "enforce_financial_booking_before_trip_submission", + ) + or 0 + ) + if not enforce_financial_booking: + return + + issues = [] + if self.transporter_type == "In House": + if not self.stock_out_entry: + issues.append(_("Fuel stockout is not processed: Stock Out Entry is missing")) + elif frappe.db.get_value("Stock Entry", self.stock_out_entry, "docstatus") != 1: + issues.append( + _("Fuel stockout is not processed: Stock Entry {0} is not submitted").format( + self.stock_out_entry + ) + ) + + if po_required: + for row in self.fuel_request_history: + if row.status == "Approved" and row.purchase_order: + if frappe.db.get_value("Purchase Order", row.purchase_order, "docstatus") != 1: + issues.append( + _("Fuel request row #{0}: Purchase Order {1} is not submitted").format( + row.idx, row.purchase_order + ) + ) + + if je_required: + for row in self.requested_fund_accounts_table: + if row.request_status == "Approved" and row.journal_entry: + if frappe.db.get_value("Journal Entry", row.journal_entry, "docstatus") != 1: + issues.append( + _("Fund request row #{0}: Journal Entry {1} is not submitted").format( + row.idx, row.journal_entry + ) + ) + + if issues: + details = "
".join([f"- {frappe.utils.escape_html(i)}" for i in issues]) + frappe.throw( + _( + "Trip submission blocked due to pending financial items:
{0}" + ).format(details) + ) + + def sync_trip_status(self): + if self.trip_status == "Breakdown": + return + + self.trip_status = "Completed" if cint(self.trip_completed) == 1 else "Pending" + + def get_truck_number(self): + if self.truck_number: + return self.truck_number + if self.manifest: + return frappe.db.get_value("Manifest", self.manifest, "truck") + return None + + def validate_active_trip_for_truck(self): + truck_number = self.get_truck_number() + if self.transporter_type != "In House" or not truck_number: + return + + if cint(self.trip_completed) == 1 or self.trip_status == "Breakdown": + return + + filters = { + "truck_number": truck_number, + "trip_completed": 0, + "docstatus": ["!=", 2], + } + if self.name: + filters["name"] = ["!=", self.name] + + active_trip = frappe.db.get_value("Trips", filters, "name", order_by="modified desc") + if active_trip: + frappe.throw( + _("Truck {0} is already on another trip: {1}").format(truck_number, active_trip) + ) + + def sync_truck_status(self): + truck_number = self.get_truck_number() + if self.transporter_type != "In House" or not truck_number: + return + + if cint(self.trip_completed) == 0 and self.trip_status != "Breakdown": + frappe.db.set_value( + "Truck", + truck_number, + {"status": "On Trip", "trans_ms_current_trip": self.name}, + update_modified=False, + ) + return + + other_active_trip = frappe.db.get_value( + "Trips", + { + "truck_number": truck_number, + "trip_completed": 0, + "docstatus": ["!=", 2], + "name": ["!=", self.name], + }, + "name", + order_by="modified desc", + ) + + if other_active_trip: + frappe.db.set_value( + "Truck", + truck_number, + {"status": "On Trip", "trans_ms_current_trip": other_active_trip}, + update_modified=False, + ) + else: + frappe.db.set_value( + "Truck", + truck_number, + {"status": "Idle", "trans_ms_current_trip": ""}, + update_modified=False, + ) + # ------------------ Whitelisted Functions ------------------ #