fix(received-invoices): treat amount as gross (VAT-inclusive), back-calc VAT

The amount on a received invoice is the GROSS total the user pays (VAT
included), and VAT is the portion contained within it — not a net base with
VAT added on top. Switch the formula from amount*rate/100 to the
VAT-inclusive amount*rate/(100+rate) via a shared, tested vatFromGross()
helper used by both the create (manual upload + AI import share this
endpoint) and edit paths. Rate 0 → no VAT.

- AI extraction now asks Claude for the total INCLUDING VAT (was "základ bez
  DPH"), reinforced in the structured-output schema description.
- Label the amount field "Částka s DPH" in the AI review card and the manual
  upload/edit forms so the gross convention is explicit.
- Add unit tests with the user-confirmed figures (22 542,91 @ 21% → 3 912,41,
  base 18 630,50) plus other rates and the no-VAT case.

Existing rows keep their stored (gross) amounts; their vat_amount recomputes
on next edit. A one-shot backfill can correct historical vat_amount if wanted.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
BOHA
2026-06-08 16:27:56 +02:00
parent 58e5fd2b1d
commit f4bc038f8b
5 changed files with 55 additions and 16 deletions

View File

@@ -207,9 +207,16 @@ const INVOICE_SCHEMA: Record<string, unknown> = {
properties: {
supplier_name: { type: "string" },
invoice_number: { type: ["string", "null"] },
amount: { type: "number" },
amount: {
type: "number",
description:
"Celková částka k úhradě VČETNĚ DPH (gross total), NE základ bez DPH.",
},
currency: { type: "string" },
vat_rate: { type: "number" },
vat_rate: {
type: "number",
description: "Sazba DPH v procentech; 0 pokud faktura nemá DPH.",
},
issue_date: { type: ["string", "null"] },
due_date: { type: ["string", "null"] },
description: { type: ["string", "null"] },
@@ -244,9 +251,10 @@ export async function extractInvoice(
{
type: "text",
text:
"Vyčti z této přijaté faktury pole dodavatele, číslo faktury, částku (základ bez DPH), " +
"Vyčti z této přijaté faktury tato pole: dodavatele, číslo faktury, " +
"celkovou částku k úhradě VČETNĚ DPH (tj. konečný součet, NE základ bez DPH), " +
"měnu (ISO kód), sazbu DPH v procentech, datum vystavení a splatnosti (YYYY-MM-DD) a krátký popis. " +
"Pokud pole chybí, vrať null.",
"Pokud faktura nemá DPH, vrať sazbu 0. Pokud pole chybí, vrať null.",
},
],
},