diff --git a/.changeset/three-dodos-admire.md b/.changeset/three-dodos-admire.md new file mode 100644 index 0000000000..0a58bd5201 --- /dev/null +++ b/.changeset/three-dodos-admire.md @@ -0,0 +1,5 @@ +--- +"@medusajs/core-flows": patch +--- + +fix(core-flows): Access orderItem.variant safely inside convertDraftOrderWorkflow when containing custom items diff --git a/integration-tests/http/__tests__/draft-order/admin/draft-order.spec.ts b/integration-tests/http/__tests__/draft-order/admin/draft-order.spec.ts index 4e419efc4c..bc6fd04c18 100644 --- a/integration-tests/http/__tests__/draft-order/admin/draft-order.spec.ts +++ b/integration-tests/http/__tests__/draft-order/admin/draft-order.spec.ts @@ -416,6 +416,102 @@ medusaIntegrationTestRunner({ expect(response.status).toBe(200) expect(response.data.order.status).toBe("pending") }) + + it("should convert a draft order with a custom item (without variant_id) to an order", async () => { + await api.post( + `/admin/draft-orders/${testDraftOrder.id}/edit`, + {}, + adminHeaders + ) + + await api.post( + `/admin/draft-orders/${testDraftOrder.id}/edit/items`, + { + items: [ + { + title: "Custom Item", + quantity: 2, + unit_price: 1500, + }, + ], + }, + adminHeaders + ) + + await api.post( + `/admin/draft-orders/${testDraftOrder.id}/edit/confirm`, + {}, + adminHeaders + ) + + const response = await api.post( + `/admin/draft-orders/${testDraftOrder.id}/convert-to-order`, + {}, + adminHeaders + ) + + expect(response.status).toBe(200) + expect(response.data.order.status).toBe("pending") + }) + + it("should convert a draft order with both variant items and custom items to an order", async () => { + await api.post( + `/admin/draft-orders/${testDraftOrder.id}/edit`, + {}, + adminHeaders + ) + + await api.post( + `/admin/draft-orders/${testDraftOrder.id}/edit/items`, + { + items: [ + { + variant_id: product.variants.find((v) => v.title === "L shirt") + .id, + quantity: 1, + }, + { + title: "Custom Item", + quantity: 1, + unit_price: 2000, + }, + ], + }, + adminHeaders + ) + + await api.post( + `/admin/draft-orders/${testDraftOrder.id}/edit/confirm`, + {}, + adminHeaders + ) + + let reservations = (await api.get(`/admin/reservations`, adminHeaders)) + .data.reservations + + expect(reservations.length).toBe(0) + + const response = await api.post( + `/admin/draft-orders/${testDraftOrder.id}/convert-to-order`, + {}, + adminHeaders + ) + + reservations = (await api.get(`/admin/reservations`, adminHeaders)).data + .reservations + + expect(reservations).toEqual( + expect.arrayContaining([ + expect.objectContaining({ + inventory_item_id: inventoryItemLarge.id, + quantity: 1, + }), + ]) + ) + + expect(response.status).toBe(200) + expect(response.data.order.status).toBe("pending") + }) }) describe("POST /draft-orders/:id/edit/items/:item_id", () => { diff --git a/packages/core/core-flows/src/draft-order/workflows/convert-draft-order.ts b/packages/core/core-flows/src/draft-order/workflows/convert-draft-order.ts index c7334616a2..8170c23b49 100644 --- a/packages/core/core-flows/src/draft-order/workflows/convert-draft-order.ts +++ b/packages/core/core-flows/src/draft-order/workflows/convert-draft-order.ts @@ -143,11 +143,13 @@ export const convertDraftOrderWorkflow = createWorkflow( for (const orderItem of orderItems.items ?? []) { items.push({ - variant_id: orderItem.variant.id, + variant_id: orderItem.variant?.id, quantity: orderItem.quantity, id: orderItem.id, }) - variants.push(orderItem.variant) + if (orderItem.variant) { + variants.push(orderItem.variant) + } } return {