diff --git a/.changeset/dry-kids-hear.md b/.changeset/dry-kids-hear.md new file mode 100644 index 0000000000..4c830c7a11 --- /dev/null +++ b/.changeset/dry-kids-hear.md @@ -0,0 +1,5 @@ +--- +"@medusajs/medusa": patch +--- + +fix(medusa): Throw upon draft order creation if a variant does not have any prices diff --git a/integration-tests/api/__tests__/admin/draft-order/draft-order.js b/integration-tests/api/__tests__/admin/draft-order/draft-order.js index 18cf678659..fe12d897fe 100644 --- a/integration-tests/api/__tests__/admin/draft-order/draft-order.js +++ b/integration-tests/api/__tests__/admin/draft-order/draft-order.js @@ -80,6 +80,41 @@ describe("/admin/draft-orders", () => { expect(response.status).toEqual(200) }) + it("creates a draft order cart containing variant without prices should fail", async () => { + const api = useApi() + + const payload = { + email: "oli@test.dk", + shipping_address: "oli-shipping", + items: [ + { + variant_id: "test-variant-without-prices", + quantity: 2, + metadata: {}, + }, + ], + region_id: "test-region", + customer_id: "oli-test", + shipping_methods: [ + { + option_id: "test-option", + }, + ], + } + + const response = await api + .post("/admin/draft-orders", payload, adminReqConfig) + .catch((err) => { + return err.response + }) + + expect(response.status).toEqual(400) + expect(response.data.type).toEqual("invalid_data") + expect(response.data.message).toEqual( + `Cannot generate line item for variant "test variant without prices" without a price` + ) + }) + it("creates a draft order with a custom shipping option price", async () => { const api = useApi() diff --git a/integration-tests/api/helpers/draft-order-seeder.js b/integration-tests/api/helpers/draft-order-seeder.js index c1749dcffc..91b289fa9f 100644 --- a/integration-tests/api/helpers/draft-order-seeder.js +++ b/integration-tests/api/helpers/draft-order-seeder.js @@ -59,6 +59,19 @@ module.exports = async (dataSource, data = {}) => { `insert into product_sales_channel values ('test-product-2', '${salesChannel.id}');` ) + await manager.insert(ProductVariant, { + id: "test-variant-without-prices", + title: "test variant without prices", + product_id: "test-product", + inventory_quantity: 1, + options: [ + { + option_id: "test-option", + value: "no prices", + }, + ], + }) + await manager.insert(ProductVariant, { id: "test-variant", title: "test variant", diff --git a/packages/medusa/src/api/routes/admin/discounts/__tests__/create-discount.js b/packages/medusa/src/api/routes/admin/discounts/__tests__/create-discount.js index 9d0cbb7964..cea0999562 100644 --- a/packages/medusa/src/api/routes/admin/discounts/__tests__/create-discount.js +++ b/packages/medusa/src/api/routes/admin/discounts/__tests__/create-discount.js @@ -7,8 +7,8 @@ const validRegionId = IdMap.getId("region-france") describe("POST /admin/discounts", () => { const adminSession = { jwt: { - userId: IdMap.getId("admin_user") - } + userId: IdMap.getId("admin_user"), + }, } describe("successful creation", () => { diff --git a/packages/medusa/src/services/draft-order.ts b/packages/medusa/src/services/draft-order.ts index 186fffff4a..1232ba4816 100644 --- a/packages/medusa/src/services/draft-order.ts +++ b/packages/medusa/src/services/draft-order.ts @@ -1,4 +1,4 @@ -import { isDefined, MedusaError } from "medusa-core-utils" +import { MedusaError } from "medusa-core-utils" import { EntityManager, FindOptionsWhere, @@ -29,6 +29,7 @@ import EventBusService from "./event-bus" import LineItemService from "./line-item" import ProductVariantService from "./product-variant" import ShippingOptionService from "./shipping-option" +import { isDefined } from "@medusajs/utils" type InjectedDependencies = { manager: EntityManager diff --git a/packages/medusa/src/services/line-item.ts b/packages/medusa/src/services/line-item.ts index bc7443b014..53d9d30489 100644 --- a/packages/medusa/src/services/line-item.ts +++ b/packages/medusa/src/services/line-item.ts @@ -332,6 +332,15 @@ class LineItemService extends TransactionBaseService { unit_price = context.variantPricing?.calculated_price ?? undefined } + if (unit_price == null) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Cannot generate line item for variant "${ + variant.title ?? variant.product.title ?? variant.id + }" without a price` + ) + } + const rawLineItem: Partial = { unit_price: unit_price, title: variant.product.title,