Skip to content

Run Sheet Job Status Update Summary

kitler edited this page Jan 23, 2026 · 3 revisions

This document explains how Run Sheet status updates relate to Transport Job status updates and the overall status update flow.

Overview

Run Sheet status and Transport Job status are both updated based on Transport Leg status changes. When a Transport Leg status changes, it triggers updates to both the Run Sheet and the Transport Job that contain that leg.

Status Update Flow

Transport Leg Status Change
    ↓
TransportLeg.after_save() Hook
    ↓
    ├─→ update_run_sheet_status() → Updates Run Sheet status
    └─→ update_transport_job_status() → Updates Transport Job status

Key Point: Run Sheet status does NOT directly update Transport Job status. Both are updated independently by Transport Leg status changes.

Run Sheet Status Values

The Run Sheet status field can have the following values:

  • Draft - Initial state for new documents (docstatus = 0)
  • Dispatched - Run Sheet is submitted and all legs are "Open"
  • In-Progress - At least one leg has status "Started" or "Assigned"
  • Completed - All legs have status "Completed" or "Billed"
  • Hold - Manually set status (prevents auto-updates)
  • Cancelled - Document has been cancelled (docstatus = 2)

Transport Job Status Values

The Transport Job status field can have the following values:

  • Draft - Initial state for new documents (docstatus = 0)
  • Submitted - Document has been submitted, all legs are "Open"
  • In Progress - At least one leg has status "Started" or "Assigned"
  • Completed - All legs have status "Completed" or "Billed"
  • Cancelled - Document has been cancelled (docstatus = 2)

Run Sheet Status Update Triggers

1. Document Lifecycle Hooks

1.1 before_save() Hook

  • Location: run_sheet.py line 23-27
  • When: Before saving the document (every save)
  • Action:
    • Skips status update if document is being submitted (flagged with _submitting)
    • Otherwise calls update_status() to calculate correct status
  • Why Skip During Submit: Prevents status from being reset to "Draft" during submission process

1.2 after_submit() Hook

  • Location: run_sheet.py line 35-66
  • When: Immediately after document submission
  • Actions:
    1. Ensures docstatus is 1 (reloads from database if needed)
    2. Sets status to "Dispatched" if not already a valid submitted status
    3. Valid submitted statuses: "Dispatched", "In-Progress", "Completed", "Hold"
  • Purpose: Ensures status is set correctly on submission

1.3 on_cancel() Hook

  • Location: run_sheet.py line 68-70
  • When: When document is cancelled
  • Action: Sets status to "Cancelled" via db_set()

2. Transport Leg Status Changes

2.1 TransportLeg.after_save() Hook

  • Location: transport_leg.py line 39-44
  • When: After Transport Leg is saved (any change to leg)
  • Actions:
    • Calls update_run_sheet_status() (line 42)
    • Calls update_transport_job_status() (line 43)
  • 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"

2.2 TransportLeg.update_run_sheet_status() Method

  • Location: transport_leg.py line 400-491
  • When: Called from TransportLeg.after_save() hook
  • Actions:
    1. Checks if leg has a run_sheet assigned
    2. Verifies Run Sheet is submitted (docstatus = 1)
    3. Skips if Run Sheet status is "Hold" (manually set)
    4. Gets all leg statuses for the Run Sheet from database
    5. Uses in-memory status for current leg (most up-to-date)
    6. Calculates new Run Sheet status based on leg statuses
    7. Updates Run Sheet status via db_set() if changed
  • Status Mapping:
    • All legs "Completed" or "Billed" → Run Sheet "Completed"
    • Any leg "Started" or "Assigned" → Run Sheet "In-Progress"
    • All legs "Open" → Run Sheet "Dispatched"
    • Mixed statuses → Run Sheet "In-Progress" (if any leg is in progress/completed)

2.3 TransportLeg.update_transport_job_status() Method

  • Location: transport_leg.py line 280-398
  • When: Called from TransportLeg.after_save() hook
  • Actions:
    1. Checks if leg has a transport_job assigned
    2. Verifies Transport Job is submitted (docstatus = 1)
    3. Gets all leg statuses for the Transport Job from database
    4. Uses in-memory status for current leg (most up-to-date)
    5. Calculates new Transport Job status based on leg statuses
    6. Updates Transport Job status via db_set() if changed
    7. Publishes realtime event transport_job_status_changed
  • Status Mapping:
    • All legs "Completed" or "Billed" → Job "Completed"
    • Any leg "Started" or "Assigned" → Job "In Progress"
    • All legs "Open" → Job "Submitted"
    • Mixed statuses → Job "In Progress" (if any leg is in progress/completed)

Run Sheet Status Calculation Logic

The update_status() method (line 539-623 in run_sheet.py) determines status based on:

For New Documents

  • Sets status to "Draft" if not set

For Cancelled Documents (docstatus = 2)

  • Always sets status to "Cancelled"

For Draft Documents (docstatus = 0)

  • Ensures status is "Draft" (unless manually set to "Hold" or "Cancelled")

For Submitted Documents (docstatus = 1)

  1. Skips auto-update if status is "Hold" (manually set)
  2. Gets all Transport Leg statuses from database (fresh query)
  3. Maps leg statuses to Run Sheet status:
    • All legs "Completed" or "Billed" → Run Sheet status = "Completed"
    • Any leg "Started" or "Assigned" → Run Sheet status = "In-Progress"
    • All legs "Open" → Run Sheet status = "Dispatched"
    • Mixed statuses → Run Sheet status = "In-Progress" (if any leg is in progress/completed)
  4. Updates status via db_set() if changed (for submitted documents)

