Skip to content

[Bug][SubscriptionBilling]: "Prices Including VAT" handling is incomplete — contract billing invoice treats VAT‑exclusive Subscription Line amounts as VAT‑inclusive - #10093

Open
Miljan Milosavljević (miljance) wants to merge 1 commit into
microsoft:mainfrom
miljance:SBPricesIncludingVAT2

Conversation

@miljance

@miljance Miljan Milosavljević (miljance) commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

What & why

When a Subscription Contract is billed for a customer/vendor whose prices include VAT, the contract invoice was created with the net (VAT-exclusive) amount placed onto a "Prices Including VAT" = YES document, so the platform treated that net value as gross and the resulting VAT base/amounts did not reconcile with the original order.

Add a generic helper "ToVATInclusiveUnitPrice" that grosses up a net price by the line's VAT factor (rounded to the currency's Unit-Amount Rounding Precision), and apply it at every price-assignment site when the document has "Prices Including VAT":

  • Sales: standard line and usage-based path ("Unit Price")
  • Purchase: standard line and usage-based path ("Direct Unit Cost")

Full VAT and zero-VAT lines are left untouched. The factor is determined before the value is validated, so each price is validated exactly once.

Add tests covering the VAT-inclusive and prices-excluding-VAT cases for both the customer (sales) and vendor (purchase) contract billing flows.

Linked work

Fixes #8642

How I validated this

  • I read the full diff and it contains only changes I intended.
  • I built the affected app(s) locally with no new analyzer warnings.
  • I ran the change in Business Central and confirmed it behaves as expected.
  • I added or updated tests for the new behavior, or explained below why none are needed.

What I tested and the outcome (required — be specific: scenarios, commands, screenshots for UI changes)

  1. Set up a customer whose default Prices Including VAT = YES, and an item with a non-zero VAT rate (Normal VAT).
  2. Created a Sales Order for a subscription item for that customer and set Prices Including VAT = YES on the header.
  3. Confirmed the Sales Subscription Line / Calculation Base Amount is stored net.
  4. Posted the Sales Order so a Customer Subscription Contract is created.
  5. Run contract billing to create the contract invoice.
  6. Opened the generated contract invoice and inspect the sales line amounts, VAT base and VAT amount, plus the header Prices Including VAT flag.

Risk & compatibility

  • Gated on the document header — the gross-up runs only when Prices Including VAT = YES; every other document is byte-identical to before (asserted by the …PricesExcludeVAT tests).
  • No schema or extensibility change — no new fields or upgrade code, helper is local, event signatures and firing order unchanged. Subscribers on VAT-inclusive documents now see a gross price, which is the correct value for such a document.
  • New documents only — existing and posted documents are not corrected retroactively; contract data stays net, so a rollback leaves nothing inconsistent.
  • VAT types — Normal, Reverse Charge and No Taxable VAT are all reversed by the base app as /(1 + "VAT %"/100), so the gross-up is their exact inverse. Full VAT is skipped on purpose. Sales Tax is not covered (the base app reverses it via ReverseCalculateTax), which NA setups don't combine with Prices Including VAT.
  • Rounding — grossed up once, to the currency's Unit-Amount Rounding Precision; a net → gross → net round trip can land one rounding step off. Inherent to VAT-inclusive documents, and the document totals stay consistent.
  • Performance-neutral — the factor is applied before the field is written, so the price is still validated once, preserving the direct-assignment optimization from [Bug][SubscriptionBilling]: Performance: Billing document creation does not scale to large datasets (4M+ subscription lines) #8553.
  • Verified — 92/92 in codeunit 139687 on BC 29.0.53247; the VAT-inclusive assertion is mutation-verified (conversion disabled → red at 157.69047 vs 143.35497).

…usive when document prices include VAT

When a Subscription Contract is billed for a customer/vendor whose prices
include VAT, the contract invoice was created with the net (VAT-exclusive)
amount placed onto a "Prices Including VAT" = YES document, so the platform
treated that net value as gross and the resulting VAT base/amounts did not
reconcile with the original order.

Add a generic helper "ToVATInclusiveUnitPrice" that grosses up a net price by
the line's VAT factor (rounded to the currency's Unit-Amount Rounding
Precision), and apply it at every price-assignment site when the document has
"Prices Including VAT":
- Sales: standard line and usage-based path ("Unit Price")
- Purchase: standard line and usage-based path ("Direct Unit Cost")

Full VAT and zero-VAT lines are left untouched. The factor is determined
before the value is validated, so each price is validated exactly once.

Add tests covering the VAT-inclusive and prices-excluding-VAT cases for both
the customer (sales) and vendor (purchase) contract billing flows.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@github-actions github-actions Bot added AL: Apps (W1) Add-on apps for W1 From Fork Pull request is coming from a fork Finance GitHub request for Finance area needs-approval Workflow runs require maintainer approval to start labels Aug 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

AL: Apps (W1) Add-on apps for W1 Finance GitHub request for Finance area From Fork Pull request is coming from a fork needs-approval Workflow runs require maintainer approval to start

Projects

None yet

1 participant