feat(core-flows,medusa,utils,types): adds delivered_quantity to order (#9130)

what:

- adds delivered_quantity to order


https://github.com/user-attachments/assets/709b1727-08ed-4a88-ae29-38f13540e301
This commit is contained in:
Riqwan Thamir
2024-09-16 11:59:01 +02:00
committed by GitHub
parent 950cf9af79
commit 3e97a64b21
41 changed files with 794 additions and 25 deletions

View File

@@ -13,6 +13,7 @@ export const updateFulfillmentStep = createStep(
{ container }
) => {
const { id, ...data } = input
const service = container.resolve<IFulfillmentModuleService>(
Modules.FULFILLMENT
)

View File

@@ -9,8 +9,8 @@ export * from "./create-shipping-profiles"
export * from "./delete-fulfillment-sets"
export * from "./delete-service-zones"
export * from "./delete-shipping-options"
export * from "./mark-fulfillment-as-delivered"
export * from "./update-fulfillment"
export * from "./update-service-zones"
export * from "./update-shipping-options"
export * from "./update-shipping-profiles"

View File

@@ -0,0 +1,67 @@
import { FulfillmentDTO } from "@medusajs/types"
import { MedusaError } from "@medusajs/utils"
import {
StepResponse,
WorkflowData,
WorkflowResponse,
createStep,
createWorkflow,
transform,
} from "@medusajs/workflows-sdk"
import { useRemoteQueryStep } from "../../common"
import { updateFulfillmentWorkflow } from "./update-fulfillment"
export const validateFulfillmentDeliverabilityStepId =
"validate-fulfillment-deliverability"
/**
* This step validates that if a fulfillment can be marked delivered
*/
export const validateFulfillmentDeliverabilityStep = createStep(
validateFulfillmentDeliverabilityStepId,
async (fulfillment: FulfillmentDTO) => {
if (fulfillment.canceled_at) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
"Cannot deliver an already canceled fulfillment"
)
}
if (fulfillment.delivered_at) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
"Fulfillment has already been marked delivered"
)
}
return new StepResponse(void 0)
}
)
export const markFulfillmentAsDeliveredWorkflowId =
"mark-fulfillment-as-delivered-workflow"
/**
* This workflow marks fulfillment as delivered.
*/
export const markFulfillmentAsDeliveredWorkflow = createWorkflow(
markFulfillmentAsDeliveredWorkflowId,
({ id }: WorkflowData<{ id: string }>) => {
const fulfillment = useRemoteQueryStep({
entry_point: "fulfillment",
fields: ["id", "delivered_at", "canceled_at"],
variables: { id },
throw_if_key_not_found: true,
list: false,
})
validateFulfillmentDeliverabilityStep(fulfillment)
const updateInput = transform({ id }, ({ id }) => ({
id,
delivered_at: new Date(),
}))
return new WorkflowResponse(
updateFulfillmentWorkflow.runAsStep({ input: updateInput })
)
}
)

View File

@@ -0,0 +1,31 @@
import { IOrderModuleService, RegisterOrderDeliveryDTO } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/utils"
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
export const registerOrderDeliveryStepId = "register-order-delivery"
/**
* This step registers a delivery for an order fulfillment.
*/
export const registerOrderDeliveryStep = createStep(
registerOrderDeliveryStepId,
async (data: RegisterOrderDeliveryDTO, { container }) => {
const service = container.resolve<IOrderModuleService>(
ModuleRegistrationName.ORDER
)
await service.registerDelivery(data)
return new StepResponse(void 0, data.order_id)
},
async (orderId, { container }) => {
if (!orderId) {
return
}
const service = container.resolve<IOrderModuleService>(
ModuleRegistrationName.ORDER
)
await service.revertLastVersion(orderId)
}
)

View File

@@ -41,6 +41,7 @@ export * from "./exchange/update-exchange-add-item"
export * from "./exchange/update-exchange-shipping-method"
export * from "./get-order-detail"
export * from "./get-orders-list"
export * from "./mark-order-fulfillment-as-delivered"
export * from "./mark-payment-collection-as-paid"
export * from "./order-edit/begin-order-edit"
export * from "./order-edit/cancel-begin-order-edit"