Key Implementation Details

Database Updates for Submitted Documents

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 update_status():

if self.docstatus == 1:
    self.db_set("status", new_status, update_modified=False)

Status Update Coordination

When a Transport Leg status changes:

  1. Transport Leg saves → Triggers after_save() hook
  2. Both methods called in parallel:
    • update_run_sheet_status() → Updates Run Sheet if leg has run_sheet
    • update_transport_job_status() → Updates Transport Job if leg has transport_job
  3. Both use same leg status data but calculate independently
  4. Both use db_set() to update submitted documents

Status Freshness

Both Run Sheet and Transport Job status updates:

  • Fetch leg statuses directly from database to ensure latest values
  • Use in-memory status for the current leg being saved (most up-to-date)
  • This ensures status calculations are based on the most current data

Hold Status Protection

Run Sheet has a special "Hold" status that:

  • Prevents automatic status updates
  • Can only be set manually
  • Allows Run Sheet to be paused without status changes
  • Transport Job does NOT have a "Hold" status

Status Update Flow Diagram

Transport Leg Created/Updated
    ↓
TransportLeg.after_save()
    ↓
    ├─→ update_run_sheet_status()
    │       ↓
    │   Check if leg has run_sheet
    │       ↓
    │   Get all leg statuses for Run Sheet
    │       ↓
    │   Calculate Run Sheet status
    │       ↓
    │   Update Run Sheet via db_set()
    │
    └─→ update_transport_job_status()
            ↓
        Check if leg has transport_job
            ↓
        Get all leg statuses for Transport Job
            ↓
        Calculate Transport Job status
            ↓
        Update Transport Job via db_set()
            ↓
        Publish realtime event

Relationship Between Run Sheet and Transport Job Status

Independent Updates

  • Run Sheet status and Transport Job status are updated independently
  • Both are calculated from the same Transport Leg statuses
  • Both use the same logic but may have different status values:
    • Run Sheet: "Dispatched" vs Transport Job: "Submitted" (both mean "all legs Open")
    • Run Sheet: "In-Progress" vs Transport Job: "In Progress" (same meaning, different formatting)

Common Legs

  • A Transport Leg can belong to both a Run Sheet and a Transport Job
  • When that leg's status changes, both Run Sheet and Transport Job are updated
  • The updates happen in the same after_save() hook, so they're synchronized

Status Consistency

  • Both statuses are calculated from the same source (Transport Leg statuses)
  • Both use similar logic (all completed → completed, any started → in progress)
  • Statuses should generally be consistent, but may differ due to:
    • Different status value names ("Dispatched" vs "Submitted")
    • Different leg sets (Run Sheet may have support legs, Transport Job has all legs)
    • Hold status on Run Sheet (prevents Run Sheet updates but not Transport Job updates)

Troubleshooting

Run Sheet Status Not Updating

If Run Sheet status is not updating correctly:

  1. Check if Run Sheet is submitted: Status updates only work for submitted Run Sheets (docstatus = 1)
  2. Check if status is "Hold": Hold status prevents automatic updates
  3. Check Transport Leg statuses: Run Sheet status is calculated from leg statuses
  4. Check Transport Leg linkage: Ensure legs are properly linked to the Run Sheet (run_sheet field)
  5. Check for errors: Look for errors in logs when hooks are triggered

Transport Job Status Not Updating

If Transport Job status is not updating correctly:

  1. Check if Transport Job is submitted: Status updates only work for submitted jobs (docstatus = 1)
  2. Check Transport Leg statuses: Transport Job status is calculated from leg statuses
  3. Check Transport Leg linkage: Ensure legs are properly linked to the Transport Job (transport_job field)
  4. Check for errors: Look for errors in logs when hooks are triggered

Status Mismatch Between Run Sheet and Transport Job

If Run Sheet and Transport Job statuses don't match:

  1. Check status value names: "Dispatched" (Run Sheet) vs "Submitted" (Transport Job) both mean "all legs Open"
  2. Check leg sets: Run Sheet may have support legs (Dispatch, Connecting, Return) that Transport Job doesn't have
  3. Check Hold status: Run Sheet with "Hold" status won't update, but Transport Job will continue updating
  4. Check leg assignments: Ensure legs are properly assigned to both Run Sheet and Transport Job

Summary

Run Sheet and Transport Job status updates work as follows:

  • Both updated by Transport Leg status changes (via after_save() hook)
  • Both use same leg status data but calculate independently
  • Both use db_set() for submitted documents
  • Both fetch fresh leg statuses from database
  • Both use in-memory status for current leg being saved
  • Run Sheet does NOT directly update Transport Job (they're updated in parallel)
  • Transport Job does NOT directly update Run Sheet (they're updated in parallel)

The statuses are automatically calculated based on Transport Leg statuses, ensuring both Run Sheet and Transport Job status always reflect the current state of their legs.

Getting Started

Setup and Settings

Sea Freight

Air Freight

Transport

Customs

Warehousing

Pricing Center

Job Management

Sustainability

Intercompany

Special Projects

Pages

Features

Reports

Glossary

Clone this wiki locally