Architecture
The fulfillment system connects four models:- Order has many shipments (
OrderShipping) and tracks overallshipping_status - Each shipment has its own
status(ShipmentStatus) and a timeline of events (OrderShippingEvent) - Each item tracks its own fulfillment status independently
Database Schema
OrderShipping Table
OrderShippingEvent Table
OrderItem Fulfillment Columns
Fulfillment Status
TheFulfillmentStatus enum defines the lifecycle of each item:
Status Flow
Shipping Status (Order Level)
TheShippingStatus enum lives on the Order model and reflects the combined state of all its shipments. It answers “has this order been shipped/delivered?”.
Shipment Status (Package Level)
TheShipmentStatus enum lives on the OrderShipping model and tracks the delivery progress of a single package. Each shipment goes through this lifecycle independently.
Shipment Transitions
TheHasFulfillmentTransitions trait on OrderShipping enforces valid state transitions:
Transitioning Shipment Status
UsetransitionTo() to update the shipment status. It validates the transition and automatically logs a tracking event:
OrderShippingEvent record with the status, timestamp, and optional location data.
Tracking Events
Each shipment has a timeline of events that record its journey:Relationships
Order → Shipments
OrderShipping → Items & Events
OrderItem → Shipment
Creating Shipments
Single Shipment (All Items Together)
When all items ship in one package:Partial Shipment (Split Across Packages)
When items ship in multiple packages with different carriers:Marking as Delivered
Dropshipping Workflow
For external products sourced from suppliers, the fulfillment flow includes an additional step where the order is forwarded to the supplier who ships directly to the customer.Dropshipping requires the Supplier feature to be enabled. External products must be linked to a supplier.
Complete Dropshipping Flow
Mixed Orders (Own Products + Supplier Products)
An order can contain both your own products and dropshipped products:Querying Fulfillment Data
Items by Status
Orders Needing Attention
Shipment History
Handling Returns
Actions
Shopper provides dedicated action classes for fulfillment operations. These handle side effects like syncing order statuses, updating item states, and dispatching events automatically.RecordShipmentEventAction
The recommended way to record shipment events. It validates the transition, updates the shipment status, logs the event, and handles side effects based on the new status:FulfillmentStatus::Shipped and changes the order status from New to Processing.
When a shipment transitions to Delivered, the action updates all items to FulfillmentStatus::Delivered and completes the order if all items across all shipments are delivered.
When a shipment transitions to Returned, the action updates all items to FulfillmentStatus::Cancelled.
MarkShipmentDeliveredAction
A convenience action for marking a shipment as delivered. It validates that the shipment can transition toDelivered and dispatches the OrderShipmentDelivered event:
SyncOrderShippingStatusAction
This action computes the order-levelshipping_status from the fulfillment statuses of all its items. It runs automatically after every shipment event, but you can call it manually if you update item statuses directly:
When the status transitions to
Shipped, the OrderShipped event is dispatched.