docs: add Reports implementation page

shad0w 2026-06-24 10:02:20 +00:00
parent 96cd2334cf
commit e5716ca7ff

68
Reports.md Normal file

@ -0,0 +1,68 @@
# Reports — Purchasing spend analytics
The implemented spend-analytics section, reached via **Reports → Purchasing** in
the sidebar. (The original UX proposal — annotated screens — is on
[Reports Mockup](Reports-Mockup); this page documents what shipped.)
## Access
Gated by the **`view_analytics`** permission — **Manager, SuperUser, Auditor,
Admin**. CSV export uses the same gate. The sidebar **Reports** section carries a
**“Purchasing”** subheading so other domains (e.g. Crewing) can add their own
report groups later.
## Report families
Each is an **index → drill / detail** pair:
- **Cost Centres** (`/reports/cost-centres`) — approved spend compared across
**vessels** (the PO cost centre). A row opens **`/reports/cost-centres/[id]`**:
KPI tiles, a spend-trend chart, and a **Top accounting codes** breakdown
re-pivotable by tier (Heading / Sub-heading / Leaf) and Top-N.
- **Accounting Codes** (`/reports/accounting-codes`) — drills the `Account`
tree (headings → sub-headings → leaves) via a `?parent=` query; a leaf opens
**`/reports/accounting-codes/[id]`**: trend + breakdown **by cost centre** (or,
for a non-leaf, by sub-account).
## What counts as spend
A PO is counted once it reaches `POST_APPROVAL_STATUSES` (MGR_APPROVED … CLOSED),
dated by **`approvedAt`**, valued at **`totalAmount`** — the same basis as the
dashboard tiles. Financial year is the Indian **AprMar** year. Each PO's amount is
**allocated across the accounting codes its line items carry** (falling back to the
PO-level account), proportionally so the per-PO pieces sum back to the total — so
multi-account POs attribute correctly. PO counts are **distinct POs**. Sites are
**not** cost centres; only vessels are.
The aggregation is a pure, unit-tested core in **`lib/reports.ts`** — one query in
`getReportDataset()`, everything else pure functions over it.
## Filters (URL-driven, shareable)
All filters live in the **URL query**, so the server component re-renders and any
view is bookmarkable — no client-side fetching:
- **Granularity** — Weekly / Monthly / Yearly. Weekly focuses one FY **month** and
buckets by week-of-month (W1W5).
- **Financial Year**, plus **Month** (weekly only).
- **Show** — Top 5 / Top 10 / Bottom 5 / All.
- **Add to graph** — tick rows (`?sel=`) and compare just the selected set
(`?cmp=1`); export honours the selection.
- Accounting drill-down (`?parent=`) and detail re-pivot controls
(`tier` / `break` / `topn`).
Charts use **recharts**; the comparison chart draws **one colour per item** (cost
centre / accounting code) in every granularity, including the yearly grouped-bars
view. KPI tiles, tables and breadcrumbs are server-rendered.
## Export
The toolbar **Export** links to `/api/reports/spend?dim=…` — a CSV mirroring the
on-screen view (including a custom `?sel=` selection).
## Code
`lib/reports.ts` (aggregation), `lib/report-colors.ts` (shared palette, kept out of
the `"use client"` charts module so server components receive the real array),
`app/(portal)/reports/**` (pages), `components/reports/**` (toolbar + charts),
`app/api/reports/spend/` (CSV export).