miler map
This commit is contained in:
@@ -719,6 +719,77 @@ class MilerApi {
|
||||
),
|
||||
);
|
||||
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
// THE HANDOVER — the rider gives a hub-routed parcel to a base
|
||||
// ═══════════════════════════════════════════════════════════════════════
|
||||
|
||||
/// Hands a `Created` consignment in at a base, ending this rider's part.
|
||||
///
|
||||
/// ── The leg that had no route ──
|
||||
///
|
||||
/// A parcel bound for another district is collected at a customer's door and
|
||||
/// carried to a base; the network takes it from there. The rider could do the
|
||||
/// first half and had no way to record the second, so an intercity parcel sat
|
||||
/// in his queue until somebody inwarded it in the console — and every one of
|
||||
/// those jobs reported zero distance and zero value on `/miler/earnings`,
|
||||
/// because the assignment was never closed against him.
|
||||
///
|
||||
/// ── The body is optional, all of it ──
|
||||
///
|
||||
/// Sent with nothing, the parcel is handed into the base it was already
|
||||
/// routed to. [hubId] is worth sending when the app has one — it is what the
|
||||
/// server reconciles against — and the coordinates are stamped onto the
|
||||
/// history row as evidence of where the hand-over happened.
|
||||
///
|
||||
/// ── Idempotent twice over ──
|
||||
///
|
||||
/// The shared `Idempotency-Key` middleware covers a retry after a dropped
|
||||
/// response, and a parcel already inwarded answers **200 with
|
||||
/// `already_inwarded: true`** rather than a 4xx — so a rider on bad signal at
|
||||
/// a loading bay who presses again is confirmed, not refused. Read the result
|
||||
/// through [MilerLifecycle.inwardAtHub], which treats that reply as the
|
||||
/// success it is.
|
||||
///
|
||||
/// Refusals carry their own reason: `CONSIGNMENT_NOT_FOUND`,
|
||||
/// `CONSIGNMENT_NOT_ASSIGNED`, `HUB_REQUIRED`, `HUB_NOT_FOUND`,
|
||||
/// `INVALID_STATE` for a parcel already past this leg.
|
||||
static Future<ApiResult> inwardAtHub(
|
||||
Object consignmentId, {
|
||||
Object? hubId,
|
||||
double? lat,
|
||||
double? lon,
|
||||
}) => _guarded(
|
||||
'inward-at-hub:$consignmentId',
|
||||
() => _send(
|
||||
'POST',
|
||||
'/miler/consignments/$consignmentId/inward-at-hub',
|
||||
idempotencyKey: _idempotencyKey('inward-at-hub', consignmentId),
|
||||
body: {
|
||||
if (hubId != null) 'hub_id': hubId,
|
||||
if (lat != null) 'latitude': lat,
|
||||
if (lon != null) 'longitude': lon,
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
/// The bases this rider may hand a parcel in at.
|
||||
///
|
||||
/// ── Why this is not the tenant locations route ──
|
||||
///
|
||||
/// `GET /admin/tenants/:id/locations` is a **different dataset** — a client's
|
||||
/// own sites, not bases — and `/admin/*` requires roles 1/3/4 while a rider is
|
||||
/// role 5. The 401 this app has been logging as a gap on that route was by
|
||||
/// design, not an oversight. This is the rider-readable one.
|
||||
///
|
||||
/// Returns `{id, name, address, pincode, latitude, longitude}` per base, plus
|
||||
/// `distance_km` and nearest-first ordering once the rider has reported a
|
||||
/// position.
|
||||
static Future<ApiResult> bases({String status = 'Active'}) => _send(
|
||||
'GET',
|
||||
'/miler/bases',
|
||||
query: {if (status.isNotEmpty) 'status': status},
|
||||
);
|
||||
|
||||
/// The consignment's current state and what may be done to it.
|
||||
///
|
||||
/// Returns `status` plus the backend's own derived flags — `collected`,
|
||||
|
||||
Reference in New Issue
Block a user