
Here's a finding from a recent audit, lightly anonymized: customer applies a 20% discount code at checkout, sees a total of $86.40, pays, and receives an invoice for $88.13.
A dollar seventy-three. Small enough that most customers won't dispute it. Large enough that some of them email support, and every one of those emails takes longer to resolve than the amount is worth — because the support agent can't explain the difference either.
The cause is almost always the same: discount and tax were applied in a different order in two different places.
The checkout page computed: subtotal, minus 20%, then tax on the discounted amount. The invoicing system computed: subtotal, plus tax, then 20% off the subtotal only. Both are defensible ways to do math. They just don't agree with each other, and each one lived in a separate codebase — checkout in the frontend, invoicing in a billing service someone integrated a year earlier.
Nobody decided this. It emerged. That's what makes it common: there's no single wrong line of code to point at, just two systems that were never forced to agree.
We see the same split show up between:
Four documents, one order, and it only takes two of them disagreeing to generate a ticket.
Discounts get tested. Tax gets tested. The combination rarely does — because the combination only misbehaves under specific conditions: a percentage discount plus a tax rate, applied to a cart where rounding actually bites.
A 10% discount on a $100 cart with no tax rounds cleanly everywhere. The same discount on a $47.99 cart with 8.875% tax does not, and whether you round at each line or once at the end changes the final cent. Multiply by thousands of orders and finance starts asking why the numbers never reconcile.
There's a nastier variant we've caught twice: stacking a percentage discount with a fixed-amount discount. Depending on the order they're applied, the customer pays a different total. One of the two orders is almost always what the pricing page implied. The other is what the code does.
You don't need hundreds of cases. You need the right dozen. On audits we build a small matrix and run every cell against every surface that displays a price:
Discount types: percentage, fixed amount, free shipping, stacked (if allowed)
Cart shapes: single item, multi-item, an amount that rounds badly (anything ending in .99 with a fractional tax rate), a cart where the discount exceeds an item's price
Tax situations: no tax, single rate, and — if you sell across borders — a VAT-inclusive price and a tax-exclusive one
For each combination, capture the total from the checkout page, the confirmation screen, the email, the invoice, and the payment provider's dashboard. Five numbers per test. They should be identical to the cent.
The whole matrix takes an afternoon. Every mismatch you find was going to be a recurring support ticket forever.
A few specific checks that have paid for themselves repeatedly:
The 100% discount. Full-discount codes exist in almost every system (internal orders, comps, gifts). Apply one and see whether tax is charged on zero, whether the payment step is skipped or attempts a $0.00 charge, and whether the invoice renders at all. This path fails constantly.
The discount larger than the item. A $50-off code on a $30 item. Does the total floor at zero, or does something go negative downstream?
Removing the code after tax was calculated. Apply a code, let the page recalculate, remove the code, pay. We've seen the discounted tax survive the removal.
Currency rounding. If you sell in multiple currencies, run one bad-rounding cart in each. Rounding rules differ by currency, and so do the bugs.
When the numbers disagree, resist the temptation to patch the display. The fix is structural: one system owns the calculation, everything else reads from it. Checkout, emails, invoices, and exports should render the same computed result — never recompute it.
Until that's true, every new surface that shows a price is a new chance for the numbers to drift apart.
We run this exact matrix, along with the rest of the checkout suite, in every audit. If your support inbox has a slow drip of "why doesn't my invoice match" tickets, you already know the answer — the useful part is finding out exactly which combinations produce it. That takes us about a day. Send us the product and we'll show you.
Want us to catch bugs like these before your customers do? Get a free mini-audit or see our services.