UNPKG

@medusajs/utils

Version:

Medusa utilities functions shared by Medusa core and Modules

100 lines 4.96 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getVariantAvailability = getVariantAvailability; exports.getTotalVariantAvailability = getTotalVariantAvailability; /** * 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 */ async function getVariantAvailability(query, data) { 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; }, {}); } /** * 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 */ async function getTotalVariantAvailability(query, data) { 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; }, {}); } const computeVariantAvailability = (variantInventoryItems, channelLocationsSet, { requireChannelCheck } = { requireChannelCheck: true }) => { const inventoryQuantities = []; 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; }; const getDataForComputation = async (query, data) => { 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 }; }; //# sourceMappingURL=get-variant-availability.js.map