# 04 — Loading Event **Status**: Not Started **Depends On**: 03 — Ride Lifecycle --- ## Goal Move stock from a source warehouse onto an opened ride's vehicle, with two-party confirmation. Covers the dispatch half of [mainPlan.md §6](./mainPlan.md#6-warehouse-management): `generatePickList`, `confirmPicking`, `packOrder`, `buildDispatchLoad`, and `calculateLoadPlan` from §5. --- ## Background / Context This is the first place the [02_stock_ledger.md](./02_stock_ledger.md) movement model gets exercised end-to-end: a `Load` movement debits the warehouse and credits the vehicle location created when the ride opened ([03_ride_lifecycle.md](./03_ride_lifecycle.md)). --- ## Data Model Changes ### Loading Sheet Header record: `RideId`, `SourceWarehouseId`, `Status` (`Pending`, `DispatchConfirmed`, `ReceiptConfirmed`, `DiscrepancyFlagged`, `Resolved`). ### Loading Line Item `LoadingSheetId`, `ItemId`, `QuantityDispatched` (set by warehouse manager), `QuantityReceived` (set by driver) — a mismatch between the two is a discrepancy. ### Two-Party Confirmation Warehouse manager confirms what was dispatched (`generatePickList` → `confirmPicking` → `packOrder`); driver separately confirms what was received onto the vehicle. Both confirmations are required before the ride can move `Open → Active`. --- ## API Endpoints | Function reference | Endpoint intent | |---|---| | `generatePickList(orderIds[])` (§6) | `POST /api/loading-sheets` | | `confirmPicking(pickListId, pickedItems[])` (§6) | `POST /api/loading-sheets/{id}/confirm-dispatch` | | `packOrder(orderId, packageDetails)` (§6) | `POST /api/loading-sheets/{id}/pack` | | `buildDispatchLoad(vehicleId, orderIds[])` (§6) | Groups multiple orders into one loading sheet | | `calculateLoadPlan(vehicleId, orderIds[])` (§5) | Validates total volume/weight against vehicle capacity before dispatch confirmation | | — | `POST /api/loading-sheets/{id}/confirm-receipt` — driver-side confirmation | --- ## Business Rules - `QuantityDispatched != QuantityReceived` on any line flags the sheet `DiscrepancyFlagged` and blocks ride activation until resolved. - `calculateLoadPlan` must reject a load exceeding vehicle capacity before dispatch is confirmed, not after. --- ## Fraud / Control Considerations - Discrepancies must be immediately visible, not silently averaged into stock adjustments — see [09_fraud_controls.md](./09_fraud_controls.md). --- ## Open Questions - Does `Vehicle` need a `Capacity` field added now (volume/weight), or is `calculateLoadPlan` deferred until that's available? --- ## Implementation Notes > Fill this section in during planning discussion before writing any code.