fix(database): unblock credit note constraint validation (#1024)
* docs: record legacy credit note migration repair * fix(database): assert repaired credit note state --------- Co-authored-by: Jakob Wennberg <jakob.wennberg@gmail.com>
This commit is contained in:
@@ -166,3 +166,4 @@ One line per decision: `[YYYY-MM-DD] <decision>: <why>`. Appended by agents and
|
||||
[2026-07-15] Credit note creation uses a completion marker plus unique company guards instead of a large creation RPC: incomplete parents are never returned, concurrent requests converge, and all journal writes remain in the bookkeeping engine.
|
||||
|
||||
[2026-07-16] Two bugs from one customer report (an AB). Bug 1 (acct 2893 showed 2393's "langfristig del" memo after an andringsverifikation): root cause = CorrectionEntryDialog never re-derived line_description on account change (JournalEntryForm does). Fixed forward via a pure helper (correction-line-description.ts) that refreshes the memo only when it is empty or still equals the prev account's name (preserves hand-typed memos). Chose NO prod data repair: the wrong memo sits on a POSTED verifikat (immutable per migration-017 trigger); it is cosmetic (account number + amounts correct, all reports key off the number); ~26 posted lines across 11 cos share this stale-echo pattern, all fix-forward only. Deferred the twin entry-level header fix (#1031). Bug 2 (auto tax-deadlines never appeared): root cause = generation only fired on a settings save where a TAX field CHANGED value (didTaxFieldsChange); settings are filled once at onboarding so re-saving generated nothing -> only 5/776 real cos had system deadlines. Chose count-based self-heal (regenerate when the company has 0 system deadlines) over always-regenerate, because generateTaxDeadlinesForUser deletes+reinserts and would reset is_completed/status on every unrelated save. Also wired the /deadlines empty-state to the existing (dead) /api/tax-deadlines/generate route, and fixed a 1000-row PostgREST cap in the annual cron. Backfilled 771 real cos with zero system deadlines via scripts/backfill-tax-deadlines.ts. Deferred moms_period=yearly config (#1030, 295 filers, largest VAT cohort): helarsmoms deadline (SFL 26 kap. 33-33b) depends on EU-trade status (no flag in CompanySettingsForDeadlines) and, for AB, the income-tax-return date.
|
||||
[2026-07-15] Repaired the single legacy paid credit note blocking invoices_credit_note_not_paid validation by normalizing its invoice metadata to sent, clearing payment fields, setting zero payable remainder, and linking its existing balanced posted V44 reversal: the immutable voucher already exactly reversed V42 and was not edited or duplicated.
|
||||
|
||||
@@ -0,0 +1,24 @@
|
||||
-- The linked production database contained one legacy credit note in the
|
||||
-- ordinary payment lifecycle. It was reconciled before this migration by
|
||||
-- linking its existing balanced reversal voucher and normalizing the invoice
|
||||
-- metadata. Keep an explicit forward migration that verifies the repaired
|
||||
-- invariant before the remaining migration chain proceeds.
|
||||
-- pg-test: covered-by lib/invoices/__tests__/credit-note-not-payable.pg.test.ts
|
||||
DO $reconcile$
|
||||
BEGIN
|
||||
IF EXISTS (
|
||||
SELECT 1
|
||||
FROM public.invoices
|
||||
WHERE credited_invoice_id IS NOT NULL
|
||||
AND status IN ('paid', 'partially_paid')
|
||||
) THEN
|
||||
RAISE EXCEPTION
|
||||
'Legacy credit notes still use ordinary customer-payment states';
|
||||
END IF;
|
||||
END
|
||||
$reconcile$;
|
||||
|
||||
ALTER TABLE public.invoices
|
||||
VALIDATE CONSTRAINT invoices_credit_note_not_paid;
|
||||
|
||||
NOTIFY pgrst, 'reload schema';
|
||||
Reference in New Issue
Block a user