Bug Description
When a product is configured with tax_type = 'inclusive' (price already contains tax) and an order-level discount is applied, the order total is incorrectly inflated. The code adds the extracted tax component on top of a discounted subtotal that already includes the tax inside it.
Steps to Reproduce
- Create a product with
tax_type = 'inclusive', tax_rate = 5, price = ₹1000
- Create an order with this product
- Apply a 10% order-level discount via
PATCH /orders/:id/discount
- Observe the resulting total
Expected vs Actual
|
Value |
| Discounted subtotal |
₹900 |
| Tax (inclusive — already inside the price) |
embedded in ₹900 |
| Expected total |
₹900 |
| Scaled tax incorrectly added on top (bug) |
₹42.86 |
| Actual total |
₹942.86 ❌ |
Root Cause
In main/routes/orders.ts, when a discount is applied the code:
- Computes
discountedSubtotal = subtotal - discountAmount
- Scales
newTaxAmount = freshTax × (discountedSubtotal / subtotal)
- Computes
total = discountedSubtotal + newTaxAmount
For exclusive tax this is correct — tax is separate from the price.
For inclusive tax, subtotal already contains the tax. After discounting, discountedSubtotal still contains the embedded tax — adding newTaxAmount on top is double-counting.
Affected Code
main/routes/orders.ts — PATCH /:id/discount handler (~line 695)
main/routes/orders.ts — POST /:id/items add-items recalculation (~line 396)
main/routes/orders.ts — PATCH /:id/items/:itemId/discount order recalculation (~line 884)
Suggested Fix
The ratio approach needs to be aware of tax type. Options:
Option A (simpler): Separate the order subtotal into inclusive and exclusive portions before applying the ratio. Only add newTaxAmount to the exclusive portion; the inclusive portion needs no additional tax added.
Option B (more correct): Rather than scaling the original freshTax by ratio at the order level, recalculate item-level tax properly by running computeTaxAmount('inclusive', discountedItemSubtotal, rate) per item after the discount is applied — matching how item creation works.
Impact
- Only affects orders with
tax_type = 'inclusive' products + an order-level discount applied simultaneously
- Without a discount: inclusive tax is calculated correctly ✅
- Exclusive tax at any time: always correct ✅
- Common in Southeast Asia (Thailand VAT), Europe, and UK where tax-inclusive pricing is standard
Not Introduced By Recent Commits
This is a pre-existing bug. The recent 4aee1ce commit correctly fixed the tax compounding issue (closed #60) but the inclusive-tax + discount interaction was never handled in any prior commit.
Bug Description
When a product is configured with
tax_type = 'inclusive'(price already contains tax) and an order-level discount is applied, the order total is incorrectly inflated. The code adds the extracted tax component on top of a discounted subtotal that already includes the tax inside it.Steps to Reproduce
tax_type = 'inclusive',tax_rate = 5, price = ₹1000PATCH /orders/:id/discountExpected vs Actual
Root Cause
In
main/routes/orders.ts, when a discount is applied the code:discountedSubtotal = subtotal - discountAmountnewTaxAmount = freshTax × (discountedSubtotal / subtotal)total = discountedSubtotal + newTaxAmountFor exclusive tax this is correct — tax is separate from the price.
For inclusive tax,
subtotalalready contains the tax. After discounting,discountedSubtotalstill contains the embedded tax — addingnewTaxAmounton top is double-counting.Affected Code
main/routes/orders.ts—PATCH /:id/discounthandler (~line 695)main/routes/orders.ts—POST /:id/itemsadd-items recalculation (~line 396)main/routes/orders.ts—PATCH /:id/items/:itemId/discountorder recalculation (~line 884)Suggested Fix
The ratio approach needs to be aware of tax type. Options:
Option A (simpler): Separate the order subtotal into inclusive and exclusive portions before applying the ratio. Only add
newTaxAmountto the exclusive portion; the inclusive portion needs no additional tax added.Option B (more correct): Rather than scaling the original
freshTaxby ratio at the order level, recalculate item-level tax properly by runningcomputeTaxAmount('inclusive', discountedItemSubtotal, rate)per item after the discount is applied — matching how item creation works.Impact
tax_type = 'inclusive'products + an order-level discount applied simultaneouslyNot Introduced By Recent Commits
This is a pre-existing bug. The recent
4aee1cecommit correctly fixed the tax compounding issue (closed #60) but the inclusive-tax + discount interaction was never handled in any prior commit.