fix: Handle region updates on cart (1/n) (#9369)
**What**
On cart creation:
- If region only has one country -> create cart with country code
On cart updates:
- If shipping address country code is provided in input ->
- If cart region doesn't include that country -> throw
- If cart includes the country -> update shipping address
- If region is provided in input and is different from the one currently on the cart ->
- If there is a shipping address on the cart -> clear the address
- If the region only has one country -> set country code of address
- If there is not a shipping address on the cart ->
- If the region only has one country -> set country code of address
Closes CC-545
This commit is contained in:
@@ -18,7 +18,9 @@ export const findOneOrAnyRegionStep = createStep(
|
||||
|
||||
if (data.regionId) {
|
||||
try {
|
||||
const region = await service.retrieveRegion(data.regionId)
|
||||
const region = await service.retrieveRegion(data.regionId, {
|
||||
relations: ["countries"],
|
||||
})
|
||||
return new StepResponse(region)
|
||||
} catch (error) {
|
||||
return new StepResponse(null)
|
||||
@@ -31,9 +33,12 @@ export const findOneOrAnyRegionStep = createStep(
|
||||
throw new MedusaError(MedusaError.Types.NOT_FOUND, "Store not found")
|
||||
}
|
||||
|
||||
const [region] = await service.listRegions({
|
||||
id: store.default_region_id,
|
||||
})
|
||||
const [region] = await service.listRegions(
|
||||
{
|
||||
id: store.default_region_id,
|
||||
},
|
||||
{ relations: ["countries"] }
|
||||
)
|
||||
|
||||
if (!region) {
|
||||
return new StepResponse(null)
|
||||
|
||||
@@ -27,9 +27,6 @@ import { refreshPaymentCollectionForCartWorkflow } from "./refresh-payment-colle
|
||||
import { updateCartPromotionsWorkflow } from "./update-cart-promotions"
|
||||
import { updateTaxLinesWorkflow } from "./update-tax-lines"
|
||||
|
||||
// TODO: The createCartWorkflow are missing the following steps:
|
||||
// - Refresh/delete shipping methods (fulfillment module)
|
||||
|
||||
export const createCartWorkflowId = "create-cart"
|
||||
/**
|
||||
* This workflow creates a cart.
|
||||
@@ -119,6 +116,13 @@ export const createCartWorkflow = createWorkflow(
|
||||
data_.sales_channel_id = data.salesChannel.id
|
||||
}
|
||||
|
||||
// If there is only one country in the region, we prepare a shipping address with that country's code.
|
||||
if (!data.input.shipping_address && data.region.countries.length === 1) {
|
||||
data_.shipping_address = {
|
||||
country_code: data.region.countries[0].iso_2,
|
||||
}
|
||||
}
|
||||
|
||||
return data_
|
||||
}
|
||||
)
|
||||
|
||||
@@ -2,11 +2,7 @@ import {
|
||||
AdditionalData,
|
||||
UpdateCartWorkflowInputDTO,
|
||||
} from "@medusajs/framework/types"
|
||||
import {
|
||||
MedusaError,
|
||||
PromotionActions,
|
||||
isPresent,
|
||||
} from "@medusajs/framework/utils"
|
||||
import { MedusaError, PromotionActions } from "@medusajs/framework/utils"
|
||||
import {
|
||||
WorkflowData,
|
||||
WorkflowResponse,
|
||||
@@ -14,10 +10,10 @@ import {
|
||||
createWorkflow,
|
||||
parallelize,
|
||||
transform,
|
||||
when,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
import { useRemoteQueryStep } from "../../common"
|
||||
import {
|
||||
findOneOrAnyRegionStep,
|
||||
findOrCreateCustomerStep,
|
||||
findSalesChannelStep,
|
||||
refreshCartShippingMethodsStep,
|
||||
@@ -35,35 +31,85 @@ export const updateCartWorkflowId = "update-cart"
|
||||
export const updateCartWorkflow = createWorkflow(
|
||||
updateCartWorkflowId,
|
||||
(input: WorkflowData<UpdateCartWorkflowInputDTO & AdditionalData>) => {
|
||||
const [salesChannel, region, customerData] = parallelize(
|
||||
const cartToUpdate = useRemoteQueryStep({
|
||||
entry_point: "cart",
|
||||
variables: { id: input.id },
|
||||
fields: ["id", "shipping_address.*", "region.*", "region.countries.*"],
|
||||
list: false,
|
||||
throw_if_key_not_found: true,
|
||||
}).config({ name: "get-cart" })
|
||||
|
||||
const [salesChannel, customerData] = parallelize(
|
||||
findSalesChannelStep({
|
||||
salesChannelId: input.sales_channel_id,
|
||||
}),
|
||||
findOneOrAnyRegionStep({
|
||||
regionId: input.region_id,
|
||||
}),
|
||||
findOrCreateCustomerStep({
|
||||
customerId: input.customer_id,
|
||||
email: input.email,
|
||||
})
|
||||
)
|
||||
|
||||
const newRegion = when({ input }, (data) => {
|
||||
return !!data.input.region_id
|
||||
}).then(() => {
|
||||
return useRemoteQueryStep({
|
||||
entry_point: "region",
|
||||
variables: { id: input.region_id },
|
||||
fields: ["id", "countries.*", "currency_code", "name"],
|
||||
list: false,
|
||||
throw_if_key_not_found: true,
|
||||
}).config({ name: "get-region" })
|
||||
})
|
||||
|
||||
const region = transform({ cartToUpdate, newRegion }, (data) => {
|
||||
return data.newRegion ?? data.cartToUpdate.region
|
||||
})
|
||||
|
||||
const cartInput = transform(
|
||||
{ input, region, customerData, salesChannel },
|
||||
{ input, region, customerData, salesChannel, cartToUpdate },
|
||||
(data) => {
|
||||
const { promo_codes, ...updateCartData } = data.input
|
||||
const data_ = { ...updateCartData }
|
||||
|
||||
if (isPresent(updateCartData.region_id)) {
|
||||
if (!data.region) {
|
||||
const data_ = {
|
||||
...updateCartData,
|
||||
currency_code: data.region?.currency_code,
|
||||
region_id: data.region?.id, // This is either the region from the input or the region from the cart or null
|
||||
}
|
||||
|
||||
// When the region is updated, we do a few things:
|
||||
// - We need to make sure the provided shipping address country code is in the new region
|
||||
// - We clear the shipping address if the new region has more than one country
|
||||
const regionIsNew = data.region?.id !== data.cartToUpdate.region?.id
|
||||
const shippingAddress = data.input.shipping_address
|
||||
|
||||
if (shippingAddress?.country_code) {
|
||||
const country = data.region.countries.find(
|
||||
(c) => c.iso_2 === shippingAddress.country_code
|
||||
)
|
||||
|
||||
if (!country) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
"Region not found"
|
||||
MedusaError.Types.INVALID_DATA,
|
||||
`Country with code ${shippingAddress.country_code} is not within region ${data.region.name}`
|
||||
)
|
||||
}
|
||||
|
||||
data_.currency_code = data.region.currency_code
|
||||
data_.region_id = data.region.id
|
||||
data_.shipping_address = {
|
||||
...shippingAddress,
|
||||
country_code: country.iso_2,
|
||||
}
|
||||
}
|
||||
|
||||
if (regionIsNew) {
|
||||
if (data.region.countries.length === 1) {
|
||||
data_.shipping_address = {
|
||||
country_code: data.region.countries[0].iso_2,
|
||||
}
|
||||
}
|
||||
|
||||
if (!data_.shipping_address?.country_code) {
|
||||
data_.shipping_address = null
|
||||
}
|
||||
}
|
||||
|
||||
if (
|
||||
|
||||
Reference in New Issue
Block a user