diff --git a/.changeset/clever-avocados-jog.md b/.changeset/clever-avocados-jog.md new file mode 100644 index 0000000000..bbcab8816c --- /dev/null +++ b/.changeset/clever-avocados-jog.md @@ -0,0 +1,5 @@ +--- +"@medusajs/core-flows": patch +--- + +chore(core-flows): only allow published products in addToCartWorkflow diff --git a/integration-tests/http/__tests__/cart/store/cart.spec.ts b/integration-tests/http/__tests__/cart/store/cart.spec.ts index d690546102..6ff7470ff8 100644 --- a/integration-tests/http/__tests__/cart/store/cart.spec.ts +++ b/integration-tests/http/__tests__/cart/store/cart.spec.ts @@ -2036,6 +2036,7 @@ medusaIntegrationTestRunner({ { title: "Product without inventory management", description: "test", + status: ProductStatus.PUBLISHED, options: [ { title: "Size", @@ -2229,6 +2230,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: `Test fixture ${shippingProfile.id}`, + status: ProductStatus.PUBLISHED, shipping_profile_id: shippingProfile.id, options: [ { title: "pack", values: ["1-pack", "2-pack", "3-pack"] }, @@ -2548,6 +2550,7 @@ medusaIntegrationTestRunner({ `/admin/products`, { title: "test product", + status: ProductStatus.PUBLISHED, description: "test", options: [ { @@ -2893,6 +2896,7 @@ medusaIntegrationTestRunner({ { title: "Gift Card", description: "test", + status: ProductStatus.PUBLISHED, is_giftcard: true, options: [ { @@ -3452,6 +3456,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Medusa T-Shirt not discountable", + status: ProductStatus.PUBLISHED, handle: "t-shirt-not-discountable", discountable: false, options: [ @@ -3628,6 +3633,7 @@ medusaIntegrationTestRunner({ { title: "Product for free", description: "test", + status: ProductStatus.PUBLISHED, options: [ { title: "Size", @@ -3744,6 +3750,7 @@ medusaIntegrationTestRunner({ { title: "Product for free", description: "test", + status: ProductStatus.PUBLISHED, options: [ { title: "Size", @@ -3862,6 +3869,7 @@ medusaIntegrationTestRunner({ { title: "Product for free", description: "test", + status: ProductStatus.PUBLISHED, options: [ { title: "Size", @@ -3980,6 +3988,7 @@ medusaIntegrationTestRunner({ { title: "Product for free", description: "test", + status: ProductStatus.PUBLISHED, options: [ { title: "Size", @@ -4117,6 +4126,7 @@ medusaIntegrationTestRunner({ { title: "Product for free", description: "test", + status: ProductStatus.PUBLISHED, options: [ { title: "Size", @@ -4233,6 +4243,7 @@ medusaIntegrationTestRunner({ { title: "Product for free", description: "test", + status: ProductStatus.PUBLISHED, options: [ { title: "Size", @@ -4370,6 +4381,7 @@ medusaIntegrationTestRunner({ { title: "Product for free", description: "test", + status: ProductStatus.PUBLISHED, options: [ { title: "Size", @@ -4464,6 +4476,7 @@ medusaIntegrationTestRunner({ `/admin/products`, { title: "Product for free", + status: ProductStatus.PUBLISHED, description: "test", options: [ { diff --git a/integration-tests/http/__tests__/claims/claims.spec.ts b/integration-tests/http/__tests__/claims/claims.spec.ts index 3246be0980..cce6bd0336 100644 --- a/integration-tests/http/__tests__/claims/claims.spec.ts +++ b/integration-tests/http/__tests__/claims/claims.spec.ts @@ -4,6 +4,7 @@ import { ClaimType, ContainerRegistrationKeys, Modules, + ProductStatus, RuleOperator, } from "@medusajs/utils" import { @@ -82,6 +83,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Test product", + status: ProductStatus.PUBLISHED, options: [{ title: "size", values: ["large", "small"] }], shipping_profile_id: shippingProfile.id, variants: [ @@ -107,6 +109,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Extra product", + status: ProductStatus.PUBLISHED, options: [{ title: "size", values: ["large", "small"] }], shipping_profile_id: shippingProfile.id, variants: [ 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 535107a13e..178b0fed00 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 @@ -1,6 +1,6 @@ import { medusaIntegrationTestRunner } from "@medusajs/test-utils" import { HttpTypes } from "@medusajs/types" -import { ModuleRegistrationName } from "@medusajs/utils" +import { ModuleRegistrationName, ProductStatus } from "@medusajs/utils" import { adminHeaders, createAdminUser, } from "../../../../helpers/create-admin-user" import { setupTaxStructure } from "../../../../modules/__tests__/fixtures" @@ -312,6 +312,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Shirt", + status: ProductStatus.PUBLISHED, options: [ { title: "size", values: ["large", "medium", "small"] }, ], @@ -537,6 +538,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Shirt", + status: ProductStatus.PUBLISHED, options: [{ title: "size", values: ["large", "small"] }], variants: [ { diff --git a/integration-tests/http/__tests__/exchanges/exchanges.spec.ts b/integration-tests/http/__tests__/exchanges/exchanges.spec.ts index b74a57fb94..b72de66c80 100644 --- a/integration-tests/http/__tests__/exchanges/exchanges.spec.ts +++ b/integration-tests/http/__tests__/exchanges/exchanges.spec.ts @@ -2,6 +2,7 @@ import { medusaIntegrationTestRunner } from "@medusajs/test-utils" import { ContainerRegistrationKeys, Modules, + ProductStatus, RuleOperator, } from "@medusajs/utils" import { @@ -80,6 +81,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Test product", + status: ProductStatus.PUBLISHED, shipping_profile_id: shippingProfile.id, options: [{ title: "size", values: ["large", "small"] }], variants: [ @@ -105,6 +107,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Extra product", + status: ProductStatus.PUBLISHED, shipping_profile_id: shippingProfile.id, options: [{ title: "size", values: ["large", "small"] }], variants: [ @@ -130,6 +133,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Extra product 2, same price", + status: ProductStatus.PUBLISHED, shipping_profile_id: shippingProfile.id, options: [{ title: "size", values: ["large", "small"] }], variants: [ diff --git a/integration-tests/http/__tests__/fixtures/order.ts b/integration-tests/http/__tests__/fixtures/order.ts index a8626cf96c..4f1f0bf61b 100644 --- a/integration-tests/http/__tests__/fixtures/order.ts +++ b/integration-tests/http/__tests__/fixtures/order.ts @@ -6,7 +6,7 @@ import { AdminStockLocation, MedusaContainer, } from "@medusajs/types" -import { ContainerRegistrationKeys, Modules } from "@medusajs/utils" +import { ContainerRegistrationKeys, Modules, ProductStatus } from "@medusajs/utils" import { adminHeaders, generatePublishableKey, @@ -116,6 +116,7 @@ export async function createOrderSeeder({ "/admin/products", { title: `Test fixture ${shippingProfile.id}`, + status: ProductStatus.PUBLISHED, shipping_profile_id: withoutShipping ? undefined : shippingProfile.id, options: [ { title: "size", values: ["large", "small"] }, 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 f2b1237f70..1c8fc8ee01 100644 --- a/integration-tests/http/__tests__/order-edits/order-edits.spec.ts +++ b/integration-tests/http/__tests__/order-edits/order-edits.spec.ts @@ -3,6 +3,7 @@ import { ContainerRegistrationKeys, Modules, OrderChangeStatus, + ProductStatus, RuleOperator, } from "@medusajs/utils" import { @@ -109,6 +110,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Test product", + status: ProductStatus.PUBLISHED, options: [{ title: "size", values: ["large", "small"] }], shipping_profile_id: shippingProfile.id, variants: [ @@ -134,6 +136,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Extra product", + status: ProductStatus.PUBLISHED, options: [{ title: "size", values: ["large", "small"] }], shipping_profile_id: shippingProfile.id, variants: [ @@ -607,6 +610,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Shirt", + status: ProductStatus.PUBLISHED, options: [ { title: "size", values: ["large", "medium", "small"] }, ], diff --git a/integration-tests/http/__tests__/order/admin/order.spec.ts b/integration-tests/http/__tests__/order/admin/order.spec.ts index cdb164410b..a863e84a5b 100644 --- a/integration-tests/http/__tests__/order/admin/order.spec.ts +++ b/integration-tests/http/__tests__/order/admin/order.spec.ts @@ -1,6 +1,6 @@ import { medusaIntegrationTestRunner } from "@medusajs/test-utils" import { AdminShippingOption } from "@medusajs/types" -import { ModuleRegistrationName } from "@medusajs/utils" +import { ModuleRegistrationName, ProductStatus } from "@medusajs/utils" import { adminHeaders, createAdminUser, @@ -705,6 +705,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: `Test fixture`, + status: ProductStatus.PUBLISHED, shipping_profile_id: shippingProfile.id, options: [ { title: "size", values: ["large", "small"] }, @@ -793,6 +794,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: `Test fixture 2`, + status: ProductStatus.PUBLISHED, options: [ { title: "size", values: ["large", "small"] }, { title: "color", values: ["green"] }, @@ -829,6 +831,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: `Test fixture 3`, + status: ProductStatus.PUBLISHED, shipping_profile_id: shippingProfile.id, options: [ { title: "size", values: ["large", "small"] }, @@ -883,6 +886,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: `Test override 4`, + status: ProductStatus.PUBLISHED, shipping_profile_id: shippingProfile.id, options: [{ title: "size", values: ["large"] }], variants: [ @@ -924,6 +928,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: `Test fixture 4`, + status: ProductStatus.PUBLISHED, shipping_profile_id: shippingProfileOverride.id, options: [ { title: "size", values: ["large", "small"] }, @@ -1310,6 +1315,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: `Wooden table`, + status: ProductStatus.PUBLISHED, shipping_profile_id: shippingProfile.id, options: [{ title: "color", values: ["green"] }], variants: [ @@ -1474,6 +1480,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: `Tablet`, + status: ProductStatus.PUBLISHED, shipping_profile_id: shippingProfile.id, options: [{ title: "color", values: ["green"] }], variants: [ @@ -1697,6 +1704,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: `Tablet`, + status: ProductStatus.PUBLISHED, shipping_profile_id: shippingProfile.id, options: [{ title: "color", values: ["green"] }], variants: [ @@ -2101,6 +2109,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: `Bottle Packs`, + status: ProductStatus.PUBLISHED, shipping_profile_id: shippingProfile.id, options: [{ title: "packs", values: ["one", "two", "three"] }], variants: [ @@ -2907,6 +2916,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: `Wooden table`, + status: ProductStatus.PUBLISHED, shipping_profile_id: shippingProfile.id, options: [{ title: "color", values: ["green"] }], variants: [ diff --git a/integration-tests/http/__tests__/promotions/admin/promotions.spec.ts b/integration-tests/http/__tests__/promotions/admin/promotions.spec.ts index 58b941e0b0..6cd4bb1639 100644 --- a/integration-tests/http/__tests__/promotions/admin/promotions.spec.ts +++ b/integration-tests/http/__tests__/promotions/admin/promotions.spec.ts @@ -1,5 +1,5 @@ import { medusaIntegrationTestRunner } from "@medusajs/test-utils" -import { Modules, PromotionStatus, PromotionType } from "@medusajs/utils" +import { Modules, ProductStatus, PromotionStatus, PromotionType } from "@medusajs/utils" import { createAdminUser, generatePublishableKey, @@ -1724,6 +1724,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Discounted Medusa T-Shirt", + status: ProductStatus.PUBLISHED, handle: "discounted-medusa-t-shirt", options: [ { diff --git a/integration-tests/http/__tests__/shipping-option/store/shipping-option-calculated.spec.ts b/integration-tests/http/__tests__/shipping-option/store/shipping-option-calculated.spec.ts index 61ffbc46f3..7ace8c0991 100644 --- a/integration-tests/http/__tests__/shipping-option/store/shipping-option-calculated.spec.ts +++ b/integration-tests/http/__tests__/shipping-option/store/shipping-option-calculated.spec.ts @@ -4,6 +4,7 @@ import { generatePublishableKey, generateStoreHeaders, } from "../../../../helpers/create-admin-user" +import { ProductStatus } from "@medusajs/utils" jest.setTimeout(50000) @@ -80,6 +81,7 @@ medusaIntegrationTestRunner({ { title: "Test fixture", shipping_profile_id: shippingProfile.id, + status: ProductStatus.PUBLISHED, options: [ { title: "size", values: ["large", "small"] }, { title: "color", values: ["green"] }, diff --git a/integration-tests/http/__tests__/shipping-option/store/shipping-option.spec.ts b/integration-tests/http/__tests__/shipping-option/store/shipping-option.spec.ts index 0fb0631483..2642474a6e 100644 --- a/integration-tests/http/__tests__/shipping-option/store/shipping-option.spec.ts +++ b/integration-tests/http/__tests__/shipping-option/store/shipping-option.spec.ts @@ -4,6 +4,7 @@ import { generatePublishableKey, generateStoreHeaders, } from "../../../../helpers/create-admin-user" +import { ProductStatus } from "@medusajs/utils" jest.setTimeout(50000) @@ -78,6 +79,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Test fixture", + status: ProductStatus.PUBLISHED, options: [ { title: "size", values: ["large", "small"] }, { title: "color", values: ["green"] }, @@ -634,6 +636,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Test prod", + status: ProductStatus.PUBLISHED, options: [ { title: "size", values: ["large", "small"] }, { title: "color", values: ["green"] }, diff --git a/integration-tests/modules/__tests__/cart/store/cart.completion.ts b/integration-tests/modules/__tests__/cart/store/cart.completion.ts index 33f1c67cb9..bfeb8d7c8c 100644 --- a/integration-tests/modules/__tests__/cart/store/cart.completion.ts +++ b/integration-tests/modules/__tests__/cart/store/cart.completion.ts @@ -26,6 +26,7 @@ import { import { ContainerRegistrationKeys, Modules, + ProductStatus, remoteQueryObjectFromString, } from "@medusajs/utils" import { @@ -316,6 +317,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", @@ -472,6 +474,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", @@ -605,6 +608,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", @@ -764,6 +768,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", diff --git a/integration-tests/modules/__tests__/cart/store/cart.workflows.spec.ts b/integration-tests/modules/__tests__/cart/store/cart.workflows.spec.ts index 7eeb408a19..68b0eee107 100644 --- a/integration-tests/modules/__tests__/cart/store/cart.workflows.spec.ts +++ b/integration-tests/modules/__tests__/cart/store/cart.workflows.spec.ts @@ -36,6 +36,7 @@ import { Modules, PriceListStatus, PriceListType, + ProductStatus, RuleOperator, } from "@medusajs/utils" import { @@ -184,6 +185,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", @@ -422,6 +424,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", @@ -538,6 +541,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", @@ -687,6 +691,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", @@ -855,6 +860,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", @@ -1263,6 +1269,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", @@ -1456,6 +1463,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", @@ -1691,6 +1699,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", @@ -1809,6 +1818,153 @@ medusaIntegrationTestRunner({ ) }) + it("should throw if product is not published", async () => { + const salesChannel = await scModuleService.createSalesChannels({ + name: "Webshop", + }) + + const location = await stockLocationModule.createStockLocations({ + name: "Warehouse", + }) + + let cart = await cartModuleService.createCarts({ + currency_code: "usd", + sales_channel_id: salesChannel.id, + }) + + const [product] = await productModule.createProducts([ + { + title: "Test product", + status: ProductStatus.DRAFT, + variants: [ + { + title: "Test variant", + }, + ], + }, + ]) + + const inventoryItem = await inventoryModule.createInventoryItems({ + sku: "inv-1234", + }) + + await inventoryModule.createInventoryLevels([ + { + inventory_item_id: inventoryItem.id, + location_id: location.id, + stocked_quantity: 2, + reserved_quantity: 0, + }, + ]) + + const priceSet = await pricingModule.createPriceSets({ + prices: [ + { + amount: 3000, + currency_code: "usd", + }, + ], + }) + + await pricingModule.createPricePreferences({ + attribute: "currency_code", + value: "usd", + is_tax_inclusive: true, + }) + + await remoteLink.create([ + { + [Modules.PRODUCT]: { + variant_id: product.variants[0].id, + }, + [Modules.PRICING]: { + price_set_id: priceSet.id, + }, + }, + { + [Modules.SALES_CHANNEL]: { + sales_channel_id: salesChannel.id, + }, + [Modules.STOCK_LOCATION]: { + stock_location_id: location.id, + }, + }, + { + [Modules.PRODUCT]: { + variant_id: product.variants[0].id, + }, + [Modules.INVENTORY]: { + inventory_item_id: inventoryItem.id, + }, + }, + ]) + + cart = await cartModuleService.retrieveCart(cart.id, { + select: ["id", "region_id", "currency_code", "sales_channel_id"], + }) + + const { errors } = await addToCartWorkflow(appContainer).run({ + input: { + items: [ + { + variant_id: product.variants[0].id, + quantity: 1, + }, + ], + cart_id: cart.id, + }, + throwOnError: false, + }) + + expect(errors).toEqual([ + { + action: "get-variant-items-with-prices-workflow-as-step", + handlerType: "invoke", + error: expect.objectContaining({ + message: expect.stringContaining( + `Variants ${product.variants[0].id} do not exist or belong to a product that is not published` + ), + }), + }, + ]) + }) + + it("should throw if variant doesn't exist", async () => { + const salesChannel = await scModuleService.createSalesChannels({ + name: "Webshop", + }) + + let cart = await cartModuleService.createCarts({ + currency_code: "usd", + sales_channel_id: salesChannel.id, + }) + + const { errors } = await addToCartWorkflow(appContainer).run({ + input: { + items: [ + { + variant_id: "var_1234", + quantity: 1, + }, + ], + cart_id: cart.id, + }, + throwOnError: false, + }) + + expect(errors).toEqual([ + { + action: "get-variant-items-with-prices-workflow-as-step", + handlerType: "invoke", + error: expect.objectContaining({ + message: expect.stringContaining( + `Variants var_1234 do not exist or belong to a product that is not published` + ), + }), + }, + ]) + }) + it("should throw if no price sets for variant exist", async () => { const salesChannel = await scModuleService.createSalesChannels({ name: "Webshop", @@ -1910,6 +2066,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", @@ -2062,6 +2219,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", diff --git a/integration-tests/modules/__tests__/cart/store/carts.spec.ts b/integration-tests/modules/__tests__/cart/store/carts.spec.ts index 98434e0685..110dfbc568 100644 --- a/integration-tests/modules/__tests__/cart/store/carts.spec.ts +++ b/integration-tests/modules/__tests__/cart/store/carts.spec.ts @@ -109,6 +109,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { manage_inventory: false, @@ -215,6 +216,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product default tax", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant default tax", manage_inventory: false }, ], @@ -1334,6 +1336,7 @@ medusaIntegrationTestRunner({ "/admin/products", { title: "Test fixture", + status: ProductStatus.PUBLISHED, options: [ { title: "size", values: ["large", "small"] }, { title: "color", values: ["green"] }, diff --git a/integration-tests/modules/__tests__/order/draft-order.spec.ts b/integration-tests/modules/__tests__/order/draft-order.spec.ts index 553b312dc6..c5807cde77 100644 --- a/integration-tests/modules/__tests__/order/draft-order.spec.ts +++ b/integration-tests/modules/__tests__/order/draft-order.spec.ts @@ -11,6 +11,7 @@ import { import { ContainerRegistrationKeys, Modules, + ProductStatus, PromotionStatus, PromotionType, } from "@medusajs/utils" @@ -71,6 +72,7 @@ medusaIntegrationTestRunner({ const [product, product_2] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", @@ -79,6 +81,7 @@ medusaIntegrationTestRunner({ }, { title: "Another product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Variant variable", @@ -401,6 +404,7 @@ medusaIntegrationTestRunner({ const [product, product_2] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", @@ -409,6 +413,7 @@ medusaIntegrationTestRunner({ }, { title: "Another product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Variant variable", @@ -815,6 +820,7 @@ medusaIntegrationTestRunner({ const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, type_id: productType.id, variants: [ { diff --git a/integration-tests/modules/__tests__/order/workflows/__fixtures__/index.ts b/integration-tests/modules/__tests__/order/workflows/__fixtures__/index.ts index 11d6c8a783..05dece6752 100644 --- a/integration-tests/modules/__tests__/order/workflows/__fixtures__/index.ts +++ b/integration-tests/modules/__tests__/order/workflows/__fixtures__/index.ts @@ -9,6 +9,7 @@ import { import { ContainerRegistrationKeys, Modules, + ProductStatus, remoteQueryObjectFromString, } from "@medusajs/utils" @@ -94,6 +95,7 @@ export async function prepareDataFixtures({ container }) { const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", diff --git a/integration-tests/modules/__tests__/order/workflows/begin-order-exchange.spec.ts b/integration-tests/modules/__tests__/order/workflows/begin-order-exchange.spec.ts index e4568afa40..fe46960752 100644 --- a/integration-tests/modules/__tests__/order/workflows/begin-order-exchange.spec.ts +++ b/integration-tests/modules/__tests__/order/workflows/begin-order-exchange.spec.ts @@ -19,6 +19,7 @@ import { import { ContainerRegistrationKeys, Modules, + ProductStatus, RuleOperator, remoteQueryObjectFromString, } from "@medusajs/utils" @@ -108,6 +109,7 @@ async function prepareDataFixtures({ container }) { const [product] = await productModule.createProducts([ { title: "Test product", + status: ProductStatus.PUBLISHED, variants: [ { title: "Test variant", diff --git a/packages/core/core-flows/src/cart/utils/fields.ts b/packages/core/core-flows/src/cart/utils/fields.ts index 14cc80c0cb..21e3524781 100644 --- a/packages/core/core-flows/src/cart/utils/fields.ts +++ b/packages/core/core-flows/src/cart/utils/fields.ts @@ -157,6 +157,7 @@ export const productVariantsFields = [ "product.id", "product.title", "product.description", + "product.status", "product.subtitle", "product.thumbnail", "product.type.value", diff --git a/packages/core/core-flows/src/cart/workflows/get-variants-and-items-with-prices.ts b/packages/core/core-flows/src/cart/workflows/get-variants-and-items-with-prices.ts index df6ecfdef0..f82931cc03 100644 --- a/packages/core/core-flows/src/cart/workflows/get-variants-and-items-with-prices.ts +++ b/packages/core/core-flows/src/cart/workflows/get-variants-and-items-with-prices.ts @@ -13,6 +13,7 @@ import { filterObjectByKeys, isDefined, MedusaError, + ProductStatus, simpleHash, } from "@medusajs/framework/utils" import { @@ -167,6 +168,7 @@ export const getVariantsAndItemsWithPrices = createWorkflow( calculatedPriceSets, }): GetVariantsAndItemsWithPricesWorkflowOutput => { const priceNotFound: string[] = [] + const variantNotFoundOrPublished: string[] = [] const items = (inputItems ?? cart.items ?? []).map((item) => { const item_ = item as any @@ -182,6 +184,11 @@ export const getVariantsAndItemsWithPrices = createWorkflow( } const variant = variantsData.find((v) => v.id === item.variant_id) + if ((item.variant_id && !variant) || // variant specified but doesn't exist + (variant && (!variant?.product?.status || variant.product.status !== ProductStatus.PUBLISHED)) // variant exists but product is not published + ) { + variantNotFoundOrPublished.push(item_.variant_id) + } if (variant) { variant.calculated_price = calculatedPriceSet @@ -215,6 +222,12 @@ export const getVariantsAndItemsWithPrices = createWorkflow( } }) + if (variantNotFoundOrPublished.length > 0) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Variants ${variantNotFoundOrPublished.join(", ")} do not exist or belong to a product that is not published` + ) + } if (priceNotFound.length > 0) { throw new MedusaError( MedusaError.Types.INVALID_DATA, diff --git a/packages/core/core-flows/src/order/utils/fields.ts b/packages/core/core-flows/src/order/utils/fields.ts index e82712d9fa..59831a146f 100644 --- a/packages/core/core-flows/src/order/utils/fields.ts +++ b/packages/core/core-flows/src/order/utils/fields.ts @@ -8,6 +8,7 @@ export const productVariantsFields = [ "product.id", "product.title", "product.description", + "product.status", "product.subtitle", "product.thumbnail", "product.type.value",