From e7e741b0ddba7ad0eb4c6c1933e3ddd2164122c0 Mon Sep 17 00:00:00 2001 From: Sebastian Rindom Date: Thu, 5 Dec 2024 16:23:53 +0100 Subject: [PATCH 1/5] fix: calculate inventory quantities based on sales channel and locations --- .../__tests__/product/store/product.spec.ts | 144 ++++++++++++++ .../product/steps/get-variant-availability.ts | 20 ++ .../src/product/get-variant-availability.ts | 178 ++++++++++++++++++ packages/core/utils/src/product/index.ts | 1 + .../src/api/admin/product-variants/route.ts | 4 +- .../api/admin/products/[id]/variants/route.ts | 4 +- .../src/api/store/products/[id]/route.ts | 7 +- .../medusa/src/api/store/products/helpers.ts | 29 +-- .../src/api/store/products/middlewares.ts | 8 - .../medusa/src/api/store/products/route.ts | 4 +- .../products/variant-inventory-quantity.ts | 140 ++++++-------- 11 files changed, 416 insertions(+), 123 deletions(-) create mode 100644 packages/core/core-flows/src/product/steps/get-variant-availability.ts create mode 100644 packages/core/utils/src/product/get-variant-availability.ts diff --git a/integration-tests/http/__tests__/product/store/product.spec.ts b/integration-tests/http/__tests__/product/store/product.spec.ts index f4f449b53ca36..4b64e5e1b96c4 100644 --- a/integration-tests/http/__tests__/product/store/product.spec.ts +++ b/integration-tests/http/__tests__/product/store/product.spec.ts @@ -1329,6 +1329,150 @@ medusaIntegrationTestRunner({ ) }) + it("should handle inventory items and location levels correctly", async () => { + const container = getContainer() + const channelService = container.resolve("sales_channel") + const locationService = container.resolve("stock_location") + const inventoryService = container.resolve("inventory") + const productService = container.resolve("product") + const pubKeyService = container.resolve("api_key") + const linkService = container.resolve("remoteLink") + + const [channelOne, channelTwo] = + await channelService.createSalesChannels([ + { name: "Sales Channel 1" }, + { name: "Sales Channel 2" }, + ]) + + const product = await productService.createProducts({ + status: "published", + title: "my prod", + options: [{ title: "color", values: ["green", "blue"] }], + variants: [ + { title: "variant one", options: { color: "green" } }, + { title: "variant two", options: { color: "blue" } }, + ], + }) + console.log(product) + const [variantOne, variantTwo] = product.variants + + const [itemOne, itemTwo, itemThree] = + await inventoryService.createInventoryItems([ + { sku: "sku-one" }, + { sku: "sku-two" }, + { sku: "sku-three" }, + ]) + + const [locationOne, locationTwo] = + await locationService.createStockLocations([ + { name: "Location One" }, + { name: "Location Two" }, + ]) + + await inventoryService.createInventoryLevels([ + { + location_id: locationOne.id, + inventory_item_id: itemOne.id, + stocked_quantity: 23, + }, + { + location_id: locationOne.id, + inventory_item_id: itemTwo.id, + stocked_quantity: 10, + }, + { + location_id: locationTwo.id, + inventory_item_id: itemThree.id, + stocked_quantity: 5, + }, + ]) + + const [pubKeyOne, pubKeyTwo] = await pubKeyService.createApiKeys([ + { title: "pub key one", type: "publishable", created_by: "me" }, + { title: "pub key two", type: "publishable", created_by: "me" }, + ]) + + await linkService.create([ + { + product: { product_id: product.id }, + sales_channel: { sales_channel_id: channelOne.id }, + }, + { + product: { product_id: product.id }, + sales_channel: { sales_channel_id: channelTwo.id }, + }, + { + product: { variant_id: variantOne.id }, + inventory: { inventory_item_id: itemOne.id }, + }, + { + product: { variant_id: variantTwo.id }, + inventory: { inventory_item_id: itemTwo.id }, + }, + { + product: { variant_id: variantTwo.id }, + inventory: { inventory_item_id: itemThree.id }, + data: { required_quantity: 2 }, + }, + { + sales_channel: { sales_channel_id: channelOne.id }, + stock_location: { stock_location_id: locationOne.id }, + }, + { + sales_channel: { sales_channel_id: channelTwo.id }, + stock_location: { stock_location_id: locationOne.id }, + }, + { + sales_channel: { sales_channel_id: channelTwo.id }, + stock_location: { stock_location_id: locationTwo.id }, + }, + { + api_key: { publishable_key_id: pubKeyOne.id }, + sales_channel: { sales_channel_id: channelOne.id }, + }, + { + api_key: { publishable_key_id: pubKeyTwo.id }, + sales_channel: { sales_channel_id: channelTwo.id }, + }, + ]) + + let response = await api.get( + `/store/products?fields=+variants.inventory_quantity`, + { headers: { "x-publishable-api-key": pubKeyOne.token } } + ) + + expect(response.status).toEqual(200) + for (const variant of response.data.products + .map((p) => p.variants) + .flat()) { + if (variant.id === variantOne.id) { + expect(variant.inventory_quantity).toEqual(23) + } else if (variant.id === variantTwo.id) { + expect(variant.inventory_quantity).toEqual(0) + } else { + throw new Error("Unexpected variant") + } + } + + response = await api.get( + `/store/products?fields=+variants.inventory_quantity`, + { headers: { "x-publishable-api-key": pubKeyTwo.token } } + ) + + expect(response.status).toEqual(200) + for (const variant of response.data.products + .map((p) => p.variants) + .flat()) { + if (variant.id === variantOne.id) { + expect(variant.inventory_quantity).toEqual(23) + } else if (variant.id === variantTwo.id) { + expect(variant.inventory_quantity).toEqual(2) + } else { + throw new Error("Unexpected variant") + } + } + }) + it("should list all inventory items for a variant", async () => { let response = await api.get( `/store/products?sales_channel_id[]=${salesChannel1.id}&fields=variants.inventory_items.inventory.location_levels.*`, diff --git a/packages/core/core-flows/src/product/steps/get-variant-availability.ts b/packages/core/core-flows/src/product/steps/get-variant-availability.ts new file mode 100644 index 0000000000000..93f17b7ebd086 --- /dev/null +++ b/packages/core/core-flows/src/product/steps/get-variant-availability.ts @@ -0,0 +1,20 @@ +import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk" +import { getVariantAvailability } from "@medusajs/framework/utils" + +export type GetVariantAvailabilityStepInput = { + variant_ids: string[] + sales_channel_id: string +} + +export const getVariantAvailabilityId = "get-variant-availability" +/** + * Computes the varaint availability for a list of variants in a given sales channel + */ +export const getVariantAvailabilityStep = createStep( + getVariantAvailabilityId, + async (data: GetVariantAvailabilityStepInput, { container }) => { + const query = container.resolve("query") + const availability = await getVariantAvailability(query, data) + return new StepResponse(availability) + } +) diff --git a/packages/core/utils/src/product/get-variant-availability.ts b/packages/core/utils/src/product/get-variant-availability.ts new file mode 100644 index 0000000000000..1d47ffec9af89 --- /dev/null +++ b/packages/core/utils/src/product/get-variant-availability.ts @@ -0,0 +1,178 @@ +import { RemoteQueryFunction } from "@medusajs/types" + +/** + * Computes the varaint availability for a list of variants in a given sales channel + * + * The availability algorithm works as follows: + * 1. For each variant, we retrieve its inventory items. + * 2. We calculate the available quantity for each inventory item, considering only the stock locations associated with the given sales channel. + * 3. For each inventory item, we calculate the maximum deliverable quantity by dividing the available quantity by the quantity required for the variant. + * 4. We take the minimum of these maximum deliverable quantities across all inventory items for the variant. + * 5. This minimum value represents the overall availability of the variant in the given sales channel. + * + * The algorithm takes into account: + * - Variant inventory items: The inventory records associated with each variant. + * - Required quantities: The quantity of each inventory item required to fulfill one unit of the variant. + * - Sales channels: The specific sales channel for which we're calculating availability. + * - Stock locations: The inventory locations associated with the sales channel. + * + * @param query - The Query function + * @param data - An object containing the variant ids and the sales channel id to compute the availability for + * @returns an object containing the variant ids and their availability + */ +export async function getVariantAvailability( + query: Omit, + data: VariantAvailabilityData +): Promise<{ + [variant_id: string]: { + availability: number + sales_channel_id: string + } +}> { + const { variantInventoriesMap, locationIds } = await getDataForComputation( + query, + data + ) + + return data.variant_ids.reduce((acc, variantId) => { + const variantInventoryItems = variantInventoriesMap.get(variantId) || [] + acc[variantId] = { + availability: computeVariantAvailability( + variantInventoryItems, + locationIds, + { requireChannelCheck: true } + ), + sales_channel_id: data.sales_channel_id, + } + return acc + }, {}) +} + +type TotalVariantAvailabilityData = { + variant_ids: string[] +} + +/** + * Computes the total availability for a list of variants across all stock locations + * + * @param query - The Query function + * @param data - An object containing the variant ids to compute the availability for + * @returns the total availability for the given variants + */ +export async function getTotalVariantAvailability( + query: Omit, + data: TotalVariantAvailabilityData +): Promise<{ + [variant_id: string]: { + availability: number + } +}> { + const { variantInventoriesMap, locationIds } = await getDataForComputation( + query, + data + ) + + return data.variant_ids.reduce((acc, variantId) => { + const variantInventoryItems = variantInventoriesMap.get(variantId) || [] + acc[variantId] = { + availability: computeVariantAvailability( + variantInventoryItems, + locationIds, + { requireChannelCheck: false } + ), + } + return acc + }, {}) +} + +interface VariantItems { + variant_id: string + required_quantity: number + variant: { + manage_inventory: boolean + allow_backorder: boolean + } + inventory: { + location_levels: { + location_id: string + available_quantity: number + }[] + } +} + +const computeVariantAvailability = ( + variantInventoryItems: VariantItems[], + channelLocationsSet: Set, + { requireChannelCheck } = { requireChannelCheck: true } +) => { + const inventoryQuantities: number[] = [] + + for (const link of variantInventoryItems) { + const requiredQuantity = link.required_quantity + const availableQuantity = (link.inventory?.location_levels || []).reduce( + (sum, level) => { + if ( + requireChannelCheck && + !channelLocationsSet.has(level.location_id) + ) { + return sum + } + + return sum + (level?.available_quantity || 0) + }, + 0 + ) + + // This will give us the maximum deliverable quantities for each inventory item + const maxInventoryQuantity = Math.floor( + availableQuantity / requiredQuantity + ) + + inventoryQuantities.push(maxInventoryQuantity) + } + + return inventoryQuantities.length ? Math.min(...inventoryQuantities) : 0 +} + +type VariantAvailabilityData = { + variant_ids: string[] + sales_channel_id: string +} + +const getDataForComputation = async ( + query: Omit, + data: { variant_ids: string[]; sales_channel_id?: string } +) => { + const { data: variantInventoryItems } = await query.graph({ + entity: "product_variant_inventory_items", + fields: [ + "variant_id", + "required_quantity", + "variant.manage_inventory", + "variant.allow_backorder", + "inventory.*", + "inventory.location_levels.*", + ], + filters: { variant_id: data.variant_ids }, + }) + + const variantInventoriesMap = new Map() + variantInventoryItems.forEach((link) => { + const array = variantInventoriesMap.get(link.variant_id) || [] + array.push(link) + variantInventoriesMap.set(link.variant_id, array) + }) + + const locationIds = new Set() + if (data.sales_channel_id) { + const { data: channelLocations } = await query.graph({ + entity: "sales_channel_locations", + fields: ["stock_location_id"], + filters: { sales_channel_id: data.sales_channel_id }, + }) + + channelLocations.forEach((loc) => locationIds.add(loc.stock_location_id)) + } + + return { variantInventoriesMap, locationIds } +} diff --git a/packages/core/utils/src/product/index.ts b/packages/core/utils/src/product/index.ts index 26b7c25691056..77e637b81d9b8 100644 --- a/packages/core/utils/src/product/index.ts +++ b/packages/core/utils/src/product/index.ts @@ -6,3 +6,4 @@ export enum ProductStatus { } export * from "./events" +export * from "./get-variant-availability" diff --git a/packages/medusa/src/api/admin/product-variants/route.ts b/packages/medusa/src/api/admin/product-variants/route.ts index b44456fd194f4..43e30217f5836 100644 --- a/packages/medusa/src/api/admin/product-variants/route.ts +++ b/packages/medusa/src/api/admin/product-variants/route.ts @@ -4,7 +4,7 @@ import { refetchEntities, } from "@medusajs/framework/http" import { HttpTypes } from "@medusajs/framework/types" -import { wrapVariantsWithInventoryQuantity } from "../../utils/middlewares" +import { wrapVariantsWithTotalInventoryQuantity } from "../../utils/middlewares" import { remapKeysForVariant, remapVariantResponse } from "../products/helpers" export const GET = async ( @@ -30,7 +30,7 @@ export const GET = async ( ) if (withInventoryQuantity) { - await wrapVariantsWithInventoryQuantity(req, variants || []) + await wrapVariantsWithTotalInventoryQuantity(req, variants || []) } res.json({ diff --git a/packages/medusa/src/api/admin/products/[id]/variants/route.ts b/packages/medusa/src/api/admin/products/[id]/variants/route.ts index 356c2c80aac6c..c151d4312817b 100644 --- a/packages/medusa/src/api/admin/products/[id]/variants/route.ts +++ b/packages/medusa/src/api/admin/products/[id]/variants/route.ts @@ -4,7 +4,7 @@ import { AuthenticatedMedusaRequest, MedusaResponse, } from "@medusajs/framework/http" -import { wrapVariantsWithInventoryQuantity } from "../../../../utils/middlewares" +import { wrapVariantsWithTotalInventoryQuantity } from "../../../../utils/middlewares" import { refetchEntities, refetchEntity } from "@medusajs/framework/http" import { remapKeysForProduct, @@ -38,7 +38,7 @@ export const GET = async ( ) if (withInventoryQuantity) { - await wrapVariantsWithInventoryQuantity(req, variants || []) + await wrapVariantsWithTotalInventoryQuantity(req, variants || []) } res.json({ diff --git a/packages/medusa/src/api/store/products/[id]/route.ts b/packages/medusa/src/api/store/products/[id]/route.ts index d1bc08f3bf597..6c96a075e1b54 100644 --- a/packages/medusa/src/api/store/products/[id]/route.ts +++ b/packages/medusa/src/api/store/products/[id]/route.ts @@ -1,6 +1,6 @@ import { isPresent, MedusaError } from "@medusajs/framework/utils" import { MedusaResponse } from "@medusajs/framework/http" -import { wrapVariantsWithInventoryQuantity } from "../../../utils/middlewares" +import { wrapVariantsWithInventoryQuantityForSalesChannel } from "../../../utils/middlewares" import { refetchProduct, RequestWithContext, @@ -48,7 +48,10 @@ export const GET = async ( } if (withInventoryQuantity) { - await wrapVariantsWithInventoryQuantity(req, product.variants || []) + await wrapVariantsWithInventoryQuantityForSalesChannel( + req, + product.variants || [] + ) } await wrapProductsWithTaxPrices(req, [product]) diff --git a/packages/medusa/src/api/store/products/helpers.ts b/packages/medusa/src/api/store/products/helpers.ts index cc73a4df77633..12c0d13678db1 100644 --- a/packages/medusa/src/api/store/products/helpers.ts +++ b/packages/medusa/src/api/store/products/helpers.ts @@ -1,8 +1,4 @@ -import { - MedusaRequest, - refetchEntities, - refetchEntity, -} from "@medusajs/framework/http" +import { MedusaStoreRequest, refetchEntity } from "@medusajs/framework/http" import { HttpTypes, ItemTaxLineDTO, @@ -13,7 +9,7 @@ import { import { calculateAmountsWithTax, Modules } from "@medusajs/framework/utils" import { TaxModuleService } from "@medusajs/tax/dist/services" -export type RequestWithContext = MedusaRequest & { +export type RequestWithContext = MedusaStoreRequest & { taxContext: { taxLineContext?: TaxCalculationContext taxInclusivityContext?: { @@ -30,27 +26,6 @@ export const refetchProduct = async ( return await refetchEntity("product", idOrFilter, scope, fields) } -export const maybeApplyStockLocationId = async (req: MedusaRequest, ctx) => { - const withInventoryQuantity = req.remoteQueryConfig.fields.some((field) => - field.includes("variants.inventory_quantity") - ) - - if (!withInventoryQuantity) { - return - } - - const salesChannelId = req.filterableFields.sales_channel_id || [] - - const entities = await refetchEntities( - "sales_channel_location", - { sales_channel_id: salesChannelId }, - req.scope, - ["stock_location_id"] - ) - - return entities.map((entity) => entity.stock_location_id) -} - export const wrapProductsWithTaxPrices = async ( req: RequestWithContext, products: HttpTypes.StoreProduct[] diff --git a/packages/medusa/src/api/store/products/middlewares.ts b/packages/medusa/src/api/store/products/middlewares.ts index dc10ace14f688..3b5282f9bed35 100644 --- a/packages/medusa/src/api/store/products/middlewares.ts +++ b/packages/medusa/src/api/store/products/middlewares.ts @@ -6,7 +6,6 @@ import { clearFiltersByKey, maybeApplyLinkFilter, MiddlewareRoute, - setContext, } from "@medusajs/framework/http" import { isPresent, ProductStatus } from "@medusajs/framework/utils" import { @@ -15,7 +14,6 @@ import { setPricingContext, setTaxContext, } from "../../utils/middlewares" -import { maybeApplyStockLocationId } from "./helpers" import * as QueryConfig from "./query-config" import { StoreGetProductsParams } from "./validators" @@ -32,9 +30,6 @@ export const storeProductRoutesMiddlewares: MiddlewareRoute[] = [ QueryConfig.listProductQueryConfig ), filterByValidSalesChannels(), - setContext({ - stock_location_id: maybeApplyStockLocationId, - }), maybeApplyLinkFilter({ entryPoint: "product_sales_channel", resourceId: "product_id", @@ -73,9 +68,6 @@ export const storeProductRoutesMiddlewares: MiddlewareRoute[] = [ ), applyParamsAsFilters({ id: "id" }), filterByValidSalesChannels(), - setContext({ - stock_location_id: maybeApplyStockLocationId, - }), maybeApplyLinkFilter({ entryPoint: "product_sales_channel", resourceId: "product_id", diff --git a/packages/medusa/src/api/store/products/route.ts b/packages/medusa/src/api/store/products/route.ts index 97e63531e0aa7..4fbc50419bf5a 100644 --- a/packages/medusa/src/api/store/products/route.ts +++ b/packages/medusa/src/api/store/products/route.ts @@ -4,7 +4,7 @@ import { remoteQueryObjectFromString, } from "@medusajs/framework/utils" import { MedusaResponse } from "@medusajs/framework/http" -import { wrapVariantsWithInventoryQuantity } from "../../utils/middlewares" +import { wrapVariantsWithInventoryQuantityForSalesChannel } from "../../utils/middlewares" import { RequestWithContext, wrapProductsWithTaxPrices } from "./helpers" import { HttpTypes } from "@medusajs/framework/types" @@ -43,7 +43,7 @@ export const GET = async ( const { rows: products, metadata } = await remoteQuery(queryObject) if (withInventoryQuantity) { - await wrapVariantsWithInventoryQuantity( + await wrapVariantsWithInventoryQuantityForSalesChannel( req, products.map((product) => product.variants).flat(1) ) diff --git a/packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts b/packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts index 2e4adb9f35c8d..2bb1edf1c6bdc 100644 --- a/packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts +++ b/packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts @@ -1,89 +1,54 @@ import { - ContainerRegistrationKeys, - LINKS, - remoteQueryObjectFromString, + getTotalVariantAvailability, + getVariantAvailability, + MedusaError, } from "@medusajs/framework/utils" -import { MedusaRequest } from "@medusajs/framework/http" - -export async function getVariantInventoryItems({ - req, - variantIds, - additionalFilters = {}, - asMap = true, -}) { - const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY) - - const linkQuery = remoteQueryObjectFromString({ - service: LINKS.ProductVariantInventoryItem, - variables: { - filters: { - variant_id: variantIds, - }, - ...additionalFilters, - }, - fields: [ - "variant_id", - "variant.manage_inventory", - "variant.allow_backorder", - "required_quantity", - "inventory.*", - "inventory.location_levels.*", - ], - } as any) - - const links = await remoteQuery(linkQuery) - - if (!asMap) { - return links - } - - const variantInventoriesMap = new Map() +import { MedusaRequest, MedusaStoreRequest } from "@medusajs/framework/http" - links.forEach((link) => { - const array = variantInventoriesMap.get(link.variant_id) || [] +export const wrapVariantsWithTotalInventoryQuantity = async ( + req: MedusaRequest, + variants: VariantInput[] +) => { + const variantIds = (variants ?? []).map((variant) => variant.id).flat(1) - array.push(link) + if (!variantIds.length) { + return + } - variantInventoriesMap.set(link.variant_id, array) + const query = req.scope.resolve("query") + const availability = await getTotalVariantAvailability(query, { + variant_ids: variantIds, }) - return variantInventoriesMap + wrapVariants(variants, availability) } -export async function computeVariantInventoryQuantity({ - variantInventoryItems, -}) { - const links = variantInventoryItems - const inventoryQuantities: number[] = [] - - for (const link of links) { - const requiredQuantity = link.required_quantity - const availableQuantity = (link.inventory?.location_levels || []).reduce( - (sum, level) => sum + (level?.available_quantity || 0), - 0 - ) - - // This will give us the maximum deliverable quantities for each inventory item - const maxInventoryQuantity = Math.floor( - availableQuantity / requiredQuantity - ) +export const wrapVariantsWithInventoryQuantityForSalesChannel = async ( + req: MedusaStoreRequest, + variants: VariantInput[] +) => { + const salesChannelId = req.filterableFields.sales_channel_id as + | string + | string[] + const { sales_channel_ids: idsFromPublishableKey = [] } = + req.publishable_key_context + + let channelToUse: string | undefined + if (salesChannelId && !Array.isArray(salesChannelId)) { + channelToUse = salesChannelId + } - inventoryQuantities.push(maxInventoryQuantity) + if (idsFromPublishableKey.length === 1) { + channelToUse = idsFromPublishableKey[0] } - // Since each of these inventory items need to be available to perform an order, - // we pick the smallest of the deliverable quantities as the total inventory quantity. - return inventoryQuantities.length ? Math.min(...inventoryQuantities) : 0 -} + if (!channelToUse) { + throw new MedusaError( + MedusaError.Types.INVALID_DATA, + `Inventory availability cannot be calculated in the given context. Either provide a sales channel id or configure a single sales channel in the publishable key` + ) + } -export const wrapVariantsWithInventoryQuantity = async ( - req: MedusaRequest, - variants: { - id: string - inventory_quantity?: number - manage_inventory?: boolean - }[] -) => { variants ??= [] const variantIds = variants.map((variant) => variant.id).flat(1) @@ -91,19 +56,34 @@ export const wrapVariantsWithInventoryQuantity = async ( return } - const variantInventoriesMap = await getVariantInventoryItems({ - req, - variantIds, + const query = req.scope.resolve("query") + const availability = await getVariantAvailability(query, { + variant_ids: variantIds, + sales_channel_id: channelToUse, }) + wrapVariants(variants, availability) +} + +type VariantInput = { + id: string + inventory_quantity?: number + manage_inventory?: boolean +} + +type VariantAvailability = Awaited< + ReturnType +> + +const wrapVariants = ( + variants: VariantInput[], + availability: VariantAvailability +) => { for (const variant of variants) { if (!variant.manage_inventory) { continue } - const links = variantInventoriesMap.get(variant.id) || [] - variant.inventory_quantity = await computeVariantInventoryQuantity({ - variantInventoryItems: links, - }) + variant.inventory_quantity = availability[variant.id].availability } } From 91fd344189c340f5c63401e94203e6de6a2fbd66 Mon Sep 17 00:00:00 2001 From: Sebastian Rindom Date: Thu, 5 Dec 2024 18:46:13 +0100 Subject: [PATCH 2/5] Update packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com> --- .../utils/middlewares/products/variant-inventory-quantity.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts b/packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts index 2bb1edf1c6bdc..917a1a2ec4d57 100644 --- a/packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts +++ b/packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts @@ -15,7 +15,7 @@ export const wrapVariantsWithTotalInventoryQuantity = async ( return } - const query = req.scope.resolve("query") + const query = req.scope.resolve(ContainerRegistrationKeys.QUERY) const availability = await getTotalVariantAvailability(query, { variant_ids: variantIds, }) From 7d62743f8507dca00df8a374d337b67485f90eca Mon Sep 17 00:00:00 2001 From: Sebastian Rindom Date: Thu, 5 Dec 2024 18:46:42 +0100 Subject: [PATCH 3/5] Update packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com> --- .../utils/middlewares/products/variant-inventory-quantity.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts b/packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts index 917a1a2ec4d57..e8aefb99cda0f 100644 --- a/packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts +++ b/packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts @@ -56,7 +56,7 @@ export const wrapVariantsWithInventoryQuantityForSalesChannel = async ( return } - const query = req.scope.resolve("query") + const query = req.scope.resolve(ContainerRegistrationKeys.QUERY) const availability = await getVariantAvailability(query, { variant_ids: variantIds, sales_channel_id: channelToUse, From 4c1efdb3bde61c8b0c20517d1265a1fa8534deb9 Mon Sep 17 00:00:00 2001 From: Sebastian Rindom Date: Thu, 5 Dec 2024 18:46:57 +0100 Subject: [PATCH 4/5] Update packages/core/core-flows/src/product/steps/get-variant-availability.ts Co-authored-by: Carlos R. L. Rodrigues <37986729+carlos-r-l-rodrigues@users.noreply.github.com> --- .../core-flows/src/product/steps/get-variant-availability.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/core/core-flows/src/product/steps/get-variant-availability.ts b/packages/core/core-flows/src/product/steps/get-variant-availability.ts index 93f17b7ebd086..9f1b8ae9e3daa 100644 --- a/packages/core/core-flows/src/product/steps/get-variant-availability.ts +++ b/packages/core/core-flows/src/product/steps/get-variant-availability.ts @@ -13,7 +13,7 @@ export const getVariantAvailabilityId = "get-variant-availability" export const getVariantAvailabilityStep = createStep( getVariantAvailabilityId, async (data: GetVariantAvailabilityStepInput, { container }) => { - const query = container.resolve("query") + const query = container.resolve(ContainerRegistrationKeys.QUERY) const availability = await getVariantAvailability(query, data) return new StepResponse(availability) } From 06f7825bfe7b710f5f6ff3cd0ea13dbdeaa14c3c Mon Sep 17 00:00:00 2001 From: Sebastian Rindom Date: Thu, 5 Dec 2024 18:55:30 +0100 Subject: [PATCH 5/5] fix: crk --- .../core-flows/src/product/steps/get-variant-availability.ts | 5 ++++- .../utils/middlewares/products/variant-inventory-quantity.ts | 1 + 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/core/core-flows/src/product/steps/get-variant-availability.ts b/packages/core/core-flows/src/product/steps/get-variant-availability.ts index 9f1b8ae9e3daa..c7bcb47942707 100644 --- a/packages/core/core-flows/src/product/steps/get-variant-availability.ts +++ b/packages/core/core-flows/src/product/steps/get-variant-availability.ts @@ -1,5 +1,8 @@ import { createStep, StepResponse } from "@medusajs/framework/workflows-sdk" -import { getVariantAvailability } from "@medusajs/framework/utils" +import { + ContainerRegistrationKeys, + getVariantAvailability, +} from "@medusajs/framework/utils" export type GetVariantAvailabilityStepInput = { variant_ids: string[] diff --git a/packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts b/packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts index e8aefb99cda0f..e6f34cc7ab2ed 100644 --- a/packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts +++ b/packages/medusa/src/api/utils/middlewares/products/variant-inventory-quantity.ts @@ -1,4 +1,5 @@ import { + ContainerRegistrationKeys, getTotalVariantAvailability, getVariantAvailability, MedusaError,