# EDR Freight — Major Flow Variants (each self-contained) The single master graph lives in [`FREIGHT_MASTER_FLOW.md`](./FREIGHT_MASTER_FLOW.md). This file breaks the business logic into **one comprehensive, self-contained diagram per major scenario**, each organised with phase **subgraphs** so it can be read on its own. **Axes covered** | Axis | Values | | --------------- | -------------------------------------------------------------------------------------------- | | Origin | **One-time booking** · **General contract** (Path A transport-only / Path B GENERAL+customs) | | Trade direction | **Export** · **Import** · **Intercity / Domestic** | | Customs | **With customs** · **Without customs** | **Legend** — (P) Portal (customer) · (B) Backoffice (staff) · (sys) System/event · (green) rounded = success end · (red) rounded = fail end · <> decision. **Which diagram do I read?** ```mermaid flowchart LR classDef dec fill:#f8fafc,stroke:#475569,color:#111 classDef box fill:#e0e7ff,stroke:#3730a3,color:#111 A{"Origin?"}:::dec A -->|"one-time"| B{"Trade direction?
(gate is direction-driven, NOT a customs toggle)"}:::dec A -->|"framework agreement"| C{"Contract type?"}:::dec B -->|"DOMESTIC"| D1["§1 One-time · DOMESTIC (no gate)"]:::box B -->|"IMPORT / EXPORT
(with or without customs)"| D2["§2 One-time · IMPORT/EXPORT (gate)"]:::box C -->|"transport-only (self-clearance)"| D3["§3 Contract · Path A"]:::box C -->|"GENERAL + customs"| D4["§4 Contract · Path B"]:::box D1 --> E{"Physical direction?"}:::dec D2 --> E D3 --> E D4 --> E E -->|"export"| F5["§5 EXPORT operations"]:::box E -->|"import"| F6["§6 IMPORT operations"]:::box E -->|"domestic"| F7["§7 INTERCITY operations"]:::box ``` > **How the two halves connect:** §1–§4 are the **commercial** journeys (intake → approval → contract → > clearance → operation → payment). §5–§7 are the **physical** journeys (mile legs → warehouse → train → > delivery). A shipment = one commercial variant **+** one physical variant. Each diagram fully details its > own half and summarises the other so it stands alone. --- ## §1 — One-time booking · DOMESTIC (no clearance gate) The commercial lifecycle when the counter-sign gate resolves to **no clearance** — which, in code, means **trade direction = DOMESTIC** (not a customs toggle). Counter-sign goes straight to `FULLY_EXECUTED` and the booking is enqueued **directly into the scheduling batch pipeline, skipping the operation-request/clearance phase**. NOTE: Import/export bookings — _even with customs off_ — do **not** land here; they always hit the clearance gate (§2, just with a lighter "without customs" document set). ```mermaid flowchart TD classDef port fill:#dbeafe,stroke:#2563eb,color:#111 classDef back fill:#fef3c7,stroke:#b45309,color:#111 classDef sys fill:#dcfce7,stroke:#15803d,color:#111 classDef dec fill:#f8fafc,stroke:#475569,color:#111 classDef good fill:#86efac,stroke:#166534,color:#062e14 classDef bad fill:#fecaca,stroke:#991b1b,color:#450a0a pre(["Company ACTIVE (approved profile)"]):::sys subgraph DRAFT["1 · Create & price"] direction TB d1["POST /bookings → DRAFT
reference, containers, cargo modifiers, files (P)"]:::port d2["POST /bookings/:id/generate-price
rule-engine: LIVE rates + surcharges (P)"]:::port dW{"weight-limit-rules"}:::dec dWx(["HARD BLOCK 400 — VGM > capacity"]):::bad d3["POST /bookings/:id/submit → SUBMITTED
freeze booking_rate_snapshot (P)"]:::port dP{"price moved?"}:::dec d3c["confirm-submit → SUBMITTED (P)"]:::port d1 --> d2 --> dW dW -->|"over capacity"| dWx dW -->|"ok / warn+surcharge"| d3 --> dP dP -->|"yes"| d3c dP -->|"no"| out1 d3c --> out1 d1 -.->|"delete draft"| ddx(["removed"]):::bad d3 -.->|"reject price"| drx(["REJECTED"]):::bad end out1[" "]:::sys subgraph INTAKE["2 · Staff intake & approval"] direction TB g{"government?"}:::dec gexp["governmentExpedite → PAID + Eligible (B)"]:::back i{"staff/accept | request-changes | reject (B)"}:::dec ir["CHANGES_REQUESTED (B)"]:::back irx(["REJECTED"]):::bad ia["→ PENDING_APPROVAL
instantiate approval steps + validity window (B)"]:::back ac{"chain: LINE_STAFF → DIRECTOR → CEO (B)"}:::dec acx(["rejectStep → REJECTED"]):::bad g -->|"yes"| gexp g -->|"no"| i i -->|"request-changes"| ir i -->|"reject"| irx i -->|"accept"| ia --> ac ac -->|"rejectStep"| acx end subgraph SIGN["3 · Contract doc & sign (DOMESTIC → no gate)"] direction TB s1["contract/generate → CONTRACT_READY (B)"]:::back s2["customer sign → SIGNED_CUSTOMER (P)"]:::port s3["staff counter-sign (DOMESTIC) → FULLY_EXECUTED
enqueueScheduleProcessing (no op-request) (B)(sys)"]:::back s1 --> s2 --> s3 end subgraph OPPAY["4 · Batch pipeline & payment"] direction TB fe["FULLY_EXECUTED enters day batch pool (sys)"]:::sys b1["batch engine offers wagons → SELECTED_FOR_BATCH
invoice generated (sys)"]:::sys p1["customer pays → gateway → PAID (P)"]:::port pexp(["pay window lapses → reservation EXPIRED"]):::bad fe --> b1 --> p1 p1 -.->|"unpaid"| pexp end phys(["Physical execution:
§7 intercity → COMPLETED (done)"]):::good pre --> DRAFT out1 --> INTAKE ac -->|"APPROVED"| SIGN SIGN --> OPPAY p1 --> phys gexp -.->|"gov → PAID/Eligible"| phys ``` > **Road-mode note:** a domestic booking billed by road (truck) instead of rail goes through > `operation/review` → `ROAD_DISPATCH_PENDING` (the road branch shown in the master graph), not the rail > batch pool above. --- ## §2 — One-time booking · IMPORT / EXPORT (clearance gate) Every IMPORT/EXPORT one-time booking traverses the clearance gate — **whether or not customs is enabled** (the customs flag only selects a heavier vs lighter `clearance_*` document set; both go through `AWAITING_DOCUMENTS`). Commercial spine as §1 (phases 1–3) **plus** the gate: counter-sign → `AWAITING_DOCUMENTS` → document review loop → `CLEARANCE_READY`, phased ET/DJ actions, then operation-request → payment. ```mermaid flowchart TD classDef port fill:#dbeafe,stroke:#2563eb,color:#111 classDef back fill:#fef3c7,stroke:#b45309,color:#111 classDef sys fill:#dcfce7,stroke:#15803d,color:#111 classDef dec fill:#f8fafc,stroke:#475569,color:#111 classDef good fill:#86efac,stroke:#166534,color:#062e14 classDef bad fill:#fecaca,stroke:#991b1b,color:#450a0a a0(["Booking APPROVED & signed by customer
(see §1 phases 1–3)"]):::sys subgraph CS["Counter-sign with customs"] direction TB cs1["staff counter-sign (IMPORT/EXPORT) → AWAITING_DOCUMENTS (B)"]:::back end subgraph DOCS["5 · Document clearance gate"] direction TB x1["customer clearance/documents
→ DOCUMENTS_UNDER_REVIEW (P)"]:::port x2{"GL clearance/review each doc (B)"}:::dec x2q["doc Queried → customer re-uploads (B)"]:::back x3["clearance/finalize (100% approved) → CLEARANCE_READY (B)"]:::back x1 --> x2 x2 -->|"query"| x2q --> x1 x2 -->|"approve all"| x3 end subgraph PHASED["6 · Phased ET / DJ clearance (as applicable)"] direction TB ph1["upload declaration (serial) (B)"]:::back ph2["duty/tax advise → customer duty-slip (P)(B)"]:::back ph3["transit permit (ET) (B)"]:::back ph4["delivery order / release order (DJ) (B)"]:::back ph5["T1 docs → T1 close (B)"]:::back ph6["export release / finalize-pre-clearance (B)"]:::back ph1 --> ph2 --> ph3 --> ph4 --> ph5 --> ph6 end subgraph OPPAY2["7 · Operation request & payment"] direction TB o1["clearance/proceed → OPERATION_REQUEST_PENDING (P)"]:::port o2{"operation/review (B)"}:::dec o2c["OPERATION_CHANGES_REQUESTED (B)"]:::back om{"mode?"}:::dec ot["accept=train: invoice → FULLY_EXECUTED
→ batch offer → SELECTED_FOR_BATCH (B)(sys)"]:::back orr["accept=road: invoice → ROAD_DISPATCH_PENDING (B)"]:::back p1["customer pays → PAID (sys)(P)"]:::sys pexp(["pay window lapses → EXPIRED"]):::bad o1 --> o2 o2 -->|"request-changes"| o2c --> o1 o2 -->|"accept"| om om -->|"train"| ot --> p1 om -->|"road"| orr --> p1 p1 -.->|"unpaid"| pexp end cancel(["CANCELLED — staff-only, only from
OPERATION_REQUEST_PENDING here (not from
AWAITING_DOCUMENTS / DOCUMENTS_UNDER_REVIEW)"]):::bad phys(["Physical execution:
§5 export · §6 import → COMPLETED (done)"]):::good a0 --> CS --> DOCS x3 --> PHASED ph6 --> OPPAY2 p1 --> phys o1 -.->|"cancel"| cancel ``` --- ## §3 — General contract · Path A (transport-only, self-clearance) Framework agreement where the customer clears customs independently. After the contract is active and operations verify self-clearance (`SELF_CLEARED`), the **customer books directly** under the contract; each booking then runs the operation/payment/physical flow. ```mermaid flowchart TD classDef port fill:#dbeafe,stroke:#2563eb,color:#111 classDef back fill:#fef3c7,stroke:#b45309,color:#111 classDef sys fill:#dcfce7,stroke:#15803d,color:#111 classDef dec fill:#f8fafc,stroke:#475569,color:#111 classDef good fill:#86efac,stroke:#166534,color:#062e14 classDef bad fill:#fecaca,stroke:#991b1b,color:#450a0a pre(["Company ACTIVE"]):::sys subgraph CTR["1 · Contract lifecycle"] direction TB c1["POST /contracts → DRAFT
routes + cargo scope + unit rates (NO quantities) (P)"]:::port c2["generate-price → submit → SUBMITTED
freeze contract_rate_snapshots (P)"]:::port c3{"staff/accept | request-changes | reject (B)"}:::dec c3r["CHANGES_REQUESTED (B)"]:::back c3x(["Contract REJECTED"]):::bad c4["→ PENDING_APPROVAL (B)"]:::back c4a{"approval chain (B)"}:::dec c4x(["rejectStep → REJECTED"]):::bad c5["generate-contract → CONTRACT_READY (B)"]:::back c6["customer sign → SIGNED_CUSTOMER (P)"]:::port c7["staff counter-sign (IMPORT/EXPORT self-clearance) →
AWAITING_CLEARANCE_DOCUMENTS (B)"]:::back c1 --> c2 --> c3 c3 -->|"request-changes"| c3r --> c2 c3 -->|"reject"| c3x c3 -->|"accept"| c4 --> c4a c4a -->|"reject"| c4x c4a -->|"approve"| c5 --> c6 --> c7 c7 -.->|"lapse"| cexp(["EXPIRED"]):::bad c7 -.->|"renew"| cren(["RENEWAL_DRAFT → new cycle"]):::bad end subgraph SELF["2 · Self-clearance verification"] direction TB o1["customer uploads self-clearance docs (P)"]:::port o2{"ops-review each doc (B)"}:::dec o2q["query → re-upload (B)"]:::back o3["ops-finalize → clearanceStatus SELF_CLEARED (B)"]:::back o1 --> o2 o2 -->|"query"| o2q --> o1 o2 -->|"approve"| o3 end subgraph BK["3 · Book directly under contract"] direction TB b1["customer POST /contracts/:id/bookings (P)"]:::port bv{"validate-shipment:
window + capacity draw-down + pairing"}:::dec bvx(["rejected: over capacity /
20ft pairing hard-block"]):::bad b2["Booking created under contract
(bookings.contract_id) (sys)"]:::sys b1 --> bv bv -->|"fail"| bvx bv -->|"ok"| b2 end op(["Booking runs operation + payment
(see §1 phase 4) then §5/§6/§7 → COMPLETED (done)"]):::good pre --> CTR c7 --> SELF o3 --> BK b2 --> op ``` --- ## §4 — General contract · Path B (GENERAL + customs) Framework agreement **with** customs. The customer cannot book directly — they submit a **BookingRequest** (date + quantities only); GL Ethiopia accepts it and creates the booking, which then runs **per-booking phased customs** on the `/contracts/bookings/:bookingId/*` surface. ```mermaid flowchart TD classDef port fill:#dbeafe,stroke:#2563eb,color:#111 classDef back fill:#fef3c7,stroke:#b45309,color:#111 classDef sys fill:#dcfce7,stroke:#15803d,color:#111 classDef dec fill:#f8fafc,stroke:#475569,color:#111 classDef good fill:#86efac,stroke:#166534,color:#062e14 classDef bad fill:#fecaca,stroke:#991b1b,color:#450a0a pre(["Company ACTIVE"]):::sys subgraph CTR["1 · Contract lifecycle (customs)"] direction TB c1["POST /contracts → DRAFT → submit → approve → sign (P)(B)"]:::port c7["staff counter-sign (GENERAL + customs) → CONTRACT_ACTIVE
(contract clearance cycle SKIPPED — runs per-booking) (B)"]:::back c1 --> c7 c1 -.->|"reject / lapse"| cx(["REJECTED / EXPIRED"]):::bad end subgraph REQ["2 · Booking request → GL creates booking"] direction TB r1["customer POST /contracts/:id/booking-requests
(date + quantities, no per-unit data) (P)"]:::port r2{"GL booking-request queue (B)"}:::dec r2x(["reject / customer cancel →
REJECTED / CANCELLED"]):::bad r3["GL accept → GL creates booking under contract
(ct:create_booking) (B)"]:::back r1 --> r2 r2 -->|"reject/cancel"| r2x r2 -->|"accept"| r3 end subgraph GLC["3 · Per-booking GL clearance & milestones"] direction TB g1["station-assign (route + bind staff) (B)"]:::back g2["declaration → duty advise (GREEN/YELLOW/RED risk) (B)"]:::back g3["customer duty-slip → transit / delivery / release order (P)(B)"]:::back g4["T1 docs → T1 close (B)"]:::back g5["final-invoice → customer slip → confirm paid (P)(B)"]:::back g6["second-duty (post-arrival import) → slip (P)(B)"]:::back gi["incident reports (photos) as needed (B)"]:::back g1 --> g2 --> g3 --> g4 --> g5 --> g6 g4 -.-> gi end op(["Booking runs operation + payment (see §1 phase 4)
then §5/§6 physical → COMPLETED (done)"]):::good pre --> CTR c7 --> REQ r3 --> GLC g6 --> op ``` --- ## §5 — EXPORT operations (physical execution) Given a PAID, scheduled **export** booking: optional first-mile road leg → origin warehouse inbound → train build & dispatch → corridor transit → Djibouti port unload → interchange handover. Cargo leaves the country at the port; the booking's terminal here is **dispatched/handed-over at Djibouti**. ```mermaid flowchart TD classDef port fill:#dbeafe,stroke:#2563eb,color:#111 classDef back fill:#fef3c7,stroke:#b45309,color:#111 classDef sys fill:#dcfce7,stroke:#15803d,color:#111 classDef dec fill:#f8fafc,stroke:#475569,color:#111 classDef good fill:#86efac,stroke:#166534,color:#062e14 classDef bad fill:#fecaca,stroke:#991b1b,color:#450a0a pre(["Export booking PAID & Eligible
(see §1/§2/§3/§4)"]):::sys subgraph FM["1 · First-mile (if EXPORT + requested)"] direction TB fmq{"first-mile requested?"}:::dec fm1["leg auto-created firstMile.acceptBooking
READY_TO_TRANSIT (sys)"]:::sys fm2["setVehicles → vehicle BUSY, SMS driver, fleet_events (B)"]:::back fm3["IN_TRANSIT (needs vehicle) → RECEIVED_TO_PORT (B)"]:::back fm4["first-mile invoice (FIRST_MILE fee); distances lock once invoiced (B)"]:::back fmq -->|"yes"| fm1 --> fm2 --> fm3 --> fm4 fmq -->|"no"| fmskip[" "]:::sys end subgraph WH["2 · Origin warehouse inbound"] direction TB w1["receive / bulkReceive → RECEIVED
capacity assert, GRN, notify owner SMS (B)"]:::back w2{"inspection"}:::dec w2f["FAILED / NEEDS_REVIEW → hold + re-inspect (B)"]:::back w3["store (allocation rule → yard/zone) → STORED (B)"]:::back w4["reserve (booking PAID) → RESERVED (B)"]:::back w5["mark-ready-for-loading (inspection PASSED) → READY_FOR_LOADING (B)"]:::back w6["load onto wagon → LOADED (+ warehouse_loadings) (B)"]:::back w1 --> w2 w2 -->|"fail"| w2f --> w2 w2 -->|"PASSED"| w3 --> w4 --> w5 --> w6 end subgraph SCHED["3 · Train build & schedule"] direction TB s1["schedule DRAFT (≥2 locos, derive EXPORT direction) (B)"]:::back s2["assign-bookings + run-allocation (wagons) (B)"]:::back s3["pin wagons → finalize → SCHEDULED (bookings Scheduled) (B)"]:::back s3x["cancel schedule → bookings Eligible (B)"]:::back s1 --> s2 --> s3 s3 -.->|"cancel"| s3x -.-> s1 s3 -.->|"gov preempt / maintenance"| sr["reschedule: retained/displaced/readmitted (B)"]:::back sr -.-> s2 end subgraph RUN["4 · Dispatch → Djibouti"] direction TB r1["dispatch → DISPATCHED
train_number, locos ASSIGNED, window CLOSED, unpaid EXPIRED (B)"]:::back r2["checkpoints (corridor) → train_checkpoint_events (B)"]:::back rc["customer tracking page GET /tracking/:id (JWT) (P)
NOTE: tracking_events has no writer — timeline empty"]:::port r3["arrive → ARRIVED (bookings IN_TRANSIT, wagons/locos freed) (B)"]:::back ru["export/auto-unload-at-djibouti →
UNLOADED_AT_DJIBOUTI_PORT (B)"]:::back ri["interchange document generate-from-schedule → GENERATED (B)"]:::back ria{"port acknowledges?"}:::dec r1 --> r2 --> r3 --> ru --> ri --> ria r2 -.-> rc end done(["Export dispatched & handed over at Djibouti (done)"]):::good disp(["interchange DISPUTED → remarks / re-issue"]):::bad pre --> FM fm4 --> WH fmskip --> WH w6 --> SCHED s3 --> RUN ria -->|"acknowledge"| done ria -->|"dispute"| disp ``` --- ## §6 — IMPORT operations (physical execution) Given a PAID, scheduled **import** booking arriving by train from Djibouti: destination warehouse unload → inspection → import customs finalization → optional last-mile → fee gate-clearance → release → delivery → **COMPLETED**. ```mermaid flowchart TD classDef port fill:#dbeafe,stroke:#2563eb,color:#111 classDef back fill:#fef3c7,stroke:#b45309,color:#111 classDef sys fill:#dcfce7,stroke:#15803d,color:#111 classDef dec fill:#f8fafc,stroke:#475569,color:#111 classDef good fill:#86efac,stroke:#166534,color:#062e14 classDef bad fill:#fecaca,stroke:#991b1b,color:#450a0a pre(["Import booking PAID & scheduled
(see §1/§2/§4)"]):::sys subgraph RAIL["1 · Import train arrival"] direction TB t1["import train dispatched from Djibouti → DISPATCHED (B)"]:::back t2["checkpoints → train_checkpoint_events (B)"]:::back tc["customer tracking page GET /tracking/:id (JWT) (P)
NOTE: tracking_events has no writer — timeline empty"]:::port t3["arrive → ARRIVED (bookings IN_TRANSIT) → warehouse arrival automation (B)"]:::back t1 --> t2 --> t3 t2 -.-> tc end subgraph WH["2 · Destination warehouse"] direction TB w1["import/auto-unload-arrived-bookings (assign WH/yard/zone) → UNLOADED (B)"]:::back w2{"inspection PASSED?"}:::dec w2f["FAILED → hold / re-inspect / djibouti-incident report (B)"]:::back w3["→ READY_FOR_PICKUP (IMPORT) (B)"]:::back w1 --> w2 w2 -->|"no"| w2f --> w2 w2 -->|"yes"| w3 end subgraph CUST["3 · Import customs finalization (timestamp-driven)"] direction TB u1["upload docs (IM4/IM5/T1_CLOSURE/TRANSIT_PERMIT/…) (B)"]:::back u2["record declaration serial (B)"]:::back u3["notify duties/taxes (B)"]:::back u4["mark duties paid (needs CUSTOMER_PAYMENT_SLIP) (B)"]:::back u5["assign risk (GREEN/YELLOW/BLUE/RED) (B)"]:::back u6{"release gates satisfied?
T1 + release permit + declaration + risk + paid"}:::dec u6x["blocked — missing gate → resolve (B)"]:::back u7["release-permitted → completedAt (B)"]:::back u1 --> u2 --> u3 --> u4 --> u5 --> u6 u6 -->|"no"| u6x --> u6 u6 -->|"yes"| u7 end subgraph LM["4 · Last-mile (if requested)"] direction TB lq{"last-mile requested?"}:::dec l1["leg auto-created lastMile.acceptBooking
READY_TO_TRANSIT (sys)"]:::sys l2["setVehicles → IN_TRANSIT → DELIVERED (free vehicles) (B)"]:::back l3["last-mile invoice (LAST_MILE fee) (B)"]:::back lq -->|"yes"| l1 --> l2 --> l3 lq -->|"no"| lskip[" "]:::sys end subgraph DEL["5 · Release & delivery"] direction TB d0{"warehouse/storage fees fully PAID?"}:::dec d0x["gate-clearance BLOCKED (findBlockingInvoice) (B)"]:::back d0p["customer pays storage/demurrage online (P)"]:::port d1["release order (DO) + gate-clearance → deliver (B)"]:::back d2["customer approve-delivery (saved signature) → POD (P)"]:::port d3["inventory DELIVERED, POD to cargo, container freed (sys)"]:::sys d0 -->|"no"| d0x --> d0p --> d0 d0 -->|"yes"| d1 --> d2 --> d3 end ecr(["empty-container-return chain (post-import):
RETURNED → … → HANDOVER_ISSUED → COMPLETED"]):::sys done(["Booking COMPLETED (done) (operations/complete)"]):::good pre --> RAIL t3 --> WH w3 --> CUST u7 --> LM l3 --> DEL lskip --> DEL d3 --> done done -.-> ecr ``` --- ## §7 — INTERCITY / DOMESTIC operations (no cross-border customs) Rail movement **between Ethiopian yards** (e.g. inland dry ports). No import/export customs, no Djibouti port unload or interchange handover. Optional road mile legs if the service includes door delivery. ```mermaid flowchart TD classDef port fill:#dbeafe,stroke:#2563eb,color:#111 classDef back fill:#fef3c7,stroke:#b45309,color:#111 classDef sys fill:#dcfce7,stroke:#15803d,color:#111 classDef dec fill:#f8fafc,stroke:#475569,color:#111 classDef good fill:#86efac,stroke:#166534,color:#062e14 classDef bad fill:#fecaca,stroke:#991b1b,color:#450a0a pre(["Domestic booking PAID & Eligible
(see §1 — customs OFF)"]):::sys subgraph FMD["1 · Optional origin pickup (road)"] direction TB fq{"door pickup / first-mile requested?"}:::dec f1["first-mile leg → vehicle assign → RECEIVED_TO_PORT (B)"]:::back fq -->|"yes"| f1 --> fnext[" "]:::sys fq -->|"no (drop at origin yard)"| fnext end subgraph WHO["2 · Origin warehouse"] direction TB w1["receive → RECEIVED (B)"]:::back w2{"inspection PASSED?"}:::dec w2f["hold + re-inspect (B)"]:::back w3["store → STORED → reserve (PAID) → RESERVED (B)"]:::back w4["ready-for-loading → LOADED onto wagon (B)"]:::back w1 --> w2 w2 -->|"no"| w2f --> w2 w2 -->|"yes"| w3 --> w4 end subgraph RUN["3 · Train (ET yard → ET yard)"] direction TB s1["schedule DRAFT (direction DOMESTIC) → assign → finalize → SCHEDULED (B)"]:::back r1["dispatch → DISPATCHED (unpaid EXPIRED) (B)"]:::back r2["checkpoints → train_checkpoint_events; customer tracking (JWT) (P)(B)"]:::back r3["arrive → ARRIVED (bookings IN_TRANSIT) (B)"]:::back s1 --> r1 --> r2 --> r3 end subgraph WHD["4 · Destination warehouse & delivery"] direction TB d1["auto-unload arrived → UNLOADED / RECEIVED (B)"]:::back di{"inspection PASSED?"}:::dec dif["hold + re-inspect (B)"]:::back d2["READY_FOR_PICKUP (B)"]:::back fee{"storage fees paid?"}:::dec feex["gate-clearance blocked → customer pays (P)"]:::port d3["release order → deliver (B)"]:::back lq{"door delivery / last-mile?"}:::dec l1["last-mile leg → DELIVERED (B)"]:::back d4["customer approve-delivery → POD → inventory DELIVERED (P)(sys)"]:::sys d1 --> di di -->|"no"| dif --> di di -->|"yes"| d2 --> fee fee -->|"no"| feex --> fee fee -->|"yes"| d3 --> lq lq -->|"yes"| l1 --> d4 lq -->|"no (pickup at yard)"| d4 end done(["Booking COMPLETED (done)"]):::good pre --> FMD fnext --> WHO w4 --> RUN r3 --> WHD d4 --> done ``` --- ## Cross-reference | Variant | Distinctive gate(s) | Terminal ends unique to it | | --------------------------- | --------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------- | | §1 One-time · DOMESTIC | counter-sign → `FULLY_EXECUTED` (skips clearance **and** op-request; enters batch directly) | HARD BLOCK, price/intake/approval REJECTED, EXPIRED | | §2 One-time · IMPORT/EXPORT | `AWAITING_DOCUMENTS` → review loop → phased ET/DJ → op-request (gate applies with **or without** customs) | + doc-query loop, CANCELLED (only from OPERATION_REQUEST_PENDING) | | §3 Contract · Path A | `SELF_CLEARED` via ops-review; customer books direct | contract REJECTED/EXPIRED/RENEWAL, capacity/pairing block | | §4 Contract · Path B | BookingRequest → GL creates booking; per-booking milestones | BookingRequest REJECTED/CANCELLED | | §5 Export ops | first-mile → Djibouti unload → interchange handover | dispatched@Djibouti (success), interchange DISPUTED | | §6 Import ops | import customs finalization gates → last-mile → gate-clearance | COMPLETED (+ empty-container-return chain) | | §7 Intercity ops | ET→ET rail, no cross-border customs, optional mile legs | COMPLETED | Full endpoint tables & per-domain state machines: [`FREIGHT_SYSTEM_FLOW.md`](./FREIGHT_SYSTEM_FLOW.md). Single all-in-one branching graph: [`FREIGHT_MASTER_FLOW.md`](./FREIGHT_MASTER_FLOW.md).