feat(medusa, core-flows): add ppdate inventory item endpoint (#6735)

* init update inventory item

* prep for pr
This commit is contained in:
Philip Korsholm
2024-03-20 14:45:06 +01:00
committed by GitHub
parent 8155e2cfad
commit 64c2731e46
8 changed files with 249 additions and 26 deletions

View File

@@ -89,31 +89,6 @@ medusaIntegrationTestRunner({
)
})
it.skip("should update the inventory item", async () => {
const inventoryItemId = inventoryItems[0].id
const response = await api.post(
`/admin/inventory-items/${inventoryItemId}`,
{
mid_code: "updated mid_code",
weight: 120,
},
adminHeaders
)
expect(response.data.inventory_item).toEqual(
expect.objectContaining({
origin_country: "UK",
hs_code: "hs001",
mid_code: "updated mid_code",
weight: 120,
length: 100,
height: 200,
width: 150,
})
)
})
it.skip("should fail to update the location level to negative quantity", async () => {
const inventoryItemId = inventoryItems[0].id
@@ -229,6 +204,40 @@ medusaIntegrationTestRunner({
)
})
describe("Update inventory item", () => {
let inventoryItemId
beforeEach(async () => {
const inventoryItemResponse = await api.post(
`/admin/inventory-items`,
{
sku: "test-sku",
},
adminHeaders
)
inventoryItemId = inventoryItemResponse.data.inventory_item.id
})
it("should update the inventory item", async () => {
const response = await api.post(
`/admin/inventory-items/${inventoryItemId}`,
{
mid_code: "updated mid_code",
weight: 120,
},
adminHeaders
)
expect(response.data.inventory_item).toEqual(
expect.objectContaining({
sku: "test-sku",
mid_code: "updated mid_code",
weight: 120,
})
)
})
})
describe("Delete inventory levels", () => {
const locationId = "loc_1"
let inventoryItem

View File

@@ -5,4 +5,5 @@ export * from "./create-inventory-items"
export * from "./validate-singular-inventory-items-for-tags"
export * from "./create-inventory-levels"
export * from "./validate-inventory-locations"
export * from "./update-inventory-items"
export * from "./delete-inventory-levels"

View File

@@ -0,0 +1,49 @@
import { IInventoryServiceNext, InventoryNext } from "@medusajs/types"
import { StepResponse, createStep } from "@medusajs/workflows-sdk"
import {
convertItemResponseToUpdateRequest,
getSelectsAndRelationsFromObjectArray,
} from "@medusajs/utils"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
export const updateInventoryItemsStepId = "update-inventory-items-step"
export const updateInventoryItemsStep = createStep(
updateInventoryItemsStepId,
async (input: InventoryNext.UpdateInventoryItemInput[], { container }) => {
const inventoryService = container.resolve<IInventoryServiceNext>(
ModuleRegistrationName.INVENTORY
)
const { selects, relations } = getSelectsAndRelationsFromObjectArray(input)
const dataBeforeUpdate = await inventoryService.list(
{ id: input.map(({ id }) => id) },
{}
)
const updatedInventoryItems = await inventoryService.update(input)
return new StepResponse(updatedInventoryItems, {
dataBeforeUpdate,
selects,
relations,
})
},
async (revertInput, { container }) => {
if (!revertInput?.dataBeforeUpdate?.length) {
return
}
const { dataBeforeUpdate, selects, relations } = revertInput
const inventoryService = container.resolve<IInventoryServiceNext>(
ModuleRegistrationName.INVENTORY
)
await inventoryService.update(
dataBeforeUpdate.map((data) =>
convertItemResponseToUpdateRequest(data, selects, relations)
)
)
}
)

View File

@@ -1,4 +1,5 @@
export * from "./delete-inventory-items"
export * from "./create-inventory-items"
export * from "./create-inventory-levels"
export * from "./update-inventory-items"
export * from "./delete-inventory-levels"

View File

@@ -0,0 +1,17 @@
import { WorkflowData, createWorkflow } from "@medusajs/workflows-sdk"
import { InventoryNext } from "@medusajs/types"
import { updateInventoryItemsStep } from "../steps"
interface WorkflowInput {
updates: InventoryNext.UpdateInventoryItemInput[]
}
export const updateInventoryItemsWorkflowId = "update-inventory-items-workflow"
export const updateInventoryItemsWorkflow = createWorkflow(
updateInventoryItemsWorkflowId,
(
input: WorkflowData<WorkflowInput>
): WorkflowData<InventoryNext.InventoryItemDTO[]> => {
return updateInventoryItemsStep(input.updates)
}
)

View File

@@ -4,8 +4,12 @@ import {
remoteQueryObjectFromString,
} from "@medusajs/utils"
import { MedusaRequest, MedusaResponse } from "../../../../types/routing"
import {
deleteInventoryItemWorkflow,
updateInventoryItemsWorkflow,
} from "@medusajs/core-flows"
import { deleteInventoryItemWorkflow } from "@medusajs/core-flows"
import { AdminPostInventoryItemsInventoryItemReq } from "../validators"
export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
const { id } = req.params
@@ -38,6 +42,36 @@ export const GET = async (req: MedusaRequest, res: MedusaResponse) => {
})
}
// Update inventory item
export const POST = async (
req: MedusaRequest<AdminPostInventoryItemsInventoryItemReq>,
res: MedusaResponse
) => {
const { id } = req.params
await updateInventoryItemsWorkflow(req.scope).run({
input: {
updates: [{ id, ...req.validatedBody }],
},
})
const remoteQuery = req.scope.resolve(ContainerRegistrationKeys.REMOTE_QUERY)
const [inventory_item] = await remoteQuery(
remoteQueryObjectFromString({
entryPoint: "inventory",
variables: {
id,
},
fields: req.retrieveConfig.select as string[],
})
)
res.status(200).json({
inventory_item,
})
}
export const DELETE = async (req: MedusaRequest, res: MedusaResponse) => {
const id = req.params.id
const deleteInventoryItems = deleteInventoryItemWorkflow(req.scope)

View File

@@ -3,6 +3,8 @@ import * as QueryConfig from "./query-config"
import {
AdminGetInventoryItemsItemParams,
AdminGetInventoryItemsParams,
AdminPostInventoryItemsInventoryItemParams,
AdminPostInventoryItemsInventoryItemReq,
AdminPostInventoryItemsItemLocationLevelsReq,
AdminPostInventoryItemsReq,
} from "./validators"
@@ -53,4 +55,15 @@ export const adminInventoryRoutesMiddlewares: MiddlewareRoute[] = [
),
],
},
{
method: ["POST"],
matcher: "/admin/inventory-items/:id",
middlewares: [
transformBody(AdminPostInventoryItemsInventoryItemReq),
transformQuery(
AdminPostInventoryItemsInventoryItemParams,
QueryConfig.retrieveTransformQueryConfig
),
],
},
]

