update son the admincontroller acoording datas and update the md file as well
This commit is contained in:
@@ -2116,8 +2116,26 @@ func GetAdminBookings(c *fiber.Ctx) error {
|
|||||||
return utils.Internal(c, "failed to count bookings")
|
return utils.Internal(c, "failed to count bookings")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Newest first, and deterministically so.
|
||||||
|
//
|
||||||
|
// Without an ORDER BY the row order is unspecified — Postgres returns heap
|
||||||
|
// order, which in practice is oldest first. Two things follow, and both bit:
|
||||||
|
//
|
||||||
|
// 1. The newest booking sits on the LAST page. The console drains a
|
||||||
|
// bounded window, so once pickupbookings outgrows that window a
|
||||||
|
// just-created customer-app booking can never reach the Orders page at
|
||||||
|
// all. It is written correctly and is simply never fetched.
|
||||||
|
// 2. OFFSET pagination over an unordered result is not stable: the same
|
||||||
|
// page can return different rows across two requests, so draining pages
|
||||||
|
// can duplicate and skip rows well before that threshold.
|
||||||
|
//
|
||||||
|
// bookingid rather than createdat: it is the primary key and unique, so the
|
||||||
|
// sort needs no tiebreaker and the paging cannot wobble between equal
|
||||||
|
// timestamps. It also matches the order the console already sorts into
|
||||||
|
// client-side, so page 1 is the newest page by both definitions.
|
||||||
var bookings []models.PickupBooking
|
var bookings []models.PickupBooking
|
||||||
if err := query.Preload("Parcels").Preload("ServiceOptions").
|
if err := query.Preload("Parcels").Preload("ServiceOptions").
|
||||||
|
Order("bookingid DESC").
|
||||||
Offset(offset).Limit(pagesize).Find(&bookings).Error; err != nil {
|
Offset(offset).Limit(pagesize).Find(&bookings).Error; err != nil {
|
||||||
return utils.Internal(c, "failed to fetch bookings")
|
return utils.Internal(c, "failed to fetch bookings")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -251,10 +251,25 @@ delivered, riderkms, ridercharges, dutyminutes }`.
|
|||||||
|
|
||||||
| Method | Path | Notes |
|
| Method | Path | Notes |
|
||||||
|---|---|---|
|
|---|---|---|
|
||||||
| GET | `/admin/bookings` | tenant-scoped list |
|
| GET | `/admin/bookings` | tenant-scoped list, **newest first** (`bookingid DESC`) |
|
||||||
| POST | `/admin/expressbooking` | create one — passes CityGate |
|
| POST | `/admin/expressbooking` | create one — passes CityGate |
|
||||||
| POST | `/admin/expressbooking/bulk` | `{ "bookings": [ ... ] }`, max 200, per-row results |
|
| POST | `/admin/expressbooking/bulk` | `{ "bookings": [ ... ] }`, max 200, per-row results |
|
||||||
| GET | `/admin/bookings/:id` | 404 if outside your tenant |
|
| GET | `/admin/bookings/:id` | 404 if outside your tenant |
|
||||||
|
|
||||||
|
`GET /admin/bookings` is ordered `bookingid DESC` — page 1 is always the newest
|
||||||
|
page. The order is guaranteed, not incidental: `bookingid` is the primary key
|
||||||
|
and unique, so `OFFSET` paging over it is stable and two requests for the same
|
||||||
|
page return the same rows. Before this was explicit the result order was
|
||||||
|
unspecified (Postgres heap order, in practice oldest first), which put the
|
||||||
|
newest booking on the LAST page — a client draining a bounded number of pages
|
||||||
|
could never reach a just-created booking.
|
||||||
|
|
||||||
|
It also accepts `?status=` as an EXACT, case-sensitive, single-value match
|
||||||
|
against the stored enum. The stored values are capitalised
|
||||||
|
(`Pending_Pickup`, `Converted_To_Consignment`); `?status=pending_pickup`
|
||||||
|
matches nothing and returns an empty list rather than an error. There is no
|
||||||
|
multi-status or date filter, so a client grouping several statuses into one tab
|
||||||
|
still has to filter its own rows.
|
||||||
| GET | `/admin/bookings/:id/track` | **the tracking screen** — see below |
|
| GET | `/admin/bookings/:id/track` | **the tracking screen** — see below |
|
||||||
| POST | `/admin/bookings/:id/assign-miler` | |
|
| POST | `/admin/bookings/:id/assign-miler` | |
|
||||||
| POST | `/admin/bookings/:id/assign-vehicle` | |
|
| POST | `/admin/bookings/:id/assign-vehicle` | |
|
||||||
@@ -393,7 +408,12 @@ rather than making the console reconcile two stores.
|
|||||||
- **Envelope**: `{ "success": true, "data": ... }` on success,
|
- **Envelope**: `{ "success": true, "data": ... }` on success,
|
||||||
`{ "success": false, "message": "..." }` on failure. Lists add `total`,
|
`{ "success": false, "message": "..." }` on failure. Lists add `total`,
|
||||||
paginated lists add `page`.
|
paginated lists add `page`.
|
||||||
- **Pagination**: `?pageno=1&pagesize=100`. Default 500, cap 1000.
|
- **Pagination**: `?pageno=1&pagesize=100`. Default 20, cap 100. Both numbers
|
||||||
|
are enforced server-side (`min(100, max(1, pagesize))`); a request for a
|
||||||
|
larger page silently receives 100 rows and the response's own `pagesize`
|
||||||
|
field reports 100. This entry previously read "default 500, cap 1000", which
|
||||||
|
was wrong on both counts — clients sizing a page budget off it fetched a
|
||||||
|
twelfth of what they expected.
|
||||||
- **Rate limits**: 300/min per IP globally, 10/min shared across all credential
|
- **Rate limits**: 300/min per IP globally, 10/min shared across all credential
|
||||||
endpoints. Behind the ingress this keys on the proxy IP unless
|
endpoints. Behind the ingress this keys on the proxy IP unless
|
||||||
`TRUSTED_PROXIES` is set.
|
`TRUSTED_PROXIES` is set.
|
||||||
|
|||||||
Reference in New Issue
Block a user