Files
accounted/tests
Jakob Wennberg f776e375c5 feat(payments): supplier payment batch schema + pain.001 domain lib (betalfil 1/3) (#1500)
* feat(payments): supplier payment batch schema + pain.001 domain lib

Betalfil for leverantorsfakturor, part 1 of 3. New tables
supplier_payment_batches + supplier_payment_batch_items (RLS, immutable
item snapshots, FK RESTRICT on invoices), payee/reference resolution,
eligibility rules shared by preview and create, and a supplier-dialect
pain.001.001.03 generator (SESBA 9900 BGNR / 9960 BBAN / clearing BBAN,
SCOR for Luhn-valid OCR, Ustrd fallback, no SvcLvl/CtgyPurp).
Deterministic regeneration: msg_id derives from the batch id, CreDtTm
from created_at, so re-downloads are byte-identical.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* refactor(payments): use lib/money helpers instead of raw ore rounding

The naive-ore-round ratchet flags new Math.round(x*100)/100 sites;
roundOre/sumOre/ORE_TOLERANCE are the sanctioned forms.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(payments): classify batch tables in full-archive contract + fixture

The no-phantom-columns contract requires every company-scoped table to
be triaged in full-archive-export; the batch rows are underlag for the
payments they initiated, so they dump with the archive. makeSupplier
gains the clearing/account columns the Supplier type now carries.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(payments): harden batch integrity per review

Composite (id, company_id) FKs so items can never cross-link a batch and
an invoice from different companies; BEFORE UPDATE trigger keeps batches
immutable outside lifecycle + download metadata and one-way on
created -> cancelled; active-batch lookup now fails closed (an error no
longer reads as no active batches, which would have silently disabled
the duplicate-batch guard); today derives from Europe/Stockholm, not
UTC; pain.001 control sums add the amounts as rendered so CtrlSum always
equals sum(InstdAmt); event-bus reset in test hooks; Danske LB date
claim in DECISIONS verified against the primary page (the bot's 12 May
date is the alias-initiation date, not LB retirement).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

* fix(payments): bind cancellation metadata to the cancel transition

cancelled_at/cancelled_by may only be written by created -> cancelled;
cancelled_by may still become NULL so the FK's ON DELETE SET NULL keeps
working when the cancelling user's account is deleted (proven in pg).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

---------

Co-authored-by: Jakob Wennberg <311770904+jakobwennberg-oss@users.noreply.github.com>
Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
2026-08-10 19:53:39 +02:00
..