fix(core-flows, medusa): Prevent cart addresses duplication on update (#13841)
* Allow id field in addresses properties for cart update validator * Update cart addresses in update step where id is provided, both reference and nested fields * Add tests * Add changeset * Remove unnecessary map step * Review changes
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import {
|
||||
ICartModuleService,
|
||||
UpdateAddressDTO,
|
||||
UpdateCartDTO,
|
||||
UpdateCartWorkflowInputDTO,
|
||||
} from "@medusajs/framework/types"
|
||||
@@ -46,17 +47,53 @@ export const updateCartsStep = createStep(
|
||||
{ select: selects, relations }
|
||||
)
|
||||
|
||||
// Since service factory udpate method will correctly keep the reference to the addresses,
|
||||
// but won't update its fields, we do this separately
|
||||
const addressesInput = data
|
||||
.flatMap((cart) => [cart.shipping_address, cart.billing_address])
|
||||
.filter((address) => !!address)
|
||||
let addressesToUpdateIds: string[] = []
|
||||
const addressesToUpdate = addressesInput.filter(
|
||||
(address): address is UpdateAddressDTO => {
|
||||
if ("id" in address && !!address.id) {
|
||||
addressesToUpdateIds.push(address.id as string)
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
)
|
||||
const addressesBeforeUpdate = await cartModule.listAddresses({
|
||||
id: addressesToUpdate.map((address) => address.id),
|
||||
})
|
||||
if (addressesToUpdate.length) {
|
||||
await cartModule.updateAddresses(addressesToUpdate)
|
||||
}
|
||||
|
||||
const updatedCart = await cartModule.updateCarts(data)
|
||||
|
||||
return new StepResponse(updatedCart, cartsBeforeUpdate)
|
||||
return new StepResponse(updatedCart, {
|
||||
cartsBeforeUpdate,
|
||||
addressesBeforeUpdate,
|
||||
})
|
||||
},
|
||||
async (cartsBeforeUpdate, { container }) => {
|
||||
if (!cartsBeforeUpdate) {
|
||||
async (dataToCompensate, { container }) => {
|
||||
if (!dataToCompensate) {
|
||||
return
|
||||
}
|
||||
|
||||
const { cartsBeforeUpdate, addressesBeforeUpdate } = dataToCompensate
|
||||
|
||||
const cartModule = container.resolve<ICartModuleService>(Modules.CART)
|
||||
|
||||
const addressesToUpdate: UpdateAddressDTO[] = []
|
||||
for (const address of addressesBeforeUpdate) {
|
||||
addressesToUpdate.push({
|
||||
...address,
|
||||
metadata: address.metadata ?? undefined
|
||||
})
|
||||
}
|
||||
await cartModule.updateAddresses(addressesToUpdate)
|
||||
|
||||
const dataToUpdate: UpdateCartDTO[] = []
|
||||
|
||||
for (const cart of cartsBeforeUpdate) {
|
||||
|
||||
@@ -43,13 +43,17 @@ export const StoreRemoveCartPromotions = z
|
||||
})
|
||||
.strict()
|
||||
|
||||
const StoreCartUpsertAddress = AddressPayload.merge(z.object({
|
||||
id: z.string().optional(),
|
||||
}))
|
||||
|
||||
export type StoreUpdateCartType = z.infer<typeof UpdateCart>
|
||||
export const UpdateCart = z
|
||||
.object({
|
||||
region_id: z.string().optional(),
|
||||
email: z.string().email().nullish(),
|
||||
billing_address: z.union([AddressPayload, z.string()]).optional(),
|
||||
shipping_address: z.union([AddressPayload, z.string()]).optional(),
|
||||
billing_address: z.union([StoreCartUpsertAddress, z.string()]).optional(),
|
||||
shipping_address: z.union([StoreCartUpsertAddress, z.string()]).optional(),
|
||||
sales_channel_id: z.string().nullish(),
|
||||
metadata: z.record(z.unknown()).nullish(),
|
||||
promo_codes: z.array(z.string()).optional(),
|
||||
|
||||
Reference in New Issue
Block a user