Commit Graph

10 Commits

Author SHA1 Message Date
ee79c80338 updates 2026-09-22 15:27:13 +05:30
ba2cd2299c fix: close price-tamper, premature rider-free, and IST/txn gaps in merged cx/handover work
Reviewed the 10 merged customer-app/base-handover commits and fixed the
defects found:

- HIGH (money): CreateCxBooking let the request body's `estimate` set the
  billed price with no server-side check; it flows into Estimatedprice →
  ridercharges (miler pay + tenant bill) with no weight re-price, so
  {min:1,max:1} settled a delivery at ₹1. Now the client estimate is honoured
  only when it matches the server quote within 15%, else the server quote
  stands.
- MED: base handover freed the rider and closed the booking-level assignment
  after the FIRST parcel of a multi-destination pickup, dropping the remaining
  stops and crediting one leg. Now finalized only when no consignment of the
  booking is still in the rider's hands.
- MED: inwardedat/completedat were written with time.Now() (UTC) instead of
  DBNow() (IST), skewing them ~5h30 vs createdat and the earnings/reconcile
  windows. Fixed in the handover, inbound-scan, reconcile and pickup-complete
  paths.
- MED: B2C customers got two "miler assigned" pushes on auto-assign (two token
  stores) and none on manual assign. Reconciled to one cxstage.Notify on both
  paths.
- LOW: ReconcileHubInbound now runs in a transaction and checks its audit
  inserts (was returning 200 with a silently-missing history row); CxLogout no
  longer reports signedOut when the token revoke fails; a rider-named handover
  base far from their reported position is rejected instead of silently
  rerouting the parcel to another city.

go build, go vet and go test ./... all pass.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01WRaFH5hMRqmUQvVPQsyjZD
2026-09-16 12:16:50 +05:30
1b2690b21a backend requirements onthe xustomer app 2026-09-07 10:55:11 +05:30
Suriyakumarvijayanayagam
f6d339a33f 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
2026-08-24 10:34:12 +05:30
Suriya
2158031191 fix: assignment retries no longer die with the pod
AssignCustomerMiler and AssignCRMMiler retried five times, two minutes
apart, using time.Sleep inside a bare goroutine — about ten minutes of
state held only in one pod's memory. Any restart dropped every retry in
flight, and nothing recorded it: the booking just stayed unassigned
forever with no failure event, because publishAssignmentFailed only runs
at the end of a loop that no longer existed. Deploying during a quiet
patch was enough to lose bookings this way, and it happened during
today's rollout.

Retries now run on the ASSIGNMENTS stream. Each entry point publishes
one booking.assignment_requested message; a durable consumer performs a
single attempt per delivery and NAKs with retryDelay when no miler is
available, so JetStream owns both the waiting and the delivery count.
A pod dying mid-wait costs nothing — the message is still on the server
and another replica takes it.

Behaviour is deliberately unchanged from the caller's side: same five
attempts, same two-minute spacing, same publishAssignmentFailed handoff
to the DispatchAgent. The failure event is fired explicitly on the last
delivery, since JetStream stops redelivering at MaxDeliver and would
otherwise let the booking fail silently again.

runInline keeps the old loop as a fallback for when JetStream is down.
Assignment is how a booking reaches a rider, so it must not become
dependent on the event bus: an outage should cost durability, which is
what we had before, not stop bookings being assigned at all.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-08-10 16:29:32 +05:30
c272a33fa6 feat: 14 new endpoints closing jupiter->Doormile API gaps, plus two tenant-scoping bug fixes
New endpoints:
- Admin: partner CRUD (GET/POST /admin/partners, GET/PUT/DELETE
  /admin/partners/:id), bulk express booking create
  (POST /admin/expressbooking/bulk), bulk cancel
  (POST /admin/bookings/bulk-cancel), reports (GET /admin/reports),
  password change (PUT /admin/profile/password), miler notify
  (POST /admin/milers/:id/notify)
- Miler: PIN reset (POST /miler/reset-pin), cancel assignment
  (POST /miler/bookings/:bookingid/cancel), skip delivery
  (POST /miler/consignments/:id/skip)
- Hub: batch assign (POST /hub/bookings/batch-assign) - greedy
  nearest-rider queue clearing, capped per rider

Bug fixes:
- BookingPickupComplete now sets Consignment.Tenantid from the
  booking's tenant instead of the completing miler's own tenant
  (fixes cross-tenant shipment mis-attribution)
- GetHubUnassignedBookings/GetHubBookingsRange now scoped via
  scopeBookingsToOwnTenant (fixes partner hub staff seeing other
  tenants' bookings)

Also: CRM booking routes renamed to expressbooking to end the naming
collision with the separate CRM clients feature; PickupBooking gains
nullable Tenantid; adds CLAUDE.md project memory.

Verified: go build ./... and go vet ./... both clean.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2026-08-05 12:22:39 +05:30
Suriya
77a723e047 internal modifications 2026-08-04 20:44:42 +05:30
707323b68c feat: hub console backend — complete API surface 2026-07-04 16:14:12 +05:30
c8adaf7815 hub apis 2026-07-04 11:10:52 +05:30
c91c887726 Add assignment engine, FCM, WebSockets, city gate, and internal APIs
- internal/assignment: GEORADIUS miler assignment with retry/escalation,
  customer-side provider scoring, FCM notifications on assign
- internal/notify: Firebase Admin SDK (FCM) client initialisation
- internal/ws: WebSocket handlers for live parcel tracking and
  customer↔miler chat
- middlewares: city gate (pincode prefix validation), internal API key
  auth, WebSocket JWT auth
- controllers: InternalNotify + InternalReassign for machine-to-machine
  calls; pricing helpers wired into CreateCustomerBooking and CreateCRMBooking
- routes: /internal/*, /ws/bookings/:id/track, /ws/bookings/:id/chat
- models/users, models/doormile_pricing: new fields for device tokens,
  assignment state, pricing bands
- seed_data.sql: initial pricing seed rows

.env and Firebase service-account JSON intentionally excluded.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-06-25 12:31:53 +05:30