fix(invoices): carry ROT/RUT deduction into the editor PDF preview (#1687)

The preview route built previewInvoice without any deduction fields and
its item mapping dropped deduction_type, so the editor's PDF preview of a
ROT/RUT invoice showed no avdrag row, no deduction info box, and "Att
betala" at the full undeduced total, unlike the invoice that is then
created and sent.

The preview now mirrors build-invoice-write.ts: per-line deduction_amount
via computeDeduction (base inkl. moms at the rendered rate, invoice
document type only), invoice-level deduction_total via
computeInvoiceDeductionTotal, and the per-line work_type / labor_hours /
housing fields the PDF's info box reads. The masked personnummer is
resolved like the write path (typed value, else an individual customer's
kundkort personnummer). The editor posts deduction_personnummer and
deduction_housing_designation to the preview only when a line claims a
deduction.

Closes #1686

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:
Jakob Wennberg
2026-08-18 16:32:32 +02:00
committed by GitHub
co-authored by Jakob Wennberg Claude Fable 5
parent 3ea03c0fe1
commit ffa18019f4
4 changed files with 283 additions and 4 deletions
+10
View File
@@ -1722,6 +1722,16 @@ export default function InvoiceEditor(props: InvoiceEditorProps = { mode: 'creat
notes: data.notes,
payment_link_url: data.payment_link_url,
invoice_number: numberPreview,
// ROT/RUT claim card: the preview shows the same masked personnummer
// and fastighetsbeteckning in its deduction box as the created
// invoice will. Only sent when a line actually claims a deduction
// (same privacy rule as buildInvoiceWritePayload).
...(data.items.some((i) => i.deduction_type)
? {
deduction_personnummer: data.deduction_personnummer,
deduction_housing_designation: data.deduction_housing_designation,
}
: {}),
}),
})