@company-manager/docs

Shipping & Fulfillment

Shipment lifecycle, carrier integration, and delivery tracking diagrams

Shipping & Fulfillment

This page covers the complete shipping and fulfillment process from order fulfillment through delivery confirmation.

Shipment State Machine

stateDiagram-v2
    [*] --> CREATED: Create Shipment

    CREATED --> LABEL_GENERATED: Generate Label
    CREATED --> CANCELLED: Cancel

    LABEL_GENERATED --> PICKED_UP: Carrier Pickup
    LABEL_GENERATED --> CANCELLED: Cancel Before Pickup

    PICKED_UP --> IN_TRANSIT: In Transit
    IN_TRANSIT --> OUT_FOR_DELIVERY: Out for Delivery
    IN_TRANSIT --> EXCEPTION: Transit Issue

    OUT_FOR_DELIVERY --> DELIVERED: Delivery Confirmed
    OUT_FOR_DELIVERY --> EXCEPTION: Delivery Failed

    EXCEPTION --> IN_TRANSIT: Issue Resolved
    EXCEPTION --> RETURNED: Return to Sender
    EXCEPTION --> HELD: Held at Location

    HELD --> OUT_FOR_DELIVERY: Rescheduled
    HELD --> RETURNED: Customer No-Show

    DELIVERED --> [*]
    RETURNED --> [*]
    CANCELLED --> [*]

    note right of EXCEPTION
        Includes: address issues,
        customs hold, weather delay
    end note

Shipment Status Descriptions

StatusDescriptionCarrier Code Examples
CREATEDShipment record created-
LABEL_GENERATEDShipping label printedlabel_created
PICKED_UPCarrier collected packagepicked_up, accepted
IN_TRANSITPackage moving through networkin_transit, departed
OUT_FOR_DELIVERYOn delivery vehicleout_for_delivery
DELIVEREDSuccessfully delivereddelivered
EXCEPTIONIssue encounteredexception, delayed
HELDHeld at carrier facilityheld, available_for_pickup
RETURNEDReturned to senderreturn_to_sender

Fulfillment Flow

flowchart TD
    subgraph "Order Confirmation"
        ORDER[Order Confirmed] --> ASSIGN[Assign to Warehouse]
        ASSIGN --> CREATE_FULFILL[Create Fulfillment]
    end

    subgraph "Picking"
        CREATE_FULFILL --> GENERATE_PICKLIST[Generate Pick List]
        GENERATE_PICKLIST --> ASSIGN_PICKER[Assign to Picker]
        ASSIGN_PICKER --> PICK_ITEMS[Pick Items]

        PICK_ITEMS --> VERIFY{All Items Found?}
        VERIFY -->|Yes| COMPLETE_PICK[Complete Picking]
        VERIFY -->|No| HANDLE_SHORT[Handle Shortage]

        HANDLE_SHORT --> PARTIAL{Partial Ship?}
        PARTIAL -->|Yes| COMPLETE_PICK
        PARTIAL -->|No| WAIT_STOCK[Wait for Stock]
        WAIT_STOCK --> PICK_ITEMS
    end

    subgraph "Packing"
        COMPLETE_PICK --> SELECT_BOX[Select Packaging]
        SELECT_BOX --> PACK[Pack Items]
        PACK --> ADD_PACKING[Add Packing Materials]
        ADD_PACKING --> WEIGHT[Weigh Package]
        WEIGHT --> SEAL[Seal Package]
    end

    subgraph "Shipping"
        SEAL --> SELECT_CARRIER[Select Carrier/Service]
        SELECT_CARRIER --> GEN_LABEL[Generate Label]
        GEN_LABEL --> PRINT_LABEL[Print Label]
        PRINT_LABEL --> APPLY_LABEL[Apply Label]
        APPLY_LABEL --> STAGE[Stage for Pickup]
        STAGE --> HANDOFF[Hand to Carrier]
    end

    HANDOFF --> TRACK[Track Shipment]

    style ORDER fill:#e1f5fe
    style HANDOFF fill:#e8f5e9

Shipping Label Generation Sequence

sequenceDiagram
    participant Staff
    participant UI as Fulfillment UI
    participant API as TRPC Router
    participant Service as Shipping Service
    participant Carrier as Carrier API
    participant DB as Database
    participant Printer as Label Printer

    Staff->>UI: Request shipping label
    UI->>API: generateLabel(shipmentId)
    API->>Service: createShippingLabel(shipment)

    Service->>DB: Get shipment details
    DB-->>Service: Shipment + order data

    Service->>Service: Calculate dimensions & weight
    Service->>Service: Select optimal service

    Service->>Carrier: Create shipment request
    Note over Service,Carrier: Address, weight, service type

    Carrier-->>Service: Tracking number + label data

    Service->>DB: Update shipment (trackingNumber)
    Service->>DB: Create ShippingLabel record
    DB-->>Service: Created

    Service->>Service: Generate label PDF/ZPL

    Service-->>API: Label data + tracking
    API-->>UI: Label ready

    Staff->>UI: Print label
    UI->>Printer: Send to printer
    Printer-->>UI: Printed

    UI->>API: confirmLabelPrinted(labelId)
    API->>Service: markLabelPrinted(labelId)
    Service->>DB: Update label status

