Files
Fuchs_Intranet/hlp/2026-10-01 check negative invoice amounts.sql
T
StefanandClaude Opus 5.5 d0002ccdad
Playwright Tests / test (push) Canceled after 0s
fix(invoices): send invoice amounts as exact cent-rounded decimals
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>
2026-10-01 10:57:41 +02:00

23 lines
1.7 KiB
Transact-SQL

-- 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.
--
-- 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],
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
WHERE i.[InvoiceBalance] < 0 OR i.[InvoiceBalance_net] < 0 OR i.[InvoiceVAT_net1] < 0
ORDER BY vat_scaled_by_bug DESC, i.[DateModified] DESC;