diff --git a/.changeset/olive-days-jog.md b/.changeset/olive-days-jog.md new file mode 100644 index 0000000000..794a060f41 --- /dev/null +++ b/.changeset/olive-days-jog.md @@ -0,0 +1,5 @@ +--- +"@medusajs/medusa": minor +--- + +Fix(medusa): include quantities when listing admin products with an inventory module installed diff --git a/packages/medusa/src/api/routes/admin/products/list-products.ts b/packages/medusa/src/api/routes/admin/products/list-products.ts index 534e1d88cf..da3a53e675 100644 --- a/packages/medusa/src/api/routes/admin/products/list-products.ts +++ b/packages/medusa/src/api/routes/admin/products/list-products.ts @@ -1,10 +1,16 @@ import { IsNumber, IsOptional, IsString } from "class-validator" -import { PricingService, ProductService } from "../../../../services" +import { + PricingService, + ProductService, + ProductVariantInventoryService, + SalesChannelService, +} from "../../../../services" -import { Type } from "class-transformer" -import { Product } from "../../../../models" -import { PricedProduct } from "../../../../types/pricing" import { FilterableProductProps } from "../../../../types/product" +import { PricedProduct } from "../../../../types/pricing" +import { Product } from "../../../../models" +import { Type } from "class-transformer" +import { IInventoryService } from "@medusajs/types" /** * @oas [get] /admin/products @@ -214,6 +220,13 @@ import { FilterableProductProps } from "../../../../types/product" */ export default async (req, res) => { const productService: ProductService = req.scope.resolve("productService") + const inventoryService: IInventoryService | undefined = + req.scope.resolve("inventoryService") + const productVariantInventoryService: ProductVariantInventoryService = + req.scope.resolve("productVariantInventoryService") + const salesChannelService: SalesChannelService = req.scope.resolve( + "salesChannelService" + ) const pricingService: PricingService = req.scope.resolve("pricingService") const { skip, take, relations } = req.listConfig @@ -232,6 +245,18 @@ export default async (req, res) => { products = await pricingService.setProductPrices(rawProducts) } + if (inventoryService) { + const [salesChannelsIds] = await salesChannelService.listAndCount( + {}, + { select: ["id"] } + ) + + products = await productVariantInventoryService.setProductAvailability( + products, + salesChannelsIds.map((salesChannel) => salesChannel.id) + ) + } + res.json({ products, count, diff --git a/packages/medusa/src/services/product-variant-inventory.ts b/packages/medusa/src/services/product-variant-inventory.ts index b18f736b95..a175fda741 100644 --- a/packages/medusa/src/services/product-variant-inventory.ts +++ b/packages/medusa/src/services/product-variant-inventory.ts @@ -1,16 +1,17 @@ +import { EntityManager, In } from "typeorm" import { ICacheService, IInventoryService, - InventoryItemDTO, IStockLocationService, + InventoryItemDTO, ReservationItemDTO, ReserveQuantityContext, } from "@medusajs/types" -import { isDefined, MedusaError, TransactionBaseService } from "@medusajs/utils" -import { EntityManager, In } from "typeorm" import { LineItem, Product, ProductVariant } from "../models" -import { ProductVariantInventoryItem } from "../models/product-variant-inventory-item" +import { MedusaError, TransactionBaseService, isDefined } from "@medusajs/utils" import { PricedProduct, PricedVariant } from "../types/pricing" + +import { ProductVariantInventoryItem } from "../models/product-variant-inventory-item" import ProductVariantService from "./product-variant" import SalesChannelInventoryService from "./sales-channel-inventory" import SalesChannelLocationService from "./sales-channel-location" @@ -629,7 +630,7 @@ class ProductVariantInventoryService extends TransactionBaseService { async setVariantAvailability( variants: ProductVariant[] | PricedVariant[], - salesChannelId: string | undefined + salesChannelId: string | string[] | undefined ): Promise { if (!this.inventoryService_) { return variants @@ -649,11 +650,23 @@ class ProductVariantInventoryService extends TransactionBaseService { // first get all inventory items required for a variant const variantInventory = await this.listByVariant(variant.id) - variant.inventory_quantity = - await this.getVariantQuantityFromVariantInventoryItems( - variantInventory, - salesChannelId - ) + const salesChannelArray = Array.isArray(salesChannelId) + ? salesChannelId + : [salesChannelId] + + const quantities = await Promise.all( + salesChannelArray.map(async (salesChannel) => { + return await this.getVariantQuantityFromVariantInventoryItems( + variantInventory, + salesChannel + ) + }) + ) + + variant.inventory_quantity = quantities.reduce( + (acc, next) => acc + (next || 0), + 0 + ) return variant }) @@ -662,7 +675,7 @@ class ProductVariantInventoryService extends TransactionBaseService { async setProductAvailability( products: (Product | PricedProduct)[], - salesChannelId: string | undefined + salesChannelId: string | string[] | undefined ): Promise<(Product | PricedProduct)[]> { return await Promise.all( products.map(async (product) => {