Repository navigation
230f78af: CLI path to correct and reissue an issued sponsor invoice - #367
Merged
Merged
Conversation
Correcting an issued sponsor invoice had no CLI path: record-invoice could re-record metadata but captured no reason, and once an invoice PDF was linked, neither attach-invoice nor linkInvoice would accept the corrected document. The corrected invoice itself must still be issued in Finom's UI (the repo has no Finom API client; same manual step as marking an invoice paid there) - this lands the tracking side. correctInvoice (POST /api/sponsor-crm/deals/:id/finance/invoice-correction) requires a reason, replaces the recorded invoice metadata with issueInvoice's exact semantics, and optionally supersedes the linked PDF in the same transaction: the old claim and link rows are deleted, the corrected document takes the claim, and the original document stays in bookkeeping for audit. The history event invoice-corrected records the reason plus before/after for every changed field and the superseded document ids; the projection exposes finance.invoiceCorrection. Corrections are refused before anything was issued, when nothing changes, on stale versions, on documents claimed elsewhere, and on voided finance. dataops sponsors correct-invoice previews and applies the correction, uploading the corrected PDF through the shared verified-storage helper that attach-invoice now also uses; --file makes the dry run upload nothing. The CLI skill documents the Finom manual step.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Task
230f78af - CLI gap: no way to correct/reissue an issued sponsor invoice PDF (Finom) from CLI.
What the gap was
Sponsor invoices are issued in Finom's UI; DataOps tracks the lifecycle in sponsor finance. Verified inventory:
issueInvoice(POST /finance/issue) could re-record metadata (it already emittedinvoice-reissuedwhen re-called), but captured no reason and no before/after - no audit trail for a correction.attach-invoicerefused when an original was attached, andlinkInvoiceconditioned onattribute_not_exists(invoiceLinkId). The only workaround (unlink + link) was not exposed on the CLI and produced two unrelated audit events.dataops invoice-pdfs reissueexists only for contractor render workflows and keeps its reason in a local sidecar file with no server record.What this lands
Tracking side (the corrected invoice itself is still issued in Finom's UI - the repo has no Finom API client):
correctInvoice(POST /api/sponsor-crm/deals/:id/finance/invoice-correction): requires a nonempty reason (bounded 500), replaces the recorded invoice metadata withissueInvoice's exact replace-set semantics, and optionally supersedes the linked PDF in the same DynamoDB transaction - old claim + link rows deleted, corrected document takes over the claim, original document retained in bookkeeping for audit. History eventinvoice-correctedrecords reason, before/after per changed field, andreplacedDocumentids. The projection exposesfinance.invoiceCorrection(at,reason);invoiceStatestaysissued.dataops sponsors correct-invoice <deal-id> --data @correction.json [--file corrected.pdf] [--apply]: previews by default (dry run never uploads), merges reviewed metadata likerecord-invoice(omitted preserved, explicitnullclears optional number/sent date), uploads the corrected PDF through the shared verified-storage helper thatattach-invoicenow also uses.cli/skill/SKILL.mdsponsor invoice lifecycle +sponsors --help, including the manual Finom step.Tests (targeted, touched files only)
cli/test/sponsor-finance.test.mjs: correction preview/apply round-trip with idempotency header, null-clear semantics, superseding-PDF upload path, dry-run-never-uploads, validation errors - 9 pass (33 with neighbouring sponsor suites).backend/tests/sponsor-finance-transaction.ddb.ts(DynamoDB Local): full original -> corrected round-trip: metadata-only correction with reason and history details, idempotent replay, document supersede (claim/link swap verified row-by-row, original retained, projection coherent and pointing at the corrected document), plus every refusal above - 29 pass.backendtsc --noEmit(all three tsconfigs) clean; backend sponsor-finance unit suites (38) pass.Prod was only read, never written; no real invoices were touched. Worktree left in place for review.