docs: report→PO drill-down, PO History accounting-code filter, PR-review watcher

Covers changes merged after the last wiki update (2026-06-24):
- #126/#123 report detail "View POs" drill-down + PO History accounting-code
  filter and approved-date window (Reports, Purchase-Orders, Pages-and-Navigation)
- #129/#131/#134 PR review-comment watcher (Issue-to-Deploy-Pipeline)
- Changelog mirror entries
shad0w 2026-06-26 02:49:06 +05:30
parent dfe7f7220f
commit 0e178b670e
5 changed files with 77 additions and 1 deletions

@ -9,6 +9,8 @@ checked out in `~/pms`. See [Deployment and Operations](Deployment-and-Operation
### Added ### Added
- **Reports — Purchasing spend analytics** (`view_analytics`) — `/reports/cost-centres` and `/reports/accounting-codes`, each index → drill-down → detail; KPI tiles, comparison/trend charts (one colour per item), Top-N tables, sparklines, CSV export; URL-driven filters (Weekly/Monthly/Yearly, FY, Top/Bottom-N, "Add to graph"). Spend = post-approval POs by `approvedAt`/`totalAmount`, allocated per line-item account. See [Reports](Reports). - **Reports — Purchasing spend analytics** (`view_analytics`) — `/reports/cost-centres` and `/reports/accounting-codes`, each index → drill-down → detail; KPI tiles, comparison/trend charts (one colour per item), Top-N tables, sparklines, CSV export; URL-driven filters (Weekly/Monthly/Yearly, FY, Top/Bottom-N, "Add to graph"). Spend = post-approval POs by `approvedAt`/`totalAmount`, allocated per line-item account. See [Reports](Reports).
- **Report → PO drill-down** (#126) — the Cost Centre and Accounting Code report detail pages gain a **"View POs"** link that opens **PO History** pre-filtered to that cost centre / accounting code and the period currently in view (mapped to the approved-date window via `periodRange`, since spend is dated by `approvedAt`). PO History gains an **Accounting Code** filter that accepts any tree node and matches a PO whose PO-level account **or** any line-item account falls under that node's leaves. The History page and its CSV/PDF export share one `buildPoHistoryWhere` builder so they never diverge. See [Reports](Reports#drill-down-to-pos) and [Purchase Orders](Purchase-Orders#po-history--export).
- **PR review-comment watcher** (#129/#131/#134) — a second pms1 cron watcher (`automation/claude-pr-review-watcher.sh`) closes the loop on the review side: leave a comment starting with **`claude-review:`** on any Claude-raised PR and the watcher checks out the PR branch, runs headless Claude to address every collaborator `claude-review:` comment, pushes the fix, and acknowledges. Own clone (`~/pelagia-pr-review`), config, and lock; a one-command updater redeploys it. See [Issue to Deploy Pipeline](Issue-to-Deploy-Pipeline#pr-review-comment-watcher).
- **Email PO to vendor** (issue #14) — Outlook draft with a 7-day PO-PDF link, rendered by the **PdfService** microservice and cached per PO. See [Deployment and Operations](Deployment-and-Operations#microservices). - **Email PO to vendor** (issue #14) — Outlook draft with a 7-day PO-PDF link, rendered by the **PdfService** microservice and cached per PO. See [Deployment and Operations](Deployment-and-Operations#microservices).
- **Microservices**`EpfoService` (UAN/EPFO lookup) and `PdfService` (PO→PDF) join `GstService`; all auto-deployed on each release tag via `ecosystem.config.js`. - **Microservices**`EpfoService` (UAN/EPFO lookup) and `PdfService` (PO→PDF) join `GstService`; all auto-deployed on each release tag via `ecosystem.config.js`.
- **Unsaved-changes prompt** (issue #18) — leaving the PO create/edit screen with unsaved edits offers Save as draft / Discard / Stay. - **Unsaved-changes prompt** (issue #18) — leaving the PO create/edit screen with unsaved edits offers Save as draft / Discard / Stay.

@ -91,5 +91,29 @@ So the fix stage verifies against realistic data without touching production:
- Schema-migration issues are routed to `interactive`, so the unattended fixer - Schema-migration issues are routed to `interactive`, so the unattended fixer
should not be altering the schema. should not be altering the schema.
## PR review-comment watcher
Where the issue watcher turns *issues* into PRs, a second watcher
(`automation/claude-pr-review-watcher.sh`) closes the loop on the **review** side —
it addresses review comments left on the PRs Claude already raised, so a reviewer
can request changes in plain English instead of editing code by hand.
- **How to drive it (as a reviewer):** on any open Claude-raised PR, leave a comment
(inline, a review summary, or a general comment) that **starts with the marker
`claude-review:`**. The text after the marker is the instruction, e.g.
`claude-review: null-check order.vendor before dereferencing it, and add a test`.
- **Each run (every 10 min via its own cron entry):** it scans **all** open
Claude-raised PRs, collects every `claude-review:` comment **from repo
collaborators only**, skips ones it has already handled (it stamps an
`<!-- ppms-review-bot handled: … -->` acknowledgement), checks out the **PR's own
branch** in its dedicated clone, runs headless Claude to implement the changes, and
pushes the result back onto the PR branch.
- **Isolation:** own clone (`~/pelagia-pr-review`), own config + lock, separate from
both the deployed `~/pms` and the issue watcher's `~/pelagia-autofix`, so the two
watchers can't race. Sensitive changes (migrations, payments, permissions) are left
uncommitted for a human; the bot posts back why and waits for a follow-up
`claude-review:` instruction. A one-command updater redeploys the script + config
from the repo onto pms1.
See [Deployment and Operations](Deployment-and-Operations) for the deploy See [Deployment and Operations](Deployment-and-Operations) for the deploy
workflow and staging, and `automation/README.md` for the authoritative runbook. workflow and staging, and `automation/README.md` for the authoritative runbook.

@ -48,7 +48,7 @@ SuperUser Requests /admin/superuser-requests ← ADMIN
| `/approvals/[id]` | Approval Detail | Approve / Approve+Note / Reject / Request Edits / Request Vendor ID; inline line-item edit | | `/approvals/[id]` | Approval Detail | Approve / Approve+Note / Reject / Request Edits / Request Vendor ID; inline line-item edit |
| `/payments` | Payment Queue | MGR_APPROVED & SENT_FOR_PAYMENT cards; send/mark paid; partial | | `/payments` | Payment Queue | MGR_APPROVED & SENT_FOR_PAYMENT cards; send/mark paid; partial |
| `/payments/history` | Payment History | Completed payments (ACCOUNTS, MANAGER) | | `/payments/history` | Payment History | Completed payments (ACCOUNTS, MANAGER) |
| `/history` | History & Export | All POs; filter by date/cost centre/multiple statuses; CSV/PDF. `export_reports` holders, plus submitters when the `SUBMITTER_VIEW_ALL` flag is on | | `/history` | History & Export | All POs; filter by created-date / **approved-date** / cost centre / **accounting code** / multiple statuses; CSV/PDF. `export_reports` holders, plus submitters when the `SUBMITTER_VIEW_ALL` flag is on. The accounting-code filter and approved-date window back the report → PO drill-down (see [Reports](Reports#drill-down-to-pos)) |
| `/reports/cost-centres` | Reports → Cost Centres | Approved spend compared across cost centres (vessels); drill to a cost-centre report. `view_analytics` | | `/reports/cost-centres` | Reports → Cost Centres | Approved spend compared across cost centres (vessels); drill to a cost-centre report. `view_analytics` |
| `/reports/accounting-codes` | Reports → Accounting Codes | Approved spend by the accounting-code tree (drill headings → sub → leaf); leaf opens its report. `view_analytics` | | `/reports/accounting-codes` | Reports → Accounting Codes | Approved spend by the accounting-code tree (drill headings → sub → leaf); leaf opens its report. `view_analytics` |
| `/inventory/items` | Items (read-only) | Catalogue; expand for per-vendor prices; Cheapest/★Closest tags | | `/inventory/items` | Items (read-only) | Catalogue; expand for per-vendor prices; Cheapest/★Closest tags |

@ -117,6 +117,29 @@ brand-colour bar (`#92D050`) runs full-width along the bottom. Each piece is
optional except the bar, which is always drawn. See optional except the bar, which is always drawn. See
[File Storage](File-Storage#where-files-attach). [File Storage](File-Storage#where-files-attach).
## PO History & Export
`/history` (**History & Export**, gated by `export_reports` — see
[Roles and Permissions](Roles-and-Permissions)) lists **every** PO with a filter
panel and a CSV / PDF export of the filtered set. Filters:
- **Created-date** range (`dateFrom` / `dateTo`, on `createdAt`).
- **Approved-date** range (`approvedFrom` / `approvedTo`, on `approvedAt`) — the
window the [Reports](Reports#drill-down-to-pos) drill-down uses, since spend is
dated by approval.
- **Cost Centre** (`vesselId`).
- **Accounting Code** (`accountId`) — accepts **any** node of the 3-level account
tree (Heading / Sub-heading / Leaf), not just leaves. It expands to the leaf codes
beneath (`accountLeafIds`) and matches a PO whose **PO-level `accountId` _or_ any
line-item `accountId`** is in that set — the same allocation basis as the spend
reports, so a report figure and its “View POs” list reconcile.
- **Status** (multi-select).
The page list **and** the CSV/PDF export route share a single
**`buildPoHistoryWhere()`** builder (`lib/history-filter.ts`), so the on-screen
results and the exported file can never diverge. All filters are URL query params,
so a filtered view (including a report drill-down link) is bookmarkable.
## Import PO → CLOSED ## Import PO → CLOSED
`/po/import` parses a Pelagia-format Excel PO (`lib/po-import-parser.ts`, `/po/import` parses a Pelagia-format Excel PO (`lib/po-import-parser.ts`,

@ -55,6 +55,33 @@ Charts use **recharts**; the comparison chart draws **one colour per item** (cos
centre / accounting code) in every granularity, including the yearly grouped-bars centre / accounting code) in every granularity, including the yearly grouped-bars
view. KPI tiles, tables and breadcrumbs are server-rendered. 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](Purchase-Orders#po-history--export).
## Export ## Export
The toolbar **Export** links to `/api/reports/spend?dim=…` — a CSV mirroring the The toolbar **Export** links to `/api/reports/spend?dim=…` — a CSV mirroring the