fix: received invoices — amount field is VAT-inclusive, extract VAT from it

Previously: amount was treated as base, VAT added on top (amount * rate / 100)
Now: amount includes VAT, VAT is extracted (amount - amount / (1 + rate/100))

Example: 9798.58 at 21% → VAT = 9798.58 - 8098.00 = 1700.58

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
BOHA
2026-03-23 13:24:54 +01:00
parent fe12fde9db
commit 8b5f216960

View File

@@ -143,7 +143,8 @@ export default async function receivedInvoicesRoutes(fastify: FastifyInstance):
const meta = invoicesMeta[i] || {};
const amount = Number(meta.amount ?? 0);
const vatRate = Number(meta.vat_rate ?? 21);
const vatAmount = Math.round(amount * vatRate) / 100;
// Amount includes VAT — extract VAT portion: amount - amount/(1 + rate/100)
const vatAmount = vatRate > 0 ? Math.round((amount - amount / (1 + vatRate / 100)) * 100) / 100 : 0;
const invoice = await prisma.received_invoices.create({
data: {
@@ -195,7 +196,7 @@ export default async function receivedInvoicesRoutes(fastify: FastifyInstance):
amount,
currency: body.currency ? String(body.currency) : 'CZK',
vat_rate: vatRate,
vat_amount: Number(body.vat_amount ?? 0),
vat_amount: vatRate > 0 ? Math.round((amount - amount / (1 + vatRate / 100)) * 100) / 100 : 0,
issue_date: body.issue_date ? new Date(String(body.issue_date)) : null,
due_date: body.due_date ? new Date(String(body.due_date)) : null,
status: status as received_invoices_status,
@@ -232,7 +233,8 @@ export default async function receivedInvoicesRoutes(fastify: FastifyInstance):
// Recalculate vat_amount when amount or vat_rate changes (matching PHP)
const finalAmount = body.amount !== undefined ? Number(body.amount) : Number(existing.amount);
const finalVatRate = body.vat_rate !== undefined ? Number(body.vat_rate) : Number(existing.vat_rate);
const computedVat = Math.round(finalAmount * finalVatRate) / 100;
// Amount includes VAT — extract VAT portion: amount - amount/(1 + rate/100)
const computedVat = finalVatRate > 0 ? Math.round((finalAmount - finalAmount / (1 + finalVatRate / 100)) * 100) / 100 : 0;
// Auto-set paid_date when status transitions to paid (matching PHP)
const newStatus = body.status !== undefined ? String(body.status) : String(existing.status);