Repository navigation
MP-54008 Fix 1-cent VAT rounding in line totals and VAT base - #7
Merged
Merged
Conversation
A line's VAT may differ from net x rate by one cent when net and VAT are derived from a fixed gross price. The item-based tax check now compares numbers and fails on a mismatch instead of only noting it.
amin19948
approved these changes
Oct 8, 2026
stereosupersonic
approved these changes
Oct 8, 2026
2 of 4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Ticket
https://miceportal.atlassian.net/browse/MP-54008
Story
Auftragsbuch's invoice rows are gross-leading: the gross price is fixed and net and VAT are derived from it. That VAT can be one cent off net × rate — 8 nights at 52.00 gross give net 388.79 and VAT 27.21, while 388.79 × 7 % rounds to 27.22. The gem demands exact equality, so Auftragsbuch has to let it recalculate the VAT, and the XML then says 27.22 / 416.01 while the PDF says 27.21 / 416.00. The XML is the legally relevant part of a ZUGFeRD invoice, so it must carry the invoice's own amounts. EN 16931 allows this rounding itself (BR-CO-17).
With this change a line's VAT may differ from net × rate by at most one cent, and the
:ITEM_BASEDcheck — which Auftragsbuch will use to pass the rows' own VAT — actually works: it compared a string with a number, only recorded the mismatch and still reported the invoice as valid.The second commit fixes the same drift on the invoice level. The gem summed the VAT base (BT-116) from unit price × quantity instead of the line totals. When unit prices are stored with four decimals the two drift apart: 2 days × 120 participants at 41.6667 (5,000.00 net per day) gave lines of 5,000.00 + 5,000.00 but a VAT base and total of 10,000.01 — an XML that contradicts itself (BR-CO-10, BR-S-08). The base is now the sum of the line totals, as EN 16931 defines it.
How to review
Two commits, best read one by one:
fix: allow 1-cent line VAT roundinglib/secretariat/line_item.rb—LINE_TAX_ROUNDING_TOLERANCEand the one changed comparison in#valid?.lib/secretariat/invoice.rb— the:ITEM_BASEDbranch of#valid?.test/invoice_test.rb— four tests: the gross-leading invoice is accepted and its XML carries 27.21 / 416.00; a line two cents off is still refused; item-based totals passed as strings leave no error; an item-based total that differs from its lines is refused.fix: use line totals as the VAT baselib/secretariat/line_item.rb—#signed_charge_amount.lib/secretariat/invoice.rb—#taxessums it instead of unit price × quantity.test/invoice_test.rb— the two-day example: VAT base 10000.00, not 10000.01.All tests were written before the change.
Design Choices
main, not from ourmain. The same commit is offered upstream as well; upstream has related rounding PRs open since January (Use charge_amount for tax base calculation instead of multiplying net amount with quantity halfbyte/ruby-secretariat#45, Rounding issue when summing tax amount halfbyte/ruby-secretariat#51) and no merges since April, so we do not wait for it — this PR is the one we use.to_xmlside effects) are not taken: the contact conflicts with our fork's own, the rest is unrelated to this ticket.to_xml(validate: false)would switch off all of the gem's checks instead of relaxing one.Links
Checklist