2 Reports
shad0w edited this page 2026-06-26 02:49:06 +05:30
This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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; 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.

Drill-down to POs

Every detail page (cost-centre and accounting-code) carries a “View POs · period link that opens PO History (/history) pre-filtered to that dimension and the period currently in view — closing the loop from an aggregate number back to the underlying purchase orders.

  • Cost-centre detail links to /history?vesselId=<id>&approvedFrom=…&approvedTo=….
  • Accounting-code detail links to /history?accountId=<id>&approvedFrom=…&approvedTo=….

Because spend is dated by approvedAt (not createdAt), the link filters PO History by its approved-date window, not the created-date one. periodRange(gran, fy, month, fys) (lib/reports.ts) maps the on-screen period onto that window so the two always agree:

Granularity Approved-date window
Weekly the focused FY month (calendar from/to for that month)
Monthly the selected financial year (Apr 1 → Mar 31)
Yearly the full span of FYs in view (first FY's Apr 1 → last FY's Mar 31)

On the History side, the accounting-code filter expands any account-tree node to its leaf codes (accountLeafIds) and matches a PO whose PO-level account or any line-item account falls under it — the same attribution basis the reports use, so the PO list reconciles with the report total. See Purchase Orders → PO History & Export.

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).