Files
ERP_Distribution/Distribution/docs/05_delivery_ride.md
T
Kalana B. Thilakarathna 6d8b6b3e59 Add DeliveryTask, Payment, and Sale features
Implemented DeliveryTask, Payment, and Sale entities with full CRUD, business logic, and API endpoints. Updated Order/OrderItem for sale linkage and fulfillment tracking. Registered new DbSets and DI services. Revised documentation for delivery, sale, and payment workflows.
2026-08-24 21:34:57 +05:30

5.3 KiB

05 — Delivery Ride Execution

Status: Planning Depends On: 04 — Loading Event


Goal

Fulfill pending orders against an active Delivery ride. The driver visits each store on the route, delivers the ordered items, gets customer confirmation, and the system creates the stock movement, updates the order, and completes the sale.


Background / Context

  • A Delivery ride goes Active after the loading event is confirmed.
  • Orders are linked to a ride implicitly through route: Ride → Route → Stores → Pending Orders.
  • QuantityFulfilled on OrderItem tracks what was actually delivered (added in pre-planning).
  • No separate backorder entity — partially fulfilled orders stay PartiallyFulfilled and get picked up by the next delivery ride on the same route.
  • Customer confirmation in v1 is a boolean flag (CustomerConfirmed). Full signature/OTP deferred to Step 09 (Fraud Controls).

Data Model Changes

New Entity — DeliveryTask

Extends Template (adds IsActive, CreatedAt — consistent with all other entities).

Column Type Notes
Id Guid PK (from Template)
FK_RideId Guid FK → DeliveryRun
FK_OrderId Guid FK → Order
Sequence int Visit order on the route
Status DeliveryTaskStatus State machine below
CustomerConfirmed bool Set to true at confirm time
ConfirmedAt DateTime? Timestamp of customer confirmation
Note string? Driver note on failure or partial delivery
IsActive bool From Template (soft delete)
CreatedAt DateTime From Template

New Enum — DeliveryTaskStatus

public enum DeliveryTaskStatus
{
    Pending,
    Delivered,
    PartiallyDelivered,
    Failed
}

No new columns on OrderItem

QuantityFulfilled already added in pre-planning. No further model changes needed.


State Machine

Pending → Delivered          (all lines fully delivered + customer confirmed)
Pending → PartiallyDelivered (some lines short + customer confirmed)
Pending → Failed             (driver could not deliver, no stock movement)

Stock Movements

Created on Delivered or PartiallyDelivered after customer confirmation. One movement per item:

  • Debit vehicle: -QuantityFulfilled at LocationType.Vehicle, FK_LocationId = VehicleId
  • VehicleId is resolved from DeliveryTask.FK_RideId → DeliveryRun.FK_VehicleId
  • MovementType.Sale
  • ReferenceId = OrderId

No movement on Failed.


Order and Sale Status Transitions (triggered internally)

Condition Order Sale
All OrderItem lines: QuantityFulfilled == Quantity → Fulfilled → Completed
Any OrderItem line: QuantityFulfilled < Quantity → PartiallyFulfilled stays Pending
Task Failed stays Pending stays Pending

API Endpoints

Base routes: /api/rides/{rideId}/tasks and /api/delivery-tasks

Method Route Who Description
POST /api/rides/{rideId}/tasks/generate Driver/System Auto-create tasks from all Pending/PartiallyFulfilled orders for stores on ride's route
GET /api/rides/{rideId}/tasks Driver List all tasks for this ride with current status
GET /api/delivery-tasks/{id} Driver Task detail with order items and quantities
PUT /api/delivery-tasks/{id}/quantities Driver Set QuantityFulfilled per order item before confirming
POST /api/delivery-tasks/{id}/confirm Driver Customer confirmed — creates stock movements, transitions order/sale
POST /api/delivery-tasks/{id}/fail Driver Mark task as failed with a note

Business Rules

  1. Delivery tasks can only be created for a ride in Active status and of type Delivery.
  2. One task per order per ride — cannot create a second task for the same order on the same ride.
  3. QuantityFulfilled must be set on all order items before calling confirm.
  4. QuantityFulfilled cannot exceed Quantity on any line.
  5. CustomerConfirmed must be true before the task can move to Delivered or PartiallyDelivered.
  6. Stock movement is created only once — at confirm. Never on fail.
  7. A failed task does not change the order or sale status — the order stays available for the next ride.
  8. Partial delivery: the unfulfilled quantity (Quantity - QuantityFulfilled) remains on the same order. The next delivery ride on the same route will pick it up automatically via generate.

Implementation Build Order

  1. Enum — add DeliveryTaskStatus to Models/Enums.cs
  2. Entity — DeliveryTask in Models/
  3. AppDBContext — new DbSet + Fluent config (Restrict on Ride, Order FKs)
  4. Migration
  5. DTOs — DeliveryTaskDTOs.cs in Features/DeliveryRide/
  6. Repository — IDeliveryTaskRepository, DeliveryTaskRepository
  7. Service — DeliveryTaskService
  8. Controller — DeliveryTaskController
  9. DI registration in Program.cs

Feature folder: Features/DeliveryRide/


Open Questions — Resolved

  • ✅ Customer confirmation — boolean flag in v1, full signature/OTP in Step 09
  • ✅ Backorder — no separate entity; same order stays PartiallyFulfilled for next ride
  • ✅ Task generation — on-demand via generate endpoint, not automatic on ride activation
  • ✅ Failed task — order stays Pending, available for next ride, no stock movement