fix(invoices): remaining_amount can no longer be inserted as 0 on an unpaid invoice (#1655)
* fix(invoices): remaining_amount can no longer be inserted as 0 on an unpaid invoice remaining_amount is NOT NULL DEFAULT 0 and every payment surface (payment dialog, bank match, Stripe sync, agent mark-paid) reads it as the customer's open balance. Four writers omitted it, so their invoices looked settled: the dialog rejected every payment as an overpayment and the bank match saw nothing to clear. Prod carried 337 such open invoices on 2026-08-17 (backfilled the same day, snapshot in _backfill_remaining_20260817). - Migration 20260817191708: BEFORE INSERT trigger invoices_derive_remaining_amount. When remaining_amount is NULL/0 on a real invoice (document_type invoice, not a credit note) with total > 0 and a status that still owes money, it becomes total - paid_amount - deduction_total (>= 0). The ROT/RUT share is a 1513 receivable on Skatteverket, never the customer's, exactly as buildInvoiceWriteData computes it. INSERT only: settlement code owns updates and legitimately writes 0 when paid in full. - pg-real test: derivation, explicit value respected, paid/prior/deduction arithmetic, drafts + overdue, paid/cancelled keep 0, credit notes and proformas untouched, never negative. - Writers fixed as well: proforma -> invoice conversion (dashboard route and MCP commitConvertInvoice), MCP commitCreateInvoice, sandbox seed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> * fix(sandbox): every row in the seed invoice batch carries remaining_amount + paid_amount PostgREST normalises a bulk insert to the union of keys, so a row that omits a column the others set arrives as NULL, not as the default. Keep the draft row on the same contract as the rest of the batch (CodeRabbit). 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>
This commit is contained in:
co-authored by
Claude Fable 5
Jakob Wennberg
parent
e030393fe6
commit
a447b29210
@@ -1671,6 +1671,11 @@ async function commitCreateInvoice(
|
||||
vat_amount_sek: vatAmountSek,
|
||||
total,
|
||||
total_sek: totalSek,
|
||||
// Fresh unpaid receivable: remaining_amount is what every payment
|
||||
// surface reads as the open balance; leaving the NOT NULL DEFAULT 0
|
||||
// made every agent-created invoice look settled.
|
||||
remaining_amount: total,
|
||||
paid_amount: 0,
|
||||
vat_treatment: notVatRegistered ? 'exempt' : vatRules.treatment,
|
||||
vat_rate: isMixedRate ? null : (uniqueRates.values().next().value ?? vatRules.rate),
|
||||
moms_ruta: notVatRegistered ? null : vatRules.momsRuta,
|
||||
@@ -4438,6 +4443,8 @@ async function commitConvertInvoice(
|
||||
vat_amount: proforma.vat_amount,
|
||||
vat_amount_sek: proforma.vat_amount_sek,
|
||||
total: proforma.total,
|
||||
remaining_amount: proforma.total,
|
||||
paid_amount: 0,
|
||||
total_sek: proforma.total_sek,
|
||||
vat_treatment: proforma.vat_treatment,
|
||||
vat_rate: proforma.vat_rate,
|
||||
|
||||
Reference in New Issue
Block a user