# 03 — Ride Lifecycle **Status**: Not Started **Depends On**: 02 — Stock Ledger --- ## Goal Turn the currently-unused `DeliveryRun` model into a working ride: a session that turns a vehicle into a temporary warehouse. Covers `assignVehicleToRoute`, `assignDriverToVehicle`, `checkDriverCompliance` from [mainPlan.md §5](./mainPlan.md#5-vehicle--fleet-management) and `planDeliveryRoute` from §3. --- ## Background / Context `Models/DeliveryRun.cs` exists (`FK_VehicleId`, `FK_RouteId`, `Meterstart`, `Meterend`) but has no repository, service, or controller — it is completely unwired today, per [mainPlan.md](./mainPlan.md)'s "Known Gaps" table. `FK_DriverId`/`Driver` navigation is commented out because no `Driver` entity exists yet (gap #10 in [00_existing_gaps.md](./00_existing_gaps.md)) — this step is blocked on that being resolved first if driver assignment is required at ride-open time. --- ## Data Model Changes ### Ride (extending DeliveryRun) Add a `Status` field to `DeliveryRun` for the state machine below, and a `RideType` field (`Delivery` | `Sale`). ### Ride State Machine `Draft → Open → Active → Closed`. A vehicle can only be on one `Open`/`Active` ride at a time — enforced in the service layer, not the database. ### Ride Type (Delivery vs Sale) `Delivery` rides fulfill pre-confirmed orders (see [05_delivery_ride.md](./05_delivery_ride.md)); `Sale` rides create invoices on the spot with no pre-orders (see [06_sale_ride.md](./06_sale_ride.md)). Both share the same ride lifecycle and loading event. --- ## API Endpoints | Function reference | Endpoint intent | |---|---| | `assignVehicleToRoute(vehicleId, routeId)` (§5) | Implicit in `POST /api/rides` — a ride binds a vehicle to a route for its duration | | `assignDriverToVehicle(vehicleId, driverId)` (§5) | `PUT /api/rides/{id}/driver` — blocked on Driver entity, see gap #10 | | `checkDriverCompliance(driverId)` (§5) | Called internally before a ride can move `Draft → Open` | | `planDeliveryRoute(warehouseId, orderIds[])` (§3) | `POST /api/rides` (for `RideType = Delivery`) | | — | `POST /api/rides/{id}/open`, `POST /api/rides/{id}/close` — state transitions | --- ## Business Rules - A ride cannot open without a compliant driver (once Driver entity exists) and a vehicle not already on an open ride. - Opening a ride creates the vehicle's stock ledger location (see [02_stock_ledger.md](./02_stock_ledger.md)). --- ## Fraud / Control Considerations - `checkDriverCompliance` failures must block ride open, not just warn. --- ## Open Questions - Is a `Driver` a new entity distinct from `User`, or is "driver" just a `User` with a specific `Role`? Affects whether gap #10 needs a new table or just a role addition. --- ## Implementation Notes > Fill this section in during planning discussion before writing any code.