Revert "Refactor API modules to remove mock implementations and integrate real endpoints"

This reverts commit
This commit is contained in:
2026-07-15 10:27:38 +05:30
parent 0415794473
commit cb9fd7dfa8
27 changed files with 2811 additions and 416 deletions
+13 -34
View File
@@ -13,37 +13,25 @@ Convention: `docs/01-DOC-GUIDE.md §6`. Update this file in the **same commit**
> **Scope note:** this foundation was built alongside the GRN feature and only covers the endpoints GRN consumes (items, warehouses/bins, vendors, uoms, purchase-orders, grns). Other master-data/procurement API methods still need their own `lib/api/*.ts` files when those screens are built.
> **2026-07-14 — mock data removed, `lib/api/mock-data.ts` deleted.** Every `lib/api/*.ts` file's commented-out real `fetch` block was restored and the in-memory mock block deleted, per user request. Master Data + Procurement modules (`categories`, `uoms`, `warehouses`, `items`, `vendors`, `requisitions`, `rfqs`, `purchase-orders`) now call the live backend (`Backend/ERPCore` §1/§2, both implemented + smoke-tested). GRN/Stock/Purchase-Return/Reason-Code modules (`grns`, `stock`, `stock-transfers`, `stock-adjustments`, `stock-counts`, `purchase-returns`, `reason-codes`, `wastage`) also now call real (documented-or-assumed) endpoint paths, but **no backend controller exists for any of them yet** (`Backend/PROGRESS.md` §3/§4/§5 are unstarted, and Purchase Return is explicitly deferred) — those calls will 404 against a running backend until that work happens. This was a deliberate tradeoff the user confirmed explicitly (see the two `AskUserQuestion` exchanges this session) rather than silently faking data.
## 1. Auth
- [~] Login screen — UI built (`app/login`); not yet wired to `POST /auth/login` / token storage
- [~] Forgot password — add email screen — UI built (`app/login/forgot`); not yet wired to API
- [~] Forgot password — verify OTP screen — UI built (`app/login/forgot/otp`); not yet wired to API
- [~] Forgot password — change password screen — UI built (`app/login/forgot/reset`); not yet wired to API
> **2026-07-14:** left untouched during the mock-data removal pass — there was never a mock `lib/api/auth.ts` to begin with (these screens simply don't call anything yet), and `Backend/PROGRESS.md` §6 confirms no `POST /auth/login` controller exists (`ICurrentUser`/JWT validation are wired, but there's no token issuer). Nothing to wire until that lands.
## 2. Master Data screens
- [x] Items (`app/dashboard/products` list + filters, `/new` create, `/[id]` full edit + ETag/If-Match with 412-conflict handling + activate/deactivate) — FR-MD-01/08. Reused the pre-existing "Products" sidebar entry/stub route rather than adding a new nav item. **2026-07-14: wired to the live backend** (`lib/api/items.ts`), no more mock data.
- [x] UOM + conversions (`app/dashboard/products/uoms` flat list + create dialog; conversions edited inline on the Item detail page via `PUT /items/{itemId}/uom-conversions`) — FR-MD-02/03. **2026-07-14: wired to the live backend.** Note: the real `ItemDetailDto` does not include a `conversions` field (only `Reorder`) — the Item detail page's conversion editor now round-trips purely through `PUT /items/{itemId}/uom-conversions`'s own request/response, not the GET response.
- [x] Categories (`app/dashboard/products/categories` indented tree view + create dialog with parent picker) — FR-MD-04. **2026-07-14: wired to the live backend.**
- [x] Vendors (`app/dashboard/vendors` list + search/status-filter + create dialog, `[id]` full edit + ETag/If-Match with 412-conflict handling + activate/deactivate) — FR-MD-06. First screen this session to exercise the ETag/`If-Match`/412 pattern end-to-end (`lib/api-client.ts`'s `ApiResult<T>` was built earlier but unused until now). **2026-07-14: wired to the live backend.**
- [x] Warehouses + Bins (`app/dashboard/warehouse` list + create-warehouse dialog, `[id]` bin list + create-bin dialog) — FR-WH-01/FR-MD-07. **2026-07-14: wired to the live backend**; added `warehousesApi.get()` (the page needed it but the original stub never had it) and wrapped the real `GET /warehouses/{id}/bins` (`IReadOnlyList<BinDto>`, not paged) into a synthetic single-page `PagedResponse<Bin>` so existing `.items`-based call sites didn't need touching.
- [x] Item reorder settings — edited inline on the Item detail page (per-warehouse point/qty rows) via `PUT /items/{itemId}/reorder` — FR-MD-05. **2026-07-14: wired to the live backend.**
- [~] Items (`app/dashboard/products` list + filters, `/new` create, `/[id]` full edit + ETag/If-Match with 412-conflict handling + activate/deactivate) — FR-MD-01/08. Reused the pre-existing "Products" sidebar entry/stub route rather than adding a new nav item.
- [~] UOM + conversions (`app/dashboard/products/uoms` flat list + create dialog; conversions edited inline on the Item detail page via `PUT /items/{itemId}/uom-conversions`) — FR-MD-02/03
- [~] Categories (`app/dashboard/products/categories` indented tree view + create dialog with parent picker) — FR-MD-04
- [~] Vendors (`app/dashboard/vendors` list + search/status-filter + create dialog, `[id]` full edit + ETag/If-Match with 412-conflict handling + activate/deactivate) — FR-MD-06. First screen this session to exercise the ETag/`If-Match`/412 pattern end-to-end (`lib/api-client.ts`'s `ApiResult<T>` was built earlier but unused until now).
- [~] Warehouses + Bins (`app/dashboard/warehouse` list + create-warehouse dialog, `[id]` bin list + create-bin dialog) — FR-WH-01/FR-MD-07. Frontend-only (see note below); no ETag handling since there's no edit/delete yet, only create.
- [~] Item reorder settings — edited inline on the Item detail page (per-warehouse point/qty rows) via `PUT /items/{itemId}/reorder` — FR-MD-05
## 3. Procurement screens
- [x] Requisition (`app/dashboard/procurement/requisitions` list, `/new` create, `/[id]` detail + Submit) — FR-PROC-01. **2026-07-14: wired to the live backend**; dropped `RequisitionSummary.lineCount` (the real `RequisitionSummaryDto` doesn't return it) from the list screen.
- [x] RFQ + quotations + comparison view (`.../rfqs` list, `/new` create with vendor multi-invite, `/[id]` detail: lines, comparison matrix, record-quotation form, "Create PO from vendor") — FR-PROC-02. **2026-07-14: wired to the live backend**, with real contract mismatches found and fixed (see the dedicated deviation note below — this one needed real rework, not just an API-client swap).
- [x] Purchase Order (`.../purchase-orders` list, `/new` create — auto-approved, prefillable from a Requisition or an RFQ+vendor quotation via query params — `/[id]` detail: edit-while-open with ETag/If-Match, Cancel with reason) — FR-PROC-03..07. **2026-07-14: wired to the live backend.**
- [~] Purchase Return (`.../purchase-returns` list, `/new` create against a Confirmed/Closed GRN's lines) — FR-PROC-08; also reachable from a `Rejected` GRN line via a "Create Return" button on the GRN detail page. **Still `[~]`:** the API client now calls real endpoint paths, but `Backend/PROGRESS.md` §2 explicitly defers Purchase Return until GRN + Stock Core exist — these calls 404 against a live backend today.
> **2026-07-14 — RFQ real-backend contract mismatches found while removing mock data (`Backend/ERPCore/Dtos/Procurement/RfqDtos.cs` / `RfqService.cs` vs. the frontend's speculative types):**
> - The backend does **not** persist which vendors were invited to an RFQ (`RfqService.MapRfq` never sets a vendor list) — `Rfq`/`RfqSummary` no longer carry `vendorIds`. `types/procurement.ts` and the `[id]`/list pages were updated to stop relying on it; the RFQ detail page now shows "Quoted: ..." (derived from `RfqComparison.vendorIds`, i.e. vendors who have actually submitted a quotation) instead of "Invited: ...".
> - `CreateRfqRequest.RequisitionId` is `[Required]` server-side, not optional as the frontend assumed — `app/dashboard/procurement/rfqs/new/page.tsx` now requires picking a Submitted requisition (a picker was added for the case where one wasn't passed in via `?requisitionId=`) before an RFQ can be created.
> - `RfqComparisonDto`'s real shape is `{ rfqId, vendorIds, rows: [{ itemId, qty, quotes: [{ vendorId, quotationId, unitPrice, leadDays }] }] }` — the frontend's assumed `{ lines: [{ cells }] }` naming was wrong; `types/procurement.ts` (`RfqComparisonRow`/`RfqComparisonCell`) and both consuming pages (RFQ detail, PO-from-RFQ prefill) were corrected to match.
> - The "Record a quotation" vendor picker on the RFQ detail page now offers any active vendor who hasn't already quoted (matching what `AddQuotationAsync` actually validates — vendor exists + hasn't already quoted, not "was invited") rather than a now-nonexistent "pending invited vendors" list.
> - `GET /rfqs` (list) still does not exist on `RfqsController` (only `GET /rfqs/{id}`) — `rfqsApi.list()` calls it anyway per the user's "remove all mock data" instruction, so the RFQ list screen 404s until that endpoint is added. Flagged here for whoever picks up `Backend/PROGRESS.md` §2.
> - Also fixed while cross-checking DTOs: `ReqLine.requiredBy` is nullable (`DateOnly?` server-side, not a mandatory string), and `RequisitionSummary` never had a `lineCount` field (removed from the requisitions list column and the RFQ picker label).
- [~] Requisition (`app/dashboard/procurement/requisitions` list, `/new` create, `/[id]` detail + Submit) — FR-PROC-01
- [~] RFQ + quotations + comparison view (`.../rfqs` list, `/new` create with vendor multi-invite, `/[id]` detail: lines, comparison matrix, record-quotation form, "Create PO from vendor") — FR-PROC-02
- [~] Purchase Order (`.../purchase-orders` list, `/new` create — auto-approved, prefillable from a Requisition or an RFQ+vendor quotation via query params — `/[id]` detail: edit-while-open with ETag/If-Match, Cancel with reason) — FR-PROC-03..07
- [~] Purchase Return (`.../purchase-returns` list, `/new` create against a Confirmed/Closed GRN's lines) — FR-PROC-08; also reachable from a `Rejected` GRN line via a "Create Return" button on the GRN detail page
## 4. Receiving screens
- [~] GRN list (`app/dashboard/receiving/grn/page.tsx`) — loading/empty/error states, links to detail
@@ -54,7 +42,7 @@ Convention: `docs/01-DOC-GUIDE.md §6`. Update this file in the **same commit**
> **`[~]` not `[x]`, by design:** these screens are built against the documented+planned contract in `docs/11-BACKEND-PHASE1.md` §4, but **no GRN backend exists yet** (this was frontend-only work; see the deviation below).
>
> **2026-07-14 — mock data removed:** `lib/api/grns.ts` now calls real endpoint paths (`apiRequest`/`apiRequestWithETag` against `/grns`) instead of an in-memory store. There is still no `GrnsController` on the backend (`Backend/PROGRESS.md` §3 unstarted), so every call here 404s against a running backend — this was a deliberate, user-confirmed tradeoff (see `AskUserQuestion` exchange this session), not an oversight. Also added `grnsApi.getWithETag()` (the assumed `GET /grns/{id}` didn't have an ETag-returning variant, but `app/dashboard/receiving/grn/[id]/edit/page.tsx`'s `update()` call needs an `If-Match` token to send — matching the same pattern `purchase-orders.ts` already uses for `get`/`getWithETag`).
> **UI-only / mock-data mode (temporary):** `lib/api/{grns,purchase-orders,warehouses,items,vendors,uoms}.ts` currently return **in-memory sample data** (`lib/api/mock-data.ts`) instead of calling the real API, so the three screens are fully browsable/demoable (list → create against a mocked PO or as a direct receipt → detail → confirm → release/reject) without a running backend. Each `lib/api/*.ts` file keeps the real `fetch`-based implementation **commented out directly above** the mock block — switch back by deleting the mock block, uncommenting the real block, and deleting `lib/api/mock-data.ts` once the GRN backend exists. `npm run dev` + `tsc --noEmit` + `eslint` are clean (aside from the pre-existing, unrelated `app/login/page.tsx` resolver-typing error and the two `react-hooks/set-state-in-effect` warnings shared with `hooks/use-mobile.ts`).
>
> **Deviation — `GET /grns` and `GET /grns/{id}`:** the API doc only specifies `POST /grns`, `POST /grns/{id}/confirm`, `POST /grns/{id}/lines/{id}/release` (no list/detail read). A list screen and a confirm/release screen both need to reload a GRN, so `lib/api/grns.ts` (`grnsApi.list`/`grnsApi.get`) and `types/grn.ts` assume these two GET endpoints will exist once the backend is built — flag this to whoever implements `Backend/PROGRESS.md` §3 so `docs/11-BACKEND-PHASE1.md` gets the corresponding doc update.
@@ -70,11 +58,9 @@ Convention: `docs/01-DOC-GUIDE.md §6`. Update this file in the **same commit**
- [~] Wastage (`.../stock/wastage` report, `/new` record) — **not a documented endpoint or SRS document type**: damage/theft-loss/expiry write-offs are modeled as Stock Adjustments with a loss-type reason code (FR-STK-07); `lib/api/wastage.ts` is a frontend-only lens over `stockAdjustmentsApi` + the shared mock ledger (filters to reason codes `DMG`/`LOSS`/`EXPWO`, flattens adjustment lines to per-item wastage records, sums matching outbound ledger entries for cost). No new backend concept — confirmed with the user before building (asked whether "Wastage" meant this vs. a distinct document type).
- Sidebar: added "Stock" nav entry (`components/Layouts/AppSidebar.tsx`) → `/dashboard/stock`; top-bar titles mapped per route (`components/Layouts/Header.tsx`)
> **`[~]` not `[x]`, by design — same posture as §4 Receiving:** built frontend-only (user request), against the documented+assumed Stock Core contract (`docs/11-BACKEND-PHASE1.md` §5), with **no real backend**.
> **`[~]` not `[x]`, by design — same posture as §4 Receiving:** built frontend-only (user request), against the documented+assumed Stock Core contract (`docs/11-BACKEND-PHASE1.md` §5), with **no real backend**. Unlike Receiving, though, this pass wired a genuine in-memory Stock Core (`lib/api/mock-data.ts`: `mockStockLayers`, `mockStockLedger`, `receiveLayer`/`consumeFifo`/`postLedgerEntry`/`computeOnHand`) that GRN confirm now posts through too (previously GRN confirm fabricated a throwaway response; it now creates real layers/ledger entries and accrues PO `qtyReceived`/status) — so Enquiry/Ledger/Valuation reflect what actually happened in the session, and FIFO consumption (transfers, adjustment decreases, count variance decreases) genuinely throws a `STOCK_NEGATIVE_BLOCKED`-style error when stock is insufficient. `tsc --noEmit` and `eslint` are clean across all new/changed files (only the pre-existing `login/page.tsx` error and the established `set-state-in-effect` warnings remain, same as §4).
>
> **2026-07-14 — mock data removed:** the in-memory Stock Core (`mockStockLayers`/`mockStockLedger`/`receiveLayer`/`consumeFifo`/etc., previously in `lib/api/mock-data.ts`) is gone. `stock.ts`/`stock-transfers.ts`/`stock-adjustments.ts`/`stock-counts.ts`/`reason-codes.ts` now call real endpoint paths; `stockApi.onHandList()` was rewritten to compose real (`itemsApi.list` × `warehousesApi.list` × `stockApi.onHand` per pair) calls instead of iterating a mock-derived key set. `wastage.ts` was rewritten the same way — it now calls `reasonCodesApi.list()`/`stockAdjustmentsApi.list()+get()`/`stockApi.ledger()` instead of reading mock arrays directly, so `wastageReasonCodeIds()` and `wastageApi.list()` are now `async` (both call sites in `app/dashboard/stock/wastage/{page,new/page}.tsx` were updated accordingly). **None of §5's backend exists yet** (`Backend/PROGRESS.md` §4/§5 unstarted), so every one of these calls 404s against a running backend — a deliberate, user-confirmed tradeoff (see `AskUserQuestion` exchange this session), not an oversight. `tsc --noEmit` and `eslint` are clean (only the pre-existing `login/page.tsx` error and the established `set-state-in-effect` pattern remain, unchanged from before this pass).
>
> **Deviations (same pattern as GRN, see §4):** `GET`/detail list endpoints for transfers/adjustments/counts (`lib/api/stock-transfers.ts`, `stock-adjustments.ts`, `stock-counts.ts`) are assumed extensions beyond `docs/11-BACKEND-PHASE1.md` §5.4-5.6, which document only the transactional POSTs/PUT. `stockApi.onHandList()` (used by the Enquiry screen) is also not a documented endpoint — it's a frontend-only convenience; a real backend would want a proper list endpoint instead. Flag all of these to whoever implements `Backend/PROGRESS.md` §4/§5 (Stock Core + stock transactions).
> **Deviations (same pattern as GRN, see §4):** `GET`/detail list endpoints for transfers/adjustments/counts (`lib/api/stock-transfers.ts`, `stock-adjustments.ts`, `stock-counts.ts`) are assumed extensions beyond `docs/11-BACKEND-PHASE1.md` §5.4-5.6, which document only the transactional POSTs/PUT. `stockApi.onHandList()` (used by the Enquiry screen) is also not a documented endpoint — it's a frontend-only convenience that iterates known item/warehouse pairs and calls the (documented) on-hand computation per pair; a real backend would want a proper list endpoint instead. Flag all of these to whoever implements `Backend/PROGRESS.md` §4/§5 (Stock Core + stock transactions).
>
> **Simplifications (mock-data limitations, not spec decisions):** `StockLayer` has no per-bin field (matches the real ER model, docs/10 Part C.5 — only `StockLedger` carries `bin_id`), so Count lines don't attempt bin-level snapshotting. Transfers don't expose batch selection in the create UI (FIFO picks layers regardless of batch). Adjustment increases always cost at "last known cost" for that item/warehouse (FR-STK-07); there's no landed-cost/manual-cost override. In-transit quantity is shown for visibility at the destination warehouse only and is not subtracted a second time from the source's `available` (dispatch already reduced the source layer's `qtyRemaining`) — the docs' `available = onHand onHold reserved inTransit(out)` formula is ambiguous on this point given dispatch semantics; this was a judgment call, noted here for whoever builds the real backend to confirm or correct.
@@ -142,10 +128,3 @@ Convention: `docs/01-DOC-GUIDE.md §6`. Update this file in the **same commit**
- **Housekeeping:** removed `app/dashboard/vendors/view vendors/` — confirmed byte-for-byte identical to `vendors/[id]/page.tsx` and untracked in git, same IDE-artifact pattern (malformed file-open path) as the garbled GRN duplicate folders removed in the Warehouse Management pass; noted here rather than silently dropped. Left `app/dashboard/receiving/grn/[id]/edit/` alone — it's untracked too but is a distinct, non-duplicate GRN-edit screen, not an artifact.
- Same `[~]` posture as every other module this session: built against the documented+assumed Master Data contract (`docs/11-BACKEND-PHASE1.md` §2), no Master Data backend exists (`Backend/PROGRESS.md` §1 unchanged).
- Verified: `tsc --noEmit` clean after clearing a stale `.next` type cache that still referenced the just-deleted `view vendors` route (same pre-existing `login/page.tsx` error only remains); `eslint` clean aside from the same established `set-state-in-effect` pattern; `npm run build` compiles successfully via Turbopack (same pre-existing login type-check failure, unrelated). All 5 new/changed routes confirmed rendering 200 with no error boundary against the dev server (one false-alarm 500 during testing traced to an unrelated stale process already bound to port 3000, not this code — retested clean on the actual dev server port).
### 2026-07-14 — Mock data removed everywhere; Master Data + Procurement wired to the live backend
- User asked to integrate the (now-built) backend into the frontend, frontend-only, no mock data. Confirmed scope first: the backend only has controllers for Master Data (`Backend/PROGRESS.md` §1) and Procurement minus returns (§2) — GRN (§3), Stock Core (§4), Stock Transactions (§5), and Auth (§6) have no controllers at all yet. User's explicit instruction after that was still "remove mock data in all" — so every `lib/api/*.ts` module was switched to real `fetch` calls, accepting that GRN/Stock/Purchase-Return/Reason-Code calls will 404 against a live backend until that work exists (not silently left mocked).
- **Deleted `lib/api/mock-data.ts` entirely** and restored the real-`fetch` implementation in every one of: `categories`, `uoms`, `warehouses` (added missing `get()`; wrapped the real non-paged `GET /warehouses/{id}/bins` array response into a synthetic `PagedResponse<Bin>` so existing `.items` call sites kept working), `items`, `vendors`, `requisitions`, `purchase-orders`, `purchase-returns`, `reason-codes`, `grns` (added `getWithETag()` for the GRN edit page's `If-Match`), `stock`, `stock-transfers`, `stock-adjustments`, `stock-counts`. `wastage.ts` had no prior real-mode block (it's a frontend-only lens with no documented endpoint of its own) — rewrote it to compose the now-real `reasonCodesApi`/`stockAdjustmentsApi`/`stockApi` calls instead of reading mock arrays directly; its two exports became `async` as a result, and both call sites (`app/dashboard/stock/wastage/{page,new/page}.tsx`) were updated.
- **Did not blindly trust the frontend's pre-written "real implementation" comments** — cross-checked every Master Data/Procurement DTO against the actual `Backend/ERPCore/Dtos/**/*.cs` and controllers before wiring, since those blocks were written speculatively before/alongside the real backend and had drifted in the RFQ case (see the dedicated §3 deviation note above): the backend doesn't persist RFQ-invited vendors, `requisitionId` is required (not optional) to create an RFQ, `RfqComparisonDto` uses `rows`/`quotes`/`quotationId` (not `lines`/`cells`), and `RequisitionSummaryDto` has no `lineCount`. Fixed `types/procurement.ts` and the RFQ list/detail/new pages plus the PO-from-RFQ prefill accordingly, rather than shipping types that would silently be `undefined` at runtime.
- Left `app/login/*` untouched — no mock auth existed to remove, and there's still no `POST /auth/login` controller to wire to.
- Verified: `tsc --noEmit` clean (only the pre-existing, unrelated `login/page.tsx` resolver-typing error remains — confirmed pre-existing via `git` history, not introduced here). `eslint` shows the same established `react-hooks/set-state-in-effect`/`static-components` pattern as before, confirmed unchanged by spot-checking it also fires on files untouched this session (`app/login/forgot/reset/page.tsx`). Did not start the backend/Postgres or click through the UI live in this pass — verification was type-check + lint only; the Master Data/Procurement screens should be smoke-tested against a running `dotnet run` + Postgres before considering this "done" in practice.