View File

@@ -257,3 +257,102 @@ export class AdminPostInventoryItemsReq {
@IsOptional()
metadata?: Record<string, unknown>
}
/**
* @schema AdminPostInventoryItemsInventoryItemReq
* type: object
* description: "The attributes to update in an inventory item."
* properties:
* 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
* 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
* weight:
* description: The weight 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
* length:
* description: The length of the Inventory Item. May be used in shipping rate calculations.
* type: number
* 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
* requires_shipping:
* description: Whether the item requires shipping.
* type: boolean
*/
export class AdminPostInventoryItemsInventoryItemReq {
@IsString()
@IsOptional()
sku?: string
@IsOptional()
@IsString()
origin_country?: string
@IsOptional()
@IsString()
hs_code?: string
@IsOptional()
@IsString()
mid_code?: string
@IsOptional()
@IsString()
material?: string
@IsOptional()
@IsNumber()
weight?: number
@IsOptional()
@IsNumber()
height?: number
@IsOptional()
@IsNumber()
length?: number
@IsOptional()
@IsNumber()
width?: number
@IsString()
@IsOptional()
title?: string
@IsString()
@IsOptional()
description?: string
@IsString()
@IsOptional()
thumbnail?: string
@IsBoolean()
@IsOptional()
requires_shipping?: boolean
}
export class AdminPostInventoryItemsInventoryItemParams extends FindParams {}