Carrier Integration Architecture

flowchart TB
    subgraph "Shipping Service"
        ROUTER[Carrier Router]
        RATE[Rate Calculator]
        LABEL[Label Generator]
        TRACK[Tracking Poller]
    end

    subgraph "Carrier Adapters"
        COL[Colissimo Adapter]
        CHRON[Chronopost Adapter]
        DPD[DPD Adapter]
        UPS[UPS Adapter]
    end

    subgraph "Carrier APIs"
        COL_API[Colissimo API]
        CHRON_API[Chronopost API]
        DPD_API[DPD API]
        UPS_API[UPS API]
    end

    ROUTER --> COL
    ROUTER --> CHRON
    ROUTER --> DPD
    ROUTER --> UPS

    COL --> COL_API
    CHRON --> CHRON_API
    DPD --> DPD_API
    UPS --> UPS_API

    RATE --> ROUTER
    LABEL --> ROUTER
    TRACK --> ROUTER

    style ROUTER fill:#e1f5fe

Rate Calculation Flow

flowchart TD
    START[Calculate Shipping Rates] --> GET_DEST[Get Destination Address]
    GET_DEST --> GET_DIMS[Get Package Dimensions]
    GET_DIMS --> GET_WEIGHT[Get Package Weight]

    GET_WEIGHT --> FIND_ZONE[Determine Shipping Zone]
    FIND_ZONE --> ZONE_TYPE{Zone Type?}

    ZONE_TYPE -->|Domestic| DOMESTIC[Domestic Rates]
    ZONE_TYPE -->|Corsica| CORSICA[Corsica Rates]
    ZONE_TYPE -->|DOM-TOM| DOMTOM[DOM-TOM Rates]
    ZONE_TYPE -->|EU| EU[EU Rates]
    ZONE_TYPE -->|International| INTL[International Rates]

    DOMESTIC --> CALC[Calculate Base Rate]
    CORSICA --> CALC
    DOMTOM --> CALC
    EU --> CALC
    INTL --> CALC

    CALC --> ADD_SURCHARGE{Surcharges?}

    ADD_SURCHARGE -->|Fuel| FUEL[+ Fuel Surcharge]
    ADD_SURCHARGE -->|Rural| RURAL[+ Rural Surcharge]
    ADD_SURCHARGE -->|Oversize| OVERSIZE[+ Oversize Fee]
    ADD_SURCHARGE -->|Insurance| INSURANCE[+ Insurance]

    FUEL --> TOTAL
    RURAL --> TOTAL
    OVERSIZE --> TOTAL
    INSURANCE --> TOTAL
    ADD_SURCHARGE -->|None| TOTAL[Calculate Total]

    TOTAL --> ADD_VAT[Add VAT if Applicable]
    ADD_VAT --> RETURN[Return Rate]

    style RETURN fill:#e8f5e9

Tracking Event Flow

sequenceDiagram
    participant Carrier as Carrier System
    participant Webhook as Webhook Handler
    participant Service as Tracking Service
    participant DB as Database
    participant Email as Email Service
    participant User

    Carrier->>Webhook: POST tracking event
    Note over Carrier,Webhook: {tracking_number, status, location, timestamp}

    Webhook->>Webhook: Verify signature
    Webhook->>Service: processTrackingEvent(event)

    Service->>DB: Find shipment by tracking number
    DB-->>Service: Shipment data

    Service->>Service: Normalize carrier status
    Service->>DB: Create TrackingEvent
    Service->>DB: Update shipment status
    DB-->>Service: Updated

    alt Status is significant
        Service->>Email: queueNotification(shipment, event)

        alt Out for Delivery
            Email->>User: "Your package is out for delivery"
        else Delivered
            Email->>User: "Your package has been delivered"
        else Exception
            Email->>User: "Delivery issue - action needed"
        end
    end

    Service-->>Webhook: 200 OK
    Webhook-->>Carrier: Acknowledged

Pickup Point Selection

flowchart TD
    START[Customer Selects Pickup] --> GET_ADDR[Get Customer Address]
    GET_ADDR --> SEARCH[Search Nearby Pickup Points]

    SEARCH --> CARRIER_SEARCH[Query Carrier APIs]
    CARRIER_SEARCH --> AGGREGATE[Aggregate Results]

    AGGREGATE --> FILTER{Apply Filters}
    FILTER --> HOURS[Filter by Opening Hours]
    FILTER --> WEIGHT[Filter by Max Weight]
    FILTER --> FEATURES[Filter by Features]

    HOURS --> SORT
    WEIGHT --> SORT
    FEATURES --> SORT

    SORT[Sort by Distance] --> DISPLAY[Display to Customer]
    DISPLAY --> SELECT[Customer Selects Point]
    SELECT --> SAVE[Save Preference]

    SAVE --> USE[Use for Shipment]

    style USE fill:#e8f5e9

