Picks up the three pieces deferred from the initial reports PR:
#3 Line-item account allocation — allocatePoSpend() splits each PO across the
accounting codes its line items carry (line accountId, falling back to the
PO-level account), proportionally so per-PO rows sum back to totalAmount. The
accounting-code report now attributes multi-account POs correctly. SpendRow
gains poId; poCount is now distinct POs, not row count.
#2 Custom "Add to graph" — tick rows on either index (SelectCheckbox links
write ?sel=id1,id2), then "Compare selected" (?cmp=1) shows a custom comparison
of just those entities. Fully server-rendered + shareable; export honours sel.
#1 Weekly granularity — a third Granularity that focuses one FY month and
buckets spend by week-of-month (W1–W5) from approvedAt, with a Month picker in
the toolbar. Real buckets (not the mockup's synthetic split).
All three are URL-driven like the rest, so no client fetching. Charts/KPIs/
detail trends all branch on the new mode.
Tests: +8 unit cases (allocation proportional/fallback/empty, weekly buckets,
sel parse/toggle, month + granularity parsing); fixture updated for poId/week.
Full unit suite 311 green; tsc clean. Smoke-tested weekly + custom-compare +
exports end-to-end (all 200). Docs + wiki updated to mark them implemented.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Implements the wiki "Reports Mockup" as a Reports → Purchasing sidebar section,
wired to real approved-PO spend.
Two report families, each index → drill/detail:
- Cost Centres (/reports/cost-centres) — spend compared across vessels; row
opens a cost-centre report with a Top-accounting-codes breakdown re-pivotable
by tier (Heading/Sub/Leaf) + Top-N.
- Accounting Codes (/reports/accounting-codes) — drills the Account tree
(headings → sub → leaves) via ?parent=; a leaf opens its report broken down by
cost centre (or, for a non-leaf, by sub-account).
Shared: a pinned filter toolbar (Granularity Monthly/Yearly, Financial Year,
Show Top5/Top10/Bottom5/All) whose values live in the URL query so the server
component re-renders — no client fetching. KPI tiles, recharts comparison/trend/
breakdown charts, per-row trend sparklines, and CSV export (/api/reports/spend).
- lib/reports.ts: the pure, unit-tested aggregation core. Spend = a PO once it
reaches POST_APPROVAL_STATUSES, dated by approvedAt, valued at totalAmount
(the dashboard's basis); Indian Apr–Mar FY; each PO's leaf accountId rolled up
to parents. One query in getReportDataset(), everything else pure.
- Sidebar: new collapsible "Reports" section with a "Purchasing" subheading
(subgroup support added to the Section model). Gated by view_analytics
(Manager/SuperUser/Auditor/Admin); export by the same.
Deferred (documented): synthetic Weekly granularity, the "Add to graph" custom
multi-select, and line-item-level account allocation (v1 uses the PO-level
account). Sites are not cost centres — only vessels.
Tests: 11 unit cases for the aggregation core + 3 sidebar cases for the Reports
section. Full unit suite 303 green; tsc clean. Smoke-tested all routes end to
end against seed data (index/drill/detail/export 200; non-analytics role 307/403).
Wiki: "Reports Mockup" marked implemented; "Pages and Navigation" lists the new
routes.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>