fix(invoices): send invoice amounts as exact cent-rounded decimals
Playwright Tests / test (push) Canceled after 0s
Playwright Tests / test (push) Canceled after 0s
Stornorechnung saves still failed: the VAT amount was formatted invariantly
("-615.3757999999999") and re-parsed under the server's de-DE culture as
-6153757999999999, overflowing numeric(10,3) in fds__setInvoice.
- FdsInvoiceData.BuildInvoiceParams: amount params are decimal(10,x) via
AmountParam/ParseAmount (culture-independent, rounded to cents); amounts
beyond +/-9,999,999.99 throw InvoiceAmountOutOfRangeException.
- InvoiceService.RegisterInvoiceAsync: refuses such an invoice with a logged
error (EventId InvoiceAmountRejected) instead of storing a wrong amount.
- Invoice editor: vat_val is cent-rounded decimal, no float noise.
- Tests: InvoiceAmountParamTests replaces the float-based Storno test.
- Bump Azure.Storage.Blobs 12.30.0; OCORE/OCORE_web submodules (AngleSharp
1.8.3, Azure.Storage.Files.Shares 12.28.0).
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5.5
parent
0a8384ab33
commit
d0002ccdad
@@ -1,29 +1,22 @@
|
||||
-- Read-only check for amounts mangled by the OCORE SQL_Float sign bug (fixed 2026-10-01).
|
||||
-- Before the fix, a negative amount posted as "-19.95" was parsed with the server's de-DE culture
|
||||
-- ("." = thousands separator) and stored scaled up, e.g. -19.95 -> -1995. Positive amounts were fine.
|
||||
-- Affected: fds__invoices header totals (Stornos / credits) and fds__invoice_details service totals
|
||||
-- written through fds__setInvoice / fds__createInvoice / fds__createInvoice_Details, plus reminder
|
||||
-- amounts written by ReminderService. Line items (fds__invoice_items) were NOT affected.
|
||||
-- Read-only check for amounts mangled by the SQL_Float culture bug (fixed 2026-10-01).
|
||||
-- No corrections are to be made from this: issued invoices are not changed retrospectively.
|
||||
--
|
||||
-- Signal: the header net total disagrees with the sum of the invoice's own line items.
|
||||
|
||||
-- 1) Invoices with a negative header total, compared against their persisted line items.
|
||||
-- What was at risk: only the VAT amount of a negative invoice (Storno / Gutschrift / Korrektur).
|
||||
-- FdsInvoiceData.HighestVat formatted it invariantly ("-615.38"), and the old OCORE SQL_Float parsed a
|
||||
-- negative value with the server's de-DE culture ("." = thousands separator) -> -61538. When the VAT
|
||||
-- carried float noise ("-615.3757999999999") the result overflowed numeric(10,3) and the save failed
|
||||
-- (the reported error); without noise it would have been stored scaled by 10/100/1000.
|
||||
-- The header totals (InvoiceBalance / _net) and service totals were formatted and parsed in the same
|
||||
-- culture and were never affected. Negative amounts themselves are legitimate.
|
||||
--
|
||||
-- Bug signature: InvoiceVAT_net1 = (InvoiceBalance - InvoiceBalance_net) * 10 / 100 / 1000.
|
||||
SELECT i.[Id], i.[InvoiceId], i.[InvoiceType], i.[IsFinal], i.[DateCreated], i.[DateModified],
|
||||
i.[InvoiceBalance], i.[InvoiceBalance_net], i.[InvoiceVAT_net1],
|
||||
d.[InvoiceService_net], d.[InvoiceService_VAT],
|
||||
items_net = it.[items_net],
|
||||
suspicious = CASE WHEN it.[items_net] IS NOT NULL
|
||||
AND ABS(i.[InvoiceBalance_net] - it.[items_net]) > 0.05 THEN 1 ELSE 0 END
|
||||
vat_from_totals = i.[InvoiceBalance] - i.[InvoiceBalance_net],
|
||||
vat_scaled_by_bug = CASE WHEN EXISTS (SELECT 1 FROM (VALUES (10), (100), (1000)) f(n)
|
||||
WHERE i.[InvoiceBalance] - i.[InvoiceBalance_net] <> 0
|
||||
AND ABS(i.[InvoiceVAT_net1] - (i.[InvoiceBalance] - i.[InvoiceBalance_net]) * f.n) <= 0.05 * f.n)
|
||||
THEN 1 ELSE 0 END
|
||||
FROM [dbo].[fds__invoices] i
|
||||
LEFT JOIN [dbo].[fds__invoice_details] d ON d.[InvId] = i.[Id]
|
||||
OUTER APPLY (SELECT [items_net] = SUM(x.[value_total])
|
||||
FROM [dbo].[fds__invoice_items] x
|
||||
WHERE x.[InvId] = i.[Id]) it
|
||||
WHERE i.[InvoiceBalance] < 0 OR i.[InvoiceBalance_net] < 0
|
||||
OR d.[InvoiceService_net] < 0 OR d.[InvoiceService_VAT] < 0
|
||||
ORDER BY suspicious DESC, i.[DateModified] DESC;
|
||||
|
||||
-- 2) Reminders with a negative amount (same helper).
|
||||
SELECT *
|
||||
FROM [dbo].[fds__reminder]
|
||||
WHERE [amount] < 0 OR [amount_payed] < 0;
|
||||
WHERE i.[InvoiceBalance] < 0 OR i.[InvoiceBalance_net] < 0 OR i.[InvoiceVAT_net1] < 0
|
||||
ORDER BY vat_scaled_by_bug DESC, i.[DateModified] DESC;
|
||||
|
||||
Reference in New Issue
Block a user