View File

@@ -0,0 +1,140 @@
import {
FulfillmentDTO,
OrderDTO,
RegisterOrderDeliveryDTO,
} from "@medusajs/types"
import { FulfillmentEvents, Modules } from "@medusajs/utils"
import {
WorkflowData,
WorkflowResponse,
createStep,
createWorkflow,
parallelize,
transform,
} from "@medusajs/workflows-sdk"
import { emitEventStep, useRemoteQueryStep } from "../../common"
import { markFulfillmentAsDeliveredWorkflow } from "../../fulfillment"
import { registerOrderDeliveryStep } from "../steps/register-delivery"
import {
throwIfItemsDoesNotExistsInOrder,
throwIfOrderIsCancelled,
} from "../utils/order-validation"
export const orderFulfillmentDeliverablilityValidationStepId =
"order-fulfillment-deliverability-validation"
/**
* This step validates that order & fulfillment are valid
*/
export const orderFulfillmentDeliverablilityValidationStep = createStep(
orderFulfillmentDeliverablilityValidationStepId,
async ({
fulfillment,
order,
}: {
order: OrderDTO & { fulfillments: FulfillmentDTO[] }
fulfillment: FulfillmentDTO
}) => {
throwIfOrderIsCancelled({ order })
const orderFulfillment = order.fulfillments?.find(
(f) => f.id === fulfillment.id
)
if (!orderFulfillment) {
throw new Error(
`Fulfillment with id ${fulfillment.id} not found in the order`
)
}
throwIfItemsDoesNotExistsInOrder({
order,
inputItems: order.items!.map((i) => ({
id: i.id,
quantity: i.quantity,
})),
})
}
)
function prepareRegisterDeliveryData({
fulfillment,
order,
}: {
fulfillment: FulfillmentDTO
order: OrderDTO & { fulfillments: FulfillmentDTO[] }
}): RegisterOrderDeliveryDTO {
const orderFulfillment = order.fulfillments.find(
(f) => f.id === fulfillment.id
)!
return {
order_id: order.id,
reference: Modules.FULFILLMENT,
reference_id: orderFulfillment.id,
items: orderFulfillment.items!.map((i) => {
return {
id: i.line_item_id!,
quantity: i.quantity!,
}
}),
}
}
export const markOrderFulfillmentAsDeliveredWorkflowId =
"mark-order-fulfillment-as-delivered-workflow"
/**
* This workflow marks a fulfillment in an order as delivered.
*/
export const markOrderFulfillmentAsDeliveredWorkflow = createWorkflow(
markOrderFulfillmentAsDeliveredWorkflowId,
(input: WorkflowData<{ orderId: string; fulfillmentId: string }>) => {
const { fulfillmentId, orderId } = input
const fulfillment = useRemoteQueryStep({
entry_point: "fulfillment",
fields: ["id"],
variables: { id: fulfillmentId },
throw_if_key_not_found: true,
list: false,
})
const order = useRemoteQueryStep({
entry_point: "order",
fields: [
"id",
"summary",
"currency_code",
"region_id",
"fulfillments.id",
"fulfillments.items.id",
"fulfillments.items.quantity",
"fulfillments.items.line_item_id",
"items.id",
"items.quantity",
],
variables: { id: orderId },
throw_if_key_not_found: true,
list: false,
}).config({ name: "order-query" })
orderFulfillmentDeliverablilityValidationStep({ order, fulfillment })
const deliveryData = transform(
{ order, fulfillment },
prepareRegisterDeliveryData
)
const [deliveredFulfillment] = parallelize(
markFulfillmentAsDeliveredWorkflow.runAsStep({
input: { id: fulfillment.id },
}),
registerOrderDeliveryStep(deliveryData)
)
emitEventStep({
eventName: FulfillmentEvents.DELIVERY_CREATED,
data: { id: deliveredFulfillment.id },
})
return new WorkflowResponse(void 0)
}
)