feat: move create inventory to @medusajs/workflows (#5301)

**Why**
- We have some workflow-like flows in @medusajs/medusa. These should be moved over to the workflows package.
- Inventory Items <> Variant currently assume a 1-1 mapping. There should be support for a many-to-many mapping.

**What**
- PR introduces a feature flag for supporting many-to-many mappings for inventory and variants.
- Deletes legacy transaction handler in @medusajs/medusa.
- Adjusts existing createInventoryItems handler to remove dependency on variant data.

**Unkowns**
~~1. Couldn't find an existing test for the CreateProduct workflow. It should be tested that this still works as expected.~~
2. Have removed transaction managers as we should move to handling consistency through orchestration tooling. Are we ready for that?
This commit is contained in:
Sebastian Rindom
2023-10-11 11:01:56 -07:00
committed by GitHub
parent bbd9dd408f
commit 66413d094e
25 changed files with 480 additions and 281 deletions

View File

@@ -0,0 +1,8 @@
---
"@medusajs/medusa": patch
"@medusajs/inventory": patch
"@medusajs/types": patch
"@medusajs/utils": patch
"@medusajs/workflows": patch
---
fix: move create inventory workflow to @medusajs/workflows

View File

@@ -0,0 +1,96 @@
const path = require("path")
const { ProductVariantInventoryService } = require("@medusajs/medusa")
const {
bootstrapApp,
} = require("../../../../environment-helpers/bootstrap-app")
const { initDb, useDb } = require("../../../../environment-helpers/use-db")
const { setPort, useApi } = require("../../../../environment-helpers/use-api")
const adminSeeder = require("../../../../helpers/admin-seeder")
jest.setTimeout(30000)
const {
simpleProductFactory,
simpleOrderFactory,
} = require("../../../../factories")
const adminHeaders = { headers: { "x-medusa-access-token": "test_token" } }
describe("Inventory Items endpoints", () => {
let appContainer
let dbConnection
let express
let variantId
let inventoryItems
let locationId
let location2Id
let location3Id
beforeAll(async () => {
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
dbConnection = await initDb({ cwd })
const { container, app, port } = await bootstrapApp({ cwd, verbose: true })
appContainer = container
// Set feature flag
const flagRouter = appContainer.resolve("featureFlagRouter")
flagRouter.setFlag("many_to_many_inventory", true)
setPort(port)
express = app.listen(port, (err) => {
process.send(port)
})
})
beforeEach(async () => {
await adminSeeder(dbConnection)
})
afterAll(async () => {
const flagRouter = appContainer.resolve("featureFlagRouter")
flagRouter.setFlag("many_to_many_inventory", false)
const db = useDb()
await db.shutdown()
express.close()
})
afterEach(async () => {
jest.clearAllMocks()
const db = useDb()
return await db.teardown()
})
describe("Inventory Items", () => {
it("should create inventory item without variant id", async () => {
const api = useApi()
await api.post(
`/admin/inventory-items`,
{
sku: "TABLE_LEG",
description: "Table Leg",
},
adminHeaders
)
/** @type {ProductVariantInventoryService} */
const productVariantInventoryService = appContainer.resolve(
"productVariantInventoryService"
)
const inventoryService = appContainer.resolve("inventoryService")
const inventoryItems = await inventoryService.list()
expect(inventoryItems.length).toEqual(1)
const variants = await productVariantInventoryService.listByItem([
inventoryItems[0].id,
])
expect(variants.length).toEqual(0)
})
})
})

View File

@@ -345,7 +345,7 @@ describe("Inventory Items endpoints", () => {
const inventoryItemCreateRes = await api.post(
`/admin/inventory-items`,
{ variant_id: variantId },
{ variant_id: variantId, sku: "attach_this_to_variant" },
adminHeaders
)

View File

@@ -0,0 +1,93 @@
import path from "path"
import { initDb, useDb } from "../../../../environment-helpers/use-db"
import { bootstrapApp } from "../../../../environment-helpers/bootstrap-app"
import {
createInventoryItems,
CreateInventoryItemActions,
pipe,
} from "@medusajs/workflows"
import { IInventoryService, WorkflowTypes } from "@medusajs/types"
import { ModuleRegistrationName } from "@medusajs/modules-sdk"
describe("CreateInventoryItem workflow", function () {
let medusaProcess
let medusaContainer
beforeAll(async () => {
const cwd = path.resolve(path.join(__dirname, "..", "..", ".."))
await initDb({ cwd } as any)
const { container } = await bootstrapApp({ cwd })
medusaContainer = container
})
afterAll(async () => {
const db = useDb()
await db.shutdown()
medusaProcess.kill()
})
it("should compensate all the invoke if something fails", async () => {
const workflow = createInventoryItems(medusaContainer)
workflow.appendAction(
"fail_step",
CreateInventoryItemActions.createInventoryItems,
{
invoke: pipe({}, async function failStep() {
throw new Error(`Failed`)
}),
},
{
noCompensation: true,
}
)
const input: WorkflowTypes.InventoryWorkflow.CreateInventoryItemsWorkflowInputDTO =
{
inventoryItems: [
{
sku: "TABLE_LEG",
description: "Table Leg",
},
],
}
const { result, errors, transaction } = await workflow.run({
input,
context: {},
throwOnError: false,
})
expect(errors).toEqual([
{
action: "fail_step",
handlerType: "invoke",
error: new Error(`Failed`),
},
])
expect(transaction.getState()).toEqual("reverted")
expect(result).toHaveLength(1)
expect(result[0].inventoryItem).toEqual(
expect.objectContaining({ id: expect.any(String) })
)
const inventoryService: IInventoryService = medusaContainer.resolve(
ModuleRegistrationName.INVENTORY
)
const [inventoryItems] = await inventoryService.listInventoryItems(
{ id: result[0].inventoryItem.id },
{ withDeleted: true }
)
expect(inventoryItems[0]).toEqual(
expect.objectContaining({
id: result[0].inventoryItem.id,
deleted_at: expect.any(Date),
})
)
})
})

View File

@@ -11,6 +11,7 @@
"dependencies": {
"@medusajs/cache-inmemory": "workspace:*",
"@medusajs/event-bus-local": "workspace:*",
"@medusajs/inventory": "workspace:^",
"@medusajs/medusa": "workspace:*",
"@medusajs/product": "workspace:^",
"faker": "^5.5.3",

View File

@@ -41,7 +41,7 @@ export function buildQuery<TWhereKeys extends object, TEntity = unknown>(
where: buildWhere<TWhereKeys, TEntity>(selector),
}
if ("deleted_at" in selector) {
if ("deleted_at" in selector || config.withDeleted) {
query.withDeleted = true
}

View File

@@ -70,6 +70,10 @@ export function getListQuery(
queryBuilder.select(legacySelect.map((s) => "inv_item." + s))
}
if (query.withDeleted) {
queryBuilder.withDeleted()
}
if (query.order) {
const toSelect: string[] = []
const parsed = Object.entries(query.order).reduce((acc, [k, v]) => {

View File

@@ -1,15 +1,14 @@
import { FlagRouter, ManyToManyInventoryFeatureFlag } from "@medusajs/utils"
import { IsNumber, IsObject, IsOptional, IsString } from "class-validator"
import {
ProductVariantInventoryService,
ProductVariantService,
} from "../../../../services"
createInventoryItems,
CreateInventoryItemActions,
pipe,
} from "@medusajs/workflows"
import { ProductVariantInventoryService } from "../../../../services"
import { EntityManager } from "typeorm"
import { FindParams } from "../../../../types/common"
import { IInventoryService } from "@medusajs/types"
import { MedusaError } from "@medusajs/utils"
import { createInventoryItemTransaction } from "./transaction/create-inventory-item"
import { validator } from "../../../../utils/validator"
/**
* @oas [post] /admin/inventory-items
@@ -78,54 +77,106 @@ import { validator } from "../../../../utils/validator"
*/
export default async (req, res) => {
const validated = await validator(AdminPostInventoryItemsReq, req.body)
const { variant_id, ...input } = validated
const { variant_id, ...inventoryItemInput } = req.validatedBody
const inventoryService: IInventoryService =
req.scope.resolve("inventoryService")
const featureFlagRouter: FlagRouter = req.scope.resolve("featureFlagRouter")
const productVariantInventoryService: ProductVariantInventoryService =
req.scope.resolve("productVariantInventoryService")
const productVariantService: ProductVariantService = req.scope.resolve(
"productVariantService"
)
let inventoryItems = await productVariantInventoryService.listByVariant(
variant_id
)
const createInventoryItemWorkflow = createInventoryItems(req.scope)
// TODO: this is a temporary fix to prevent duplicate inventory items since we don't support this functionality yet
if (inventoryItems.length) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
"Inventory Item already exists for this variant"
if (!featureFlagRouter.isFeatureEnabled(ManyToManyInventoryFeatureFlag.key)) {
if (!variant_id) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
"variant_id is required"
)
}
createInventoryItemWorkflow.appendAction(
"attachInventoryItems",
CreateInventoryItemActions.createInventoryItems,
{
invoke: pipe(
{
invoke: {
from: CreateInventoryItemActions.createInventoryItems,
alias: "createdItems",
},
},
generateAttachInventoryToVariantHandler(
variant_id,
productVariantInventoryService
)
),
compensate: pipe(
{
invoke: {
from: "attachInventoryItems",
alias: "attachedItems",
},
},
generateDetachInventoryItemFromVariantHandler(
productVariantInventoryService
)
),
}
)
}
const manager: EntityManager = req.scope.resolve("manager")
await manager.transaction(async (transactionManager) => {
await createInventoryItemTransaction(
{
manager: transactionManager,
inventoryService,
productVariantInventoryService,
productVariantService,
},
variant_id,
input
)
const { result } = await createInventoryItemWorkflow.run({
input: {
inventoryItems: [inventoryItemInput],
},
})
inventoryItems = await productVariantInventoryService.listByVariant(
variant_id
)
res.status(200).json({ inventory_item: result[0].inventoryItem })
}
const inventoryItem = await inventoryService.retrieveInventoryItem(
inventoryItems[0].inventory_item_id,
req.retrieveConfig
)
function generateDetachInventoryItemFromVariantHandler(
productVariantInventoryService: ProductVariantInventoryService
) {
return async ({ data }) => {
if (!data.attachedItems || !data.attachedItems.length) {
return
}
res.status(200).json({ inventory_item: inventoryItem })
const [variantId, inventoryItemId] = data.attachedItems
if (!variantId || !inventoryItemId) {
return
}
return await productVariantInventoryService.detachInventoryItem(
inventoryItemId,
variantId
)
}
}
function generateAttachInventoryToVariantHandler(
variantId: string,
productVariantInventoryService: ProductVariantInventoryService
) {
return async ({ data }) => {
let inventoryItems = await productVariantInventoryService.listByVariant(
variantId
)
// TODO: this is a temporary fix to prevent duplicate inventory
// items since we don't support this functionality yet
if (inventoryItems.length) {
throw new MedusaError(
MedusaError.Types.NOT_ALLOWED,
"Inventory Item already exists for this variant"
)
}
const inventoryItemId = data.createdItems[0].inventoryItem.id
await productVariantInventoryService.attachInventoryItem(
variantId,
inventoryItemId
)
return [variantId, inventoryItemId]
}
}
/**
@@ -192,6 +243,7 @@ export default async (req, res) => {
* url: "https://docs.medusajs.com/development/entities/overview#metadata-attribute"
*/
export class AdminPostInventoryItemsReq {
@IsOptional()
@IsString()
variant_id: string

View File

@@ -1,173 +0,0 @@
import {
DistributedTransaction,
TransactionHandlerType,
TransactionOrchestrator,
TransactionPayload,
TransactionState,
TransactionStepsDefinition,
} from "@medusajs/orchestration"
import { IInventoryService, InventoryItemDTO } from "@medusajs/types"
import {
ProductVariantInventoryService,
ProductVariantService,
} from "../../../../../services"
import { EntityManager } from "typeorm"
import { MedusaError } from "@medusajs/utils"
import { ulid } from "ulid"
enum actions {
createInventoryItem = "createInventoryItem",
attachInventoryItem = "attachInventoryItem",
}
const flow: TransactionStepsDefinition = {
next: {
action: actions.createInventoryItem,
saveResponse: true,
next: {
action: actions.attachInventoryItem,
noCompensation: true,
},
},
}
const createInventoryItemStrategy = new TransactionOrchestrator(
"create-inventory-item",
flow
)
type InjectedDependencies = {
manager: EntityManager
productVariantService: ProductVariantService
productVariantInventoryService: ProductVariantInventoryService
inventoryService: IInventoryService
}
type CreateInventoryItemInput = {
sku?: string
hs_code?: string
weight?: number
length?: number
height?: number
width?: number
origin_country?: string
mid_code?: string
material?: string
title?: string
description?: string
thumbnail?: string
metadata?: Record<string, unknown>
}
export const createInventoryItemTransaction = async (
dependencies: InjectedDependencies,
variantId: string,
input: CreateInventoryItemInput
): Promise<DistributedTransaction> => {
const {
manager,
productVariantService,
inventoryService,
productVariantInventoryService,
} = dependencies
const productVariantInventoryServiceTx =
productVariantInventoryService.withTransaction(manager)
const productVariantServiceTx = productVariantService.withTransaction(manager)
async function createInventoryItem(input: CreateInventoryItemInput) {
return await inventoryService!.createInventoryItem({
sku: input.sku,
origin_country: input.origin_country,
hs_code: input.hs_code,
mid_code: input.mid_code,
material: input.material,
weight: input.weight,
length: input.length,
height: input.height,
width: input.width,
title: input.title,
description: input.description,
thumbnail: input.thumbnail,
})
}
async function removeInventoryItem(inventoryItem: InventoryItemDTO) {
if (inventoryItem) {
await inventoryService!.deleteInventoryItem(inventoryItem.id)
}
}
async function attachInventoryItem(inventoryItem: InventoryItemDTO) {
const variant = await productVariantServiceTx.retrieve(variantId)
if (!variant.manage_inventory) {
return
}
await productVariantInventoryServiceTx.attachInventoryItem(
variant.id,
inventoryItem.id
)
}
async function transactionHandler(
actionId: string,
type: TransactionHandlerType,
payload: TransactionPayload
) {
const command = {
[actions.createInventoryItem]: {
[TransactionHandlerType.INVOKE]: async (
data: CreateInventoryItemInput
) => {
return await createInventoryItem(data)
},
[TransactionHandlerType.COMPENSATE]: async (
data: CreateInventoryItemInput,
{ invoke }
) => {
await removeInventoryItem(invoke[actions.createInventoryItem])
},
},
[actions.attachInventoryItem]: {
[TransactionHandlerType.INVOKE]: async (
data: CreateInventoryItemInput,
{ invoke }
) => {
const { [actions.createInventoryItem]: inventoryItem } = invoke
return await attachInventoryItem(inventoryItem)
},
},
}
return command[actionId][type](payload.data, payload.context)
}
const transaction = await createInventoryItemStrategy.beginTransaction(
ulid(),
transactionHandler,
input
)
await createInventoryItemStrategy.resume(transaction)
if (transaction.getState() !== TransactionState.DONE) {
throw new MedusaError(
MedusaError.Types.INVALID_DATA,
transaction
.getErrors()
.map((err) => err.error?.message)
.join("\n")
)
}
return transaction
}
export const revertVariantTransaction = async (
transaction: DistributedTransaction
) => {
await createInventoryItemStrategy.cancelTransaction(transaction)
}

View File

@@ -1,3 +1,4 @@
export * as CartWorkflow from "./cart"
export * as CommonWorkflow from "./common"
export * as ProductWorkflow from "./product"
export * as InventoryWorkflow from "./inventory"

View File

@@ -0,0 +1,19 @@
export interface CreateInventoryItemInputDTO {
sku?: string
hs_code?: string
weight?: number
length?: number
height?: number
width?: number
origin_country?: string
mid_code?: string
material?: string
title?: string
description?: string
thumbnail?: string
metadata?: Record<string, unknown>
}
export interface CreateInventoryItemsWorkflowInputDTO {
inventoryItems: CreateInventoryItemInputDTO[]
}

View File

@@ -0,0 +1 @@
export * from "./create-inventory-items"

View File

@@ -6,4 +6,4 @@ export * from "./sales-channels"
export * from "./tax-inclusive-pricing"
export * from "./utils"
export * from "./workflows"
export * from "./many-to-many-inventory"

View File

@@ -0,0 +1,9 @@
import { FeatureFlagTypes } from "@medusajs/types"
export const ManyToManyInventoryFeatureFlag: FeatureFlagTypes.FlagSettings = {
key: "many_to_many_inventory",
default_val: false,
env_key: "MEDUSA_FF_MANY_TO_MANY_INVENTORY",
description:
"Enable capability to have many to many relationship between inventory items and variants",
}

View File

@@ -1,2 +1,3 @@
export * from "./cart"
export * from "./product"
export * from "./inventory"

View File

@@ -0,0 +1,64 @@
import { Workflows } from "../../definitions"
import {
TransactionStepsDefinition,
WorkflowManager,
} from "@medusajs/orchestration"
import { exportWorkflow, pipe } from "../../helper"
import { InventoryTypes, WorkflowTypes } from "@medusajs/types"
import { InventoryHandlers } from "../../handlers"
export enum CreateInventoryItemActions {
prepare = "prepare",
createInventoryItems = "createInventoryItems",
}
const workflowSteps: TransactionStepsDefinition = {
next: {
action: CreateInventoryItemActions.createInventoryItems,
},
}
const handlers = new Map([
[
CreateInventoryItemActions.createInventoryItems,
{
invoke: pipe(
{
inputAlias: CreateInventoryItemActions.prepare,
merge: true,
invoke: {
from: CreateInventoryItemActions.prepare,
},
},
InventoryHandlers.createInventoryItems
),
compensate: pipe(
{
merge: true,
invoke: {
from: CreateInventoryItemActions.createInventoryItems,
alias:
InventoryHandlers.removeInventoryItems.aliases.inventoryItems,
},
},
InventoryHandlers.removeInventoryItems
),
},
],
])
WorkflowManager.register(
Workflows.CreateInventoryItems,
workflowSteps,
handlers
)
export const createInventoryItems = exportWorkflow<
WorkflowTypes.InventoryWorkflow.CreateInventoryItemsWorkflowInputDTO,
{ tag: string; inventoryItem: InventoryTypes.InventoryItemDTO }[]
>(
Workflows.CreateInventoryItems,
CreateInventoryItemActions.createInventoryItems,
async (data) => data
)

View File

@@ -0,0 +1 @@
export * from "./create-inventory-item"

View File

@@ -11,6 +11,7 @@ import {
MiddlewaresHandlers,
ProductHandlers,
} from "../../handlers"
import { prepareCreateInventoryItems } from "./prepare-create-inventory-items"
export enum CreateProductsActions {
prepare = "prepare",
@@ -175,9 +176,10 @@ const handlers = new Map([
merge: true,
invoke: {
from: CreateProductsActions.createProducts,
alias: InventoryHandlers.createInventoryItems.aliases.products,
alias: prepareCreateInventoryItems.aliases.products,
},
},
prepareCreateInventoryItems,
InventoryHandlers.createInventoryItems
),
compensate: pipe(

View File

@@ -0,0 +1,46 @@
import { ProductTypes } from "@medusajs/types"
import { WorkflowArguments } from "../../helper"
type AssociationTaggedVariant = ProductTypes.ProductVariantDTO & {
_associationTag?: string
}
type ObjectWithVariant = { variants: ProductTypes.ProductVariantDTO[] }
export async function prepareCreateInventoryItems({
data,
}: WorkflowArguments<{
products: ObjectWithVariant[]
}>) {
const taggedVariants = data.products.reduce<AssociationTaggedVariant[]>(
(acc, product: ObjectWithVariant) => {
const cleanVariants = product.variants.reduce<AssociationTaggedVariant[]>(
(acc, variant: AssociationTaggedVariant) => {
if (!variant.manage_inventory) {
return acc
}
variant._associationTag = variant.id
acc.push(variant)
return acc
},
[]
)
return acc.concat(cleanVariants)
},
[]
)
return {
alias: prepareCreateInventoryItems.aliases.output,
value: {
inventoryItems: taggedVariants,
},
}
}
prepareCreateInventoryItems.aliases = {
products: "products",
output: "prepareCreateInventoryItemsOutput",
}

View File

@@ -4,6 +4,8 @@ export enum Workflows {
// Cart workflows
CreateCart = "create-cart",
CreateInventoryItems = "create-inventory-items",
}
export enum InputAlias {
@@ -16,4 +18,6 @@ export enum InputAlias {
AttachedInventoryItems = "attachedInventoryItems",
DetachedInventoryItems = "detachedInventoryItems",
InventoryItemsInputData = "inventoryItemsInputData",
}

View File

@@ -1,4 +1,4 @@
import { InventoryItemDTO, ProductTypes } from "@medusajs/types"
import { InventoryItemDTO } from "@medusajs/types"
import { WorkflowArguments } from "../../helper"
export async function attachInventoryItems({
@@ -7,12 +7,11 @@ export async function attachInventoryItems({
data,
}: WorkflowArguments<{
inventoryItems: {
variant: ProductTypes.ProductVariantDTO
tag: string
inventoryItem: InventoryItemDTO
}[]
}>) {
const { manager } = context
const productVariantInventoryService = container
.resolve("productVariantInventoryService")
.withTransaction(manager)
@@ -21,12 +20,10 @@ export async function attachInventoryItems({
return
}
const inventoryData = data.inventoryItems.map(
({ variant, inventoryItem }) => ({
variantId: variant.id,
inventoryItemId: inventoryItem.id,
})
)
const inventoryData = data.inventoryItems.map(({ tag, inventoryItem }) => ({
variantId: tag,
inventoryItemId: inventoryItem.id,
}))
return await productVariantInventoryService.attachInventoryItem(inventoryData)
}

View File

@@ -1,21 +1,16 @@
import {
IInventoryService,
InventoryItemDTO,
ProductTypes,
} from "@medusajs/types"
import { IInventoryService, InventoryItemDTO } from "@medusajs/types"
import { WorkflowArguments } from "../../helper"
type Result = {
variant: ProductTypes.ProductVariantDTO
tag: string
inventoryItem: InventoryItemDTO
}[]
export async function createInventoryItems({
container,
context,
data,
}: WorkflowArguments<{
products: ProductTypes.ProductDTO[]
inventoryItems: (InventoryItemDTO & { _associationTag?: string })[]
}>): Promise<Result | void> {
const inventoryService: IInventoryService =
container.resolve("inventoryService")
@@ -28,47 +23,27 @@ export async function createInventoryItems({
return void 0
}
const variants = data.products.reduce(
(
acc: ProductTypes.ProductVariantDTO[],
product: ProductTypes.ProductDTO
) => {
return acc.concat(product.variants)
},
[]
)
const result = await Promise.all(
variants.map(async (variant) => {
if (!variant.manage_inventory) {
return
}
data.inventoryItems.map(async (item) => {
const inventoryItem = await inventoryService!.createInventoryItem({
sku: item.sku!,
origin_country: item.origin_country!,
hs_code: item.hs_code!,
mid_code: item.mid_code!,
material: item.material!,
weight: item.weight!,
length: item.length!,
height: item.height!,
width: item.width!,
})
const inventoryItem = await inventoryService!.createInventoryItem(
{
sku: variant.sku!,
origin_country: variant.origin_country!,
hs_code: variant.hs_code!,
mid_code: variant.mid_code!,
material: variant.material!,
weight: variant.weight!,
length: variant.length!,
height: variant.height!,
width: variant.width!,
},
{
transactionManager: (context.transactionManager ??
context.manager) as any,
}
)
return { variant, inventoryItem }
return { tag: item._associationTag ?? inventoryItem.id, inventoryItem }
})
)
return result.filter(Boolean) as Result
return result
}
createInventoryItems.aliases = {
products: "products",
payload: "payload",
}

View File

@@ -1,4 +1,4 @@
import { InventoryItemDTO, ProductTypes } from "@medusajs/types"
import { InventoryItemDTO } from "@medusajs/types"
import { WorkflowArguments } from "../../helper"
export async function detachInventoryItems({
@@ -7,7 +7,7 @@ export async function detachInventoryItems({
data,
}: WorkflowArguments<{
inventoryItems: {
variant: ProductTypes.ProductVariantDTO
tag: string
inventoryItem: InventoryItemDTO
}[]
}>): Promise<void> {
@@ -22,10 +22,10 @@ export async function detachInventoryItems({
}
await Promise.all(
data.inventoryItems.map(async ({ variant, inventoryItem }) => {
data.inventoryItems.map(async ({ tag, inventoryItem }) => {
return await productVariantInventoryService.detachInventoryItem(
inventoryItem.id,
variant.id
tag
)
})
)

View File

@@ -3,12 +3,10 @@ import { WorkflowArguments } from "../../helper"
export async function removeInventoryItems({
container,
context,
data,
}: WorkflowArguments<{
inventoryItems: { inventoryItem: InventoryItemDTO }[]
}>) {
const { manager } = context
const inventoryService = container.resolve("inventoryService")
if (!inventoryService) {
@@ -20,8 +18,7 @@ export async function removeInventoryItems({
}
return await inventoryService!.deleteInventoryItem(
data.inventoryItems.map(({ inventoryItem }) => inventoryItem.id),
{ transactionManager: manager }
data.inventoryItems.map(({ inventoryItem }) => inventoryItem.id)
)
}

View File

@@ -6499,7 +6499,7 @@ __metadata:
languageName: node
linkType: hard
"@medusajs/inventory@workspace:packages/inventory":
"@medusajs/inventory@workspace:^, @medusajs/inventory@workspace:packages/inventory":
version: 0.0.0-use.local
resolution: "@medusajs/inventory@workspace:packages/inventory"
dependencies:
@@ -26516,6 +26516,7 @@ __metadata:
"@babel/node": ^7.12.10
"@medusajs/cache-inmemory": "workspace:*"
"@medusajs/event-bus-local": "workspace:*"
"@medusajs/inventory": "workspace:^"
"@medusajs/medusa": "workspace:*"
"@medusajs/product": "workspace:^"
babel-preset-medusa-package: "*"