fix(link-modules,core-flows): Carry over cart promotions to order promotions (#12920)
what: - Carry over cart promotions to order promotions
This commit is contained in:
1 parent
541e791b9b
commit
8c4228fc42
16 files changed
+150
-153
No files matched your search
@@ -0,0 +1,6 @@
|
||||
---
|
||||
"@medusajs/link-modules": patch
|
||||
"@medusajs/core-flows": patch
|
||||
---
|
||||
|
||||
fix(link-modules,core-flows): Carry over cart promotions to order promotions
|
||||
@@ -1252,6 +1252,60 @@ medusaIntegrationTestRunner({
|
||||
)
|
||||
})
|
||||
|
||||
it("should successfully complete cart with promotions", async () => {
|
||||
const oldCart = (
|
||||
await api.get(`/store/carts/${cart.id}`, storeHeaders)
|
||||
).data.cart
|
||||
|
||||
createCartCreditLinesWorkflow.run({
|
||||
input: [
|
||||
{
|
||||
cart_id: oldCart.id,
|
||||
amount: oldCart.total,
|
||||
currency_code: "usd",
|
||||
reference: "test",
|
||||
reference_id: "test",
|
||||
},
|
||||
],
|
||||
container: appContainer,
|
||||
})
|
||||
|
||||
const cartResponse = await api.post(
|
||||
`/store/carts/${cart.id}/complete`,
|
||||
{},
|
||||
storeHeaders
|
||||
)
|
||||
|
||||
const orderResponse = await api.get(
|
||||
`/store/orders/${cartResponse.data.order.id}?fields=+promotions.*`,
|
||||
storeHeaders
|
||||
)
|
||||
|
||||
expect(cartResponse.status).toEqual(200)
|
||||
expect(orderResponse.data.order).toEqual(
|
||||
expect.objectContaining({
|
||||
promotions: [
|
||||
expect.objectContaining({
|
||||
code: promotion.code,
|
||||
}),
|
||||
],
|
||||
items: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
unit_price: 1500,
|
||||
compare_at_unit_price: null,
|
||||
quantity: 1,
|
||||
adjustments: expect.arrayContaining([
|
||||
expect.objectContaining({
|
||||
amount: 100,
|
||||
code: promotion.code,
|
||||
}),
|
||||
]),
|
||||
}),
|
||||
]),
|
||||
})
|
||||
)
|
||||
})
|
||||
|
||||
it("should successfully complete cart without shipping for digital products", async () => {
|
||||
/**
|
||||
* Product has a shipping profile so cart item should not require shipping
|
||||
|
||||
@@ -36,6 +36,7 @@ export const cartFieldsForRefreshSteps = [
|
||||
"shipping_methods.tax_lines.*",
|
||||
"customer.*",
|
||||
"customer.groups.*",
|
||||
"promotions.id",
|
||||
"promotions.code",
|
||||
"payment_collection.id",
|
||||
"payment_collection.raw_amount",
|
||||
@@ -105,6 +106,7 @@ export const completeCartFields = [
|
||||
"credit_lines.*",
|
||||
"payment_collection.*",
|
||||
"payment_collection.payment_sessions.*",
|
||||
"promotions.id",
|
||||
"items.variant.id",
|
||||
"items.variant.product.id",
|
||||
"items.variant.product.is_giftcard",
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import {
|
||||
CartCreditLineDTO,
|
||||
CartWorkflowDTO,
|
||||
LinkDefinition,
|
||||
PromotionDTO,
|
||||
UsageComputedActions,
|
||||
} from "@medusajs/framework/types"
|
||||
import {
|
||||
@@ -326,13 +328,22 @@ export const completeCartWorkflow = createWorkflow(
|
||||
const linksToCreate = transform(
|
||||
{ cart, createdOrder },
|
||||
({ cart, createdOrder }) => {
|
||||
const links: Record<string, any>[] = [
|
||||
const links: LinkDefinition[] = [
|
||||
{
|
||||
[Modules.ORDER]: { order_id: createdOrder.id },
|
||||
[Modules.CART]: { cart_id: cart.id },
|
||||
},
|
||||
]
|
||||
|
||||
if (cart.promotions?.length) {
|
||||
cart.promotions.forEach((promotion: PromotionDTO) => {
|
||||
links.push({
|
||||
[Modules.ORDER]: { order_id: createdOrder.id },
|
||||
[Modules.PROMOTION]: { promotion_id: promotion.id },
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
if (isDefined(cart.payment_collection?.id)) {
|
||||
links.push({
|
||||
[Modules.ORDER]: { order_id: createdOrder.id },
|
||||
|
||||
@@ -27,10 +27,8 @@ export const draftOrderFieldsForRefreshSteps = [
|
||||
"shipping_methods.tax_lines.*",
|
||||
"customer.*",
|
||||
"customer.groups.*",
|
||||
"promotion_link.*",
|
||||
"promotion_link.promotion",
|
||||
"promotion_link.promotion.id",
|
||||
"promotion_link.promotion.code",
|
||||
"promotions.id",
|
||||
"promotions.code",
|
||||
"subtotal",
|
||||
"item_total",
|
||||
"total",
|
||||
|
||||
@@ -52,7 +52,8 @@ export const addDraftOrderItemsWorkflow = createWorkflow(
|
||||
function (
|
||||
input: WorkflowData<OrderWorkflow.OrderEditAddNewItemWorkflowInput>
|
||||
) {
|
||||
const order: OrderDTO = useRemoteQueryStep({
|
||||
const order: OrderDTO & { promotions: { code: string }[] } =
|
||||
useRemoteQueryStep({
|
||||
entry_point: "orders",
|
||||
fields: draftOrderFieldsForRefreshSteps,
|
||||
variables: { id: input.order_id },
|
||||
@@ -92,19 +93,10 @@ export const addDraftOrderItemsWorkflow = createWorkflow(
|
||||
},
|
||||
})
|
||||
|
||||
const appliedPromoCodes: string[] = transform(order, (order) => {
|
||||
const promotionLink = (order as any).promotion_link
|
||||
|
||||
if (!promotionLink) {
|
||||
return []
|
||||
}
|
||||
|
||||
if (Array.isArray(promotionLink)) {
|
||||
return promotionLink.map((promo) => promo.promotion.code)
|
||||
}
|
||||
|
||||
return [promotionLink.promotion.code]
|
||||
})
|
||||
const appliedPromoCodes: string[] = transform(
|
||||
order,
|
||||
(order) => order.promotions?.map((promotion) => promotion.code) ?? []
|
||||
)
|
||||
|
||||
// If any the order has any promo codes, then we need to refresh the adjustments.
|
||||
when(
|
||||
|
||||
+9
-14
@@ -69,7 +69,11 @@ export interface AddDraftOrderShippingMethodsWorkflowInput {
|
||||
export const addDraftOrderShippingMethodsWorkflow = createWorkflow(
|
||||
addDraftOrderShippingMethodsWorkflowId,
|
||||
function (input: WorkflowData<AddDraftOrderShippingMethodsWorkflowInput>) {
|
||||
const order: OrderDTO = useRemoteQueryStep({
|
||||
const order: OrderDTO & {
|
||||
promotions: {
|
||||
code: string
|
||||
}[]
|
||||
} = useRemoteQueryStep({
|
||||
entry_point: "orders",
|
||||
fields: draftOrderFieldsForRefreshSteps,
|
||||
variables: { id: input.order_id },
|
||||
@@ -133,19 +137,10 @@ export const addDraftOrderShippingMethodsWorkflow = createWorkflow(
|
||||
},
|
||||
})
|
||||
|
||||
const appliedPromoCodes = transform(order, (order) => {
|
||||
const promotionLink = (order as any).promotion_link
|
||||
|
||||
if (!promotionLink) {
|
||||
return []
|
||||
}
|
||||
|
||||
if (Array.isArray(promotionLink)) {
|
||||
return promotionLink.map((promo) => promo.promotion.code)
|
||||
}
|
||||
|
||||
return [promotionLink.promotion.code]
|
||||
})
|
||||
const appliedPromoCodes: string[] = transform(
|
||||
order,
|
||||
(order) => order.promotions?.map((promotion) => promotion.code) ?? []
|
||||
)
|
||||
|
||||
// If any the order has any promo codes, then we need to refresh the adjustments.
|
||||
when(
|
||||
|
||||
@@ -52,7 +52,11 @@ export interface CancelDraftOrderEditWorkflowInput {
|
||||
export const cancelDraftOrderEditWorkflow = createWorkflow(
|
||||
cancelDraftOrderEditWorkflowId,
|
||||
function (input: WorkflowData<CancelDraftOrderEditWorkflowInput>) {
|
||||
const order: OrderDTO = useRemoteQueryStep({
|
||||
const order: OrderDTO & {
|
||||
promotions: {
|
||||
code: string
|
||||
}[]
|
||||
} = useRemoteQueryStep({
|
||||
entry_point: "orders",
|
||||
fields: ["version", ...draftOrderFieldsForRefreshSteps],
|
||||
variables: { id: input.order_id },
|
||||
@@ -125,18 +129,12 @@ export const cancelDraftOrderEditWorkflow = createWorkflow(
|
||||
const promotionsToRefresh = transform(
|
||||
{ order, promotionsToRemove, promotionsToRestore },
|
||||
({ order, promotionsToRemove, promotionsToRestore }) => {
|
||||
const promotionLink = (order as any).promotion_link
|
||||
const orderPromotions = order.promotions
|
||||
const codes: Set<string> = new Set()
|
||||
|
||||
if (promotionLink) {
|
||||
if (Array.isArray(promotionLink)) {
|
||||
promotionLink.forEach((promo) => {
|
||||
codes.add(promo.promotion.code)
|
||||
orderPromotions?.forEach((promo) => {
|
||||
codes.add(promo.code)
|
||||
})
|
||||
} else {
|
||||
codes.add(promotionLink.promotion.code)
|
||||
}
|
||||
}
|
||||
|
||||
for (const code of promotionsToRemove) {
|
||||
codes.delete(code)
|
||||
@@ -163,9 +161,7 @@ export const cancelDraftOrderEditWorkflow = createWorkflow(
|
||||
},
|
||||
})
|
||||
|
||||
when(shippingToRestore, (methods) => {
|
||||
return !!methods?.length
|
||||
}).then(() => {
|
||||
when(shippingToRestore, (methods) => !!methods?.length).then(() => {
|
||||
restoreDraftOrderShippingMethodsStep({
|
||||
shippingMethods: shippingToRestore as any,
|
||||
})
|
||||
|
||||
+7
-14
@@ -50,7 +50,11 @@ export const removeDraftOrderActionItemWorkflow = createWorkflow(
|
||||
function (
|
||||
input: WorkflowData<OrderWorkflow.DeleteOrderEditItemActionWorkflowInput>
|
||||
): WorkflowResponse<OrderPreviewDTO> {
|
||||
const order: OrderDTO = useRemoteQueryStep({
|
||||
const order: OrderDTO & {
|
||||
promotions: {
|
||||
code: string
|
||||
}[]
|
||||
} = useRemoteQueryStep({
|
||||
entry_point: "orders",
|
||||
fields: ["id", "status", "is_draft_order", "canceled_at", "items.*"],
|
||||
variables: { id: input.order_id },
|
||||
@@ -89,19 +93,8 @@ export const removeDraftOrderActionItemWorkflow = createWorkflow(
|
||||
|
||||
const appliedPromoCodes: string[] = transform(
|
||||
refetchedOrder,
|
||||
(refetchedOrder) => {
|
||||
const promotionLink = (refetchedOrder as any).promotion_link
|
||||
|
||||
if (!promotionLink) {
|
||||
return []
|
||||
}
|
||||
|
||||
if (Array.isArray(promotionLink)) {
|
||||
return promotionLink.map((promo) => promo.promotion.code)
|
||||
}
|
||||
|
||||
return [promotionLink.promotion.code]
|
||||
}
|
||||
(refetchedOrder) =>
|
||||
refetchedOrder.promotions?.map((promotion) => promotion.code) ?? []
|
||||
)
|
||||
|
||||
// If any the order has any promo codes, then we need to refresh the adjustments.
|
||||
|
||||
+5
-13
@@ -100,19 +100,11 @@ export const removeDraftOrderActionShippingMethodWorkflow = createWorkflow(
|
||||
order,
|
||||
})
|
||||
|
||||
const appliedPromoCodes = transform(context, (context) => {
|
||||
const promotionLink = (context as any).promotion_link
|
||||
|
||||
if (!promotionLink) {
|
||||
return []
|
||||
}
|
||||
|
||||
if (Array.isArray(promotionLink)) {
|
||||
return promotionLink.map((promo) => promo.promotion.code)
|
||||
}
|
||||
|
||||
return [promotionLink.promotion.code]
|
||||
})
|
||||
const appliedPromoCodes: string[] = transform(
|
||||
context,
|
||||
(context) =>
|
||||
(context as any).promotions?.map((promotion) => promotion.code) ?? []
|
||||
)
|
||||
|
||||
when(
|
||||
appliedPromoCodes,
|
||||
|
||||
+9
-14
@@ -61,7 +61,11 @@ export interface RemoveDraftOrderShippingMethodWorkflowInput {
|
||||
export const removeDraftOrderShippingMethodWorkflow = createWorkflow(
|
||||
removeDraftOrderShippingMethodWorkflowId,
|
||||
function (input: WorkflowData<RemoveDraftOrderShippingMethodWorkflowInput>) {
|
||||
const order: OrderDTO = useRemoteQueryStep({
|
||||
const order: OrderDTO & {
|
||||
promotions: {
|
||||
code: string
|
||||
}[]
|
||||
} = useRemoteQueryStep({
|
||||
entry_point: "orders",
|
||||
fields: draftOrderFieldsForRefreshSteps,
|
||||
variables: { id: input.order_id },
|
||||
@@ -89,19 +93,10 @@ export const removeDraftOrderShippingMethodWorkflow = createWorkflow(
|
||||
},
|
||||
})
|
||||
|
||||
const appliedPromoCodes = transform(order, (order) => {
|
||||
const promotionLink = (order as any).promotion_link
|
||||
|
||||
if (!promotionLink) {
|
||||
return []
|
||||
}
|
||||
|
||||
if (Array.isArray(promotionLink)) {
|
||||
return promotionLink.map((promo) => promo.promotion.code)
|
||||
}
|
||||
|
||||
return [promotionLink.promotion.code]
|
||||
})
|
||||
const appliedPromoCodes: string[] = transform(
|
||||
order,
|
||||
(order) => order.promotions?.map((promotion) => promotion.code) ?? []
|
||||
)
|
||||
|
||||
// If any the order has any promo codes, then we need to refresh the adjustments.
|
||||
when(
|
||||
|
||||
+10
-14
@@ -53,7 +53,11 @@ export const updateDraftOrderActionItemWorkflow = createWorkflow(
|
||||
function (
|
||||
input: WorkflowData<OrderWorkflow.UpdateOrderEditAddNewItemWorkflowInput>
|
||||
) {
|
||||
const order: OrderDTO = useRemoteQueryStep({
|
||||
const order: OrderDTO & {
|
||||
promotions: {
|
||||
code: string
|
||||
}[]
|
||||
} = useRemoteQueryStep({
|
||||
entry_point: "orders",
|
||||
fields: draftOrderFieldsForRefreshSteps,
|
||||
variables: { id: input.order_id },
|
||||
@@ -112,19 +116,11 @@ export const updateDraftOrderActionItemWorkflow = createWorkflow(
|
||||
order,
|
||||
})
|
||||
|
||||
const appliedPromoCodes: string[] = transform(context, (context) => {
|
||||
const promotionLink = (context as any).promotion_link
|
||||
|
||||
if (!promotionLink) {
|
||||
return []
|
||||
}
|
||||
|
||||
if (Array.isArray(promotionLink)) {
|
||||
return promotionLink.map((promo) => promo.promotion.code)
|
||||
}
|
||||
|
||||
return [promotionLink.promotion.code]
|
||||
})
|
||||
const appliedPromoCodes: string[] = transform(
|
||||
context,
|
||||
(context) =>
|
||||
(context as any).promotions?.map((promotion) => promotion.code) ?? []
|
||||
)
|
||||
|
||||
// If any the order has any promo codes, then we need to refresh the adjustments.
|
||||
when(
|
||||
|
||||
+5
-13
@@ -142,19 +142,11 @@ export const updateDraftOrderActionShippingMethodWorkflow = createWorkflow(
|
||||
order,
|
||||
})
|
||||
|
||||
const appliedPromoCodes = transform(context, (context) => {
|
||||
const promotionLink = (context as any).promotion_link
|
||||
|
||||
if (!promotionLink) {
|
||||
return []
|
||||
}
|
||||
|
||||
if (Array.isArray(promotionLink)) {
|
||||
return promotionLink.map((promo) => promo.promotion.code)
|
||||
}
|
||||
|
||||
return [promotionLink.promotion.code]
|
||||
})
|
||||
const appliedPromoCodes: string[] = transform(
|
||||
context,
|
||||
(context) =>
|
||||
(context as any).promotions?.map((promotion) => promotion.code) ?? []
|
||||
)
|
||||
|
||||
when(
|
||||
appliedPromoCodes,
|
||||
|
||||
@@ -115,19 +115,11 @@ export const updateDraftOrderItemWorkflow = createWorkflow(
|
||||
order,
|
||||
})
|
||||
|
||||
const appliedPromoCodes: string[] = transform(context, (context) => {
|
||||
const promotionLink = (context as any).promotion_link
|
||||
|
||||
if (!promotionLink) {
|
||||
return []
|
||||
}
|
||||
|
||||
if (Array.isArray(promotionLink)) {
|
||||
return promotionLink.map((promo) => promo.promotion.code)
|
||||
}
|
||||
|
||||
return [promotionLink.promotion.code]
|
||||
})
|
||||
const appliedPromoCodes: string[] = transform(
|
||||
context,
|
||||
(context) =>
|
||||
(context as any).promotions?.map((promotion) => promotion.code) ?? []
|
||||
)
|
||||
|
||||
// If any the order has any promo codes, then we need to refresh the adjustments.
|
||||
when(
|
||||
|
||||
+5
-13
@@ -123,19 +123,11 @@ export const updateDraftOrderShippingMethodWorkflow = createWorkflow(
|
||||
throw_if_key_not_found: true,
|
||||
}).config({ name: "refetched-order-query" })
|
||||
|
||||
const appliedPromoCodes = transform(refetchedOrder, (refetchedOrder) => {
|
||||
const promotionLink = (refetchedOrder as any).promotion_link
|
||||
|
||||
if (!promotionLink) {
|
||||
return []
|
||||
}
|
||||
|
||||
if (Array.isArray(promotionLink)) {
|
||||
return promotionLink.map((promo) => promo.promotion.code)
|
||||
}
|
||||
|
||||
return [promotionLink.promotion.code]
|
||||
})
|
||||
const appliedPromoCodes = transform(
|
||||
refetchedOrder,
|
||||
(refetchedOrder) =>
|
||||
refetchedOrder.promotions?.map((promotion) => promotion.code) ?? []
|
||||
)
|
||||
|
||||
when(
|
||||
appliedPromoCodes,
|
||||
|
||||
@@ -32,7 +32,7 @@ export const OrderPromotion: ModuleJoinerConfig = {
|
||||
entity: "Promotion",
|
||||
primaryKey: "id",
|
||||
foreignKey: "promotion_id",
|
||||
alias: "promotion",
|
||||
alias: "promotions",
|
||||
args: {
|
||||
methodSuffix: "Promotions",
|
||||
},
|
||||
@@ -44,8 +44,8 @@ export const OrderPromotion: ModuleJoinerConfig = {
|
||||
serviceName: Modules.ORDER,
|
||||
entity: "Order",
|
||||
fieldAlias: {
|
||||
promotion: {
|
||||
path: "promotion_link.promotion",
|
||||
promotions: {
|
||||
path: "promotion_link.promotions",
|
||||
isList: true,
|
||||
},
|
||||
},
|
||||
@@ -54,16 +54,7 @@ export const OrderPromotion: ModuleJoinerConfig = {
|
||||
primaryKey: "order_id",
|
||||
foreignKey: "id",
|
||||
alias: "promotion_link",
|
||||
},
|
||||
},
|
||||
{
|
||||
serviceName: Modules.PROMOTION,
|
||||
entity: "Promotion",
|
||||
relationship: {
|
||||
serviceName: LINKS.OrderPromotion,
|
||||
primaryKey: "promotion_id",
|
||||
foreignKey: "id",
|
||||
alias: "order_link",
|
||||
isList: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
|
||||
Reference in new issue
Block a user