[T09] Stock Activity
Summary
Tenant-scope list of all operational_batch rows + per-batch drill-down. The destination for every Round A routerLink="['/inventory/stock-activity', batchId]" dead-end:
For STOCK_TAKE batches the drill-down renders the four report categories the 2026-02 stock-take design (operationalised via US #777) requires: In-stock (member + scanned), Missing (member + NOT scanned + flipped via STOCK_TAKE_MISSED), Outsider (scanned but not a member), Unmatched (NOT_FOUND).
T09 v1 ships with a graceful fallback for the body of the report categories — the per-batch state-log endpoint (GET /api/operational-batches/:id/state-log) is not yet exposed on develop. Until it lands the screen renders the header card + close action fully (so the dead-end links resolve) and surfaces an info banner explaining the missing endpoint in the body. See Backend follow-ups below.
|
Actor & Context
Actor: tenant admin, stock operator, finance / audit reviewer.
Frequency: ad-hoc during incident review; weekly during event seasons.
Precondition: user has TENANT_ADMIN permission; sidebar tenant scope active (see C01 § sidebar).
Entry point: Tenant-admin sidebar Inventory ▸ Stock activity, OR a deep-link from T02 / T03 / T04.
Layout
T09 renders inside C01’s shell — sidebar (tenant scope) + topbar are C01’s. T09 owns the main content area.
List screen — /inventory/stock-activity
| Region | Content |
|---|---|
Header |
Title "Operational batches" + record count. |
Filter strip |
Active filter chips (per the JHipster Tanstack substrate). Per-column popovers expose facets where the back-end criteria carries a matching filter — id (range), name (specified), type (specified), status (specified), opened-on (date range), closed-on (date range). |
Table |
Columns: |
Empty state |
"No batches match these filters" + a Clear-filters affordance when any filter is active. |
Detail screen — /inventory/stock-activity/:batchId
| Region | Content |
|---|---|
Back link |
|
Header card |
Batch eyebrow (id + type label) · name · description · status badge · full-mode badge (STOCK_TAKE only) · grid of opened-on / opened-by / closed-on / closed-by / event (when scoped) / attached-row count · (STOCK_TAKE + fullMode) missing count. |
Close action |
When |
Body — non-STOCK_TAKE |
Single chronological list of attached state-log entries. Each row: bib link (out to T02 with the per-number audit panel auto-opened via |
Body — STOCK_TAKE |
Four-tab strip — In-stock / Missing / Outsider / Unmatched. Each tab shows a count badge + inline explanation of the category + the matching list of state-log entries. |
Main Flow
-
Operator navigates to
Inventory ▸ Stock activity(or follows a deep-link from T02 / T03 / T04). -
List renders sorted by
openedOn DESC. Operator filters by type / status / date as needed. -
Operator clicks a row → detail screen.
-
Detail header card renders immediately from
GET /api/operational-batches/{id}. -
Body renders the categorised drill-down from
GET /api/operational-batches/{id}/state-log(pending — see Backend follow-ups). -
(Optional) Operator closes an OPEN batch via the Close-batch button — mode chosen by batch shape; success refreshes the header card with the closed-state DTO.
Alternative Flows
-
AF-1: Batch id in URL does not exist → 404-style alert "Couldn’t load this batch." Header card stays hidden; the Back link remains active.
-
AF-2: STOCK_TAKE state-log endpoint returns 404 → info banner explaining the backend follow-up; header card + close action remain operational.
-
AF-3: STOCK_TAKE state-log endpoint returns 5xx → "Couldn’t load batch activity. Try refreshing." alert; header card unaffected.
-
AF-4: Close action returns 403 → inline "You don’t have permission to close this batch." next to the button; batch stays OPEN.
Acceptance Criteria
-
List rendered at
/inventory/stock-activityfilterable by id / name / type / status / opened-on / closed-on. -
Default sort =
openedOn DESC; default page size = 50; both pinned on the URL on first paint. -
Sidebar entry "Stock activity" between Return and Onboard, admin-role gated.
-
Detail screen at
/inventory/stock-activity/:batchIdrenders the header card fromGET /api/operational-batches/{id}. -
Detail screen renders the close-batch action for OPEN batches; full-mode STOCK_TAKE batches route
mode=full-stock-take. -
Detail screen renders four report categories for STOCK_TAKE batches with the bucketing predicates documented above.
-
Non-STOCK_TAKE batches render the single chronological list of state-log entries.
-
Round A dead-end links from T02 / T03 / T04 now resolve to a real screen.
API Surface
| Call | Purpose |
|---|---|
|
List screen. Paginated ( |
|
Detail header card. |
|
Close-batch action (header). |
|
Pending — backend follow-up. Four-category drill-down body for STOCK_TAKE; chronological list for other types. |
Backend follow-ups
-
Expose
GET /api/operational-batches/{id}/state-log— extendsOperationalBatchResourceExwith a per-batch state-log surface returningList<RaceNumberStateLogDTO>. Until this lands the detail screen surfaces an info banner in the report body; header + close action remain fully operational. Follow-up US to file post-#748. -
Expose
GET /api/operational-batches/{id}/members— required to compute the Outsider category (scanned ∉ member set). Until this lands the In-stock category absorbs every resolved STOCK_TAKE_SCAN row and Outsider stays empty by design. Follow-up US to file post-#748.
Design Anchors
-
design-journal/2026-02/stock-take-tag-number-grouping.adoc— original four-category framing -
design-journal/2026-03/number-tag-management.adoc§ session 11 — full-mode + missing semantics -
design-journal/2026-05/number-tag-ui-orchestration.adoc§ Feature #742 — Round B wire-up -
design-journal/2026-05/stock-activity-screen-design.adoc— this screen’s decisions log