feat: miler delivery-leg fixes — consignmentid, auto route sequencing, admin consignment status

Miler app P0 + contract gaps found in the live audit:

- GET /miler/bookings now returns consignmentid + consignmentstatus on every
  row (nullable), so the app can call deliver/skip/start-delivery straight from
  the list. /miler/assignments is the active-only queue, so this is the
  authoritative fix for stops that have moved onto the delivery leg.
- GET /miler/bookings now returns sequencedat per row: non-null means the
  console/optimizer fixed this stop's order and the app follows step exactly;
  null means no route assigned and the app may fall back to nearest-first.
- Route sequencing (internal/routing) now runs automatically after every
  assignment — customer auto-assign, express auto-assign, manual assign, and
  accept — via SequenceMilerStopsAsync (fire-and-forget, no-op below two active
  stops). Previously only hub batch-assign sequenced, so most riders saw step=0.
- GET /admin/bookings now surfaces the live consignmentstatus alongside the
  frozen booking status, so a Converted_To_Consignment booking can still show
  Out_for_Delivery / Delivered instead of a generic "Active".

Two-step hyperlocal flow (Arrived_At_Pickup, Collected_By_Miler, start-delivery)
stays gated behind MILER_COLLECTED_STATE_ENABLED (default off) until the app
ships; consignmentid/status, GET /miler/consignments/:id, stable error codes and
Idempotency-Key handling are unconditional and safe on the current app.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WRaFH5hMRqmUQvVPQsyjZD
This commit is contained in:
Suriyakumarvijayanayagam
2026-08-24 10:34:12 +05:30
parent 531185cf66
commit f6d339a33f
14 changed files with 541 additions and 34 deletions

View File

@@ -33,6 +33,7 @@ const (
BookingCreated = "Created"
BookingMilerAssigned = "Miler_Assigned"
BookingPickupScheduled = "Pickup_Scheduled"
BookingArrivedAtPickup = "Arrived_At_Pickup" // miler is at the pickup point, parcel not yet collected
BookingPickedUp = "Picked_Up"
BookingConvertedConsignment = "Converted_To_Consignment"
BookingCancelled = "Cancelled"
@@ -40,8 +41,15 @@ const (
// Consignment Statuses
const (
ConsignmentCreated = "Created"
ConsignmentInwardedAtHub = "Inwarded_at_Hub"
ConsignmentCreated = "Created"
ConsignmentInwardedAtHub = "Inwarded_at_Hub"
// ConsignmentCollectedByMiler is the intermediate state for a hyperlocal
// parcel: the miler has collected it but has NOT yet started the final-mile
// run. It sits between pickup and Out_for_Delivery so the console can tell
// "collected, waiting to leave" apart from "actively delivering" — before
// this existed a hyperlocal pickup jumped straight to Out_for_Delivery and
// looked active the instant it was collected. StartDelivery moves it on.
ConsignmentCollectedByMiler = "Collected_By_Miler"
ConsignmentTripsheetLoaded = "Tripsheet_Loaded"
ConsignmentInTransit = "In_Transit"
ConsignmentOutForDelivery = "Out_for_Delivery"
@@ -52,6 +60,23 @@ const (
ConsignmentDamaged = "Damaged"
)
// Machine-readable error codes returned to the miler app in the "code" field of
// 4xx responses, so the client can branch on a stable identifier instead of
// parsing human-readable messages. Add here, never inline.
const (
ErrInvalidInput = "INVALID_INPUT"
ErrBookingNotFound = "BOOKING_NOT_FOUND"
ErrBookingNotAssigned = "BOOKING_NOT_ASSIGNED"
ErrConsignmentNotFound = "CONSIGNMENT_NOT_FOUND"
ErrConsignmentNotAssigned = "CONSIGNMENT_NOT_ASSIGNED"
ErrInvalidState = "INVALID_STATE" // action not allowed from the entity's current status
ErrAlreadyPickedUp = "ALREADY_PICKED_UP" // pre-pickup action attempted after pickup
ErrOtpRequired = "OTP_REQUIRED"
ErrOtpInvalid = "OTP_INVALID"
ErrIdempotencyInProgress = "IDEMPOTENCY_IN_PROGRESS" // an identical keyed request is still running
ErrEmailInUse = "EMAIL_IN_USE"
)
// Payment Modes
const (
PaymentModeCash = "Cash"