From 27a2dcb10d26ddc4aeda8f2727ac01ff8268f51d Mon Sep 17 00:00:00 2001 From: "Carlos R. L. Rodrigues" <37986729+carlos-r-l-rodrigues@users.noreply.github.com> Date: Wed, 21 Aug 2024 13:59:33 -0300 Subject: [PATCH] feat(core-flows): order edit request (#8705) --- .../__tests__/order-edits/order-edits.spec.ts | 14 +++ .../core/core-flows/src/order/steps/index.ts | 1 + .../core-flows/src/order/workflows/index.ts | 2 + .../order-edit/confirm-order-edit-request.ts | 30 ++++++- .../order-edit/request-order-edit.ts | 87 +++++++++++++++++++ .../order/workflows/update-order-changes.ts | 20 +++++ .../admin/order-edits/[id]/request/route.ts | 21 +++++ .../src/api/admin/order-edits/middlewares.ts | 5 ++ 8 files changed, 176 insertions(+), 4 deletions(-) create mode 100644 packages/core/core-flows/src/order/workflows/order-edit/request-order-edit.ts create mode 100644 packages/core/core-flows/src/order/workflows/update-order-changes.ts create mode 100644 packages/medusa/src/api/admin/order-edits/[id]/request/route.ts diff --git a/integration-tests/http/__tests__/order-edits/order-edits.spec.ts b/integration-tests/http/__tests__/order-edits/order-edits.spec.ts index bb188870b2..b9e76d27ed 100644 --- a/integration-tests/http/__tests__/order-edits/order-edits.spec.ts +++ b/integration-tests/http/__tests__/order-edits/order-edits.spec.ts @@ -2,6 +2,7 @@ import { ContainerRegistrationKeys, ModuleRegistrationName, Modules, + OrderChangeStatus, RuleOperator, } from "@medusajs/utils" import { medusaIntegrationTestRunner } from "medusa-test-utils" @@ -370,6 +371,19 @@ medusaIntegrationTestRunner({ expect(result.summary.original_order_total).toEqual(60) expect(result.items.length).toEqual(2) + result = ( + await api.post( + `/admin/order-edits/${orderId}/request`, + {}, + adminHeaders + ) + ).data.order_preview + + expect(result.order_change.status).toEqual(OrderChangeStatus.REQUESTED) + expect(result.summary.current_order_total).toEqual(34) + expect(result.summary.original_order_total).toEqual(60) + expect(result.items.length).toEqual(2) + result = ( await api.post( `/admin/order-edits/${orderId}/confirm`, diff --git a/packages/core/core-flows/src/order/steps/index.ts b/packages/core/core-flows/src/order/steps/index.ts index 24c98e6c57..130835a797 100644 --- a/packages/core/core-flows/src/order/steps/index.ts +++ b/packages/core/core-flows/src/order/steps/index.ts @@ -32,5 +32,6 @@ export * from "./return/update-return-items" export * from "./return/update-returns" export * from "./set-tax-lines-for-items" export * from "./update-order-change-actions" +export * from "./update-order-changes" export * from "./update-order-exchanges" export * from "./update-shipping-methods" diff --git a/packages/core/core-flows/src/order/workflows/index.ts b/packages/core/core-flows/src/order/workflows/index.ts index f6e6294c9c..77fab019e3 100644 --- a/packages/core/core-flows/src/order/workflows/index.ts +++ b/packages/core/core-flows/src/order/workflows/index.ts @@ -50,6 +50,7 @@ export * from "./order-edit/order-edit-add-new-item" export * from "./order-edit/order-edit-update-item-quantity" export * from "./order-edit/remove-order-edit-item-action" export * from "./order-edit/remove-order-edit-shipping-method" +export * from "./order-edit/request-order-edit" export * from "./order-edit/update-order-edit-add-item" export * from "./order-edit/update-order-edit-item-quantity" export * from "./order-edit/update-order-edit-shipping-method" @@ -74,4 +75,5 @@ export * from "./return/update-request-item-return" export * from "./return/update-return" export * from "./return/update-return-shipping-method" export * from "./update-order-change-actions" +export * from "./update-order-changes" export * from "./update-tax-lines" diff --git a/packages/core/core-flows/src/order/workflows/order-edit/confirm-order-edit-request.ts b/packages/core/core-flows/src/order/workflows/order-edit/confirm-order-edit-request.ts index 68a68741d1..0dcb0d6c95 100644 --- a/packages/core/core-flows/src/order/workflows/order-edit/confirm-order-edit-request.ts +++ b/packages/core/core-flows/src/order/workflows/order-edit/confirm-order-edit-request.ts @@ -1,5 +1,10 @@ -import { OrderChangeDTO, OrderDTO, OrderPreviewDTO } from "@medusajs/types" -import { ChangeActionType, OrderChangeStatus } from "@medusajs/utils" +import { + BigNumberInput, + OrderChangeDTO, + OrderDTO, + OrderPreviewDTO, +} from "@medusajs/types" +import { ChangeActionType, MathBN, OrderChangeStatus } from "@medusajs/utils" import { WorkflowResponse, createStep, @@ -127,17 +132,34 @@ export const confirmOrderEditRequestWorkflow = createWorkflow( const itemAction = orderPreview.items?.find( (item) => item.id === ordItem.id && - item.actions?.find((a) => a.action === ChangeActionType.ITEM_ADD) + item.actions?.find( + (a) => + a.action === ChangeActionType.ITEM_ADD || + a.action === ChangeActionType.ITEM_UPDATE + ) ) if (!itemAction) { return } + let quantity: BigNumberInput = + itemAction.raw_quantity ?? itemAction.quantity + + const updateAction = itemAction.actions!.find( + (a) => a.action === ChangeActionType.ITEM_UPDATE + ) + if (updateAction) { + quantity = MathBN.sub(quantity, ordItem.raw_quantity) + if (MathBN.lte(quantity, 0)) { + return + } + } + allItems.push({ id: ordItem.id, variant_id: ordItem.variant_id, - quantity: itemAction.raw_quantity ?? itemAction.quantity, + quantity, }) allVariants.push(ordItem.variant) }) diff --git a/packages/core/core-flows/src/order/workflows/order-edit/request-order-edit.ts b/packages/core/core-flows/src/order/workflows/order-edit/request-order-edit.ts new file mode 100644 index 0000000000..f785d3fd56 --- /dev/null +++ b/packages/core/core-flows/src/order/workflows/order-edit/request-order-edit.ts @@ -0,0 +1,87 @@ +import { OrderChangeDTO, OrderDTO, OrderPreviewDTO } from "@medusajs/types" +import { OrderChangeStatus } from "@medusajs/utils" +import { + WorkflowResponse, + createStep, + createWorkflow, +} from "@medusajs/workflows-sdk" +import { useRemoteQueryStep } from "../../../common" +import { previewOrderChangeStep } from "../../steps" +import { updateOrderChangesStep } from "../../steps/update-order-changes" +import { + throwIfIsCancelled, + throwIfOrderChangeIsNotActive, +} from "../../utils/order-validation" +import { createOrUpdateOrderPaymentCollectionWorkflow } from "../create-or-update-order-payment-collection" + +export type OrderEditRequestWorkflowInput = { + order_id: string +} + +/** + * This step validates that a order edit can be requested. + */ +export const requestOrderEditRequestValidationStep = createStep( + "validate-order-edit-request", + async function ({ + order, + orderChange, + }: { + order: OrderDTO + orderChange: OrderChangeDTO + }) { + throwIfIsCancelled(order, "Order") + throwIfOrderChangeIsNotActive({ orderChange }) + } +) + +export const requestOrderEditRequestWorkflowId = "order-edit-request" +/** + * This workflow requests an order edit request. + */ +export const requestOrderEditRequestWorkflow = createWorkflow( + requestOrderEditRequestWorkflowId, + function ( + input: OrderEditRequestWorkflowInput + ): WorkflowResponse { + const order: OrderDTO = useRemoteQueryStep({ + entry_point: "orders", + fields: ["id", "version", "canceled_at"], + variables: { id: input.order_id }, + list: false, + throw_if_key_not_found: true, + }).config({ name: "order-query" }) + + const orderChange: OrderChangeDTO = useRemoteQueryStep({ + entry_point: "order_change", + fields: ["id", "canceled_at"], + variables: { + filters: { + order_id: input.order_id, + status: [OrderChangeStatus.PENDING, OrderChangeStatus.REQUESTED], + }, + }, + list: false, + }).config({ name: "order-change-query" }) + + requestOrderEditRequestValidationStep({ + order, + orderChange, + }) + + updateOrderChangesStep([ + { + id: orderChange.id, + status: OrderChangeStatus.REQUESTED, + }, + ]) + + createOrUpdateOrderPaymentCollectionWorkflow.runAsStep({ + input: { + order_id: order.id, + }, + }) + + return new WorkflowResponse(previewOrderChangeStep(order.id)) + } +) diff --git a/packages/core/core-flows/src/order/workflows/update-order-changes.ts b/packages/core/core-flows/src/order/workflows/update-order-changes.ts new file mode 100644 index 0000000000..97ce0bc4ae --- /dev/null +++ b/packages/core/core-flows/src/order/workflows/update-order-changes.ts @@ -0,0 +1,20 @@ +import { OrderChangeDTO, UpdateOrderChangeActionDTO } from "@medusajs/types" +import { + WorkflowData, + WorkflowResponse, + createWorkflow, +} from "@medusajs/workflows-sdk" +import { updateOrderChangesStep } from "../steps" + +export const updateOrderChangesWorkflowId = "update-order-change" +/** + * This workflow updates one or more order changes. + */ +export const updateOrderChangesWorkflow = createWorkflow( + updateOrderChangesWorkflowId, + ( + input: WorkflowData + ): WorkflowResponse => { + return new WorkflowResponse(updateOrderChangesStep(input)) + } +) diff --git a/packages/medusa/src/api/admin/order-edits/[id]/request/route.ts b/packages/medusa/src/api/admin/order-edits/[id]/request/route.ts new file mode 100644 index 0000000000..b0dc25cc8f --- /dev/null +++ b/packages/medusa/src/api/admin/order-edits/[id]/request/route.ts @@ -0,0 +1,21 @@ +import { requestOrderEditRequestWorkflow } from "@medusajs/core-flows" +import { HttpTypes } from "@medusajs/types" +import { + AuthenticatedMedusaRequest, + MedusaResponse, +} from "../../../../../types/routing" + +export const POST = async ( + req: AuthenticatedMedusaRequest, + res: MedusaResponse +) => { + const { id } = req.params + + const { result } = await requestOrderEditRequestWorkflow(req.scope).run({ + input: { order_id: id }, + }) + + res.json({ + order_preview: result, + }) +} diff --git a/packages/medusa/src/api/admin/order-edits/middlewares.ts b/packages/medusa/src/api/admin/order-edits/middlewares.ts index 7567781f55..ed3920d327 100644 --- a/packages/medusa/src/api/admin/order-edits/middlewares.ts +++ b/packages/medusa/src/api/admin/order-edits/middlewares.ts @@ -71,6 +71,11 @@ export const adminOrderEditRoutesMiddlewares: MiddlewareRoute[] = [ matcher: "/admin/order-edits/:id/confirm", middlewares: [], }, + { + method: ["POST"], + matcher: "/admin/order-edits/:id/request", + middlewares: [], + }, { method: ["DELETE"], matcher: "/admin/order-edits/:id",