Feat(inventory-next, medusa): Add List inventory items endpoint (#6694)

* code for list inventory items

* fix integration tests

* move integration test

* calculate reserved and stocked quantities in db

* update lockfile
This commit is contained in:
Philip Korsholm
2024-03-14 14:48:34 +01:00
committed by GitHub
parent 3dd55efd15
commit c3f8c30ba6
14 changed files with 1247 additions and 16 deletions
@@ -0,0 +1,40 @@
import * as QueryConfig from "./query-config"
import {
AdminGetInventoryItemsItemParams,
AdminGetInventoryItemsParams,
AdminPostInventoryItemsItemLocationLevelsReq,
AdminPostInventoryItemsReq,
} from "./validators"
import { transformBody, transformQuery } from "../../../api/middlewares"
import { MiddlewareRoute } from "../../../types/middlewares"
import { authenticate } from "../../../utils/authenticate-middleware"
export const adminInventoryRoutesMiddlewares: MiddlewareRoute[] = [
{
method: "ALL",
matcher: "/admin/inventory-items*",
middlewares: [authenticate("admin", ["session", "bearer"])],
},
{
method: ["GET"],
matcher: "/admin/inventory-items",
middlewares: [
transformQuery(
AdminGetInventoryItemsParams,
QueryConfig.listTransformQueryConfig
),
],
},
{
method: ["POST"],
matcher: "/admin/inventory-items/:id/location-levels",
middlewares: [transformBody(AdminPostInventoryItemsItemLocationLevelsReq)],
},
{
method: ["POST"],
matcher: "/admin/inventory-items",
middlewares: [transformBody(AdminPostInventoryItemsReq)],
},
]
@@ -0,0 +1,56 @@
import { InventoryNext } from "@medusajs/types"
export const defaultAdminInventoryItemRelations = []
export const allowedAdminInventoryItemRelations = []
// eslint-disable-next-line max-len
export const defaultAdminLocationLevelFields: (keyof InventoryNext.InventoryLevelDTO)[] =
[
"id",
"inventory_item_id",
"location_id",
"stocked_quantity",
"reserved_quantity",
"incoming_quantity",
"available_quantity",
"metadata",
"created_at",
"updated_at",
]
export const defaultAdminInventoryItemFields = [
"id",
"sku",
"title",
"description",
"thumbnail",
"origin_country",
"hs_code",
"requires_shipping",
"mid_code",
"material",
"weight",
"length",
"height",
"width",
"metadata",
"reserved_quantity",
"stocked_quantity",
"created_at",
"updated_at",
...defaultAdminLocationLevelFields.map(
(field) => `location_levels.${field.toString()}`
),
]
export const retrieveTransformQueryConfig = {
defaultFields: defaultAdminInventoryItemFields,
defaultRelations: defaultAdminInventoryItemRelations,
allowedRelations: allowedAdminInventoryItemRelations,
isList: false,
}
export const listTransformQueryConfig = {
...retrieveTransformQueryConfig,
isList: true,
}
@@ -0,0 +1,38 @@
import {
AuthenticatedMedusaRequest,
MedusaResponse,
} from "../../../types/routing"
import {
ContainerRegistrationKeys,
remoteQueryObjectFromString,
} from "@medusajs/utils"
// List inventory-items
export const GET = async (
req: AuthenticatedMedusaRequest,
res: MedusaResponse
) => {
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const query = remoteQueryObjectFromString({
entryPoint: "inventory_items",
variables: {
filters: req.filterableFields,
order: req.listConfig.order,
skip: req.listConfig.skip,
take: req.listConfig.take,
},
fields: [...(req.listConfig.select as string[])],
})
const { rows: inventory_items, metadata } = await remoteQuery({
...query,
})
res.status(200).json({
inventory_items,
count: metadata.count,
offset: metadata.skip,
limit: metadata.take,
})
}
@@ -0,0 +1,268 @@
import {
DateComparisonOperator,
FindParams,
NumericalComparisonOperator,
StringComparisonOperator,
extendedFindParamsMixin,
} from "../../../types/common"
import {
IsBoolean,
IsEmail,
IsNotEmpty,
IsNumber,
IsObject,
IsOptional,
IsString,
ValidateNested,
} from "class-validator"
import { Transform, Type } from "class-transformer"
import { IsType } from "../../../utils"
export class AdminGetInventoryItemsItemParams extends FindParams {}
/**
* Parameters used to filter and configure the pagination of the retrieved inventory items.
*/
export class AdminGetInventoryItemsParams extends extendedFindParamsMixin({
limit: 20,
offset: 0,
}) {
/**
* IDs to filter inventory items by.
*/
@IsOptional()
@IsType([String, [String]])
id?: string | string[]
/**
* Search terms to search inventory items' sku, title, and description.
*/
@IsOptional()
@IsString()
q?: string
/**
* Location IDs to filter inventory items by.
*/
@IsOptional()
@IsType([String, [String]])
location_id?: string | string[]
/**
* SKUs to filter inventory items by.
*/
@IsOptional()
@IsType([String, [String]])
sku?: string | string[]
/**
* Origin countries to filter inventory items by.
*/
@IsOptional()
@IsType([String, [String]])
origin_country?: string | string[]
/**
* MID codes to filter inventory items by.
*/
@IsOptional()
@IsType([String, [String]])
mid_code?: string | string[]
/**
* Materials to filter inventory items by.
*/
@IsOptional()
@IsType([String, [String]])
material?: string | string[]
/**
* String filters to apply to inventory items' `hs_code` field.
*/
@IsOptional()
@IsType([String, [String], StringComparisonOperator])
hs_code?: string | string[] | StringComparisonOperator
/**
* Number filters to apply to inventory items' `weight` field.
*/
@IsOptional()
@IsType([Number, NumericalComparisonOperator])
weight?: number | NumericalComparisonOperator
/**
* Number filters to apply to inventory items' `length` field.
*/
@IsOptional()
@IsType([Number, NumericalComparisonOperator])
length?: number | NumericalComparisonOperator
/**
* Number filters to apply to inventory items' `height` field.
*/
@IsOptional()
@IsType([Number, NumericalComparisonOperator])
height?: number | NumericalComparisonOperator
/**
* Number filters to apply to inventory items' `width` field.
*/
@IsOptional()
@IsType([Number, NumericalComparisonOperator])
width?: number | NumericalComparisonOperator
/**
* Filter inventory items by whether they require shipping.
*/
@IsBoolean()
@IsOptional()
@Transform(({ value }) => value === "true")
requires_shipping?: boolean
}
export class AdminPostInventoryItemsItemLocationLevelsReq {
@IsString()
location_id: string
@IsNumber()
stocked_quantity: number
@IsOptional()
@IsNumber()
incoming_quantity?: number
}
// eslint-disable-next-line
export class AdminPostInventoryItemsItemLocationLevelsParams extends FindParams {}
/**
* @schema AdminPostInventoryItemsReq
* type: object
* description: "The details of the inventory item to create."
* required:
* - variant_id
* properties:
* variant_id:
* description: The ID of the variant to create the inventory item for.
* type: string
* sku:
* description: The unique SKU of the associated Product Variant.
* type: string
* ean:
* description: The EAN number of the item.
* type: string
* upc:
* description: The UPC number of the item.
* type: string
* barcode:
* description: A generic GTIN field for the Product Variant.
* type: string
* hs_code:
* description: The Harmonized System code of the Inventory Item. May be used by Fulfillment Providers to pass customs information to shipping carriers.
* type: string
* inventory_quantity:
* description: The amount of stock kept of the associated Product Variant.
* type: integer
* default: 0
* allow_backorder:
* description: Whether the associated Product Variant can be purchased when out of stock.
* type: boolean
* manage_inventory:
* description: Whether Medusa should keep track of the inventory for the associated Product Variant.
* type: boolean
* default: true
* weight:
* description: The weight of the Inventory Item. May be used in shipping rate calculations.
* type: number
* length:
* description: The length of the Inventory Item. May be used in shipping rate calculations.
* type: number
* height:
* description: The height of the Inventory Item. May be used in shipping rate calculations.
* type: number
* width:
* description: The width of the Inventory Item. May be used in shipping rate calculations.
* type: number
* origin_country:
* description: The country in which the Inventory Item was produced. May be used by Fulfillment Providers to pass customs information to shipping carriers.
* type: string
* mid_code:
* description: The Manufacturers Identification code that identifies the manufacturer of the Inventory Item. May be used by Fulfillment Providers to pass customs information to shipping carriers.
* type: string
* material:
* description: The material and composition that the Inventory Item is made of, May be used by Fulfillment Providers to pass customs information to shipping carriers.
* type: string
* title:
* description: The inventory item's title.
* type: string
* description:
* description: The inventory item's description.
* type: string
* thumbnail:
* description: The inventory item's thumbnail.
* type: string
* metadata:
* description: An optional set of key-value pairs with additional information.
* type: object
* externalDocs:
* description: "Learn about the metadata attribute, and how to delete and update it."
* url: "https://docs.medusajs.com/development/entities/overview#metadata-attribute"
*/
export class AdminPostInventoryItemsReq {
@IsOptional()
@IsString()
variant_id: string
@IsString()
@IsOptional()
sku?: string
@IsString()
@IsOptional()
hs_code?: string
@IsNumber()
@IsOptional()
weight?: number
@IsNumber()
@IsOptional()
length?: number
@IsNumber()
@IsOptional()
height?: number
@IsNumber()
@IsOptional()
width?: number
@IsString()
@IsOptional()
origin_country?: string
@IsString()
@IsOptional()
mid_code?: string
@IsString()
@IsOptional()
material?: string
@IsString()
@IsOptional()
title?: string
@IsString()
@IsOptional()
description?: string
@IsString()
@IsOptional()
thumbnail?: string
@IsObject()
@IsOptional()
metadata?: Record<string, unknown>
}