fix(medusa): Include inventory quantity when listing products (#3586)
* initial inclusion of quantities when listing admin prices * add changeset * rename variable * add inventory service check when listing products * update changeset version bump
This commit is contained in:
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/medusa": minor
|
||||||
|
---
|
||||||
|
|
||||||
|
Fix(medusa): include quantities when listing admin products with an inventory module installed
|
||||||
@@ -1,10 +1,16 @@
|
|||||||
import { IsNumber, IsOptional, IsString } from "class-validator"
|
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 { 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
|
* @oas [get] /admin/products
|
||||||
@@ -214,6 +220,13 @@ import { FilterableProductProps } from "../../../../types/product"
|
|||||||
*/
|
*/
|
||||||
export default async (req, res) => {
|
export default async (req, res) => {
|
||||||
const productService: ProductService = req.scope.resolve("productService")
|
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 pricingService: PricingService = req.scope.resolve("pricingService")
|
||||||
|
|
||||||
const { skip, take, relations } = req.listConfig
|
const { skip, take, relations } = req.listConfig
|
||||||
@@ -232,6 +245,18 @@ export default async (req, res) => {
|
|||||||
products = await pricingService.setProductPrices(rawProducts)
|
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({
|
res.json({
|
||||||
products,
|
products,
|
||||||
count,
|
count,
|
||||||
|
|||||||
@@ -1,16 +1,17 @@
|
|||||||
|
import { EntityManager, In } from "typeorm"
|
||||||
import {
|
import {
|
||||||
ICacheService,
|
ICacheService,
|
||||||
IInventoryService,
|
IInventoryService,
|
||||||
InventoryItemDTO,
|
|
||||||
IStockLocationService,
|
IStockLocationService,
|
||||||
|
InventoryItemDTO,
|
||||||
ReservationItemDTO,
|
ReservationItemDTO,
|
||||||
ReserveQuantityContext,
|
ReserveQuantityContext,
|
||||||
} from "@medusajs/types"
|
} from "@medusajs/types"
|
||||||
import { isDefined, MedusaError, TransactionBaseService } from "@medusajs/utils"
|
|
||||||
import { EntityManager, In } from "typeorm"
|
|
||||||
import { LineItem, Product, ProductVariant } from "../models"
|
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 { PricedProduct, PricedVariant } from "../types/pricing"
|
||||||
|
|
||||||
|
import { ProductVariantInventoryItem } from "../models/product-variant-inventory-item"
|
||||||
import ProductVariantService from "./product-variant"
|
import ProductVariantService from "./product-variant"
|
||||||
import SalesChannelInventoryService from "./sales-channel-inventory"
|
import SalesChannelInventoryService from "./sales-channel-inventory"
|
||||||
import SalesChannelLocationService from "./sales-channel-location"
|
import SalesChannelLocationService from "./sales-channel-location"
|
||||||
@@ -629,7 +630,7 @@ class ProductVariantInventoryService extends TransactionBaseService {
|
|||||||
|
|
||||||
async setVariantAvailability(
|
async setVariantAvailability(
|
||||||
variants: ProductVariant[] | PricedVariant[],
|
variants: ProductVariant[] | PricedVariant[],
|
||||||
salesChannelId: string | undefined
|
salesChannelId: string | string[] | undefined
|
||||||
): Promise<ProductVariant[] | PricedVariant[]> {
|
): Promise<ProductVariant[] | PricedVariant[]> {
|
||||||
if (!this.inventoryService_) {
|
if (!this.inventoryService_) {
|
||||||
return variants
|
return variants
|
||||||
@@ -649,11 +650,23 @@ class ProductVariantInventoryService extends TransactionBaseService {
|
|||||||
// first get all inventory items required for a variant
|
// first get all inventory items required for a variant
|
||||||
const variantInventory = await this.listByVariant(variant.id)
|
const variantInventory = await this.listByVariant(variant.id)
|
||||||
|
|
||||||
variant.inventory_quantity =
|
const salesChannelArray = Array.isArray(salesChannelId)
|
||||||
await this.getVariantQuantityFromVariantInventoryItems(
|
? salesChannelId
|
||||||
variantInventory,
|
: [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
|
return variant
|
||||||
})
|
})
|
||||||
@@ -662,7 +675,7 @@ class ProductVariantInventoryService extends TransactionBaseService {
|
|||||||
|
|
||||||
async setProductAvailability(
|
async setProductAvailability(
|
||||||
products: (Product | PricedProduct)[],
|
products: (Product | PricedProduct)[],
|
||||||
salesChannelId: string | undefined
|
salesChannelId: string | string[] | undefined
|
||||||
): Promise<(Product | PricedProduct)[]> {
|
): Promise<(Product | PricedProduct)[]> {
|
||||||
return await Promise.all(
|
return await Promise.all(
|
||||||
products.map(async (product) => {
|
products.map(async (product) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user