feat(core-flows,modules-sdk,types,medusa,link-modules): adds variant <> inventory item link endpoints (#7576)
what: - adds variant inventory link management endpoints: ``` Link inventory item to variant POST /products/:id/variants/:vid/inventory-items Update variant's inventory item link POST /products/:id/variants/:vid/inventory-items/:iid Unlink variant's inventory item DELETE /products/:id/variants/:vid/inventory-items/:iid ``` - a batch endpoint that does the above 3 across variants ``` POST /products/:id/variants/inventory-items ```
This commit is contained in:
1 parent
122186a78d
commit
ecfbfcc707
23 files changed
+1279
-126
No files matched your search
+66
@@ -0,0 +1,66 @@
|
||||
import { dismissLinksWorkflow, updateLinksWorkflow } from "@medusajs/core-flows"
|
||||
import { Modules } from "@medusajs/utils"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../../../../../types/routing"
|
||||
import { refetchVariant } from "../../../../../helpers"
|
||||
import { AdminUpdateVariantInventoryItemType } from "../../../../../validators"
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<AdminUpdateVariantInventoryItemType>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const variantId = req.params.variant_id
|
||||
const inventoryItemId = req.params.inventory_item_id
|
||||
|
||||
await updateLinksWorkflow(req.scope).run({
|
||||
input: [
|
||||
{
|
||||
[Modules.PRODUCT]: { variant_id: variantId },
|
||||
[Modules.INVENTORY]: { inventory_item_id: inventoryItemId },
|
||||
data: { required_quantity: req.validatedBody.required_quantity },
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const variant = await refetchVariant(
|
||||
variantId,
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
res.status(200).json({ variant })
|
||||
}
|
||||
|
||||
export const DELETE = async (
|
||||
req: AuthenticatedMedusaRequest,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const variantId = req.params.variant_id
|
||||
const inventoryItemId = req.params.inventory_item_id
|
||||
|
||||
const {
|
||||
result: [deleted],
|
||||
} = await dismissLinksWorkflow(req.scope).run({
|
||||
input: [
|
||||
{
|
||||
[Modules.PRODUCT]: { variant_id: variantId },
|
||||
[Modules.INVENTORY]: { inventory_item_id: inventoryItemId },
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const parent = await refetchVariant(
|
||||
variantId,
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
res.status(200).json({
|
||||
id: deleted,
|
||||
object: "variant-inventory-item-link",
|
||||
deleted: true,
|
||||
parent,
|
||||
})
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
import { createLinksWorkflow } from "@medusajs/core-flows"
|
||||
import { Modules } from "@medusajs/utils"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../../../../types/routing"
|
||||
import { refetchVariant } from "../../../../helpers"
|
||||
import { AdminCreateVariantInventoryItemType } from "../../../../validators"
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<AdminCreateVariantInventoryItemType>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const variantId = req.params.variant_id
|
||||
|
||||
await createLinksWorkflow(req.scope).run({
|
||||
input: [
|
||||
{
|
||||
[Modules.PRODUCT]: { variant_id: variantId },
|
||||
[Modules.INVENTORY]: {
|
||||
inventory_item_id: req.validatedBody.inventory_item_id,
|
||||
},
|
||||
data: { required_quantity: req.validatedBody.required_quantity },
|
||||
},
|
||||
],
|
||||
})
|
||||
|
||||
const variant = await refetchVariant(
|
||||
variantId,
|
||||
req.scope,
|
||||
req.remoteQueryConfig.fields
|
||||
)
|
||||
|
||||
res.status(200).json({ variant })
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
import { batchLinksWorkflow } from "@medusajs/core-flows"
|
||||
import {
|
||||
AuthenticatedMedusaRequest,
|
||||
MedusaResponse,
|
||||
} from "../../../../../../../types/routing"
|
||||
import { buildBatchVariantInventoryData } from "../../../../helpers"
|
||||
import { AdminBatchVariantInventoryItemsType } from "../../../../validators"
|
||||
|
||||
export const POST = async (
|
||||
req: AuthenticatedMedusaRequest<AdminBatchVariantInventoryItemsType>,
|
||||
res: MedusaResponse
|
||||
) => {
|
||||
const { create = [], update = [], delete: toDelete = [] } = req.validatedBody
|
||||
|
||||
const { result } = await batchLinksWorkflow(req.scope).run({
|
||||
input: {
|
||||
create: buildBatchVariantInventoryData(create),
|
||||
update: buildBatchVariantInventoryData(update),
|
||||
delete: buildBatchVariantInventoryData(toDelete),
|
||||
},
|
||||
})
|
||||
|
||||
res.status(200).json({
|
||||
created: result.created,
|
||||
updated: result.updated,
|
||||
deleted: result.deleted,
|
||||
})
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { LinkDefinition } from "@medusajs/modules-sdk"
|
||||
import {
|
||||
BatchMethodResponse,
|
||||
MedusaContainer,
|
||||
@@ -5,10 +6,12 @@ import {
|
||||
ProductVariantDTO,
|
||||
} from "@medusajs/types"
|
||||
import {
|
||||
ContainerRegistrationKeys,
|
||||
Modules,
|
||||
promiseAll,
|
||||
remoteQueryObjectFromString,
|
||||
ContainerRegistrationKeys,
|
||||
} from "@medusajs/utils"
|
||||
import { AdminBatchVariantInventoryItemsType } from "./validators"
|
||||
|
||||
const isPricing = (fieldName: string) =>
|
||||
fieldName.startsWith("variants.prices") ||
|
||||
@@ -89,6 +92,25 @@ export const refetchProduct = async (
|
||||
return products[0]
|
||||
}
|
||||
|
||||
export const refetchVariant = async (
|
||||
variantId: string,
|
||||
scope: MedusaContainer,
|
||||
fields: string[]
|
||||
) => {
|
||||
const remoteQuery = scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
|
||||
const queryObject = remoteQueryObjectFromString({
|
||||
entryPoint: "product_variant",
|
||||
variables: {
|
||||
filters: { id: variantId },
|
||||
},
|
||||
fields: remapKeysForVariant(fields ?? []),
|
||||
})
|
||||
|
||||
const [variant] = await remoteQuery(queryObject)
|
||||
|
||||
return remapVariantResponse(variant)
|
||||
}
|
||||
|
||||
export const refetchBatchProducts = async (
|
||||
batchResult: BatchMethodResponse<ProductDTO>,
|
||||
scope: MedusaContainer,
|
||||
@@ -174,3 +196,31 @@ export const refetchBatchVariants = async (
|
||||
deleted: batchResult.deleted,
|
||||
}
|
||||
}
|
||||
|
||||
export const buildBatchVariantInventoryData = (
|
||||
inputs:
|
||||
| AdminBatchVariantInventoryItemsType["create"]
|
||||
| AdminBatchVariantInventoryItemsType["update"]
|
||||
| AdminBatchVariantInventoryItemsType["delete"]
|
||||
) => {
|
||||
const results: LinkDefinition[] = []
|
||||
|
||||
for (const input of inputs || []) {
|
||||
const result: LinkDefinition = {
|
||||
[Modules.PRODUCT]: { variant_id: input.variant_id },
|
||||
[Modules.INVENTORY]: {
|
||||
inventory_item_id: input.inventory_item_id,
|
||||
},
|
||||
}
|
||||
|
||||
if ("required_quantity" in input) {
|
||||
result.data = {
|
||||
required_quantity: input.required_quantity,
|
||||
}
|
||||
}
|
||||
|
||||
results.push(result)
|
||||
}
|
||||
|
||||
return results
|
||||
}
|
||||
@@ -7,20 +7,25 @@ import { createBatchBody } from "../../utils/validators"
|
||||
import * as QueryConfig from "./query-config"
|
||||
import { maybeApplyPriceListsFilter } from "./utils"
|
||||
import {
|
||||
AdminGetProductsParams,
|
||||
AdminBatchCreateVariantInventoryItem,
|
||||
AdminBatchDeleteVariantInventoryItem,
|
||||
AdminBatchUpdateProduct,
|
||||
AdminBatchUpdateProductVariant,
|
||||
AdminBatchUpdateVariantInventoryItem,
|
||||
AdminCreateProduct,
|
||||
AdminCreateProductOption,
|
||||
AdminCreateProductVariant,
|
||||
AdminCreateVariantInventoryItem,
|
||||
AdminGetProductOptionParams,
|
||||
AdminGetProductOptionsParams,
|
||||
AdminGetProductParams,
|
||||
AdminGetProductsParams,
|
||||
AdminGetProductVariantParams,
|
||||
AdminGetProductVariantsParams,
|
||||
AdminUpdateProduct,
|
||||
AdminUpdateProductOption,
|
||||
AdminGetProductParams,
|
||||
AdminGetProductVariantsParams,
|
||||
AdminGetProductVariantParams,
|
||||
AdminUpdateProductVariant,
|
||||
AdminGetProductOptionsParams,
|
||||
AdminGetProductOptionParams,
|
||||
AdminBatchUpdateProduct,
|
||||
AdminBatchUpdateProductVariant,
|
||||
AdminUpdateVariantInventoryItem,
|
||||
} from "./validators"
|
||||
|
||||
export const adminProductRoutesMiddlewares: MiddlewareRoute[] = [
|
||||
@@ -243,4 +248,57 @@ export const adminProductRoutesMiddlewares: MiddlewareRoute[] = [
|
||||
),
|
||||
],
|
||||
},
|
||||
|
||||
// Variant inventory item endpoints
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/admin/products/:id/variants/inventory-items/batch",
|
||||
middlewares: [
|
||||
validateAndTransformBody(
|
||||
createBatchBody(
|
||||
AdminBatchCreateVariantInventoryItem,
|
||||
AdminBatchUpdateVariantInventoryItem,
|
||||
AdminBatchDeleteVariantInventoryItem
|
||||
)
|
||||
),
|
||||
validateAndTransformQuery(
|
||||
AdminGetProductVariantParams,
|
||||
QueryConfig.retrieveVariantConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher: "/admin/products/:id/variants/:variant_id/inventory-items",
|
||||
middlewares: [
|
||||
validateAndTransformBody(AdminCreateVariantInventoryItem),
|
||||
validateAndTransformQuery(
|
||||
AdminGetProductVariantParams,
|
||||
QueryConfig.retrieveVariantConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: ["POST"],
|
||||
matcher:
|
||||
"/admin/products/:id/variants/:variant_id/inventory-items/:inventory_item_id",
|
||||
middlewares: [
|
||||
validateAndTransformBody(AdminUpdateVariantInventoryItem),
|
||||
validateAndTransformQuery(
|
||||
AdminGetProductVariantParams,
|
||||
QueryConfig.retrieveVariantConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
{
|
||||
method: ["DELETE"],
|
||||
matcher:
|
||||
"/admin/products/:id/variants/:variant_id/inventory-items/:inventory_item_id",
|
||||
middlewares: [
|
||||
validateAndTransformQuery(
|
||||
AdminGetProductVariantParams,
|
||||
QueryConfig.retrieveVariantConfig
|
||||
),
|
||||
],
|
||||
},
|
||||
]
|
||||
@@ -1,3 +1,4 @@
|
||||
import { BatchMethodRequest } from "@medusajs/types"
|
||||
import { ProductStatus } from "@medusajs/utils"
|
||||
import { z } from "zod"
|
||||
import { GetProductsParams } from "../../utils/common-validators"
|
||||
@@ -235,3 +236,56 @@ export const AdminBatchUpdateProduct = AdminUpdateProduct.extend({
|
||||
// @ValidateNested({ each: true })
|
||||
// @IsArray()
|
||||
// categories?: ProductProductCategoryReq[]
|
||||
|
||||
export const AdminCreateVariantInventoryItem = z.object({
|
||||
required_quantity: z.number(),
|
||||
inventory_item_id: z.string(),
|
||||
})
|
||||
export type AdminCreateVariantInventoryItemType = z.infer<
|
||||
typeof AdminCreateVariantInventoryItem
|
||||
>
|
||||
|
||||
export const AdminUpdateVariantInventoryItem = z.object({
|
||||
required_quantity: z.number(),
|
||||
})
|
||||
export type AdminUpdateVariantInventoryItemType = z.infer<
|
||||
typeof AdminUpdateVariantInventoryItem
|
||||
>
|
||||
|
||||
export const AdminBatchCreateVariantInventoryItem = z
|
||||
.object({
|
||||
required_quantity: z.number(),
|
||||
inventory_item_id: z.string(),
|
||||
variant_id: z.string(),
|
||||
})
|
||||
.strict()
|
||||
export type AdminBatchCreateVariantInventoryItemType = z.infer<
|
||||
typeof AdminBatchCreateVariantInventoryItem
|
||||
>
|
||||
|
||||
export const AdminBatchUpdateVariantInventoryItem = z
|
||||
.object({
|
||||
required_quantity: z.number(),
|
||||
inventory_item_id: z.string(),
|
||||
variant_id: z.string(),
|
||||
})
|
||||
.strict()
|
||||
export type AdminBatchUpdateVariantInventoryItemType = z.infer<
|
||||
typeof AdminBatchUpdateVariantInventoryItem
|
||||
>
|
||||
|
||||
export const AdminBatchDeleteVariantInventoryItem = z
|
||||
.object({
|
||||
inventory_item_id: z.string(),
|
||||
variant_id: z.string(),
|
||||
})
|
||||
.strict()
|
||||
export type AdminBatchDeleteVariantInventoryItemType = z.infer<
|
||||
typeof AdminBatchDeleteVariantInventoryItem
|
||||
>
|
||||
|
||||
export type AdminBatchVariantInventoryItemsType = BatchMethodRequest<
|
||||
AdminBatchCreateVariantInventoryItemType,
|
||||
AdminBatchUpdateVariantInventoryItemType,
|
||||
AdminBatchDeleteVariantInventoryItemType
|
||||
>
|
||||
@@ -2,12 +2,13 @@ import { z } from "zod"
|
||||
|
||||
export const createBatchBody = (
|
||||
createValidator: z.ZodType,
|
||||
updateValidator: z.ZodType
|
||||
updateValidator: z.ZodType,
|
||||
deleteValidator: z.ZodType = z.string()
|
||||
) => {
|
||||
return z.object({
|
||||
create: z.array(createValidator).optional(),
|
||||
update: z.array(updateValidator).optional(),
|
||||
delete: z.array(z.string()).optional(),
|
||||
delete: z.array(deleteValidator).optional(),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user