fix: Update tax lines on cart when region changes (#9367)

**What**
- Removes broken cart retrieval step `retrieveWithCartLinks` in favor of `useRemoteQueryStep` in `updateTaxLinesWorkflows`

**Why**
- Filters variables in the step were passed with an incorrect shape
  - I removed the step, since it's only used once and the behavior is identical to the generic remote query step

**Note**
- Because the filters were passed incorrectly, the, now-removed, step has always returned the first cart in the database. As a result all tax calculations so far have been based on whatever the shape of that cart has. It basically ignores all input to this workflow
This commit is contained in:
Oli Juhl
2024-09-30 13:55:54 +02:00
committed by GitHub
parent 852df3f764
commit 8851ae7b51
9 changed files with 151 additions and 63 deletions

View File

@@ -1001,6 +1001,137 @@ medusaIntegrationTestRunner({
)
})
it("should update tax lines on cart items when region changes", async () => {
await setupTaxStructure(taxModule)
const region = await regionModule.createRegions({
name: "us",
currency_code: "usd",
countries: ["us"],
})
const otherRegion = await regionModule.createRegions({
name: "dk",
currency_code: "dkk",
countries: ["dk"],
})
const salesChannel = await scModule.createSalesChannels({
name: "Webshop",
})
const [productWithDefaultTax] = await productModule.createProducts([
{
title: "Test product default tax",
variants: [
{ title: "Test variant default tax", manage_inventory: false },
],
},
])
const [priceSetDefaultTax] = await pricingModule.createPriceSets([
{
prices: [{ amount: 2000, currency_code: "usd" }],
},
])
await remoteLink.create([
{
Product: {
variant_id: productWithDefaultTax.variants[0].id,
},
Pricing: { price_set_id: priceSetDefaultTax.id },
},
])
await api.post(
"/admin/price-preferences",
{
attribute: "currency_code",
value: "usd",
is_tax_inclusive: true,
},
adminHeaders
)
let response = await api.post(
`/store/carts`,
{
sales_channel_id: salesChannel.id,
shipping_address: {
country_code: "us",
},
region_id: region.id,
items: [
{
variant_id: productWithDefaultTax.variants[0].id,
quantity: 1,
},
],
},
storeHeaders
)
expect(response.data.cart).toEqual(
expect.objectContaining({
id: response.data.cart.id,
currency_code: "usd",
region_id: region.id,
items: expect.arrayContaining([
expect.objectContaining({
unit_price: 2000,
quantity: 1,
title: "Test variant default tax",
tax_lines: [
// Uses the california default rate
expect.objectContaining({
description: "US Default Rate",
code: "US_DEF",
rate: 2,
provider_id: "system",
}),
],
}),
]),
})
)
response = await api.post(
`/store/carts/${response.data.cart.id}`,
{
region_id: otherRegion.id,
shipping_address: {
country_code: "dk",
},
},
storeHeaders
)
expect(response.data.cart).toEqual(
expect.objectContaining({
id: response.data.cart.id,
currency_code: "dkk",
region_id: otherRegion.id,
items: expect.arrayContaining([
expect.objectContaining({
unit_price: 2000,
quantity: 1,
title: "Test variant default tax",
tax_lines: [
// Uses the danish default rate
expect.objectContaining({
description: "Denmark Default Rate",
code: "DK_DEF",
rate: 25,
provider_id: "system",
}),
],
}),
]),
})
)
})
it("should remove invalid shipping methods", async () => {
await setupTaxStructure(taxModule)
@@ -1714,6 +1845,7 @@ medusaIntegrationTestRunner({
name: "US",
currency_code: "usd",
automatic_taxes: false,
countries: ["us"],
})
const cart = await cartModule.createCarts({

View File

@@ -16,12 +16,11 @@ export * from "./get-variant-price-sets"
export * from "./get-variants"
export * from "./prepare-adjustments-from-promotion-actions"
export * from "./refresh-cart-shipping-methods"
export * from "./reserve-inventory"
export * from "./remove-line-item-adjustments"
export * from "./remove-shipping-method-adjustments"
export * from "./remove-shipping-method-from-cart"
export * from "./reserve-inventory"
export * from "./retrieve-cart"
export * from "./retrieve-cart-with-links"
export * from "./set-tax-lines-for-items"
export * from "./update-cart-promotions"
export * from "./update-carts"
@@ -29,3 +28,4 @@ export * from "./update-line-items"
export * from "./validate-cart-payments"
export * from "./validate-cart-shipping-options"
export * from "./validate-variant-prices"

View File

@@ -1,41 +0,0 @@
import { CartWorkflowDTO } from "@medusajs/framework/types"
import { ContainerRegistrationKeys, isObject } from "@medusajs/framework/utils"
import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk"
export interface RetrieveCartWithLinksStepInput {
cart_or_cart_id: string | CartWorkflowDTO
fields: string[]
}
export const retrieveCartWithLinksStepId = "retrieve-cart-with-links"
/**
* This step retrieves a cart's details with its linked records.
*/
export const retrieveCartWithLinksStep = createStep(
retrieveCartWithLinksStepId,
async (data: RetrieveCartWithLinksStepInput, { container }) => {
const { cart_or_cart_id: cartOrCartId, fields } = data
if (isObject(cartOrCartId)) {
return new StepResponse(cartOrCartId)
}
const id = cartOrCartId
const remoteQuery = container.resolve(
ContainerRegistrationKeys.REMOTE_QUERY
)
const query = {
entryPoint: "cart",
fields,
variables: {
cart: {
id,
},
},
}
const [cart] = await remoteQuery(query)
return new StepResponse(cart)
}
)

View File

@@ -112,7 +112,7 @@ export const addShippingMethodToWorkflow = createWorkflow(
updateTaxLinesWorkflow.runAsStep({
input: {
cart_or_cart_id: input.cart_id,
cart_id: input.cart_id,
shipping_methods: shippingMethodsToAdd,
},
})

View File

@@ -124,7 +124,7 @@ export const addToCartWorkflow = createWorkflow(
refreshCartShippingMethodsStep({ cart }),
updateTaxLinesWorkflow.runAsStep({
input: {
cart_or_cart_id: input.cart.id,
cart_id: input.cart.id,
items,
},
})

View File

@@ -155,7 +155,7 @@ export const createCartWorkflow = createWorkflow(
updateTaxLinesWorkflow.runAsStep({
input: {
cart_or_cart_id: cart.id,
cart_id: cart.id,
},
})

View File

@@ -96,7 +96,7 @@ export const updateCartWorkflow = createWorkflow(
refreshCartShippingMethodsStep({ cart }),
updateTaxLinesWorkflow.runAsStep({
input: {
cart_or_cart_id: carts[0].id,
cart_id: carts[0].id,
},
})
)

View File

@@ -1,18 +1,14 @@
import {
CartLineItemDTO,
CartShippingMethodDTO,
CartWorkflowDTO,
} from "@medusajs/framework/types"
import {
WorkflowData,
createWorkflow,
transform,
} from "@medusajs/framework/workflows-sdk"
import {
getItemTaxLinesStep,
retrieveCartWithLinksStep,
setTaxLinesForItemsStep,
} from "../steps"
import { useRemoteQueryStep } from "../../common"
import { getItemTaxLinesStep, setTaxLinesForItemsStep } from "../steps"
const cartFields = [
"id",
@@ -61,7 +57,7 @@ const cartFields = [
]
export type UpdateTaxLinesWorkflowInput = {
cart_or_cart_id: string | CartWorkflowDTO
cart_id: string
items?: CartLineItemDTO[]
shipping_methods?: CartShippingMethodDTO[]
force_tax_calculation?: boolean
@@ -74,17 +70,20 @@ export const updateTaxLinesWorkflowId = "update-tax-lines"
export const updateTaxLinesWorkflow = createWorkflow(
updateTaxLinesWorkflowId,
(input: WorkflowData<UpdateTaxLinesWorkflowInput>): WorkflowData<void> => {
const cart = retrieveCartWithLinksStep({
cart_or_cart_id: input.cart_or_cart_id,
const cart = useRemoteQueryStep({
entry_point: "cart",
fields: cartFields,
variables: {
id: input.cart_id,
},
list: false,
})
const taxLineItems = getItemTaxLinesStep(
transform({ input, cart }, (data) => ({
cart: data.cart,
items: data.input.items || data.cart.items,
shipping_methods:
data.input.shipping_methods || data.cart.shipping_methods,
shipping_methods: data.input.shipping_methods || data.cart.shipping_methods,
force_tax_calculation: data.input.force_tax_calculation,
}))
)

View File

@@ -1,17 +1,15 @@
import { updateTaxLinesWorkflow } from "@medusajs/core-flows"
import { HttpTypes } from "@medusajs/framework/types"
import { MedusaRequest, MedusaResponse } from "../../../../../types/routing"
import { refetchCart } from "../../helpers"
import { HttpTypes } from "@medusajs/framework/types"
export const POST = async (
req: MedusaRequest,
res: MedusaResponse<HttpTypes.StoreCartResponse>
) => {
const workflow = updateTaxLinesWorkflow(req.scope)
await workflow.run({
await updateTaxLinesWorkflow(req.scope).run({
input: {
cart_or_cart_id: req.params.id,
cart_id: req.params.id,
force_tax_calculation: true,
},
})