[T05] Stock Reports
Summary
Tenant-level reporting surface for race-number stock and assignments. Surfaces existing backend data; CSV export per report.
Actor & Context
Actor: tenant admin, finance, organiser preparing for an event.
Frequency: monthly+; ad-hoc before each event.
Precondition: user has TENANT_ADMIN (or EVENT_MANAGER for event-scoped reports) permission.
Entry point: the stock-reports screen in the Operations sidebar group (tenant scope, capability stock.view), routed at /o/:orgSeg/stock-reports. Registered in the ScopedScreen registry (core/nav/scoped-screen.ts) alongside Stock / Returns / Stock activity — see C01 § Navigation model. Event-scoped reports (Assignments per event) are additionally deep-linked from E01. Distinct from the registry’s generic dual-use reports screen (Insights group, reports.view): T05 is stock-specific reporting at tenant scope.
Main Flow
-
Operator picks a report from a list (sidebar or tab strip — TBD by design pass).
-
Report renders with appropriate filters (date range, NumberType, event).
-
Operator exports to CSV when needed.
Reports in scope (one Task each under US #557):
-
Stock status (Task #788) — counts by state and type. By-state ships now; by-type depends on the
groupBy=typebackend extension (Task #792). -
Assignments per event (Task #789) — driven by event scope. Blocked on the new assignments endpoint (Task #793).
-
UNFIT summary (Task #790) — date filtered. Buildable against existing endpoints.
-
Person pick-list (Task #791) — per
person_id→ numbers ordered bylast_used(the WS1b endpoint). Deep-link only (?personId=N) — no in-report person search; reached from T02 or a person record. Buildable against existing endpoints.
CSV export is client-side per report (build the file from the rendered/loaded rows); server-side streaming (AF-2) is deferred until a report’s dataset proves too large.
Alternative Flows
-
AF-1: Report empty — empty state with hint.
-
AF-2: CSV export large dataset — server-side pagination + streaming export (TBD).
Acceptance Criteria
-
Use-case page authored.
-
Status
design-todo → handoff-readyafter Claude Design pass. -
Reports surface against existing endpoints.
-
CSV export works for each report.
API Surface
| Call | Purpose |
|---|---|
|
Stock status report. By-state is supported today; |
|
Assignments per event. Endpoint does not exist yet — new backend Task #793. |
|
UNFIT summary. Existing list endpoint; confirm date-range criteria support, else a small criteria addition. |
|
Person pick-list (WS1b — |
Design Anchors
-
design-journal/2026-03/number-tag-management.adoc— WS1b: pick-list endpoint, timing-feed CSV
Design Decisions (2026-06-24)
Resolved with the product owner ahead of the Claude Design pass:
-
Scope — design all four reports (design runs ahead of backend). US #557 split into one Task per report (#788–#791) plus two backend Tasks for the gaps (#792 stats
groupBy=type, #793 assignments-per-event endpoint). -
Placement — tenant-scope
stock-reportsscreen in the Operations sidebar group (capabilitystock.view), one screen hosting four reports. Implemented against the ScopedScreen registry that landed on develop after this design pass (ADO-930 / C01 rev 6); the original design’s "Inventory Reports row" maps to the Operations group’sstock-reportsentry. Kept distinct from the registry’s generic dual-usereportsscreen. -
Person pick-list — deep-link only (
?personId=N); no in-report person search. -
CSV — client-side per report; server-side streaming deferred (AF-2).
Design received 2026-06-24 (:design-url: above, T05-stock-reports/Stock Reports.html). Structure to implement: tab strip (Stock status · Assignments per event · UNFIT summary · Person pick-list); Stock status = five KPI tiles + a type×state breakdown table with a totals row; UNFIT + Assignments + Person = filter row + results table reusing the T02 state-pill / table chrome; each report has an Export-CSV button (top-right, badged with live row count) and its own reasoned empty state. Filters live in the report (preserved across tab switches); the URL reflects report + filter for shareability. Open questions parked as display-only (KPI tiles not cross-filtering) and preset date ranges for now.