Files
ERP_Distribution/Distribution/docs/03_ride_lifecycle.md
T
2026-08-21 02:08:11 +05:30

9.4 KiB

03 — Ride Lifecycle

Status: Done Depends On: 02 — Stock Ledger


Goal

Turn the currently-unused DeliveryRun model into a fully working ride — a session that turns a vehicle into a temporary warehouse. Covers driver profile management, ride creation, state transitions, cancellation workflow, and the vehicle breakdown scenario.


Data Model Changes

New Entity — DriverProfile

Linked one-to-one with User. Holds compliance data only — no login or auth fields.

Column Type Notes
Id Guid PK
FK_UserId Guid FK → User (unique)
LicenseNumber string
LicenseExpiry DateTime
MedicalClearanceExpiry DateTime
IsActive bool Can be suspended without deleting
CreatedAt DateTime

No license class tied to vehicle type — not required.

Compliance check rule: Driver is compliant if IsActive = true, plus any checks that are enabled in DriverComplianceConfig. By default all checks are disabled. When enabled: LicenseExpiry > today AND/OR MedicalClearanceExpiry > today.


Updated Entity — Vehicle

Add one nullable field:

Column Type Notes
FK_DefaultWarehouseId Guid? If set, ride always loads from this warehouse. If null, warehouse is selected at ride creation.

Updated Entity — DeliveryRun (becomes Ride)

Add the following fields to the existing DeliveryRun:

Column Type Notes
RideType RideType Delivery or Sale
Status RideStatus State machine below
FK_DriverProfileId Guid FK → DriverProfile
FK_SourceWarehouseId Guid Where stock is loaded from. Must be the same warehouse stock returns to on cancel/close.
StartedAt DateTime? Set when Draft → Open
ActivatedAt DateTime? Set when Open → Active
ClosedAt DateTime? Set when Active → Closed

New Enum — RideType

public enum RideType { Delivery, Sale }

New Enum — RideStatus

public enum RideStatus { Draft, Open, Active, CancelRequested, Cancelled, Closed }

New Entity — RideCancelRequest

Column Type Notes
Id Guid PK
FK_RideId Guid FK → DeliveryRun
TypeCode CancelRequestType Reason category
Reason string Free text explanation
RequestedBy Guid UserId
RequestedAt DateTime
Status CancelRequestStatus Pending, Approved, Rejected
ApprovedBy Guid? UserId of approver
ApprovedAt DateTime?

New Enum — CancelRequestType

public enum CancelRequestType
{
    VehicleBreakdown,
    DriverUnavailable,
    RouteIssue,
    Other
}

New Entity — DriverComplianceConfig

Single-row configuration table. Controls which compliance checks are enforced at ride open time.

Column Type Notes
Id Guid PK
EnforceLicenseExpiry bool Default false. If true, ride open is blocked if driver license is expired.
EnforceMedicalClearance bool Default false. If true, ride open is blocked if medical clearance is expired.
UpdatedAt DateTime
UpdatedBy Guid UserId of last person who changed the config.

Managed via a dedicated config endpoint. Only one row ever exists.


New Enum — CancelRequestStatus

public enum CancelRequestStatus { Pending, Approved, Rejected }

State Machine

Draft → Open → Active → Closed
                      ↘ CancelRequested → Cancelled
Transition Trigger What it does
Draft → Open POST /api/rides/{id}/open Validates driver compliance. Checks vehicle has no other Open/Active ride. Sets StartedAt.
Open → Active POST /api/rides/{id}/activate Called by loading event confirmation (Step 04). Sets ActivatedAt.
Active → Closed POST /api/rides/{id}/close Called after ride reconciliation (Step 07). All stock must be returned to source warehouse. Sets ClosedAt.
Active → CancelRequested POST /api/rides/{id}/cancel-request Driver submits cancel request with type code and reason. Ride status changes to CancelRequested.
CancelRequested → Cancelled POST /api/rides/cancel-requests/{id}/approve Supervisor approves. Ride status changes to Cancelled. All stock must return to source warehouse before cancel completes.
CancelRequested → Active POST /api/rides/cancel-requests/{id}/reject Supervisor rejects. Ride returns to Active.

Order assignment window: Orders can be assigned to a Delivery ride from Draft until the ride transitions to Open. No new orders after Open.


Warehouse Configuration

