fix(medusa): Fix hanging inventory item migration script (#3624)
This commit is contained in:
1 parent
377b9ce8c2
commit
999aeb116c
6 files changed
+156
-72
No files matched your search
@@ -0,0 +1,5 @@
|
|||||||
|
---
|
||||||
|
"@medusajs/medusa": patch
|
||||||
|
---
|
||||||
|
|
||||||
|
fix(medusa): Fix hanging inventory item migration script
|
||||||
@@ -1,15 +1,16 @@
|
|||||||
import { AwilixContainer } from "awilix"
|
|
||||||
import dotenv from "dotenv"
|
|
||||||
import express from "express"
|
|
||||||
|
|
||||||
import { IInventoryService, IStockLocationService } from "@medusajs/types"
|
import { IInventoryService, IStockLocationService } from "@medusajs/types"
|
||||||
import loaders from "../loaders"
|
|
||||||
import { ProductVariant } from "../models"
|
|
||||||
import {
|
import {
|
||||||
ProductVariantInventoryService,
|
ProductVariantInventoryService,
|
||||||
ProductVariantService,
|
ProductVariantService,
|
||||||
} from "../services"
|
} from "../services"
|
||||||
|
|
||||||
|
import { AwilixContainer } from "awilix"
|
||||||
|
import { EntityManager } from "typeorm"
|
||||||
|
import { ProductVariant } from "../models"
|
||||||
|
import dotenv from "dotenv"
|
||||||
|
import express from "express"
|
||||||
|
import loaders from "../loaders"
|
||||||
|
|
||||||
dotenv.config()
|
dotenv.config()
|
||||||
|
|
||||||
const BATCH_SIZE = 100
|
const BATCH_SIZE = 100
|
||||||
@@ -17,10 +18,24 @@ const BATCH_SIZE = 100
|
|||||||
const migrateProductVariant = async (
|
const migrateProductVariant = async (
|
||||||
variant: ProductVariant,
|
variant: ProductVariant,
|
||||||
locationId: string,
|
locationId: string,
|
||||||
{ container }: { container: AwilixContainer }
|
{
|
||||||
|
container,
|
||||||
|
transactionManager,
|
||||||
|
}: { container: AwilixContainer; transactionManager: EntityManager }
|
||||||
) => {
|
) => {
|
||||||
const productVariantInventoryService: ProductVariantInventoryService =
|
const productVariantInventoryService: ProductVariantInventoryService =
|
||||||
container.resolve("productVariantInventoryService")
|
container.resolve("productVariantInventoryService")
|
||||||
|
|
||||||
|
const productVariantInventoryServiceTx =
|
||||||
|
productVariantInventoryService.withTransaction(transactionManager)
|
||||||
|
|
||||||
|
const existingVariantInventoryItems =
|
||||||
|
await productVariantInventoryServiceTx.listByVariant(variant.id)
|
||||||
|
|
||||||
|
if (existingVariantInventoryItems.length) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
const inventoryService: IInventoryService =
|
const inventoryService: IInventoryService =
|
||||||
container.resolve("inventoryService")
|
container.resolve("inventoryService")
|
||||||
|
|
||||||
@@ -28,31 +43,38 @@ const migrateProductVariant = async (
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
const inventoryItem = await inventoryService.createInventoryItem({
|
const context = { transactionManager }
|
||||||
sku: variant.sku,
|
const inventoryItem = await inventoryService.createInventoryItem(
|
||||||
material: variant.material,
|
{
|
||||||
width: variant.width,
|
sku: variant.sku,
|
||||||
length: variant.length,
|
material: variant.material,
|
||||||
height: variant.height,
|
width: variant.width,
|
||||||
weight: variant.weight,
|
length: variant.length,
|
||||||
origin_country: variant.origin_country,
|
height: variant.height,
|
||||||
hs_code: variant.hs_code,
|
weight: variant.weight,
|
||||||
mid_code: variant.mid_code,
|
origin_country: variant.origin_country,
|
||||||
requires_shipping: true,
|
hs_code: variant.hs_code,
|
||||||
})
|
mid_code: variant.mid_code,
|
||||||
|
requires_shipping: true,
|
||||||
|
},
|
||||||
|
context
|
||||||
|
)
|
||||||
|
|
||||||
await productVariantInventoryService.attachInventoryItem(
|
await productVariantInventoryServiceTx.attachInventoryItem(
|
||||||
variant.id,
|
variant.id,
|
||||||
inventoryItem.id,
|
inventoryItem.id,
|
||||||
1
|
1
|
||||||
)
|
)
|
||||||
|
|
||||||
await inventoryService.createInventoryLevel({
|
await inventoryService.createInventoryLevel(
|
||||||
location_id: locationId,
|
{
|
||||||
inventory_item_id: inventoryItem.id,
|
location_id: locationId,
|
||||||
stocked_quantity: variant.inventory_quantity,
|
inventory_item_id: inventoryItem.id,
|
||||||
incoming_quantity: 0,
|
stocked_quantity: variant.inventory_quantity,
|
||||||
})
|
incoming_quantity: 0,
|
||||||
|
},
|
||||||
|
context
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
const migrateStockLocation = async (container: AwilixContainer) => {
|
const migrateStockLocation = async (container: AwilixContainer) => {
|
||||||
@@ -75,11 +97,17 @@ const processBatch = async (
|
|||||||
locationId: string,
|
locationId: string,
|
||||||
container: AwilixContainer
|
container: AwilixContainer
|
||||||
) => {
|
) => {
|
||||||
await Promise.all(
|
const manager = container.resolve("manager")
|
||||||
variants.map(async (variant) => {
|
return await manager.transaction(async (transactionManager) => {
|
||||||
await migrateProductVariant(variant, locationId, { container })
|
await Promise.all(
|
||||||
})
|
variants.map(async (variant) => {
|
||||||
)
|
await migrateProductVariant(variant, locationId, {
|
||||||
|
container,
|
||||||
|
transactionManager,
|
||||||
|
})
|
||||||
|
})
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
const migrate = async function ({ directory }) {
|
const migrate = async function ({ directory }) {
|
||||||
|
|||||||
@@ -247,9 +247,13 @@ class ProductVariantInventoryService extends TransactionBaseService {
|
|||||||
})
|
})
|
||||||
|
|
||||||
// Verify that item exists
|
// Verify that item exists
|
||||||
await this.inventoryService_.retrieveInventoryItem(inventoryItemId, {
|
await this.inventoryService_.retrieveInventoryItem(
|
||||||
select: ["id"],
|
inventoryItemId,
|
||||||
})
|
{
|
||||||
|
select: ["id"],
|
||||||
|
},
|
||||||
|
{ transactionManager: this.activeManager_ }
|
||||||
|
)
|
||||||
|
|
||||||
const variantInventoryRepo = this.activeManager_.getRepository(
|
const variantInventoryRepo = this.activeManager_.getRepository(
|
||||||
ProductVariantInventoryItem
|
ProductVariantInventoryItem
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
import { EventBusTypes } from "@medusajs/types"
|
|
||||||
import { DeepPartial, EntityManager, In } from "typeorm"
|
import { DeepPartial, EntityManager, In } from "typeorm"
|
||||||
|
|
||||||
|
import { EventBusTypes } from "@medusajs/types"
|
||||||
|
import { FindConfig } from "../types/common"
|
||||||
import { QueryDeepPartialEntity } from "typeorm/query-builder/QueryPartialEntity"
|
import { QueryDeepPartialEntity } from "typeorm/query-builder/QueryPartialEntity"
|
||||||
import { TransactionBaseService } from "../interfaces"
|
|
||||||
import { StagedJob } from "../models"
|
import { StagedJob } from "../models"
|
||||||
import { StagedJobRepository } from "../repositories/staged-job"
|
import { StagedJobRepository } from "../repositories/staged-job"
|
||||||
import { FindConfig } from "../types/common"
|
import { TransactionBaseService } from "../interfaces"
|
||||||
import { isString } from "../utils"
|
import { isString } from "../utils"
|
||||||
|
|
||||||
type StagedJobServiceProps = {
|
type StagedJobServiceProps = {
|
||||||
@@ -42,8 +43,7 @@ class StagedJobService extends TransactionBaseService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async create(data: EventBusTypes.EmitData[] | EventBusTypes.EmitData) {
|
async create(data: EventBusTypes.EmitData[] | EventBusTypes.EmitData) {
|
||||||
return await this.atomicPhase_(async (manager) => {
|
const stagedJobRepo = this.activeManager_.withRepository(this.stagedJobRepository_)
|
||||||
const stagedJobRepo = manager.withRepository(this.stagedJobRepository_)
|
|
||||||
|
|
||||||
const data_ = Array.isArray(data) ? data : [data]
|
const data_ = Array.isArray(data) ? data : [data]
|
||||||
|
|
||||||
@@ -56,7 +56,6 @@ class StagedJobService extends TransactionBaseService {
|
|||||||
) as QueryDeepPartialEntity<StagedJob>[]
|
) as QueryDeepPartialEntity<StagedJob>[]
|
||||||
|
|
||||||
return await stagedJobRepo.insertBulk(stagedJobs)
|
return await stagedJobRepo.insertBulk(stagedJobs)
|
||||||
})
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
import { FindConfig } from "../common"
|
|
||||||
|
|
||||||
import {
|
import {
|
||||||
CreateInventoryItemInput,
|
CreateInventoryItemInput,
|
||||||
CreateInventoryLevelInput,
|
CreateInventoryLevelInput,
|
||||||
@@ -14,101 +12,139 @@ import {
|
|||||||
UpdateReservationItemInput,
|
UpdateReservationItemInput,
|
||||||
} from "./common"
|
} from "./common"
|
||||||
|
|
||||||
|
import { FindConfig } from "../common"
|
||||||
|
import { SharedContext } from ".."
|
||||||
|
|
||||||
export interface IInventoryService {
|
export interface IInventoryService {
|
||||||
listInventoryItems(
|
listInventoryItems(
|
||||||
selector: FilterableInventoryItemProps,
|
selector: FilterableInventoryItemProps,
|
||||||
config?: FindConfig<InventoryItemDTO>
|
config?: FindConfig<InventoryItemDTO>,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<[InventoryItemDTO[], number]>
|
): Promise<[InventoryItemDTO[], number]>
|
||||||
|
|
||||||
listReservationItems(
|
listReservationItems(
|
||||||
selector: FilterableReservationItemProps,
|
selector: FilterableReservationItemProps,
|
||||||
config?: FindConfig<ReservationItemDTO>
|
config?: FindConfig<ReservationItemDTO>,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<[ReservationItemDTO[], number]>
|
): Promise<[ReservationItemDTO[], number]>
|
||||||
|
|
||||||
listInventoryLevels(
|
listInventoryLevels(
|
||||||
selector: FilterableInventoryLevelProps,
|
selector: FilterableInventoryLevelProps,
|
||||||
config?: FindConfig<InventoryLevelDTO>
|
config?: FindConfig<InventoryLevelDTO>,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<[InventoryLevelDTO[], number]>
|
): Promise<[InventoryLevelDTO[], number]>
|
||||||
|
|
||||||
retrieveInventoryItem(
|
retrieveInventoryItem(
|
||||||
inventoryItemId: string,
|
inventoryItemId: string,
|
||||||
config?: FindConfig<InventoryItemDTO>
|
config?: FindConfig<InventoryItemDTO>,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<InventoryItemDTO>
|
): Promise<InventoryItemDTO>
|
||||||
|
|
||||||
retrieveInventoryLevel(
|
retrieveInventoryLevel(
|
||||||
inventoryItemId: string,
|
inventoryItemId: string,
|
||||||
locationId: string
|
locationId: string,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<InventoryLevelDTO>
|
): Promise<InventoryLevelDTO>
|
||||||
|
|
||||||
retrieveReservationItem(reservationId: string): Promise<ReservationItemDTO>
|
retrieveReservationItem(
|
||||||
|
reservationId: string,
|
||||||
|
context?: SharedContext
|
||||||
|
): Promise<ReservationItemDTO>
|
||||||
|
|
||||||
createReservationItem(
|
createReservationItem(
|
||||||
input: CreateReservationItemInput
|
input: CreateReservationItemInput,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<ReservationItemDTO>
|
): Promise<ReservationItemDTO>
|
||||||
|
|
||||||
createInventoryItem(
|
createInventoryItem(
|
||||||
input: CreateInventoryItemInput
|
input: CreateInventoryItemInput,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<InventoryItemDTO>
|
): Promise<InventoryItemDTO>
|
||||||
|
|
||||||
createInventoryLevel(
|
createInventoryLevel(
|
||||||
data: CreateInventoryLevelInput
|
data: CreateInventoryLevelInput,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<InventoryLevelDTO>
|
): Promise<InventoryLevelDTO>
|
||||||
|
|
||||||
updateInventoryLevel(
|
updateInventoryLevel(
|
||||||
inventoryItemId: string,
|
inventoryItemId: string,
|
||||||
locationId: string,
|
locationId: string,
|
||||||
update: UpdateInventoryLevelInput
|
update: UpdateInventoryLevelInput,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<InventoryLevelDTO>
|
): Promise<InventoryLevelDTO>
|
||||||
|
|
||||||
updateInventoryItem(
|
updateInventoryItem(
|
||||||
inventoryItemId: string,
|
inventoryItemId: string,
|
||||||
input: CreateInventoryItemInput
|
input: CreateInventoryItemInput,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<InventoryItemDTO>
|
): Promise<InventoryItemDTO>
|
||||||
|
|
||||||
updateReservationItem(
|
updateReservationItem(
|
||||||
reservationItemId: string,
|
reservationItemId: string,
|
||||||
input: UpdateReservationItemInput
|
input: UpdateReservationItemInput,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<ReservationItemDTO>
|
): Promise<ReservationItemDTO>
|
||||||
|
|
||||||
deleteReservationItemsByLineItem(lineItemId: string): Promise<void>
|
deleteReservationItemsByLineItem(
|
||||||
|
lineItemId: string,
|
||||||
|
context?: SharedContext
|
||||||
|
): Promise<void>
|
||||||
|
|
||||||
deleteReservationItem(reservationItemId: string | string[]): Promise<void>
|
deleteReservationItem(
|
||||||
|
reservationItemId: string | string[],
|
||||||
|
context?: SharedContext
|
||||||
|
): Promise<void>
|
||||||
|
|
||||||
deleteInventoryItem(inventoryItemId: string): Promise<void>
|
deleteInventoryItem(
|
||||||
|
inventoryItemId: string,
|
||||||
|
context?: SharedContext
|
||||||
|
): Promise<void>
|
||||||
|
|
||||||
deleteInventoryItemLevelByLocationId(locationId: string): Promise<void>
|
deleteInventoryItemLevelByLocationId(
|
||||||
|
locationId: string,
|
||||||
|
context?: SharedContext
|
||||||
|
): Promise<void>
|
||||||
|
|
||||||
deleteReservationItemByLocationId(locationId: string): Promise<void>
|
deleteReservationItemByLocationId(
|
||||||
|
locationId: string,
|
||||||
|
context?: SharedContext
|
||||||
|
): Promise<void>
|
||||||
|
|
||||||
deleteInventoryLevel(
|
deleteInventoryLevel(
|
||||||
inventoryLevelId: string,
|
inventoryLevelId: string,
|
||||||
locationId: string
|
locationId: string,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<void>
|
): Promise<void>
|
||||||
|
|
||||||
adjustInventory(
|
adjustInventory(
|
||||||
inventoryItemId: string,
|
inventoryItemId: string,
|
||||||
locationId: string,
|
locationId: string,
|
||||||
adjustment: number
|
adjustment: number,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<InventoryLevelDTO>
|
): Promise<InventoryLevelDTO>
|
||||||
|
|
||||||
confirmInventory(
|
confirmInventory(
|
||||||
inventoryItemId: string,
|
inventoryItemId: string,
|
||||||
locationIds: string[],
|
locationIds: string[],
|
||||||
quantity: number
|
quantity: number,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<boolean>
|
): Promise<boolean>
|
||||||
|
|
||||||
retrieveAvailableQuantity(
|
retrieveAvailableQuantity(
|
||||||
inventoryItemId: string,
|
inventoryItemId: string,
|
||||||
locationIds: string[]
|
locationIds: string[],
|
||||||
|
context?: SharedContext
|
||||||
): Promise<number>
|
): Promise<number>
|
||||||
|
|
||||||
retrieveStockedQuantity(
|
retrieveStockedQuantity(
|
||||||
inventoryItemId: string,
|
inventoryItemId: string,
|
||||||
locationIds: string[]
|
locationIds: string[],
|
||||||
|
context?: SharedContext
|
||||||
): Promise<number>
|
): Promise<number>
|
||||||
|
|
||||||
retrieveReservedQuantity(
|
retrieveReservedQuantity(
|
||||||
inventoryItemId: string,
|
inventoryItemId: string,
|
||||||
locationIds: string[]
|
locationIds: string[],
|
||||||
|
context?: SharedContext
|
||||||
): Promise<number>
|
): Promise<number>
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,3 @@
|
|||||||
import { FindConfig } from "../common/common"
|
|
||||||
import {
|
import {
|
||||||
CreateStockLocationInput,
|
CreateStockLocationInput,
|
||||||
FilterableStockLocationProps,
|
FilterableStockLocationProps,
|
||||||
@@ -6,25 +5,38 @@ import {
|
|||||||
UpdateStockLocationInput,
|
UpdateStockLocationInput,
|
||||||
} from "./common"
|
} from "./common"
|
||||||
|
|
||||||
|
import { FindConfig } from "../common/common"
|
||||||
|
import { SharedContext } from "../shared-context"
|
||||||
|
|
||||||
export interface IStockLocationService {
|
export interface IStockLocationService {
|
||||||
list(
|
list(
|
||||||
selector: FilterableStockLocationProps,
|
selector: FilterableStockLocationProps,
|
||||||
config?: FindConfig<StockLocationDTO>
|
config?: FindConfig<StockLocationDTO>,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<StockLocationDTO[]>
|
): Promise<StockLocationDTO[]>
|
||||||
|
|
||||||
listAndCount(
|
listAndCount(
|
||||||
selector: FilterableStockLocationProps,
|
selector: FilterableStockLocationProps,
|
||||||
config?: FindConfig<StockLocationDTO>
|
config?: FindConfig<StockLocationDTO>,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<[StockLocationDTO[], number]>
|
): Promise<[StockLocationDTO[], number]>
|
||||||
|
|
||||||
retrieve(
|
retrieve(
|
||||||
id: string,
|
id: string,
|
||||||
config?: FindConfig<StockLocationDTO>
|
config?: FindConfig<StockLocationDTO>,
|
||||||
|
context?: SharedContext
|
||||||
): Promise<StockLocationDTO>
|
): Promise<StockLocationDTO>
|
||||||
|
|
||||||
create(input: CreateStockLocationInput): Promise<StockLocationDTO>
|
create(
|
||||||
|
input: CreateStockLocationInput,
|
||||||
|
context?: SharedContext
|
||||||
|
): Promise<StockLocationDTO>
|
||||||
|
|
||||||
update(id: string, input: UpdateStockLocationInput): Promise<StockLocationDTO>
|
update(
|
||||||
|
id: string,
|
||||||
|
input: UpdateStockLocationInput,
|
||||||
|
context?: SharedContext
|
||||||
|
): Promise<StockLocationDTO>
|
||||||
|
|
||||||
delete(id: string): Promise<void>
|
delete(id: string, context?: SharedContext): Promise<void>
|
||||||
}
|
}
|
||||||
Reference in new issue
Block a user