Task 8 — Logistics and Shipment Processing Network
Objective
Create a logistics and shipment-processing network.
The system manages the complete lifecycle of packages from warehouse intake to final delivery.
The network contains:
- customers
- addresses
- regions
- warehouses
- warehouse inventory
- packages
- shipments
- shipment items
- vehicles
- drivers
- routes
- route stops
- delivery assignments
- tracking events
- delivery attempts
- returns
- damaged or lost packages
The implementation must model package ownership, shipment state, warehouse location, vehicle capacity, driver eligibility, delivery routing, tracking history, failed delivery attempts, and returns.
The system must preserve both:
current shipment state
and:
complete shipment history
Domain Overview
Conceptually:
Customer
|
+-- Address
|
+-- Shipment
|
+-- Package
|
+-- Tracking Events
|
+-- Delivery Attempts
|
+-- Return Shipment
Infrastructure:
Region
|
+-- Warehouse
|
+-- Vehicle
|
+-- Driver
|
+-- Route
Operational flow:
Shipment
|
v
Warehouse
|
v
Assignment
|
+-- Vehicle
+-- Driver
+-- Route
|
v
Delivery
Customer
A customer contains:
- ID
- Name
- Phone
For example:
type Customer struct {
ID string
Name string
Phone string
Email string
}
Address
An address belongs to a region. A possible model is:
type Address struct {
ID string
CustomerID string
Street string
City string
PostalCode string
RegionID string
}
The system must validate that shipment destinations reference valid addresses.
Region
A region defines a delivery area. For example:
type Region struct {
ID string
Name string
}
Examples:
- region-1
- region-2
- region-3
Warehouse
A warehouse belongs to one region.
For example:
type Warehouse struct {
ID string
RegionID string
Name string
}
A warehouse may contain many packages waiting for processing.
Package
Each package contains:
ID
Weight
Volume
Type
Current Warehouse
Status
A possible model is:
type Package struct {
ID string
WeightKg float64
VolumeM3 float64
PackageType PackageType
CurrentWarehouseID string
Status PackageStatus
}
Package Type
Possible package types may include:
standard
fragile
refrigerated
hazardous
oversized
Vehicle and driver restrictions may depend on package type.
Shipment
A shipment belongs to a customer and contains one or more packages. For example:
type Shipment struct {
ID string
CustomerID string
DestinationID string
Priority ShipmentPriority
Status ShipmentStatus
Deadline time.Time
PackageIDs []string
}
Shipment Priority
Supported priorities:
standard
express
critical
Higher-priority shipments should be considered first when several shipments compete for limited delivery capacity.
The exact tie-breaking rule must be deterministic. A reasonable order is:
- critical
- express
- standard
Then:
earlier deadline
Then:
Shipment ID ascending
Shipment Status
Use a controlled state model.
Possible shipment states:
- created
- reserved
- packed
- ready_for_dispatch
- dispatched
- in_transit
- out_for_delivery
- delivered
- delivery_failed
- returning
- returned
- cancelled
- lost
Not every transition is valid.
Shipment State Transitions
A possible allowed transition graph is:
created
|
v
reserved
|
v
packed
|
v
ready_for_dispatch
|
v
dispatched
|
v
in_transit
|
v
out_for_delivery
|
+-------> delivered
|
+-------> delivery_failed
|
+-------> out_for_delivery
|
+-------> returning
|
v
returned
Alternative transitions:
created -> cancelled
reserved -> cancelled
packed -> cancelled
in_transit -> lost
out_for_delivery -> lost
The implementation must reject invalid state transitions.
Vehicle
Each vehicle contains:
- ID
- Vehicle Type
- Maximum Weight
- Maximum Volume
- Allowed Regions
- Supported Package Types
- Status
A possible model is:
type Vehicle struct {
ID string
Type VehicleType
MaxWeightKg float64
MaxVolumeM3 float64
AllowedRegionIDs []string
SupportedPackageTypes []PackageType
Status VehicleStatus
}
Vehicle Status
Possible states:
- available
- assigned
- maintenance
- disabled
Only available vehicles may receive new delivery assignments.
Driver
A driver contains:
- ID
- Name
- Licenses
- Allowed Vehicle Types
- Working Hours
- Current Status
For example:
type Driver struct {
ID string
Name string
Licenses []string
AllowedVehicleTypes []VehicleType
ShiftStart time.Time
ShiftEnd time.Time
Status DriverStatus
}
Driver Status
Possible states:
- available
- assigned
- off_shift
- suspended
A driver may only be assigned when:
- status = available
- current time is within shift
- driver is eligible for vehicle type
Route
A route defines a delivery sequence. For example:
type Route struct {
ID string
RegionID string
Stops []RouteStop
}
Route Stop
Each route stop may contain:
type RouteStop struct {
Sequence int
AddressID string
}
The route model does not need to solve real-world GPS navigation.
The task focuses on shipment assignment and ordered stops.
Delivery Assignment
A delivery assignment connects:
- vehicle
- driver
- route
- shipments
For example:
type DeliveryAssignment struct {
ID string
VehicleID string
DriverID string
RouteID string
ShipmentIDs []string
Status AssignmentStatus
}
Possible assignment states:
- created
- active
- completed
- cancelled
Capacity Validation
For all shipments assigned to one vehicle:
total weight <= vehicle maximum weight
and:
total volume <= vehicle maximum volume
The implementation must calculate capacity using every package contained in the assigned shipments.
Region Validation
A vehicle may only deliver shipments to regions listed in:
AllowedRegionIDs
A driver must also be allowed to operate the selected vehicle.
Package-Type Validation
A vehicle may restrict package types.
For example:
standard truck:
standard
fragile
oversized
refrigerated van:
standard
refrigerated
hazmat truck:
standard
hazardous
A shipment containing unsupported package types cannot be assigned to that vehicle.
Base Assignment Scenario
Create:
Shipment: shipment-1001
Priority: express
Destination Region: region-2
Deadline: 16:00
Packages:
package-1:
weight = 30 kg
volume = 0.30 m3
type = standard
package-2:
weight = 45 kg
volume = 0.45 m3
type = fragile
Total:
weight = 75 kg
volume = 0.75 m3
Vehicle:
vehicle-1
maximum weight = 1000 kg
maximum volume = 12 m3
allowed regions = region-1, region-2, region-3
supported package types = standard, fragile
status = available
Driver:
driver-1
licenses = B, C
allowed vehicle type = truck
shift = 08:00 - 18:00
status = available
The system must determine whether:
shipment-1001
can be assigned to:
vehicle-1
driver-1
Warehouse Ownership
Before dispatch, every package must belong to a warehouse.
The shipment may only become:
ready_for_dispatch
when all of its packages are located at the correct dispatch warehouse.
If packages are split across multiple warehouses, the system must report that the shipment is not ready.
An optional extension may support package consolidation between warehouses.
Inventory Reservation
A warehouse should reserve packages for a shipment before packing.
A possible reservation model is:
type PackageReservation struct {
ID string
ShipmentID string
PackageID string
WarehouseID string
Status ReservationStatus
}
Possible states:
- reserved
- released
- consumed
A package must not be reserved for two active shipments at the same time.
Packing
When all shipment packages are reserved:
Shipment.Status = packed
after the packing operation succeeds.
The implementation should preserve package-to-shipment ownership.
Dispatch
When a valid delivery assignment becomes active:
Shipment.Status = dispatched
and then:
in_transit
The exact transition timing may be simplified, but transitions must remain valid.
Tracking Event
Every important shipment change must create a tracking event.
A possible model is:
type TrackingEvent struct {
ID string
ShipmentID string
Timestamp time.Time
Type TrackingEventType
LocationID string
Description string
}
Example timeline:
10:15 created
10:22 reserved
10:41 packed
11:05 ready_for_dispatch
11:20 dispatched
12:03 in_transit
14:42 out_for_delivery
15:18 delivered
Tracking history must not be reconstructed only from final shipment status.
It must be stored explicitly.
Delivery Attempt
Each delivery attempt contains:
- Attempt Number
- Timestamp
- Result
- Reason
For example:
type DeliveryAttempt struct {
ShipmentID string
AttemptNumber int
Timestamp time.Time
Result DeliveryAttemptResult
Reason string
}
Possible results:
- delivered
- failed
Possible failure reasons:
- customer_not_available
- invalid_address
- customer_refused
- vehicle_issue
- package_damaged
- other
Failed Delivery
When delivery fails:
Shipment.Status = delivery_failed
The shipment may then either:
be scheduled for another attempt
or:
enter return processing
Maximum Delivery Attempts
For the base task:
maximum delivery attempts = 3
After three failed attempts:
shipment must enter returning state
The implementation must not schedule a fourth normal delivery attempt.
Redelivery
If another attempt is allowed:
delivery_failed -> out_for_delivery
A new DeliveryAttempt must be created.
The previous failed attempts must remain in history.
Return Shipment
When a shipment can no longer be delivered, it must return to a warehouse.
A possible model is:
type ReturnShipment struct {
ID string
OriginalShipmentID string
TargetWarehouseID string
Reason string
Status ReturnStatus
}
Possible return states:
- created
- in_transit
- received
When the return reaches the warehouse:
Shipment.Status = returned
Lost Shipment
A shipment may become lost during transport.
For example:
in_transit -> lost
or:
out_for_delivery -> lost
A lost shipment is terminal for normal delivery processing.
It must not later transition directly to:
delivered
without an explicit recovery operation.
Damaged Package
A package may be marked damaged. A possible model:
type PackageIncident struct {
PackageID string
ShipmentID string
Type string
Description string
Timestamp time.Time
}
If a damaged package prevents delivery, the shipment should enter a failure or return path according to the implemented rules.
Driver Shift Validation
A delivery assignment must fit inside the driver’s shift. For example:
Driver shift ends at 18:00
Estimated route completion = 19:15
The assignment should be rejected.
The task does not require advanced travel-time prediction. A route may provide:
EstimatedDuration
for validation.
Route Duration
A route may contain:
type Route struct {
ID string
RegionID string
Stops []RouteStop
EstimatedDuration time.Duration
}
Driver shift validation may use this value.
Multiple Shipment Assignment
A vehicle may carry several shipments in one assignment. The system must validate the combined:
weight
volume
regions
package types
route compatibility
of all shipments.
Priority Processing
When several ready shipments exist and vehicle capacity is limited, process shipment priority in this order:
- critical
- express
- standard
Within the same priority:
earlier deadline first
Then:
Shipment ID ascending
This guarantees deterministic selection.
Warehouse Capacity
An optional but recommended model may track warehouse storage capacity. For example:
type WarehouseCapacity struct {
WarehouseID string
MaximumPackages int
CurrentPackages int
}
A return operation should not silently exceed warehouse capacity.
If this extension is implemented, overflow must be reported.
Cancellation
A shipment may be cancelled only before dispatch. Allowed:
created -> cancelled
reserved -> cancelled
packed -> cancelled
ready_for_dispatch -> cancelled
Not allowed:
in_transit -> cancelled
delivered -> cancelled
returned -> cancelled
When a reserved shipment is cancelled, package reservations must be released.
Idempotent Shipment Creation
Shipment creation requests should contain:
RequestID
Processing the same creation request twice must not create duplicate shipments.
A possible model:
type ShipmentCreateRequest struct {
RequestID string
Shipment Shipment
}
Idempotent Delivery Confirmation
Delivery confirmation should also be idempotent.
If the same delivery confirmation event is received twice:
stock/state/history must not be mutated twice
The second processing attempt should return the already known result.
Audit History
In addition to customer-facing tracking events, the system should maintain internal audit history.
Examples:
- shipment created
- package reserved
- shipment packed
- assignment created
- vehicle assigned
- driver assigned
- delivery attempt failed
- shipment marked lost
- return created
- return received
A possible model is:
type AuditEvent struct {
ID string
Timestamp time.Time
EntityType string
EntityID string
Action string
Details string
}
Tracking events and audit events are related but not identical.
Tracking is customer-visible shipment history. Audit history records internal system actions.
Query Operations
The system should support queries such as:
- get current shipment status
- get complete tracking history
- get all shipments for customer
- get all packages in warehouse
- get all shipments assigned to vehicle
- get current driver assignment
- get all failed delivery attempts
- get all active returns
Queries must not mutate shipment state.
Command Operations
State-changing operations include:
- create shipment
- reserve packages
- pack shipment
- create delivery assignment
- dispatch shipment
- record tracking event
- record delivery attempt
- confirm delivery
- schedule redelivery
- start return
- receive return
- cancel shipment
- mark shipment lost
Validation
The implementation should validate:
- unknown customer
- unknown address
- unknown region
- unknown warehouse
- unknown package
- unknown shipment
- unknown vehicle
- unknown driver
- unknown route
- duplicate IDs
- duplicate RequestID
- package already assigned
- package already reserved
- weight <= 0
- volume <= 0
- invalid deadline
- invalid shipment transition
- vehicle capacity exceeded
- vehicle region unsupported
- package type unsupported
- driver license invalid
- driver unavailable
- driver shift violation
- invalid delivery attempt number
Required Test Scenarios
Create tests for at least:
- successful shipment creation
- duplicate RequestID
- successful reservation
- double package reservation rejected
- successful packing
- vehicle weight capacity exceeded
- vehicle volume capacity exceeded
- unsupported region
- unsupported package type
- driver not eligible
- driver outside shift
- successful assignment
- successful dispatch
- successful delivery
- first failed delivery attempt
- redelivery after failure
- third failed attempt triggers return
- successful return
- shipment cancellation
- lost shipment
- invalid state transition
- duplicate delivery confirmation
- tracking-history ordering
- priority-based shipment selection
Modeling Goal
The goal of this task is to model a real stateful logistics process.
The important relationships are:
Customer
|
Shipment
|
+-- Packages
+-- Destination
+-- Tracking
+-- Delivery Attempts
|
v
Warehouse
|
v
Delivery Assignment
|
+-- Vehicle
+-- Driver
+-- Route
|
v
Delivery / Failure / Return
A useful architecture is:
Shipment Service
|
+-- Shipment Lifecycle
+-- Package Ownership
+-- Reservations
|
v
Warehouse Service
|
+-- Package Location
+-- Packing
+-- Returns
|
v
Dispatch Service
|
+-- Vehicle Selection
+-- Driver Validation
+-- Capacity Validation
+-- Route Assignment
|
v
Delivery Service
|
+-- Delivery Attempts
+-- Redelivery
+-- Return Processing
|
v
Tracking Service
|
+-- Tracking Events
+-- Customer History
|
v
Audit History
The main challenge is maintaining consistency between current shipment state, package location, delivery assignments, vehicle capacity, driver eligibility, tracking history, and return processing.