From 4dbf46f2cb64240092843ebfdef766ec5b2a7116 Mon Sep 17 00:00:00 2001 From: Nicolas Gorga <62995075+NicolasGorga@users.noreply.github.com> Date: Tue, 9 Dec 2025 15:28:22 -0300 Subject: [PATCH] fix(utils): avoid inflating refundable_total for tax inclusive pricing (#14237) * Prevent refundable_total inflation for tax inclusive item pricing * Add tests * Add changeset * Update changeset * Review changes --- .changeset/better-memes-move.md | 5 +++ .../core/utils/src/totals/__tests__/totals.ts | 37 +++++++++++++++++++ .../core/utils/src/totals/line-item/index.ts | 1 + packages/core/utils/src/totals/tax/index.ts | 5 +++ 4 files changed, 48 insertions(+) create mode 100644 .changeset/better-memes-move.md diff --git a/.changeset/better-memes-move.md b/.changeset/better-memes-move.md new file mode 100644 index 0000000000..f7a8f389c6 --- /dev/null +++ b/.changeset/better-memes-move.md @@ -0,0 +1,5 @@ +--- +"@medusajs/utils": patch +--- + +fix(utils): avoid inflating refundable_total for tax inclusive pricing diff --git a/packages/core/utils/src/totals/__tests__/totals.ts b/packages/core/utils/src/totals/__tests__/totals.ts index f9dc364efd..16bf0d1f4e 100644 --- a/packages/core/utils/src/totals/__tests__/totals.ts +++ b/packages/core/utils/src/totals/__tests__/totals.ts @@ -1267,4 +1267,41 @@ describe("Total calculation", function () { total: 0, }) }) + + it("should calculate refundable_total for tax inclusive items without inflating tax", function () { + const cartTaxInclusive = { + items: [ + { + unit_price: 100, + quantity: 2, + is_tax_inclusive: true, + detail: { + fulfilled_quantity: 2, + shipped_quantity: 2, + return_requested_quantity: 0, + return_received_quantity: 0, + return_dismissed_quantity: 0, + written_off_quantity: 0, + }, + tax_lines: [ + { + rate: 20, + }, + ], + adjustments: [ + { + amount: 10, + }, + ], + }, + ], + } + + const serializedTaxInclusive = JSON.parse( + JSON.stringify(decorateCartTotals(cartTaxInclusive)) + ) + + expect(serializedTaxInclusive.items[0].refundable_total).toBe(188) + expect(serializedTaxInclusive.items[0].refundable_total_per_unit).toBe(94) + }) }) diff --git a/packages/core/utils/src/totals/line-item/index.ts b/packages/core/utils/src/totals/line-item/index.ts index 67aa77537e..083ed65077 100644 --- a/packages/core/utils/src/totals/line-item/index.ts +++ b/packages/core/utils/src/totals/line-item/index.ts @@ -94,6 +94,7 @@ function setRefundableTotal( ) const taxTotal = calculateTaxTotal({ + isTaxInclusive: item.is_tax_inclusive, taxLines: item.tax_lines || [], taxableAmount: refundableSubTotal, }) diff --git a/packages/core/utils/src/totals/tax/index.ts b/packages/core/utils/src/totals/tax/index.ts index a9ceb2c656..7376118817 100644 --- a/packages/core/utils/src/totals/tax/index.ts +++ b/packages/core/utils/src/totals/tax/index.ts @@ -3,15 +3,20 @@ import { BigNumber } from "../big-number" import { MathBN } from "../math" export function calculateTaxTotal({ + isTaxInclusive = false, taxLines, taxableAmount, setTotalField, }: { + isTaxInclusive?: boolean taxLines: Pick[] taxableAmount: BigNumberInput setTotalField?: string }) { let taxTotal = MathBN.convert(0) + if (isTaxInclusive) { + return taxTotal + } for (const taxLine of taxLines) { const rate = MathBN.div(taxLine.rate, 100)