Skip to content

bug: inclusive-tax items produce inflated total when order-level discount is applied #66

Description

@khaira777

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

  1. Create a product with tax_type = 'inclusive', tax_rate = 5, price = ₹1000
  2. Create an order with this product
  3. Apply a 10% order-level discount via PATCH /orders/:id/discount
  4. 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:

  1. Computes discountedSubtotal = subtotal - discountAmount
  2. Scales newTaxAmount = freshTax × (discountedSubtotal / subtotal)
  3. 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.tsPATCH /:id/discount handler (~line 695)
  • main/routes/orders.tsPOST /:id/items add-items recalculation (~line 396)
  • main/routes/orders.tsPATCH /: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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions