-
Notifications
You must be signed in to change notification settings - Fork 2
Transport Job Status Update Summary
This document explains how the status field is updated in Transport Job after the simplification to trigger-based updates only.
The status field in Transport Job is automatically updated through trigger-based hooks - no background jobs or polling. Status updates happen immediately when events occur.
The status field can have the following values:
- Draft - Initial state for new documents
- Submitted - Document has been submitted
- In Progress - At least one leg has started or been assigned
- Completed - All legs are completed or billed
- Cancelled - Document has been cancelled
-
Location:
transport_job.pyline 46-58 - When: Before saving the document (every save)
-
Action:
- Calls
update_status()to calculate correct status - For submitted documents (docstatus = 1), if status changed, uses
db_set()to persist the change
- Calls
-
Why
db_set(): For submitted documents, we can't use regularsave()as it would trigger validation.db_set()updates the database directly.
-
Location:
transport_job.pyline 64-118 - When: Immediately after document submission
-
Actions:
- Sets status to "Submitted" via
db_set()(line 82) - Calls
update_status()to check leg statuses (line 102) - Updates status if legs are already in progress/completed (line 108)
- Sets status to "Submitted" via
- Purpose: Ensures status is set correctly on submission and reflects current leg states
-
Location:
transport_job.pyline 120-128 - When: When document is cancelled
-
Action: Sets status to "Cancelled" via
db_set()(line 124)
-
Location:
transport_leg.pyline 39-44 - When: After Transport Leg is saved (any change to leg)
-
Action: Calls
update_transport_job_status()(line 43)
-
Location:
transport_leg.pyline 279-298 -
When: Called from
TransportLeg.after_save()hook -
Actions:
- Loads parent Transport Job
- Calls
job_doc.update_status()to recalculate status - Updates status via
db_set()if changed (line 294)
-
Triggers: Transport Leg status changes due to:
- Setting
start_date→ Leg status becomes "Started" - Setting
end_date→ Leg status becomes "Completed" - Assigning
run_sheet→ Leg status becomes "Assigned" - Setting
sales_invoice→ Leg status becomes "Billed"
- Setting
The update_status() method (line 430-513 in transport_job.py) determines status based on:
- Sets status to "Draft" if not set
- Always sets status to "Cancelled"
- Gets all Transport Leg statuses from database
- Maps leg statuses to job status:
- All legs "Completed" or "Billed" → Job status = "Completed"
- Any leg "Started" or "Assigned" → Job status = "In Progress"
- All legs "Open" → Job status = "Submitted"
- Mixed statuses → Job status = "In Progress" (if any leg is in progress/completed)
- Ensures status is "Draft" if missing
- Doesn't override valid statuses during submission process
For submitted documents, status is updated using db_set() instead of save() because:
-
save()would trigger validation which might fail for submitted documents -
db_set()updates the database directly, bypassing validation - This prevents recursive save loops and validation errors
Example from before_save():
if self.docstatus == 1 and old_status != new_status and new_status:
self.db_set("status", new_status, update_modified=False)The validate_status_transition() method (line 403-428) enforces these rules:
Allowed Transitions:
- Draft → Submitted, Cancelled
- Submitted → In Progress, Cancelled
- In Progress → Completed, Cancelled
- Completed → (no transitions allowed)
- Cancelled → (no transitions allowed)
Prevention Rules:
- Cannot cancel if Sales Invoice exists
When status changes to "Completed", _trigger_auto_billing() is called (line 488) to automatically create sales invoices if enabled.
Document Creation
↓
before_save() → update_status() → Sets "Draft"
↓
Document Submit
↓
after_submit() → Sets "Submitted" → update_status() → May change to "In Progress" or "Completed"
↓
Transport Leg Changes (start_date, end_date, run_sheet, sales_invoice)
↓
TransportLeg.after_save() → update_transport_job_status() → update_status() → Updates job status via db_set()
↓
Document Save (if status changed)
↓
before_save() → update_status() → db_set() if submitted and status changed
- For submitted documents, fetches latest status from database on form refresh
- Updates UI to reflect current status
- No periodic polling - status is fetched only on form load/refresh
- After submission, fetches latest status with retry mechanism
- Ensures UI reflects server-side status changes
- ❌
update_transport_job_statuses()- Previously ran every 15 minutes - ❌
fix_stuck_transport_job_statuses()- Previously ran hourly - Reason: Status updates now happen immediately via triggers, making background jobs unnecessary
- ❌ 30-second interval status refresh in JavaScript
- Reason: Status updates happen in real-time via triggers, so polling is not needed
- Real-time Updates: Status updates happen immediately when events occur
- Simpler Architecture: No background jobs or polling to maintain
- More Reliable: Status is always in sync with actual document/leg states
- Better Performance: No unnecessary periodic checks
- Easier to Debug: Status changes are directly tied to specific events
If status is not updating correctly:
-
Check if document is submitted: Status updates for submitted documents use
db_set(), which requires docstatus = 1 - Check Transport Leg statuses: Job status is calculated from leg statuses
- Check Transport Leg linkage: Ensure legs are properly linked to the Transport Job
- Check for errors: Look for errors in logs when hooks are triggered
If needed, you can manually fix status using the whitelisted method:
frappe.call({
method: "logistics.transport.doctype.transport_job.transport_job.fix_submitted_job_status",
args: { job_name: "TRJ00000138" }
})The status field is updated through:
- ✅ Document lifecycle hooks (before_save, after_submit, on_cancel)
- ✅ Transport Leg status changes (via after_save hook)
- ✅ Client-side JavaScript (form refresh, no polling)
- ❌
Scheduled background tasks(removed) - ❌
Periodic polling(removed)
The status is automatically calculated based on Transport Leg statuses for submitted documents, ensuring the job status always reflects the current state of its legs.
Getting Started
- Getting Started
- Recent Platform Updates
- CargoNext v1 — Release Notes
- CargoNext v1 — Astraea Press Release
- Document Management
- Milestone Tracking
- Customer Portal
Setup and Settings
- Logistics Settings
- Credit Management
- Default Details and Relationships
- Sea Freight Settings
- Air Freight Settings
- Transport Settings
- Warehouse Settings
- Customs Settings
Sea Freight
- Sea Freight Module
- Sea Booking
- Sea Shipment
- Sea Consolidation
- Master Bill
- Shipper
- Consignee
- Container Type
- Container Management
Air Freight
Transport
- Transport Module
- Transport Order
- Transport Job
- Transport Consolidation
- Transport Leg
- Transport Plan
- Run Sheet
- Proof of Delivery
- Transport Template
- Load Type
- Transport Order — Inter-module Field Copy
Customs
Warehousing
- Warehousing Module
- Inbound Order
- Release Order
- Transfer Order
- VAS Order
- Stocktake Order
- Warehouse Job
- Warehouse Contract
- Gate Pass
- Periodic Billing
- Storage Location
- Handling Unit Type
Pricing Center
- Sales Quote
- Sales Quote — Separate Billings and Internal Job
- Change Request
- Sales Quote – Calculation Method
Job Management
- Job Management Module
- Revenue Recognition Policy — Accounts, Dates, and Charges
- Proforma GL Entries
- WIP and Accrual Reversal on Invoicing
Sustainability
Intercompany
Special Projects
Pages
Features
Reports
Glossary