fix(core-flows): create reservations on draft order conversion to regular order (#14010)
## Summary
**What** — What changes are introduced in this PR?
Avoid creating reservations when draft order edits are confirmed and rather, create them when the draft order is converted into a regular order.
**Why** — Why are these changes relevant or necessary?
While the order is a draft, creating reservations would potentially block inventory for regular order requests, when the draft represents a non materialized state of a purchase that might never be completed or at a latter point in time.
**How** — How have these changes been implemented?
Removed the reservation creations inside of `confirmDraftOrderEditWorkflow` and instead do it inside `convertDraftOrderWorkflow`
**Testing** — How have these changes been tested, or how can the reviewer test the feature?
Added integration tests.
---
## Examples
Provide examples or code snippets that demonstrate how this feature works, or how it can be used in practice.
This helps with documentation and ensures maintainers can quickly understand and verify the change.
```ts
// Example usage
```
---
## Checklist
Please ensure the following before requesting a review:
- [x] I have added a **changeset** for this PR
- Every non-breaking change should be marked as a **patch**
- To add a changeset, run `yarn changeset` and follow the prompts
- [x] The changes are covered by relevant **tests**
- [x] I have verified the code works as intended locally
- [x] I have linked the related issue(s) if applicable
---
## Additional Context
Add any additional context, related issues, or references that might help the reviewer understand this PR.
fixes #13773
closes SUP-2523
This commit is contained in:
@@ -1,15 +1,9 @@
|
||||
import { ChangeActionType, MathBN, OrderChangeStatus, } from "@medusajs/framework/utils"
|
||||
import { createWorkflow, transform, WorkflowResponse, } from "@medusajs/framework/workflows-sdk"
|
||||
import { BigNumberInput, OrderChangeDTO, OrderDTO, } from "@medusajs/framework/types"
|
||||
import { reserveInventoryStep } from "../../cart"
|
||||
import {
|
||||
prepareConfirmInventoryInput,
|
||||
requiredOrderFieldsForInventoryConfirmation,
|
||||
} from "../../cart/utils/prepare-confirm-inventory-input"
|
||||
import { OrderChangeStatus, } from "@medusajs/framework/utils"
|
||||
import { createWorkflow, WorkflowResponse, } from "@medusajs/framework/workflows-sdk"
|
||||
import { OrderChangeDTO, OrderDTO, } from "@medusajs/framework/types"
|
||||
import { useRemoteQueryStep } from "../../common"
|
||||
import { createOrUpdateOrderPaymentCollectionWorkflow, previewOrderChangeStep, } from "../../order"
|
||||
import { confirmOrderChanges } from "../../order/steps/confirm-order-changes"
|
||||
import { deleteReservationsByLineItemsStep } from "../../reservation"
|
||||
import { validateDraftOrderChangeStep } from "../steps/validate-draft-order-change"
|
||||
import { acquireLockStep, releaseLockStep } from "../../locking"
|
||||
|
||||
@@ -111,102 +105,6 @@ export const confirmDraftOrderEditWorkflow = createWorkflow(
|
||||
confirmed_by: input.confirmed_by,
|
||||
})
|
||||
|
||||
const orderItems = useRemoteQueryStep({
|
||||
entry_point: "order",
|
||||
fields: requiredOrderFieldsForInventoryConfirmation,
|
||||
variables: { id: input.order_id },
|
||||
list: false,
|
||||
throw_if_key_not_found: true,
|
||||
}).config({ name: "order-items-query" })
|
||||
|
||||
const { variants, items, toRemoveReservationLineItemIds } = transform(
|
||||
{ orderItems, previousOrderItems: order.items, orderPreview },
|
||||
({ orderItems, previousOrderItems, orderPreview }) => {
|
||||
const allItems: any[] = []
|
||||
const allVariants: any[] = []
|
||||
|
||||
const previousItemIds = (previousOrderItems || []).map(({ id }) => id)
|
||||
const currentItemIds = orderItems.items.map(({ id }) => id)
|
||||
|
||||
const removedItemIds = previousItemIds.filter(
|
||||
(id) => !currentItemIds.includes(id)
|
||||
)
|
||||
|
||||
const updatedItemIds: string[] = []
|
||||
|
||||
orderItems.items.forEach((ordItem) => {
|
||||
const itemAction = orderPreview.items?.find(
|
||||
(item) =>
|
||||
item.id === ordItem.id &&
|
||||
item.actions?.find(
|
||||
(a) =>
|
||||
a.action === ChangeActionType.ITEM_ADD ||
|
||||
a.action === ChangeActionType.ITEM_UPDATE
|
||||
)
|
||||
)
|
||||
|
||||
if (!itemAction) {
|
||||
return
|
||||
}
|
||||
|
||||
const unitPrice: BigNumberInput =
|
||||
itemAction.raw_unit_price ?? itemAction.unit_price
|
||||
|
||||
const compareAtUnitPrice: BigNumberInput | undefined =
|
||||
itemAction.raw_compare_at_unit_price ??
|
||||
itemAction.compare_at_unit_price
|
||||
|
||||
const updateAction = itemAction.actions!.find(
|
||||
(a) => a.action === ChangeActionType.ITEM_UPDATE
|
||||
)
|
||||
|
||||
if (updateAction) {
|
||||
updatedItemIds.push(ordItem.id)
|
||||
}
|
||||
|
||||
const newQuantity: BigNumberInput =
|
||||
itemAction.raw_quantity ?? itemAction.quantity
|
||||
|
||||
const reservationQuantity = MathBN.sub(
|
||||
newQuantity,
|
||||
ordItem.raw_fulfilled_quantity
|
||||
)
|
||||
|
||||
allItems.push({
|
||||
id: ordItem.id,
|
||||
variant_id: ordItem.variant_id,
|
||||
quantity: reservationQuantity,
|
||||
unit_price: unitPrice,
|
||||
compare_at_unit_price: compareAtUnitPrice,
|
||||
})
|
||||
allVariants.push(ordItem.variant)
|
||||
})
|
||||
|
||||
return {
|
||||
variants: allVariants,
|
||||
items: allItems,
|
||||
toRemoveReservationLineItemIds: [
|
||||
...removedItemIds,
|
||||
...updatedItemIds,
|
||||
],
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
const formatedInventoryItems = transform(
|
||||
{
|
||||
input: {
|
||||
sales_channel_id: (orderItems as any).sales_channel_id,
|
||||
variants,
|
||||
items,
|
||||
},
|
||||
},
|
||||
prepareConfirmInventoryInput
|
||||
)
|
||||
|
||||
deleteReservationsByLineItemsStep(toRemoveReservationLineItemIds)
|
||||
reserveInventoryStep(formatedInventoryItems)
|
||||
|
||||
createOrUpdateOrderPaymentCollectionWorkflow.runAsStep({
|
||||
input: {
|
||||
order_id: order.id,
|
||||
|
||||
@@ -8,13 +8,23 @@ import {
|
||||
createWorkflow,
|
||||
parallelize,
|
||||
StepResponse,
|
||||
transform,
|
||||
WorkflowData,
|
||||
WorkflowResponse,
|
||||
} from "@medusajs/framework/workflows-sdk"
|
||||
import type { IOrderModuleService, OrderDTO } from "@medusajs/framework/types"
|
||||
import type {
|
||||
ConfirmVariantInventoryWorkflowInputDTO,
|
||||
IOrderModuleService,
|
||||
OrderDTO,
|
||||
} from "@medusajs/framework/types"
|
||||
import { emitEventStep, useRemoteQueryStep } from "../../common"
|
||||
import { validateDraftOrderStep } from "../steps/validate-draft-order"
|
||||
import { acquireLockStep, releaseLockStep } from "../../locking"
|
||||
import {
|
||||
prepareConfirmInventoryInput,
|
||||
requiredOrderFieldsForInventoryConfirmation,
|
||||
} from "../../cart/utils/prepare-confirm-inventory-input"
|
||||
import { reserveInventoryStep } from "../../cart"
|
||||
|
||||
export const convertDraftOrderWorkflowId = "convert-draft-order"
|
||||
|
||||
@@ -119,6 +129,46 @@ export const convertDraftOrderWorkflow = createWorkflow(
|
||||
|
||||
validateDraftOrderStep({ order })
|
||||
|
||||
const orderItems = useRemoteQueryStep({
|
||||
entry_point: "order",
|
||||
fields: requiredOrderFieldsForInventoryConfirmation,
|
||||
variables: { id: input.id },
|
||||
list: false,
|
||||
throw_if_key_not_found: true,
|
||||
}).config({ name: "order-items-query" })
|
||||
|
||||
const { variants, items } = transform({ orderItems }, ({ orderItems }) => {
|
||||
const items: ConfirmVariantInventoryWorkflowInputDTO["items"] = []
|
||||
const variants: ConfirmVariantInventoryWorkflowInputDTO["variants"] = []
|
||||
|
||||
for (const orderItem of orderItems.items ?? []) {
|
||||
items.push({
|
||||
variant_id: orderItem.variant.id,
|
||||
quantity: orderItem.quantity,
|
||||
id: orderItem.id,
|
||||
})
|
||||
variants.push(orderItem.variant)
|
||||
}
|
||||
|
||||
return {
|
||||
variants,
|
||||
items,
|
||||
}
|
||||
})
|
||||
|
||||
const formatedInventoryItems = transform(
|
||||
{
|
||||
input: {
|
||||
sales_channel_id: (orderItems as any).sales_channel_id,
|
||||
variants,
|
||||
items,
|
||||
},
|
||||
},
|
||||
prepareConfirmInventoryInput
|
||||
)
|
||||
|
||||
reserveInventoryStep(formatedInventoryItems)
|
||||
|
||||
const updatedOrder = convertDraftOrderStep({ id: input.id })
|
||||
|
||||
parallelize(
|
||||
|
||||
Reference in New Issue
Block a user