feat(reports): usage column, attachment notes, deposit footnotes & column cleanup - #1902
Conversation
… column cleanup - Add Usage column with linked-item derivation for report line items - Add attachment count/type note per line item - Replace the generic split footnote with a dedicated deposit footnote family (‡) for deposit-driven amounts - Drop the status column on claim/proof-of-funds report sections - Remove the appendix column Fixes #1898 Co-Authored-By: Claude frontend-developer (Haiku 4.5) <noreply@anthropic.com> Co-Authored-By: Claude translator (Sonnet 4.5) <noreply@anthropic.com> Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com>
|
[ux-designer] Reviewed Spec compliance — all confirmed in the diff and cross-checked against the added tests:
Deliberate deviation — Usage column width, My spec called for Given that constraint, I accept the equal 50/50 split (
This is a reasonable, well-substantiated engineering trade-off. I'm not requesting a percentage-based fix. If a future pdfmake upgrade adds proper weighted-star support, revisiting the 1:2 ratio would be a nice-to-have, not a requirement — worth a one-line note in the PR or a follow-up issue so it isn't forgotten, but not blocking here. Verdict: APPROVED. No token/dark-mode/accessibility surface to check (correctly out of scope per my own spec), and every in-scope layout/typography/footnote convention from the spec is implemented and test-verified. The width deviation is justified, documented, and safer than the original spec's literal instruction given the newly discovered library constraint. |
|
[product-architect] Verdict: APPROVE — medium findings noted for refinement, no blockers in the diffReviewed against issue #1898 ACs, the ux-designer visual spec (issue comment), What I verified
Medium findings (address in refinement — not blocking merge)M1 — The The classification is
So consider: an invoice whose budget lines all sit on source A (the reported source), plus a deposit tagged to source B, and no untagged deposits. AC 4 bullet 1 names exactly this case — "an invoice whose only cross-source funding is a tagged deposit (its budget lines all belong to the reported source...)" → should get the deposit footnote and not the generic split footnote. And it is precisely the This is not fixable client-side: the discriminating deposit is filtered out server-side, so scenario "lines on A + deposit tagged to B" and scenario "lines genuinely split across A and B" are byte-identical in the response. Impact is bounded: the emitted footnote is less specific, not false, and it is the same text shipped today — no regression, just an incompletely-delivered improvement in one sub-case. Hence medium, not blocking. Ask: file a follow-up for a server-side discriminator so the client stops inferring. Cheapest shape that closes it without leaking other sources' data: /** How this invoice's cross-source split arises, from the server's own UNION. Only meaningful when isSplit. */
splitKind: 'lines' | 'deposits' | 'both';derived directly in the existing M2 — L3610 reads "all ibl lines per invoice (even portion 0)", and M3 —
Suggested fix — make it a compile error instead: import type { AttachmentType } from '@cornerstone/shared';
const ATTACHMENT_TYPE_KEYS: Record<AttachmentType, string> = {
quotation: 'sourceReports.table.attachmentType.quotation',
deposit: 'sourceReports.table.attachmentType.deposit',
invoice: 'sourceReports.table.attachmentType.invoice',
};Adding an enum member then breaks the build at the map. The Low / informational
Merge gate
|
…1902 review - budgetLines[]/deposits[] are both this-source-scoped server-side, so the PDF footnote classification is a proxy that cannot see a deposit tagged to another source - proposed splitKind discriminator, wiki deviation on API-Contract L3610 - pdfmake 0.3.11 has no weighted-star ('2*') width support Co-Authored-By: Claude product-architect (Opus 4.6) <noreply@anthropic.com>
server/src/routes/timeline.test.ts's "returns projectedDate equal to the max endDate of linked work items" test used hardcoded absolute calendar literals (e.g. endDate: '2026-07-30') for not_started work item fixtures. timelineService applies an implicit "today floor" CPM override to not_started items (their start date cannot be in the past), so once the real date passed the fixture's endDate the assertion expired — this is what failed Quality Gates on PR #1902, unrelated to that PR's actual report-table-refinements scope. Fake timers (jest.useFakeTimers/setSystemTime) were tried first and rejected: freezing Date pollutes schedulingEngine.ts's module-level lastRescheduleDate gate (used by ensureDailyReschedule, invoked on every /api/timeline request), which then desyncs from the real date after the test restores real timers and causes the NEXT test in the file to unexpectedly trigger a real autoReschedule pass against its own database. Fixed by adding a futureDateStr(daysFromNow) helper and rewriting the fixture dates to be relative to the real current date instead — sidesteps the today-floor entirely without touching the clock, so there's no gate interaction. Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) <noreply@anthropic.com>
|
[product-owner] Verdict: APPROVE — all AC groups of #1898 metReviewed 1. Usage column — PASS
The mixed case (some lines linked, some description-only) shows linked names only — that matches the AC as written ("one or more Deviation from the ux-designer spec, accepted: the spec called for 2. Attachments note — PASSCount + deduped translated types (Scenarios 9–11); null-type documents counted but contributing no label, degrading to a plain count (Scenarios 12, 13); singular/plural in both locales asserted against real i18next, not a key-echo mock — The note is derived purely from I specifically checked the 3. Column cleanup — PASSAppendix column removed unconditionally — header, cell, subtotal/total placeholder, and width slot all gone; Scenario 3 pins that a non-empty Status column present for 4. Deposit footnote — PASS on all four pinned casesThe implemented rule (
One residual gap, not a blocker — this is a limitation in my own AC, not in the implementation. AC case 1 also covers the variant "its budget lines all belong to the reported source" alongside "or it has none". Related refinement for that follow-up: in the co-occurrence case the 5. Translations — PASSAll new keys present in both ScopeClean. Changes are confined to Non-blocking nits (no re-review needed)
Merge precondition (outside my AC scope, per the task framing)
|
|
[product-owner] Note on mechanics: |
|
🎉 This PR is included in version 2.13.0-beta.31 🎉 The release is available on GitHub release Your semantic-release bot 📦🚀 |
Summary
Fixes #1898
Test plan
Co-Authored-By: Claude dev-team-lead (Sonnet 4.6) noreply@anthropic.com
Co-Authored-By: Claude frontend-developer (Haiku 4.5) noreply@anthropic.com
Co-Authored-By: Claude translator (Sonnet 4.5) noreply@anthropic.com
Co-Authored-By: Claude qa-integration-tester (Sonnet 4.5) noreply@anthropic.com