Shipping Zone ERD

erDiagram
    SHIPPING_CONFIGURATION ||--o{ SHIPPING_ZONE : has
    SHIPPING_ZONE ||--o{ SHIPPING_RATE : has
    SHIPPING_CARRIER ||--o{ SHIPPING_SERVICE : offers
    SHIPPING_SERVICE ||--o{ SHIPPING_RATE : priced_by

    SHIPMENT }o--|| SHIPPING_CARRIER : uses
    SHIPMENT }o--|| SHIPPING_SERVICE : uses
    SHIPMENT }o--o| PICKUP_POINT : delivered_to
    SHIPMENT ||--o{ TRACKING_EVENT : logs

    SHIPPING_CONFIGURATION {
        string id PK
        string tenantId FK
        boolean enabled
        string defaultCurrency
        int maxDeliveryDays
        int returnPolicyDays
        boolean vatIncluded
    }

    SHIPPING_ZONE {
        string id PK
        string configId FK
        enum zoneType
        string[] countries
        boolean includesCorsica
        boolean includesDomTom
        decimal freeShippingThreshold
    }

    SHIPPING_RATE {
        string id PK
        string zoneId FK
        string serviceId FK
        enum rateType
        decimal baseRate
        decimal perKgRate
        decimal fuelSurcharge
        decimal vatRate
    }

    TRACKING_EVENT {
        string id PK
        string shipmentId FK
        string status
        string statusCode
        string location
        timestamp eventDate
        json metadata
    }

Return Shipment Flow

flowchart TD
    START[Return Requested] --> APPROVE{Approved?}

    APPROVE -->|Yes| GEN_LABEL[Generate Return Label]
    APPROVE -->|No| REJECT[Reject Return]

    GEN_LABEL --> SEND_LABEL[Email Label to Customer]
    SEND_LABEL --> WAIT[Wait for Return Shipment]

    WAIT --> TRACK_RETURN[Track Return Package]
    TRACK_RETURN --> RECEIVE{Received?}

    RECEIVE -->|Yes| INSPECT[Inspect Items]
    RECEIVE -->|No| REMINDER[Send Reminder]
    REMINDER --> WAIT

    INSPECT --> CONDITION{Condition OK?}

    CONDITION -->|Good| FULL_REFUND[Process Full Refund]
    CONDITION -->|Damaged| PARTIAL[Partial Refund]
    CONDITION -->|Not Returned Item| DISPUTE[Dispute]

    FULL_REFUND --> RESTOCK[Restock Items]
    PARTIAL --> RESTOCK_PARTIAL[Partial Restock]

    RESTOCK --> COMPLETE[Return Complete]
    RESTOCK_PARTIAL --> COMPLETE

    style COMPLETE fill:#e8f5e9
    style REJECT fill:#ffebee

Bulk Shipping Operations

sequenceDiagram
    participant Staff
    participant UI as Bulk Operations UI
    participant API as TRPC Router
    participant Service as Bulk Shipping Service
    participant Queue as Job Queue
    participant Worker as Background Worker
    participant Carrier as Carrier API

    Staff->>UI: Select orders for bulk ship
    UI->>API: createBulkShipment(orderIds)
    API->>Service: initiateBulkShipment(orders)

    Service->>Service: Validate all orders
    Service->>Queue: Queue bulk job
    Queue-->>Service: Job ID

    Service-->>API: {jobId, status: "queued"}
    API-->>UI: Show progress

    Worker->>Queue: Pick up job
    Queue-->>Worker: Bulk shipment job

    loop For each order
        Worker->>Carrier: Generate label
        Carrier-->>Worker: Label + tracking
        Worker->>Worker: Update progress
    end

    Worker->>Service: Complete bulk operation
    Service->>UI: Push notification
    UI-->>Staff: Bulk shipment complete

    Staff->>UI: Print all labels
    UI->>Service: getBulkLabels(jobId)
    Service-->>UI: Combined PDF

Delivery Analytics

flowchart LR
    subgraph "Data Collection"
        EVENTS[Tracking Events]
        TIMES[Delivery Times]
        ISSUES[Exceptions]
    end

    subgraph "Analysis"
        AGG[Aggregate by Carrier]
        CALC[Calculate Metrics]
        TREND[Trend Analysis]
    end

    subgraph "Metrics"
        OTD[On-Time Delivery %]
        AVG[Avg Delivery Time]
        FAIL[Failure Rate]
        COST[Cost per Shipment]
    end

    EVENTS --> AGG
    TIMES --> AGG
    ISSUES --> AGG

    AGG --> CALC
    CALC --> TREND

    TREND --> OTD
    TREND --> AVG
    TREND --> FAIL
    TREND --> COST