Skip to main content

View Mode

View Mode is the read-only window a user gets onto the stores below their own in the supply-chain hierarchy (parentStoreId — see Data Model). A district user can look at their facilities, a province user their whole province, a Central Warehouse user anything. It is not a separate service — it's a target-org-unit parameter on endpoints that would otherwise run against the caller's own store.

Two backends, one rule

Reports go through the generic report engine. POST /generic-report-profiles/{id}/execute takes an optional organizationUnitId; resolveReportOrgTarget() (generic-report-org-target.ts) resolves it:

  • omitted, or equal to your own org → runs against your own org, unchanged;
  • another org unit → allowed only when orgUnitIsAtOrBelow(target, caller) is true, else 403.

That one function is the whole authorisation story for report View Mode. ?format=csv and ?format=pdf honour the same parameter, so a View Mode export carries the target store's name, not the caller's.

Order / issuing / stock browsing goes through ReadController (/read/*). Every method there is:

  • @RequirePermissions(Permission.VIEW_REPORTS);
  • guarded by ReportStoreScopeGuard, which rejects a store query param that isn't the caller's own org or one below it (same at-or-below check, 403).
EndpointBacks
GET /read/viewStoreUnderUnitthe "Viewing as" store selector — every org unit below store
GET /read/viewStoreStock, GET /read/viewStoreStockByProductthe View Mode Overview stock cards
GET /read/ViewCurrentSocks, GET /read/getMyInventorythe View Mode Inventory screen
GET /read/ViewRequesition, ViewDistribution, ViewReturn, ViewDispensingthe View Mode order / issuing browsing lists

The four viewStore* / snapshot endpoints take ViewStoreSnapshotDto (store + optional productId, no date range — they return current on-hand stock). The four order-history ones take ViewDateRangeDto.

Why there are no write endpoints

There is no "act as another store" API, by design. Every mutating order / issuing / return method checks X.Organization.id === user.organization.id and throws otherwise (see Order Lifecycle). The frontend's View Mode screens are correspondingly stripped of every submit / approve / acknowledge / add control — earlier versions rendered them, but they only ever produced a 400. To act on a store's behalf you need an account at that store.

History

ReadController used to also carry 8 report-only endpoints (ViewArrivalReport, ViewIssueReport, ViewWastageReports, …). They were removed once every View Mode report page moved onto the generic engine — the engine's organizationUnitId does the same job for any report profile, seeded or custom. If you find a reference to /read/View*Report anywhere, it's stale.