udpates on the ui changesand api integration
This commit is contained in:
322
docs/BACKEND_API_REQUIREMENTS.md
Normal file
322
docs/BACKEND_API_REQUIREMENTS.md
Normal file
@@ -0,0 +1,322 @@
|
||||
# Backend API Requirements — Merchant Web Console
|
||||
|
||||
**Audience:** Backend team.
|
||||
**Purpose:** These are the endpoints the merchant web app needs before it can go to staging with
|
||||
zero mock data. Every UI spot listed below currently renders an explicit
|
||||
`Awaiting backend API [Rxx]` placeholder (or a known-wrong stand-in like the
|
||||
`delivered × 355` revenue) until the matching endpoint ships.
|
||||
|
||||
## Conventions (match the existing live API)
|
||||
- **Base / proxy:** Fiesta REST at `https://fiesta.nearle.app/live/api/v1/web/<group>/<action>`.
|
||||
The frontend calls it through the dev proxy as `/fiesta/live/api/v1/web/...`.
|
||||
- **Auth:** same as current read endpoints (no extra header required for GETs).
|
||||
- **Envelope:** every response is
|
||||
```json
|
||||
{ "code": 200, "status": true, "message": "OK", "details": <payload> }
|
||||
```
|
||||
`details` is the documented payload (array or object). On failure return
|
||||
`{ "code": 4xx, "status": false, "message": "<reason>" }`.
|
||||
- **Types:** money = INR as a plain 2-dp number (e.g. `442800.00`), no currency symbol/string.
|
||||
Dates = `YYYY-MM-DD`. Timestamps = ISO-8601 (`2026-06-06T14:21:00`). Ids = integers.
|
||||
- **Tenant scope (current):** `tenantid=1087`, `applocationid=1`, primary `locationid=1097`.
|
||||
- **Paging:** where listed, accept `pageno` (1-based) and `pagesize`.
|
||||
|
||||
## Index
|
||||
| Id | Endpoint | Method | Powers (UI) | Priority |
|
||||
|---|---|---|---|---|
|
||||
| [R1] | `/orders/getrevenuesummary` | GET | Revenue KPIs, OTIF, leaderboard, fulfilment health | **P0** |
|
||||
| [R2] | `/orders/gettimeseries` | GET | Reports main chart, 7-day ledger | **P0** |
|
||||
| [R3] | `/products/getproductanalytics` | GET | Product matrix sales + per-product detail | **P0** |
|
||||
| [R4] | `/imports/getimportlogs` (+ `/imports/upload`) | GET/POST | Import audit stream + validator | P1 |
|
||||
| [R5] | `/products/getcatalogpresets` | GET | Inventory catalog presets (optional) | P2 |
|
||||
| [R6] | `/tenants/getsettings` (+ `/tenants/updatesettings`) | GET/PUT | Settings + Brand studio | P1 |
|
||||
| [R7] | `/insights/getforecast` | GET | Operations forecast tiles (optional) | P2 |
|
||||
| [R8] | `/products/stocktransfer` | POST | Operations stock-transfer modal | P1 |
|
||||
| [R9] | `/partners/getridertelemetry` | GET | Fleet rating, GPS, ETA | P1 |
|
||||
| [R10] | `/deliveries/getdispatchbuckets` | GET | StoreDetail intraday dispatch | P1 |
|
||||
| [R11] | `/customers/getcustomeranalytics` | GET | Customer CSAT/AOV/retention | P1 |
|
||||
| [R12] | `/alerts/getalerts` | GET | Operational alerts feed | P1 |
|
||||
| [R13] | `/reports/getschedules` (+ POST) | GET/POST | Scheduled reports (optional) | P2 |
|
||||
|
||||
Plus **mutation routes** already named in the endpoint sheet but not yet shape-documented — see
|
||||
the last section.
|
||||
|
||||
---
|
||||
|
||||
## [R1] Revenue summary · `GET /orders/getrevenuesummary`
|
||||
Real money totals. Today the app fakes revenue as `delivered × 355` — replace that.
|
||||
|
||||
**Request (query params)**
|
||||
| param | type | required | notes |
|
||||
|---|---|---|---|
|
||||
| `tenantid` | int | ✓ | |
|
||||
| `locationid` | int | | omit → all outlets (overall); set → store-wise |
|
||||
| `fromdate` | date | ✓ | |
|
||||
| `todate` | date | ✓ | |
|
||||
|
||||
**Response `details`** (single object)
|
||||
```json
|
||||
{
|
||||
"tenantid": 1087,
|
||||
"locationid": null,
|
||||
"grossrevenue": 1248302.00,
|
||||
"netrevenue": 1180500.00,
|
||||
"profit": 354216.00,
|
||||
"marginpct": 28.4,
|
||||
"ordercount": 4921,
|
||||
"deliveredcount": 4102,
|
||||
"cancelledcount": 142,
|
||||
"otifpct": 98.2,
|
||||
"avgordervalue": 1580.00,
|
||||
"prev_grossrevenue": 1090000.00,
|
||||
"prev_ordercount": 4370
|
||||
}
|
||||
```
|
||||
`prev_*` = same metric for the immediately preceding equal-length window (lets the UI show
|
||||
`+14.2%` deltas without a second call). `otifpct` powers the OTIF / fulfilment-health tiles.
|
||||
Frontend hook to add: `useFiestaRevenueSummary`.
|
||||
|
||||
---
|
||||
|
||||
## [R2] Orders / revenue time-series · `GET /orders/gettimeseries`
|
||||
Powers the Reports main chart (Orders / Revenue / Cancelled / SKUs) and StoreDetail 7-day ledger.
|
||||
|
||||
**Request**
|
||||
| param | type | required | notes |
|
||||
|---|---|---|---|
|
||||
| `tenantid` | int | ✓ | |
|
||||
| `locationid` | int | | omit → overall |
|
||||
| `granularity` | enum | ✓ | `day` \| `month` \| `year` |
|
||||
| `fromdate` | date | ✓ | |
|
||||
| `todate` | date | ✓ | |
|
||||
|
||||
**Response `details`** (array, one bucket per period)
|
||||
```json
|
||||
[
|
||||
{ "label": "2026-06-01", "orders": 312, "revenue": 442800.00,
|
||||
"delivered": 298, "cancelled": 9, "activeskus": 72 }
|
||||
]
|
||||
```
|
||||
`label` = `YYYY-MM-DD` (day), `YYYY-MM` (month), or `YYYY` (year). Removes all hardcoded chart
|
||||
arrays and the region-scaling multipliers (filter by `locationid` instead).
|
||||
Frontend hook: `useFiestaTimeSeries`.
|
||||
|
||||
---
|
||||
|
||||
## [R3] Product sales analytics · `GET /products/getproductanalytics`
|
||||
True units-sold + revenue per product, plus the per-product/per-outlet detail the matrix expands.
|
||||
|
||||
**Request**
|
||||
| param | type | required | notes |
|
||||
|---|---|---|---|
|
||||
| `tenantid` | int | ✓ | |
|
||||
| `locationid` | int | | omit → across all outlets |
|
||||
| `subcategoryid` | int | | |
|
||||
| `fromdate` / `todate` | date | | sales window (default month-to-date) |
|
||||
| `keyword` | string | | |
|
||||
| `pageno` / `pagesize` | int | | |
|
||||
|
||||
**Response `details`** (array)
|
||||
```json
|
||||
[
|
||||
{ "productid": 88231, "productname": "Ponni Raw Rice 10kg",
|
||||
"sku": "PONNI-RICE-10K", "categoryid": 2, "subcategoryname": "Rice",
|
||||
"image": "https://…",
|
||||
"unitssold": 12402, "revenue": 868140.00, "trend": "up",
|
||||
"closingstock": 1402, "maxcapacity": 2000,
|
||||
"binlocation": "BIN-C12", "lastauditdate": "2026-06-05", "verified": true,
|
||||
"outlets": [ { "locationid": 1097, "locationname": "RS Puram", "stock": 840 } ] }
|
||||
]
|
||||
```
|
||||
`trend` ∈ `up|flat|down`. `outlets[]` = real per-hub split (replaces hardcoded 60/40).
|
||||
If the catalog doesn't track `binlocation`/`lastauditdate`, return `null` — the UI will hide them
|
||||
rather than fake them. Frontend hook: `useFiestaProductAnalytics`.
|
||||
|
||||
---
|
||||
|
||||
## [R4] Import / sync audit log · `GET /imports/getimportlogs` + `POST /imports/upload`
|
||||
Replaces the mock "Live Sync Audit Stream" and the hardcoded "14 duplicate SKUs" validator.
|
||||
|
||||
**GET request:** `tenantid` (✓), `pageno`, `pagesize`.
|
||||
**GET `details`**
|
||||
```json
|
||||
[
|
||||
{ "importid": 921, "batchref": "#IMP_0921_A", "type": "Inventory Sync",
|
||||
"source": "ERP Export", "rows": 421, "result": "SUCCESS",
|
||||
"message": "421 rows imported", "createdat": "2026-05-31T09:12:00" }
|
||||
]
|
||||
```
|
||||
`result` ∈ `SUCCESS|FAILED|PARTIAL`.
|
||||
|
||||
**POST `/imports/upload`** (multipart, field `file` = CSV; plus `tenantid`) → returns the new log row
|
||||
plus a validation block:
|
||||
```json
|
||||
{ "importid": 922, "result": "PARTIAL",
|
||||
"validation": { "passed": false, "duplicateskus": ["ST-SONA-25K"],
|
||||
"badcolumns": [45, 82], "headerversion": "v2.8" } }
|
||||
```
|
||||
Frontend hooks: `useFiestaImportLogs`, `useFiestaImportUpload` (mutation).
|
||||
|
||||
---
|
||||
|
||||
## [R5] Catalog presets *(optional)* · `GET /products/getcatalogpresets`
|
||||
Inventory "Nilgiris Dairy / Coimbatore Heritage" quick-add packs.
|
||||
**Request:** `tenantid` (✓). **`details`:**
|
||||
```json
|
||||
[ { "presetid": 3, "name": "Nilgiris Dairy Fresh Pack",
|
||||
"items": [ { "name": "Ooty Butter 500g", "sku": "DY-OOT-BTR",
|
||||
"subcategoryname": "Dairy", "price": 340, "image": "https://…" } ] } ]
|
||||
```
|
||||
> Alternative: skip this and reuse master catalog (`/products/getproducts`) filtered by subcategory.
|
||||
|
||||
---
|
||||
|
||||
## [R6] Merchant settings + branding · `GET /tenants/getsettings` + `PUT /tenants/updatesettings`
|
||||
Replaces the localStorage `DEFAULTS` and the Brand Design Studio local state.
|
||||
|
||||
**GET request:** `tenantid` (✓). **GET `details`:**
|
||||
```json
|
||||
{
|
||||
"tenantid": 1087,
|
||||
"contactemail": "ops@ragul.com", "contactphone": "+91…",
|
||||
"minordervalue": 199, "deliverycharge": 29, "prepmins": 20,
|
||||
"deliverywindowmins": 45, "cancelwindowsecs": 120, "autoassignrider": true,
|
||||
"defaulttaxpercent": 5, "codenabled": true, "onlinepaymentenabled": true,
|
||||
"defaultregion": "Coimbatore", "defaultnewuserrole": 4,
|
||||
"ordernotifications": true, "lowstockalerts": true, "dailysummaryemail": false,
|
||||
"syncinterval": 15, "sandboxmode": false,
|
||||
"branding": { "themename": "Kaveri Org", "primarycolor": "#16a34a",
|
||||
"secondarycolor": "#f59e0b", "baglabel": "Freshly Harvested",
|
||||
"ecoverified": true, "stickerpattern": "radial" }
|
||||
}
|
||||
```
|
||||
**PUT body:** same object (partial allowed) → returns the updated object.
|
||||
Frontend hooks: `useFiestaSettings`, `useFiestaUpdateSettings` (mutation).
|
||||
|
||||
---
|
||||
|
||||
## [R7] Forecast insight *(optional)* · `GET /insights/getforecast`
|
||||
Operations "Forecast Efficiency 92% / ₹1.9L savings". Recommend dropping the tiles until a model
|
||||
exists; if kept: **request** `tenantid` (✓), `locationid` (opt). **`details`:**
|
||||
```json
|
||||
{ "forecastefficiencypct": 92, "estsavingsperweek": 190000.00, "horizondays": 7 }
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## [R8] Stock transfer · `POST /products/stocktransfer`
|
||||
Operations transfer-stock modal.
|
||||
**Body:**
|
||||
```json
|
||||
{ "tenantid": 1087, "productid": 88231,
|
||||
"fromlocationid": 1097, "tolocationid": 1101, "quantity": 100 }
|
||||
```
|
||||
**`details`:** updated stock rows for both locations
|
||||
```json
|
||||
[ { "locationid": 1097, "productid": 88231, "closingstock": 740 },
|
||||
{ "locationid": 1101, "productid": 88231, "closingstock": 360 } ]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## [R9] Rider telemetry · `GET /partners/getridertelemetry`
|
||||
Replaces hardcoded rider `rating`, `battery`, `lastPing` and the fake GPS route / "9 MINS" / "1.2 km".
|
||||
|
||||
**Request:** `applocationid` (✓), `tenantid` (opt), `userid` (opt → single rider).
|
||||
**`details`** (array)
|
||||
```json
|
||||
[
|
||||
{ "userid": 7781, "name": "Karthikeyan R", "status": "Delivering",
|
||||
"rating": 4.7, "completedtoday": 12, "battery": 84,
|
||||
"lastping": "2026-06-06T14:21:00", "zone": "RS Puram",
|
||||
"lat": 11.0041, "lng": 76.9612,
|
||||
"activedelivery": { "deliveryid": 99213, "etamins": 9, "distancekm": 1.2,
|
||||
"destlat": 11.0102, "destlng": 76.9550 } }
|
||||
]
|
||||
```
|
||||
`status` ∈ `Delivering|Idle|Offline`. `activedelivery` = `null` when the rider is idle.
|
||||
Frontend hook: `useFiestaRiderTelemetry`.
|
||||
|
||||
---
|
||||
|
||||
## [R10] Intraday dispatch buckets · `GET /deliveries/getdispatchbuckets`
|
||||
Replaces StoreDetail `intervalSlots` (Morning Rush / Midday / Evening Peak computed from %).
|
||||
|
||||
**Request:** `tenantid` (✓), `locationid` (✓), `date` (✓, default today).
|
||||
**`details`** (array, fixed buckets)
|
||||
```json
|
||||
[ { "bucket": "06:00-10:00", "label": "Morning Rush",
|
||||
"orders": 64, "revenue": 88400.00, "status": "PEAK" } ]
|
||||
```
|
||||
`status` ∈ `PEAK|HIGH|NORMAL|LOW`. Frontend hook: `useFiestaDispatchBuckets`.
|
||||
|
||||
---
|
||||
|
||||
## [R11] Customer analytics · `GET /customers/getcustomeranalytics`
|
||||
Replaces hardcoded CSAT 5.0 / retention 88.4% / AOV ₹1,580.
|
||||
|
||||
**Request:** `tenantid` (✓), `locationid` (opt), `customerid` (opt → single-customer rollup).
|
||||
**`details`** (object)
|
||||
```json
|
||||
{
|
||||
"retentionpct": 88.4, "avgordervalue": 1580.00, "csat": 4.9,
|
||||
"totalcustomers": 1240,
|
||||
"percustomer": { "customerid": 55012, "orderscount": 18,
|
||||
"totalspent": 28450.00, "csat": 5.0, "lastorderdate": "2026-06-04" }
|
||||
}
|
||||
```
|
||||
`percustomer` present only when `customerid` is supplied.
|
||||
> Customer order **history** itself already exists: `GET /orders/getorders?customerid=` — wire that, no new API.
|
||||
Frontend hook: `useFiestaCustomerAnalytics`.
|
||||
|
||||
---
|
||||
|
||||
## [R12] Operational alerts · `GET /alerts/getalerts`
|
||||
Replaces the mock `operationalAlerts` (stock-critical, latency, rebalance…).
|
||||
|
||||
**Request:** `tenantid` (✓), `locationid` (opt), `status` (`open|all`), `pageno`, `pagesize`.
|
||||
**`details`** (array)
|
||||
```json
|
||||
[ { "alertid": 5012, "tenantid": 1087, "locationid": 1097,
|
||||
"type": "critical", "title": "Stock Critical: RS Puram",
|
||||
"details": "Dairy inventory below 5%.",
|
||||
"createdat": "2026-06-06T08:24:00", "acknowledged": false } ]
|
||||
```
|
||||
`type` ∈ `critical|warning|info`. Frontend hook: `useFiestaAlerts`.
|
||||
|
||||
---
|
||||
|
||||
## [R13] Scheduled reports *(optional)* · `GET /reports/getschedules` + `POST /reports/createschedule`
|
||||
Replaces 3 hardcoded calendar events. Drop if not on the roadmap.
|
||||
**GET `details`:**
|
||||
```json
|
||||
[ { "scheduleid": 11, "name": "Monthly Assortment Audit", "cron": "0 0 1 * *",
|
||||
"nextrun": "2026-07-01T00:00:00", "format": "PDF", "recipients": ["ops@ragul.com"] } ]
|
||||
```
|
||||
**POST body:** `{ tenantid, name, cron, format, recipients[] }` → returns the created schedule.
|
||||
|
||||
---
|
||||
|
||||
## Mutation routes already named in the endpoint sheet (publish request/response, then we wire)
|
||||
These are marked `REVIEW_REQUIRED` in `Fiesta_All_Endpoints_With_Tables_And_Params.xlsx`. We need
|
||||
the exact request body + success response for each:
|
||||
|
||||
| Action | Suggested endpoint | Body (fields we'll send) |
|
||||
|---|---|---|
|
||||
| Create web order | `POST /orders/create` | tenantid, locationid, customerid, items[{productid,qty,price}], paymenttype |
|
||||
| Update order status | `PUT /orders/updatestatus` | orderheaderid, status, financialflag |
|
||||
| Assign rider / dispatch | `POST /deliveries/assign` | orderheaderid, tenantid, locationid, partnerid, userid |
|
||||
| Update pickup / delivered | `PUT /deliveries/updatestatus` | deliveryid, status |
|
||||
| Add multi-product stock | `POST /products/addstock` | tenantid, locationid, items[{productid,qty,cost}] |
|
||||
| Create / update / delete product | `POST/PUT/DELETE /products/...` | product fields |
|
||||
| Onboard tenant / store / location | `POST /tenants/onboard`, `POST /tenants/createlocation` | tenant + location fields |
|
||||
|
||||
---
|
||||
|
||||
## Frontend status (for reference)
|
||||
- All read endpoints that **already exist** are wired (orders/deliveries/stock/customers/users/
|
||||
locations/order-line-items/etc.).
|
||||
- Each `[Rxx]` above corresponds to a visible `AwaitingApi` placeholder in the UI, so QA can see
|
||||
exactly which screens are still blocked.
|
||||
- The moment an endpoint here ships with the documented shape, wiring it is one hook + swapping the
|
||||
placeholder — no redesign needed.
|
||||
Reference in New Issue
Block a user