diff --git a/.changeset/violet-carrots-unite.md b/.changeset/violet-carrots-unite.md new file mode 100644 index 0000000000..ea04031677 --- /dev/null +++ b/.changeset/violet-carrots-unite.md @@ -0,0 +1,7 @@ +--- +"@medusajs/dashboard": patch +"@medusajs/core-flows": patch +"@medusajs/medusa": patch +--- + +fix(core-flows, dashboard, medusa): prevent creatiion of a fulfilment without items diff --git a/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/components/order-create-fulfillment-form/order-create-fulfillment-form.tsx b/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/components/order-create-fulfillment-form/order-create-fulfillment-form.tsx index 4424851f37..ec5a49545f 100644 --- a/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/components/order-create-fulfillment-form/order-create-fulfillment-form.tsx +++ b/packages/admin/dashboard/src/routes/orders/order-create-fulfillment/components/order-create-fulfillment-form/order-create-fulfillment-form.tsx @@ -122,19 +122,26 @@ export function OrderCreateFulfillmentForm({ {} as Record ) + const items = Object.entries(data.quantity) + .filter( + ([id, value]) => + !!value && itemShippingProfileMap[id] === selectedShippingProfileId + ) + .map(([id, quantity]) => ({ + id, + quantity, + })) + + if (!items.length) { + toast.error(t("orders.fulfillment.error.noItems")) + return + } + const payload: HttpTypes.AdminCreateOrderFulfillment = { location_id: selectedLocationId, shipping_option_id: shippingOptionId, no_notification: !data.send_notification, - items: Object.entries(data.quantity) - .filter( - ([id, value]) => - !!value && itemShippingProfileMap[id] === selectedShippingProfileId - ) - .map(([id, quantity]) => ({ - id, - quantity, - })), + items, } try { diff --git a/packages/core/core-flows/src/order/workflows/create-fulfillment.ts b/packages/core/core-flows/src/order/workflows/create-fulfillment.ts index 17af74f648..4a764fa07d 100644 --- a/packages/core/core-flows/src/order/workflows/create-fulfillment.ts +++ b/packages/core/core-flows/src/order/workflows/create-fulfillment.ts @@ -83,6 +83,13 @@ export type CreateFulfillmentValidateOrderStepInput = { export const createFulfillmentValidateOrder = createStep( "create-fulfillment-validate-order", ({ order, inputItems }: CreateFulfillmentValidateOrderStepInput) => { + if (!inputItems.length) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + "No items to fulfill" + ) + } + throwIfOrderIsCancelled({ order }) throwIfItemsDoesNotExistsInOrder({ order, inputItems }) throwIfItemsAreNotGroupedByShippingRequirement({ order, inputItems }) diff --git a/packages/medusa/src/api/admin/orders/validators.ts b/packages/medusa/src/api/admin/orders/validators.ts index 88abafefad..98c0754bd2 100644 --- a/packages/medusa/src/api/admin/orders/validators.ts +++ b/packages/medusa/src/api/admin/orders/validators.ts @@ -71,7 +71,7 @@ export type AdminOrderCreateFulfillmentType = z.infer< typeof OrderCreateFulfillment > export const OrderCreateFulfillment = z.object({ - items: z.array(Item), + items: z.array(Item).min(1), location_id: z.string().nullish(), shipping_option_id: z.string().optional(), no_notification: z.boolean().optional(),