feat: carry over promotions toggle on exchanges (#14128)

* feat: carry over promotions toggle on exchanges

* fix: inital flag value, return the flag on preview

* fix: validation of allocation type

* fix: revert client changes

* fix: invert condition

* feat: recompute adjustments when outbound item is updated

* fix: condition again

* fix: display more accurate inbound/outbound totals for exchanges

* fix: make exchanges specs green

* feat: more testing cases

* wip: pr feedback

* fix: use plural for the flag on Admin

* fix: schema test, route refactor

* feat: tooltip

* feat: refactor to use update workflow

* feat: display applied promotion per item on order details, show copy sku on hover

* feat: refactor edits and exchanges to have common flag toggle flow

* fix: delete empty file

* fix: exchange_id param query
This commit is contained in:
Frane Polić
2025-11-30 19:31:31 +01:00
committed by GitHub
parent 9d1f09ac7b
commit 5da51064d7
40 changed files with 1367 additions and 214 deletions

View File

@@ -17,6 +17,7 @@ export * from "./delete-order-change-actions"
export * from "./delete-order-changes"
export * from "./delete-order-shipping-methods"
export * from "./exchange/cancel-exchange"
export * from "./list-order-change-actions-by-type"
export * from "./exchange/create-exchange"
export * from "./exchange/create-exchange-items-from-actions"
export * from "./exchange/delete-exchanges"

View File

@@ -0,0 +1,37 @@
import { IOrderModuleService } from "@medusajs/framework/types"
import { ChangeActionType, Modules } from "@medusajs/framework/utils"
import { StepResponse, createStep } from "@medusajs/framework/workflows-sdk"
/**
* This step lists order change actions filtered by action type.
*/
export const listOrderChangeActionsByTypeStep = createStep(
"list-order-change-actions-by-type",
async function (
{
order_change_id,
action_type,
}: {
order_change_id: string
action_type: ChangeActionType
},
{ container }
) {
const service = container.resolve<IOrderModuleService>(Modules.ORDER)
const actions = await service.listOrderChangeActions(
{
order_change_id,
},
{
select: ["id", "action"],
}
)
const filteredActions = actions.filter(
(action) => action.action === action_type
)
return new StepResponse(filteredActions.map((action) => action.id))
}
)

View File

@@ -0,0 +1,166 @@
import {
ComputeActionContext,
OrderChangeDTO,
OrderDTO,
PromotionDTO,
} from "@medusajs/framework/types"
import { ChangeActionType } from "@medusajs/framework/utils"
import {
createWorkflow,
transform,
when,
WorkflowData,
} from "@medusajs/framework/workflows-sdk"
import {
getActionsToComputeFromPromotionsStep,
prepareAdjustmentsFromPromotionActionsStep,
} from "../../cart"
import { previewOrderChangeStep } from "../steps/preview-order-change"
import { createOrderChangeActionsWorkflow } from "./create-order-change-actions"
import {
deleteOrderChangeActionsStep,
listOrderChangeActionsByTypeStep,
} from "../steps"
/**
* The data to compute adjustments for an order edit, exchange, claim, or return.
*/
export type ComputeAdjustmentsForPreviewWorkflowInput = {
/**
* The order's details.
*/
order: OrderDTO & { promotions: PromotionDTO[] }
/**
* The order change's details.
*/
orderChange: OrderChangeDTO
}
export const computeAdjustmentsForPreviewWorkflowId =
"compute-adjustments-for-preview"
/**
* This workflow computes adjustments for an order change if the carry over promotions flag is true on the order change.
* If the flag is false, it deletes the existing adjustments replacement actions.
*
* It is currently used as a part of the order edit and exchange flows.
* It's used by the [Add Items to Order Edit Admin API Route](https://docs.medusajs.com/api/admin#order-edits_postordereditsiditems),
* [Add Outbound Items Admin API Route](https://docs.medusajs.com/api/admin#exchanges_postexchangesidoutbounditems),
* and [Add Inbound Items Admin API Route](https://docs.medusajs.com/api/admin#exchanges_postexchangesidinbounditems).
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to compute adjustments
* in your custom flows.
*
* @example
* const { result } = await computeAdjustmentsForPreviewWorkflow(container)
* .run({
* input: {
* order: {
* id: "order_123",
* // other order details...
* },
* orderChange: {
* id: "orch_123",
* // other order change details...
* },
* exchange_id: "exchange_123", // optional, for exchanges
* }
* })
*
* @summary
*
* Compute adjustments for an order edit, exchange, claim, or return.
*/
export const computeAdjustmentsForPreviewWorkflow = createWorkflow(
computeAdjustmentsForPreviewWorkflowId,
function (input: WorkflowData<ComputeAdjustmentsForPreviewWorkflowInput>) {
const previewedOrder = previewOrderChangeStep(input.order.id)
when(
{ order: input.order },
({ order }) =>
/**
* Compute adjustments only if the flag on the order change is true
*/
!!order.promotions.length && !!input.orderChange.carry_over_promotions
).then(() => {
const actionsToComputeItemsInput = transform(
{ previewedOrder, order: input.order },
({ previewedOrder, order }) => {
return {
currency_code: order.currency_code,
items: previewedOrder.items.map((item) => ({
...item,
// Buy-Get promotions rely on the product ID, so we need to manually set it before refreshing adjustments
product: { id: item.product_id },
})),
} as ComputeActionContext
}
)
const orderPromotions = transform({ order: input.order }, ({ order }) => {
return order.promotions
.map((p) => p.code)
.filter((p) => p !== undefined)
})
const actions = getActionsToComputeFromPromotionsStep({
computeActionContext: actionsToComputeItemsInput,
promotionCodesToApply: orderPromotions,
})
const { lineItemAdjustmentsToCreate } =
prepareAdjustmentsFromPromotionActionsStep({ actions })
const orderChangeActionAdjustmentsInput = transform(
{
order: input.order,
previewedOrder,
orderChange: input.orderChange,
lineItemAdjustmentsToCreate,
},
({
order,
previewedOrder,
orderChange,
lineItemAdjustmentsToCreate,
}) => {
return previewedOrder.items.map((item) => {
const itemAdjustments = lineItemAdjustmentsToCreate.filter(
(adjustment) => adjustment.item_id === item.id
)
return {
order_change_id: orderChange.id,
order_id: order.id,
exchange_id: orderChange.exchange_id ?? undefined,
claim_id: orderChange.claim_id ?? undefined,
return_id: orderChange.return_id ?? undefined,
version: orderChange.version,
action: ChangeActionType.ITEM_ADJUSTMENTS_REPLACE,
details: {
reference_id: item.id,
adjustments: itemAdjustments,
},
}
})
}
)
createOrderChangeActionsWorkflow
.runAsStep({ input: orderChangeActionAdjustmentsInput })
.config({ name: "order-change-action-adjustments-input" })
})
when(
{ order: previewedOrder },
({ order }) => !order.order_change.carry_over_promotions
).then(() => {
const actionIds = listOrderChangeActionsByTypeStep({
order_change_id: input.orderChange.id,
action_type: ChangeActionType.ITEM_ADJUSTMENTS_REPLACE,
})
deleteOrderChangeActionsStep({ ids: actionIds })
})
}
)

View File

@@ -22,7 +22,7 @@ import {
} from "../../utils/order-validation"
import { addOrderLineItemsWorkflow } from "../add-line-items"
import { createOrderChangeActionsWorkflow } from "../create-order-change-actions"
import { computeAdjustmentsForPreviewWorkflow } from "../order-edit/compute-adjustments-for-preview"
import { computeAdjustmentsForPreviewWorkflow } from "../compute-adjustments-for-preview"
import { updateOrderTaxLinesWorkflow } from "../update-tax-lines"
import { refreshExchangeShippingWorkflow } from "./refresh-shipping"
@@ -140,7 +140,13 @@ export const orderExchangeAddNewItemWorkflow = createWorkflow(
const orderChange: OrderChangeDTO = useRemoteQueryStep({
entry_point: "order_change",
fields: ["id", "status", "version"],
fields: [
"id",
"status",
"version",
"exchange_id",
"carry_over_promotions",
],
variables: {
filters: {
order_id: orderExchange.order_id,
@@ -212,7 +218,6 @@ export const orderExchangeAddNewItemWorkflow = createWorkflow(
input: {
order: orderWithPromotions,
orderChange,
exchange_id: orderExchange.id,
},
})

View File

@@ -33,7 +33,7 @@ import {
throwIfOrderChangeIsNotActive,
} from "../../utils/order-validation"
import { createOrderChangeActionsWorkflow } from "../create-order-change-actions"
import { computeAdjustmentsForPreviewWorkflow } from "../order-edit/compute-adjustments-for-preview"
import { computeAdjustmentsForPreviewWorkflow } from "../compute-adjustments-for-preview"
import { refreshExchangeShippingWorkflow } from "./refresh-shipping"
/**
@@ -194,7 +194,13 @@ export const orderExchangeRequestItemReturnWorkflow = createWorkflow(
const orderChange: OrderChangeDTO = useRemoteQueryStep({
entry_point: "order_change",
fields: ["id", "status", "version"],
fields: [
"id",
"status",
"version",
"exchange_id",
"carry_over_promotions",
],
variables: {
filters: {
order_id: orderExchange.order_id,
@@ -321,7 +327,6 @@ export const orderExchangeRequestItemReturnWorkflow = createWorkflow(
input: {
order: orderWithPromotions,
orderChange,
exchange_id: orderExchange.id,
},
})

View File

@@ -3,6 +3,7 @@ import {
OrderChangeDTO,
OrderDTO,
OrderExchangeDTO,
PromotionDTO,
OrderPreviewDTO,
OrderWorkflow,
} from "@medusajs/framework/types"
@@ -24,6 +25,7 @@ import {
throwIfOrderChangeIsNotActive,
} from "../../utils/order-validation"
import { refreshExchangeShippingWorkflow } from "./refresh-shipping"
import { computeAdjustmentsForPreviewWorkflow } from "../compute-adjustments-for-preview"
/**
* The data to validate that an outbound or new item in an exchange can be updated.
@@ -150,7 +152,7 @@ export const updateExchangeAddItemWorkflow = createWorkflow(
const order: OrderDTO = useRemoteQueryStep({
entry_point: "orders",
fields: ["id", "status", "canceled_at", "items.*"],
fields: ["id", "status", "canceled_at", "items.*", "promotions.*"],
variables: { id: orderExchange.order_id },
list: false,
throw_if_key_not_found: true,
@@ -158,7 +160,14 @@ export const updateExchangeAddItemWorkflow = createWorkflow(
const orderChange: OrderChangeDTO = useRemoteQueryStep({
entry_point: "order_change",
fields: ["id", "status", "version", "actions.*"],
fields: [
"id",
"status",
"version",
"exchange_id",
"actions.*",
"carry_over_promotions",
],
variables: {
filters: {
order_id: orderExchange.order_id,
@@ -207,6 +216,20 @@ export const updateExchangeAddItemWorkflow = createWorkflow(
}
)
const orderWithPromotions = transform({ order }, ({ order }) => {
return {
...order,
promotions: (order as any).promotions ?? [],
} as OrderDTO & { promotions: PromotionDTO[] }
})
computeAdjustmentsForPreviewWorkflow.runAsStep({
input: {
order: orderWithPromotions,
orderChange,
},
})
refreshExchangeShippingWorkflow.runAsStep({
input: refreshArgs,
})

View File

@@ -50,7 +50,7 @@ export * from "./mark-payment-collection-as-paid"
export * from "./maybe-refresh-shipping-methods"
export * from "./order-edit/begin-order-edit"
export * from "./order-edit/cancel-begin-order-edit"
export * from "./order-edit/compute-adjustments-for-preview"
export * from "./compute-adjustments-for-preview"
export * from "./order-edit/confirm-order-edit-request"
export * from "./order-edit/create-order-edit-shipping-method"
export * from "./order-edit/order-edit-add-new-item"
@@ -81,11 +81,13 @@ export * from "./return/update-receive-item-return-request"
export * from "./return/update-request-item-return"
export * from "./return/update-return"
export * from "./return/update-return-shipping-method"
export * from "./on-carry-promotions-flag-set"
export * from "./transfer/accept-order-transfer"
export * from "./transfer/cancel-order-transfer"
export * from "./transfer/decline-order-transfer"
export * from "./transfer/request-order-transfer"
export * from "./update-order"
export * from "./update-order-change"
export * from "./update-order-change-actions"
export * from "./update-order-changes"
export * from "./update-tax-lines"

View File

@@ -0,0 +1,201 @@
import {
OrderChangeDTO,
OrderDTO,
PromotionDTO,
} from "@medusajs/framework/types"
import {
ApplicationMethodAllocation,
MedusaError,
} from "@medusajs/framework/utils"
import {
WorkflowData,
WorkflowResponse,
createStep,
createWorkflow,
transform,
} from "@medusajs/framework/workflows-sdk"
import { useRemoteQueryStep } from "../../common"
import { throwIfOrderChangeIsNotActive } from "../utils/order-validation"
import { computeAdjustmentsForPreviewWorkflow } from "./compute-adjustments-for-preview"
/**
* The data to set the carry over promotions flag for an order change.
*/
export type OnCarryPromotionsFlagSetWorkflowInput = {
/**
* The order change's ID.
*/
order_change_id: string
/**
* Whether to carry over promotions to outbound exchange items.
*/
carry_over_promotions: boolean
}
/**
* This step validates that the order change is an exchange and validates promotion allocation.
*/
export const validateCarryPromotionsFlagStep = createStep(
"validate-carry-promotions-flag",
async function ({
orderChange,
order,
input,
}: {
orderChange: OrderChangeDTO
order: OrderDTO & { promotions?: PromotionDTO[] }
input: OnCarryPromotionsFlagSetWorkflowInput
}) {
// Validate order change is active
throwIfOrderChangeIsNotActive({ orderChange })
// we don't need to validate promotion since we will be resetting the adjustments
if (!input.carry_over_promotions) {
return
}
// Validate promotion allocation if promotions exist
if (order.promotions && order.promotions.length > 0) {
const invalidPromotions: string[] = []
for (const promotion of order.promotions) {
const applicationMethod = (promotion as any).application_method
if (!applicationMethod) {
continue
}
const allocation = applicationMethod.allocation
const type = applicationMethod.type
if (
allocation !== ApplicationMethodAllocation.ACROSS &&
allocation !== ApplicationMethodAllocation.EACH
) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Promotion ${
promotion.code || promotion.id
} has invalid allocation. Only promotions with EACH or ACROSS allocation can be carried over to outbound exchange items.`
)
}
// For fixed promotions, allocation must be EACH
if (
type === "fixed" &&
allocation !== ApplicationMethodAllocation.EACH
) {
invalidPromotions.push(promotion.code || promotion.id)
}
// For percentage promotions, allocation must be EACH or ACROSS
if (
type === "percentage" &&
allocation !== ApplicationMethodAllocation.EACH &&
allocation !== ApplicationMethodAllocation.ACROSS
) {
invalidPromotions.push(promotion.code || promotion.id)
}
}
if (invalidPromotions.length > 0) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
`Promotions with codes ${invalidPromotions.join(
", "
)} have invalid allocation. Fixed promotions must have EACH allocation, and percentage promotions must have EACH or ACROSS allocation.`
)
}
}
}
)
export const onCarryPromotionsFlagSetId = "on-carry-promotions-flag-set"
/**
* This workflow sets the carry over promotions flag for an order change.
* It validates that the order change is active and is an exchange, validates promotion allocation,
* and either applies or removes promotion adjustments based on the flag value.
*
* @example
* const { result } = await onCarryPromotionsFlagSet(container)
* .run({
* input: {
* order_change_id: "orch_123",
* carry_over_promotions: true,
* }
* })
*
* @summary
*
* Set the carry over promotions flag for an order change.
*/
export const onCarryPromotionsFlagSet = createWorkflow(
onCarryPromotionsFlagSetId,
function (
input: WorkflowData<OnCarryPromotionsFlagSetWorkflowInput>
): WorkflowResponse<void> {
const orderChange: OrderChangeDTO = useRemoteQueryStep({
entry_point: "order_change",
fields: [
"id",
"status",
"version",
"exchange_id",
"claim_id",
"return_id",
"order_id",
"canceled_at",
"confirmed_at",
"declined_at",
"carry_over_promotions",
],
variables: {
filters: {
id: input.order_change_id,
},
},
list: false,
throw_if_key_not_found: true,
}).config({ name: "order-change-query" })
const order: OrderDTO & { promotions?: PromotionDTO[] } =
useRemoteQueryStep({
entry_point: "orders",
fields: [
"id",
"currency_code",
"promotions.*",
"promotions.application_method.*",
],
variables: {
id: orderChange.order_id,
},
list: false,
throw_if_key_not_found: true,
}).config({ name: "order-query" })
validateCarryPromotionsFlagStep({
orderChange,
order,
input,
})
const orderWithPromotions = transform({ order }, ({ order }) => {
return {
...order,
promotions: (order as any).promotions ?? [],
} as OrderDTO & { promotions: PromotionDTO[] }
})
computeAdjustmentsForPreviewWorkflow.runAsStep({
input: {
orderChange,
order: orderWithPromotions,
},
})
return new WorkflowResponse(void 0)
}
)

View File

@@ -1,163 +0,0 @@
import {
ComputeActionContext,
OrderChangeDTO,
OrderDTO,
PromotionDTO,
} from "@medusajs/framework/types"
import { ChangeActionType } from "@medusajs/framework/utils"
import {
createWorkflow,
transform,
when,
WorkflowData,
} from "@medusajs/framework/workflows-sdk"
import {
getActionsToComputeFromPromotionsStep,
prepareAdjustmentsFromPromotionActionsStep,
} from "../../../cart"
import { previewOrderChangeStep } from "../../steps/preview-order-change"
import { createOrderChangeActionsWorkflow } from "../create-order-change-actions"
/**
* The data to compute adjustments for an order edit, exchange, claim, or return.
*/
export type ComputeAdjustmentsForPreviewWorkflowInput = {
/**
* The order's details.
*/
order: OrderDTO & { promotions: PromotionDTO[] }
/**
* The order change's details.
*/
orderChange: OrderChangeDTO
/**
* Optional exchange ID to include in the order change action.
*/
exchange_id?: string
/**
* Optional claim ID to include in the order change action.
*/
claim_id?: string
/**
* Optional return ID to include in the order change action.
*/
return_id?: string
}
export const computeAdjustmentsForPreviewWorkflowId =
"compute-adjustments-for-preview"
/**
* This workflow computes adjustments for an order edit, exchange, claim, or return.
* It's used by the [Add Items to Order Edit Admin API Route](https://docs.medusajs.com/api/admin#order-edits_postordereditsiditems),
* [Add Outbound Items Admin API Route](https://docs.medusajs.com/api/admin#exchanges_postexchangesidoutbounditems),
* and [Add Inbound Items Admin API Route](https://docs.medusajs.com/api/admin#exchanges_postexchangesidinbounditems).
*
* You can use this workflow within your customizations or your own custom workflows, allowing you to compute adjustments
* in your custom flows.
*
* @example
* const { result } = await computeAdjustmentsForPreviewWorkflow(container)
* .run({
* input: {
* order: {
* id: "order_123",
* // other order details...
* },
* orderChange: {
* id: "orch_123",
* // other order change details...
* },
* exchange_id: "exchange_123", // optional, for exchanges
* }
* })
*
* @summary
*
* Compute adjustments for an order edit, exchange, claim, or return.
*/
export const computeAdjustmentsForPreviewWorkflow = createWorkflow(
computeAdjustmentsForPreviewWorkflowId,
function (input: WorkflowData<ComputeAdjustmentsForPreviewWorkflowInput>) {
const previewedOrder = previewOrderChangeStep(input.order.id)
when({ order: input.order }, ({ order }) => !!order.promotions.length).then(
() => {
const actionsToComputeItemsInput = transform(
{ previewedOrder, order: input.order },
({ previewedOrder, order }) => {
return {
currency_code: order.currency_code,
items: previewedOrder.items.map((item) => ({
...item,
// Buy-Get promotions rely on the product ID, so we need to manually set it before refreshing adjustments
product: { id: item.product_id },
})),
} as ComputeActionContext
}
)
const orderPromotions = transform(
{ order: input.order },
({ order }) => {
return order.promotions
.map((p) => p.code)
.filter((p) => p !== undefined)
}
)
const actions = getActionsToComputeFromPromotionsStep({
computeActionContext: actionsToComputeItemsInput,
promotionCodesToApply: orderPromotions,
})
const { lineItemAdjustmentsToCreate } =
prepareAdjustmentsFromPromotionActionsStep({ actions })
const orderChangeActionAdjustmentsInput = transform(
{
order: input.order,
previewedOrder,
orderChange: input.orderChange,
lineItemAdjustmentsToCreate,
exchangeId: input.exchange_id,
claimId: input.claim_id,
returnId: input.return_id,
},
({
order,
previewedOrder,
orderChange,
lineItemAdjustmentsToCreate,
exchangeId,
claimId,
returnId,
}) => {
return previewedOrder.items.map((item) => {
const itemAdjustments = lineItemAdjustmentsToCreate.filter(
(adjustment) => adjustment.item_id === item.id
)
return {
order_change_id: orderChange.id,
order_id: order.id,
...(exchangeId && { exchange_id: exchangeId }),
...(claimId && { claim_id: claimId }),
...(returnId && { return_id: returnId }),
version: orderChange.version,
action: ChangeActionType.ITEM_ADJUSTMENTS_REPLACE,
details: {
reference_id: item.id,
adjustments: itemAdjustments,
},
}
})
}
)
createOrderChangeActionsWorkflow
.runAsStep({ input: orderChangeActionAdjustmentsInput })
.config({ name: "order-change-action-adjustments-input" })
}
)
}
)

View File

@@ -22,7 +22,7 @@ import { addOrderLineItemsWorkflow } from "../add-line-items"
import { createOrderChangeActionsWorkflow } from "../create-order-change-actions"
import { updateOrderTaxLinesWorkflow } from "../update-tax-lines"
import { fieldsToRefreshOrderEdit } from "./utils/fields"
import { computeAdjustmentsForPreviewWorkflow } from "./compute-adjustments-for-preview"
import { computeAdjustmentsForPreviewWorkflow } from "../compute-adjustments-for-preview"
/**
* The data to validate that new items can be added to an order edit.
@@ -118,7 +118,7 @@ export const orderEditAddNewItemWorkflow = createWorkflow(
const orderChangeResult = useQueryGraphStep({
entity: "order_change",
fields: ["id", "status", "version", "actions.*"],
fields: ["id", "status", "version", "actions.*", "carry_over_promotions"],
filters: {
order_id: input.order_id,
status: [OrderChangeStatus.PENDING, OrderChangeStatus.REQUESTED],

View File

@@ -24,7 +24,7 @@ import {
throwIfOrderChangeIsNotActive,
} from "../../utils/order-validation"
import { createOrderChangeActionsWorkflow } from "../create-order-change-actions"
import { computeAdjustmentsForPreviewWorkflow } from "./compute-adjustments-for-preview"
import { computeAdjustmentsForPreviewWorkflow } from "../compute-adjustments-for-preview"
import { fieldsToRefreshOrderEdit } from "./utils/fields"
/**
@@ -128,7 +128,7 @@ export const orderEditUpdateItemQuantityWorkflow = createWorkflow(
const orderChangeResult = useQueryGraphStep({
entity: "order_change",
fields: ["id", "status", "version", "actions.*"],
fields: ["id", "status", "version", "actions.*", "carry_over_promotions"],
filters: {
order_id: input.order_id,
status: [OrderChangeStatus.PENDING, OrderChangeStatus.REQUESTED],

View File

@@ -22,7 +22,7 @@ import {
throwIfIsCancelled,
throwIfOrderChangeIsNotActive,
} from "../../utils/order-validation"
import { computeAdjustmentsForPreviewWorkflow } from "./compute-adjustments-for-preview"
import { computeAdjustmentsForPreviewWorkflow } from "../compute-adjustments-for-preview"
import { fieldsToRefreshOrderEdit } from "./utils/fields"
/**
@@ -143,7 +143,7 @@ export const removeItemOrderEditActionWorkflow = createWorkflow(
const orderChangeResult = useQueryGraphStep({
entity: "order_change",
fields: ["id", "status", "version", "actions.*"],
fields: ["id", "status", "version", "actions.*", "carry_over_promotions"],
filters: {
order_id: input.order_id,
status: [OrderChangeStatus.PENDING, OrderChangeStatus.REQUESTED],

View File

@@ -22,7 +22,7 @@ import {
throwIfIsCancelled,
throwIfOrderChangeIsNotActive,
} from "../../utils/order-validation"
import { computeAdjustmentsForPreviewWorkflow } from "./compute-adjustments-for-preview"
import { computeAdjustmentsForPreviewWorkflow } from "../compute-adjustments-for-preview"
import { fieldsToRefreshOrderEdit } from "./utils/fields"
/**
@@ -142,7 +142,7 @@ export const updateOrderEditAddItemWorkflow = createWorkflow(
const orderChangeResult = useQueryGraphStep({
entity: "order_change",
fields: ["id", "status", "version", "actions.*"],
fields: ["id", "status", "version", "actions.*", "carry_over_promotions"],
filters: {
order_id: input.order_id,
status: [OrderChangeStatus.PENDING, OrderChangeStatus.REQUESTED],

View File

@@ -22,7 +22,7 @@ import {
throwIfIsCancelled,
throwIfOrderChangeIsNotActive,
} from "../../utils/order-validation"
import { computeAdjustmentsForPreviewWorkflow } from "./compute-adjustments-for-preview"
import { computeAdjustmentsForPreviewWorkflow } from "../compute-adjustments-for-preview"
import { fieldsToRefreshOrderEdit } from "./utils/fields"
/**

View File

@@ -0,0 +1,59 @@
import { OrderChangeDTO, UpdateOrderChangeDTO } from "@medusajs/framework/types"
import {
WorkflowData,
WorkflowResponse,
createWorkflow,
transform,
when,
} from "@medusajs/framework/workflows-sdk"
import { updateOrderChangesStep } from "../steps/update-order-changes"
import { onCarryPromotionsFlagSet } from "./on-carry-promotions-flag-set"
export const updateOrderChangeWorkflowId = "update-order-change-workflow"
/**
* This workflow updates an order change.
* If the carry_over_promotions flag is provided, it calls onCarryPromotionsFlagSet
* to handle the promotion logic. Otherwise, it updates the order change directly.
*
* @example
* const { result } = await updateOrderChangeWorkflow(container)
* .run({
* input: {
* id: "orch_123",
* carry_over_promotions: true,
* }
* })
*
* @summary
*
* Update an order change, conditionally handling promotion carry-over if specified.
*/
export const updateOrderChangeWorkflow = createWorkflow(
updateOrderChangeWorkflowId,
function (
input: WorkflowData<UpdateOrderChangeDTO>
): WorkflowResponse<OrderChangeDTO> {
const updatedOrderChange = updateOrderChangesStep([input])
when(
"should-call-carry-over-promotion-workflow",
input,
({ carry_over_promotions }) => typeof carry_over_promotions === "boolean"
).then(() => {
return onCarryPromotionsFlagSet.runAsStep({
input: {
order_change_id: input.id,
carry_over_promotions: input.carry_over_promotions!,
},
})
})
return new WorkflowResponse(
transform(
{ updatedOrderChange },
({ updatedOrderChange }) => updatedOrderChange?.[0]
)
)
}
)