Per vehicle. A vehicle either has FK_DefaultWarehouseId set (always loads from that warehouse) or it is null (warehouse is selected manually at ride creation time).

Loading and unloading warehouse are always the same — stock must return to its source warehouse before a ride can close or cancel.


Vehicle Breakdown Scenario

  1. Driver submits cancel request with TypeCode = VehicleBreakdown.
  2. Ride status moves to CancelRequested.
  3. Supervisor views a breakdown assist endpoint that lists all currently Active rides with their current vehicle stock levels and the stranded ride's open orders — supervisor decides manually which ride takes over which orders.
  4. Supervisor approves the cancel request.
  5. Ride moves to Cancelled once all stock is confirmed returned to source warehouse.

The system surfaces the information — it does not automatically reassign orders.


API Endpoints

Base route: /api/rides

Method Route Description
POST / Create ride (Draft). If vehicle has default warehouse, pre-populate it.
GET / List rides (paginated). Filter by status, type, driverProfileId, vehicleId.
GET /{id} Get ride detail
PUT /{id}/driver Assign or change driver profile
POST /{id}/open Transition Draft → Open
POST /{id}/activate Transition Open → Active (called by loading event)
POST /{id}/close Transition Active → Closed (called by reconciliation)
POST /{id}/cancel-request Submit cancel request (Active rides only)
GET /cancel-requests List cancel requests (paginated). Filter by status.
POST /cancel-requests/{id}/approve Approve cancel request
POST /cancel-requests/{id}/reject Reject cancel request
GET /breakdown-assist/{rideId} Lists active rides with stock + stranded ride's open orders

DriverComplianceConfig

Base route: /api/driver-compliance-config

Method Route Description
GET / Get current config
PUT / Update config flags

DriverProfile

Base route: /api/driver-profiles

Method Route Description
POST / Create driver profile (links to a User)
GET / List driver profiles (paginated)
GET /{id} Get driver profile detail
PUT /{id} Update compliance fields
DELETE /{id} Soft deactivate

Business Rules

  1. A ride cannot transition Draft → Open if IsActive = false on the driver profile. If EnforceLicenseExpiry = true, also blocks if license is expired. If EnforceMedicalClearance = true, also blocks if medical clearance is expired.
  2. A vehicle cannot be on more than one Open or Active ride at a time.
  3. Orders can only be assigned to a Delivery ride while it is in Draft status.
  4. Loading and unloading warehouse must be the same — enforced at close/cancel.
  5. A CancelRequested ride cannot close or activate until the request is resolved.
  6. All cancel requests must have a TypeCode — free text reason alone is not sufficient.
  7. All list endpoints return paginated responses.

Open Questions

  1. Cancel request type codes — ✅ Resolved. VehicleBreakdown, DriverUnavailable, RouteIssue, Other.
  2. Breakdown assist endpoint — ✅ Resolved. System shows info only, supervisor decides manually. No auto-reassignment.
  3. Driver compliance — ✅ Resolved. Checks are configurable via DriverComplianceConfig. IsActive is always enforced. License and medical checks are optional flags, default off.

Implementation Notes

Build order:

  1. ✅ Enums — RideType, RideStatus, CancelRequestType, CancelRequestStatus → added to Models/Enums.cs
  2. ✅ Entities — DriverProfile, DriverComplianceConfig, RideCancelRequest (new); updated Vehicle (+FK_DefaultWarehouseId), updated DeliveryRun (+RideType, Status, FK_DriverProfileId, FK_SourceWarehouseId, StartedAt, ActivatedAt, ClosedAt)
  3. ✅ AppDBContext — new DbSets + Fluent config
  4. ✅ Migrations — RideLifecycle (schema), RidePermissions (10 new permissions seeded across all roles)
  5. ✅ DTOs — DriverProfileDTOs.cs, DriverComplianceConfigDTOs.cs, RideDTOs.cs
  6. ✅ Repositories — IDriverProfileRepository, IDriverComplianceConfigRepository, IRideRepository, IRideCancelRequestRepository
  7. ✅ Services — DriverProfileService, DriverComplianceConfigService, RideService
  8. ✅ Controllers — DriverProfileController, DriverComplianceConfigController, RideController
  9. ✅ DI registration in Program.cs

Feature folders: Features/Ride/, Features/DriverProfile/, Features/DriverComplianceConfig/

Pending: dotnet ef database update to apply migrations to DB. Tests for the three new services.