From f4ae615a3eba9f1dc058c2c374c95dbb5a0fd423 Mon Sep 17 00:00:00 2001 From: Oli Juhl <59018053+olivermrbl@users.noreply.github.com> Date: Wed, 13 Aug 2025 21:06:19 +0200 Subject: [PATCH] fix(tax): Use correct rule reference for shipping (#13195) * fix(tax): Use correct rule reference * fix tests --- .../http/__tests__/cart/store/cart.spec.ts | 60 ++++++++++++++++- .../integration-tests/__tests__/index.spec.ts | 64 ++++++++++++++++++- .../tax/src/services/tax-module-service.ts | 2 +- 3 files changed, 122 insertions(+), 4 deletions(-) diff --git a/integration-tests/http/__tests__/cart/store/cart.spec.ts b/integration-tests/http/__tests__/cart/store/cart.spec.ts index 54c3f8c6c2..731e6d3376 100644 --- a/integration-tests/http/__tests__/cart/store/cart.spec.ts +++ b/integration-tests/http/__tests__/cart/store/cart.spec.ts @@ -45,7 +45,8 @@ medusaIntegrationTestRunner({ cart, customer, promotion, - shippingProfile + shippingProfile, + taxSeedData beforeAll(async () => { appContainer = getContainer() @@ -78,7 +79,7 @@ medusaIntegrationTestRunner({ ) ).data.shipping_profile - await setupTaxStructure(appContainer.resolve(Modules.TAX)) + taxSeedData = await setupTaxStructure(appContainer.resolve(Modules.TAX)) region = ( await api.post( @@ -4173,6 +4174,61 @@ medusaIntegrationTestRunner({ ) }) + it("should add shipping method with tax rate override to cart", async () => { + let taxRegion = ( + await api.get(`/admin/tax-regions?country_code=us`, adminHeaders) + ).data.tax_regions[0] + + // Create tax rate override for shipping option + await api.post( + `/admin/tax-rates`, + { + name: "Shipping Option Override", + tax_region_id: taxRegion.id, + rate: 25, + code: "T25", + is_combinable: false, + rules: [ + { + reference: "shipping_option", + reference_id: shippingOption.id, + }, + ], + is_default: false, + }, + adminHeaders + ) + + let response = await api.post( + `/store/carts/${cart.id}/shipping-methods`, + { option_id: shippingOption.id }, + storeHeaders + ) + + expect(response.status).toEqual(200) + expect(response.data.cart).toEqual( + expect.objectContaining({ + id: cart.id, + shipping_methods: expect.arrayContaining([ + expect.objectContaining({ + shipping_option_id: shippingOption.id, + amount: 1000, + is_tax_inclusive: true, + tax_lines: expect.arrayContaining([ + expect.objectContaining({ + id: expect.any(String), + description: "Shipping Option Override", + code: "T25", + rate: 25, + provider_id: "system", + }), + ]), + }), + ]), + }) + ) + }) + it("should throw when prices are not setup for shipping option", async () => { cart = ( await api.post( diff --git a/packages/modules/tax/integration-tests/__tests__/index.spec.ts b/packages/modules/tax/integration-tests/__tests__/index.spec.ts index beeea521fc..87eb559c5f 100644 --- a/packages/modules/tax/integration-tests/__tests__/index.spec.ts +++ b/packages/modules/tax/integration-tests/__tests__/index.spec.ts @@ -1,7 +1,7 @@ import { ITaxModuleService } from "@medusajs/framework/types" import { Module, Modules, toMikroORMEntity } from "@medusajs/framework/utils" -import { TaxModuleService } from "@services" import { moduleIntegrationTestRunner } from "@medusajs/test-utils" +import { TaxModuleService } from "@services" import { setupTaxStructure } from "../utils/setup-tax-structure" jest.setTimeout(30000) @@ -717,6 +717,68 @@ moduleIntegrationTestRunner({ ]) }) + it("prioritizes specific shipping rate over default rate", async () => { + const region = await service.createTaxRegions({ + country_code: "US", + provider_id: "tp_system", + default_tax_rate: { + code: "TEST", + name: "Test Rate", + rate: 5, + }, + }) + + const rate = await service.createTaxRates({ + tax_region_id: region.id, + name: "Shipping Rate", + code: "SHIPPING_TEST", + rate: 2, + }) + + const item = { + id: "shipping_test", + shipping_option_id: "so_1234", + quantity: 1, + } + + const calculationContext = { + address: { + country_code: "US", + }, + } + + let taxLines = await service.getTaxLines([item], calculationContext) + + expect(taxLines).toEqual([ + expect.objectContaining({ + rate_id: expect.any(String), + rate: 5, + code: "TEST", + name: "Test Rate", + }), + ]) + + await service.updateTaxRates(rate.id, { + rules: [ + { + reference: "shipping_option", + reference_id: "so_1234", + }, + ], + }) + + taxLines = await service.getTaxLines([item], calculationContext) + + expect(taxLines).toEqual([ + expect.objectContaining({ + rate_id: expect.any(String), + rate: 2, + code: "SHIPPING_TEST", + name: "Shipping Rate", + }), + ]) + }) + it("should delete tax rate", async () => { const region = await service.createTaxRegions({ country_code: "US", diff --git a/packages/modules/tax/src/services/tax-module-service.ts b/packages/modules/tax/src/services/tax-module-service.ts index 3c75b356bf..6971e9dc75 100644 --- a/packages/modules/tax/src/services/tax-module-service.ts +++ b/packages/modules/tax/src/services/tax-module-service.ts @@ -654,7 +654,7 @@ export default class TaxModuleService const matchingRules = rate.rules.filter((rule) => { if (isShipping) { return ( - rule.reference === "shipping" && + rule.reference === "shipping_option" && rule.reference_id === item.shipping_option_id ) }