feat(medusa): Modules initializer (#3352)
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
import { DeepPartial, EntityManager, FindManyOptions } from "typeorm"
|
||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
||||
import {
|
||||
buildQuery,
|
||||
CreateInventoryItemInput,
|
||||
@@ -7,9 +5,11 @@ import {
|
||||
FindConfig,
|
||||
IEventBusService,
|
||||
InventoryItemDTO,
|
||||
TransactionBaseService,
|
||||
} from "@medusajs/medusa"
|
||||
|
||||
import { SharedContext } from "@medusajs/types"
|
||||
import { InjectEntityManager, MedusaContext } from "@medusajs/utils"
|
||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
||||
import { DeepPartial, EntityManager, FindManyOptions } from "typeorm"
|
||||
import { InventoryItem } from "../models"
|
||||
import { getListQuery } from "../utils/query"
|
||||
|
||||
@@ -18,18 +18,18 @@ type InjectedDependencies = {
|
||||
manager: EntityManager
|
||||
}
|
||||
|
||||
export default class InventoryItemService extends TransactionBaseService {
|
||||
export default class InventoryItemService {
|
||||
static Events = {
|
||||
CREATED: "inventory-item.created",
|
||||
UPDATED: "inventory-item.updated",
|
||||
DELETED: "inventory-item.deleted",
|
||||
}
|
||||
|
||||
protected readonly eventBusService_: IEventBusService
|
||||
|
||||
constructor({ eventBusService }: InjectedDependencies) {
|
||||
super(arguments[0])
|
||||
protected readonly manager_: EntityManager
|
||||
protected readonly eventBusService_: IEventBusService | undefined
|
||||
|
||||
constructor({ eventBusService, manager }: InjectedDependencies) {
|
||||
this.manager_ = manager
|
||||
this.eventBusService_ = eventBusService
|
||||
}
|
||||
|
||||
@@ -38,11 +38,17 @@ export default class InventoryItemService extends TransactionBaseService {
|
||||
* @param config - Configuration for query.
|
||||
* @return Resolves to the list of inventory items that match the filter.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async list(
|
||||
selector: FilterableInventoryItemProps = {},
|
||||
config: FindConfig<InventoryItem> = { relations: [], skip: 0, take: 10 }
|
||||
config: FindConfig<InventoryItem> = { relations: [], skip: 0, take: 10 },
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<InventoryItemDTO[]> {
|
||||
const queryBuilder = getListQuery(this.activeManager_, selector, config)
|
||||
const queryBuilder = getListQuery(
|
||||
context.transactionManager!,
|
||||
selector,
|
||||
config
|
||||
)
|
||||
return await queryBuilder.getMany()
|
||||
}
|
||||
|
||||
@@ -51,11 +57,17 @@ export default class InventoryItemService extends TransactionBaseService {
|
||||
* @param config - Configuration for query.
|
||||
* @return - Resolves to the list of inventory items that match the filter and the count of all matching items.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async listAndCount(
|
||||
selector: FilterableInventoryItemProps = {},
|
||||
config: FindConfig<InventoryItem> = { relations: [], skip: 0, take: 10 }
|
||||
config: FindConfig<InventoryItem> = { relations: [], skip: 0, take: 10 },
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<[InventoryItemDTO[], number]> {
|
||||
const queryBuilder = getListQuery(this.activeManager_, selector, config)
|
||||
const queryBuilder = getListQuery(
|
||||
context.transactionManager!,
|
||||
selector,
|
||||
config
|
||||
)
|
||||
return await queryBuilder.getManyAndCount()
|
||||
}
|
||||
|
||||
@@ -66,9 +78,11 @@ export default class InventoryItemService extends TransactionBaseService {
|
||||
* @return The retrieved inventory item.
|
||||
* @throws If the inventory item id is not defined or if the inventory item is not found.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async retrieve(
|
||||
inventoryItemId: string,
|
||||
config: FindConfig<InventoryItem> = {}
|
||||
config: FindConfig<InventoryItem> = {},
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<InventoryItem> {
|
||||
if (!isDefined(inventoryItemId)) {
|
||||
throw new MedusaError(
|
||||
@@ -77,7 +91,7 @@ export default class InventoryItemService extends TransactionBaseService {
|
||||
)
|
||||
}
|
||||
|
||||
const manager = this.activeManager_
|
||||
const manager = context.transactionManager!
|
||||
const itemRepository = manager.getRepository(InventoryItem)
|
||||
|
||||
const query = buildQuery({ id: inventoryItemId }, config) as FindManyOptions
|
||||
@@ -97,34 +111,35 @@ export default class InventoryItemService extends TransactionBaseService {
|
||||
* @param input - Input for creating a new inventory item.
|
||||
* @return The newly created inventory item.
|
||||
*/
|
||||
async create(data: CreateInventoryItemInput): Promise<InventoryItem> {
|
||||
return await this.atomicPhase_(async (manager) => {
|
||||
const itemRepository = manager.getRepository(InventoryItem)
|
||||
@InjectEntityManager()
|
||||
async create(
|
||||
data: CreateInventoryItemInput,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<InventoryItem> {
|
||||
const manager = context.transactionManager!
|
||||
const itemRepository = manager.getRepository(InventoryItem)
|
||||
|
||||
const inventoryItem = itemRepository.create({
|
||||
sku: data.sku,
|
||||
origin_country: data.origin_country,
|
||||
metadata: data.metadata,
|
||||
hs_code: data.hs_code,
|
||||
mid_code: data.mid_code,
|
||||
material: data.material,
|
||||
weight: data.weight,
|
||||
length: data.length,
|
||||
height: data.height,
|
||||
width: data.width,
|
||||
requires_shipping: data.requires_shipping,
|
||||
})
|
||||
|
||||
const result = await itemRepository.save(inventoryItem)
|
||||
|
||||
await this.eventBusService_
|
||||
.withTransaction(manager)
|
||||
.emit(InventoryItemService.Events.CREATED, {
|
||||
id: result.id,
|
||||
})
|
||||
|
||||
return result
|
||||
const inventoryItem = itemRepository.create({
|
||||
sku: data.sku,
|
||||
origin_country: data.origin_country,
|
||||
metadata: data.metadata,
|
||||
hs_code: data.hs_code,
|
||||
mid_code: data.mid_code,
|
||||
material: data.material,
|
||||
weight: data.weight,
|
||||
length: data.length,
|
||||
height: data.height,
|
||||
width: data.width,
|
||||
requires_shipping: data.requires_shipping,
|
||||
})
|
||||
|
||||
const result = await itemRepository.save(inventoryItem)
|
||||
|
||||
await this.eventBusService_?.emit?.(InventoryItemService.Events.CREATED, {
|
||||
id: result.id,
|
||||
})
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -132,51 +147,51 @@ export default class InventoryItemService extends TransactionBaseService {
|
||||
* @param update - The updates to apply to the inventory item.
|
||||
* @return The updated inventory item.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async update(
|
||||
inventoryItemId: string,
|
||||
data: Omit<
|
||||
DeepPartial<InventoryItem>,
|
||||
"id" | "created_at" | "metadata" | "deleted_at"
|
||||
>
|
||||
>,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<InventoryItem> {
|
||||
return await this.atomicPhase_(async (manager) => {
|
||||
const itemRepository = manager.getRepository(InventoryItem)
|
||||
const manager = context.transactionManager!
|
||||
const itemRepository = manager.getRepository(InventoryItem)
|
||||
|
||||
const item = await this.retrieve(inventoryItemId)
|
||||
const item = await this.retrieve(inventoryItemId, undefined, context)
|
||||
|
||||
const shouldUpdate = Object.keys(data).some((key) => {
|
||||
return item[key] !== data[key]
|
||||
})
|
||||
|
||||
if (shouldUpdate) {
|
||||
itemRepository.merge(item, data)
|
||||
await itemRepository.save(item)
|
||||
|
||||
await this.eventBusService_
|
||||
.withTransaction(manager)
|
||||
.emit(InventoryItemService.Events.UPDATED, {
|
||||
id: item.id,
|
||||
})
|
||||
}
|
||||
|
||||
return item
|
||||
const shouldUpdate = Object.keys(data).some((key) => {
|
||||
return item[key] !== data[key]
|
||||
})
|
||||
|
||||
if (shouldUpdate) {
|
||||
itemRepository.merge(item, data)
|
||||
await itemRepository.save(item)
|
||||
|
||||
await this.eventBusService_?.emit?.(InventoryItemService.Events.UPDATED, {
|
||||
id: item.id,
|
||||
})
|
||||
}
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
/**
|
||||
* @param inventoryItemId - The id of the inventory item to delete.
|
||||
*/
|
||||
async delete(inventoryItemId: string): Promise<void> {
|
||||
await this.atomicPhase_(async (manager) => {
|
||||
const itemRepository = manager.getRepository(InventoryItem)
|
||||
@InjectEntityManager()
|
||||
async delete(
|
||||
inventoryItemId: string,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<void> {
|
||||
const manager = context.transactionManager!
|
||||
const itemRepository = manager.getRepository(InventoryItem)
|
||||
|
||||
await itemRepository.softRemove({ id: inventoryItemId })
|
||||
await itemRepository.softRemove({ id: inventoryItemId })
|
||||
|
||||
await this.eventBusService_
|
||||
.withTransaction(manager)
|
||||
.emit(InventoryItemService.Events.DELETED, {
|
||||
id: inventoryItemId,
|
||||
})
|
||||
await this.eventBusService_?.emit?.(InventoryItemService.Events.DELETED, {
|
||||
id: inventoryItemId,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
import { DeepPartial, EntityManager, FindManyOptions, In } from "typeorm"
|
||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
||||
import {
|
||||
buildQuery,
|
||||
CreateInventoryLevelInput,
|
||||
FilterableInventoryLevelProps,
|
||||
FindConfig,
|
||||
IEventBusService,
|
||||
TransactionBaseService,
|
||||
} from "@medusajs/medusa"
|
||||
|
||||
import { SharedContext } from "@medusajs/types"
|
||||
import { InjectEntityManager, MedusaContext } from "@medusajs/utils"
|
||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
||||
import { DeepPartial, EntityManager, FindManyOptions, In } from "typeorm"
|
||||
import { InventoryLevel } from "../models"
|
||||
|
||||
type InjectedDependencies = {
|
||||
@@ -16,18 +16,18 @@ type InjectedDependencies = {
|
||||
manager: EntityManager
|
||||
}
|
||||
|
||||
export default class InventoryLevelService extends TransactionBaseService {
|
||||
export default class InventoryLevelService {
|
||||
static Events = {
|
||||
CREATED: "inventory-level.created",
|
||||
UPDATED: "inventory-level.updated",
|
||||
DELETED: "inventory-level.deleted",
|
||||
}
|
||||
|
||||
protected readonly eventBusService_: IEventBusService
|
||||
|
||||
constructor({ eventBusService }: InjectedDependencies) {
|
||||
super(arguments[0])
|
||||
protected readonly manager_: EntityManager
|
||||
protected readonly eventBusService_: IEventBusService | undefined
|
||||
|
||||
constructor({ eventBusService, manager }: InjectedDependencies) {
|
||||
this.manager_ = manager
|
||||
this.eventBusService_ = eventBusService
|
||||
}
|
||||
|
||||
@@ -37,11 +37,13 @@ export default class InventoryLevelService extends TransactionBaseService {
|
||||
* @param config - An object containing configuration options for the query.
|
||||
* @return Array of inventory levels.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async list(
|
||||
selector: FilterableInventoryLevelProps = {},
|
||||
config: FindConfig<InventoryLevel> = { relations: [], skip: 0, take: 10 }
|
||||
config: FindConfig<InventoryLevel> = { relations: [], skip: 0, take: 10 },
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<InventoryLevel[]> {
|
||||
const manager = this.activeManager_
|
||||
const manager = context.transactionManager!
|
||||
const levelRepository = manager.getRepository(InventoryLevel)
|
||||
|
||||
const query = buildQuery(selector, config) as FindManyOptions
|
||||
@@ -54,11 +56,13 @@ export default class InventoryLevelService extends TransactionBaseService {
|
||||
* @param config - An object containing configuration options for the query.
|
||||
* @return An array of inventory levels and a count.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async listAndCount(
|
||||
selector: FilterableInventoryLevelProps = {},
|
||||
config: FindConfig<InventoryLevel> = { relations: [], skip: 0, take: 10 }
|
||||
config: FindConfig<InventoryLevel> = { relations: [], skip: 0, take: 10 },
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<[InventoryLevel[], number]> {
|
||||
const manager = this.activeManager_
|
||||
const manager = context.transactionManager!
|
||||
const levelRepository = manager.getRepository(InventoryLevel)
|
||||
|
||||
const query = buildQuery(selector, config) as FindManyOptions
|
||||
@@ -72,9 +76,11 @@ export default class InventoryLevelService extends TransactionBaseService {
|
||||
* @return A inventory level.
|
||||
* @throws If the inventory level ID is not defined or the given ID was not found.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async retrieve(
|
||||
inventoryLevelId: string,
|
||||
config: FindConfig<InventoryLevel> = {}
|
||||
config: FindConfig<InventoryLevel> = {},
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<InventoryLevel> {
|
||||
if (!isDefined(inventoryLevelId)) {
|
||||
throw new MedusaError(
|
||||
@@ -83,10 +89,13 @@ export default class InventoryLevelService extends TransactionBaseService {
|
||||
)
|
||||
}
|
||||
|
||||
const manager = this.activeManager_
|
||||
const manager = context.transactionManager!
|
||||
const levelRepository = manager.getRepository(InventoryLevel)
|
||||
|
||||
const query = buildQuery({ id: inventoryLevelId }, config) as FindManyOptions
|
||||
const query = buildQuery(
|
||||
{ id: inventoryLevelId },
|
||||
config
|
||||
) as FindManyOptions
|
||||
const [inventoryLevel] = await levelRepository.find(query)
|
||||
|
||||
if (!inventoryLevel) {
|
||||
@@ -104,27 +113,29 @@ export default class InventoryLevelService extends TransactionBaseService {
|
||||
* @param data - An object containing the properties for the new inventory level.
|
||||
* @return The created inventory level.
|
||||
*/
|
||||
async create(data: CreateInventoryLevelInput): Promise<InventoryLevel> {
|
||||
return await this.atomicPhase_(async (manager) => {
|
||||
const levelRepository = manager.getRepository(InventoryLevel)
|
||||
@InjectEntityManager()
|
||||
async create(
|
||||
data: CreateInventoryLevelInput,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<InventoryLevel> {
|
||||
const manager = context.transactionManager!
|
||||
|
||||
const inventoryLevel = levelRepository.create({
|
||||
location_id: data.location_id,
|
||||
inventory_item_id: data.inventory_item_id,
|
||||
stocked_quantity: data.stocked_quantity,
|
||||
reserved_quantity: data.reserved_quantity,
|
||||
incoming_quantity: data.incoming_quantity,
|
||||
})
|
||||
const levelRepository = manager.getRepository(InventoryLevel)
|
||||
|
||||
const saved = await levelRepository.save(inventoryLevel)
|
||||
await this.eventBusService_
|
||||
.withTransaction(manager)
|
||||
.emit(InventoryLevelService.Events.CREATED, {
|
||||
id: saved.id,
|
||||
})
|
||||
|
||||
return saved
|
||||
const inventoryLevel = levelRepository.create({
|
||||
location_id: data.location_id,
|
||||
inventory_item_id: data.inventory_item_id,
|
||||
stocked_quantity: data.stocked_quantity,
|
||||
reserved_quantity: data.reserved_quantity,
|
||||
incoming_quantity: data.incoming_quantity,
|
||||
})
|
||||
|
||||
const saved = await levelRepository.save(inventoryLevel)
|
||||
await this.eventBusService_?.emit?.(InventoryLevelService.Events.CREATED, {
|
||||
id: saved.id,
|
||||
})
|
||||
|
||||
return saved
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -134,35 +145,37 @@ export default class InventoryLevelService extends TransactionBaseService {
|
||||
* @return The updated inventory level.
|
||||
* @throws If the inventory level ID is not defined or the given ID was not found.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async update(
|
||||
inventoryLevelId: string,
|
||||
data: Omit<
|
||||
DeepPartial<InventoryLevel>,
|
||||
"id" | "created_at" | "metadata" | "deleted_at"
|
||||
>
|
||||
>,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<InventoryLevel> {
|
||||
return await this.atomicPhase_(async (manager) => {
|
||||
const levelRepository = manager.getRepository(InventoryLevel)
|
||||
const manager = context.transactionManager!
|
||||
const levelRepository = manager.getRepository(InventoryLevel)
|
||||
|
||||
const item = await this.retrieve(inventoryLevelId)
|
||||
const item = await this.retrieve(inventoryLevelId, undefined, context)
|
||||
|
||||
const shouldUpdate = Object.keys(data).some((key) => {
|
||||
return item[key] !== data[key]
|
||||
})
|
||||
|
||||
if (shouldUpdate) {
|
||||
levelRepository.merge(item, data)
|
||||
await levelRepository.save(item)
|
||||
|
||||
await this.eventBusService_
|
||||
.withTransaction(manager)
|
||||
.emit(InventoryLevelService.Events.UPDATED, {
|
||||
id: item.id,
|
||||
})
|
||||
}
|
||||
|
||||
return item
|
||||
const shouldUpdate = Object.keys(data).some((key) => {
|
||||
return item[key] !== data[key]
|
||||
})
|
||||
|
||||
if (shouldUpdate) {
|
||||
levelRepository.merge(item, data)
|
||||
await levelRepository.save(item)
|
||||
|
||||
await this.eventBusService_?.emit?.(
|
||||
InventoryLevelService.Events.UPDATED,
|
||||
{
|
||||
id: item.id,
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -171,40 +184,45 @@ export default class InventoryLevelService extends TransactionBaseService {
|
||||
* @param locationId - The ID of the location.
|
||||
* @param quantity - The quantity to adjust from the reserved quantity.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async adjustReservedQuantity(
|
||||
inventoryItemId: string,
|
||||
locationId: string,
|
||||
quantity: number
|
||||
quantity: number,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<void> {
|
||||
await this.atomicPhase_(async (manager) => {
|
||||
await manager
|
||||
.createQueryBuilder()
|
||||
.update(InventoryLevel)
|
||||
.set({ reserved_quantity: () => `reserved_quantity + ${quantity}` })
|
||||
.where(
|
||||
"inventory_item_id = :inventoryItemId AND location_id = :locationId",
|
||||
{ inventoryItemId, locationId }
|
||||
)
|
||||
.execute()
|
||||
})
|
||||
const manager = context.transactionManager!
|
||||
await manager
|
||||
.createQueryBuilder()
|
||||
.update(InventoryLevel)
|
||||
.set({ reserved_quantity: () => `reserved_quantity + ${quantity}` })
|
||||
.where(
|
||||
"inventory_item_id = :inventoryItemId AND location_id = :locationId",
|
||||
{ inventoryItemId, locationId }
|
||||
)
|
||||
.execute()
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes inventory levels by inventory Item ID.
|
||||
* @param inventoryItemId - The ID or IDs of the inventory item to delete inventory levels for.
|
||||
*/
|
||||
async deleteByInventoryItemId(inventoryItemId: string | string[]): Promise<void> {
|
||||
const ids = Array.isArray(inventoryItemId) ? inventoryItemId : [inventoryItemId]
|
||||
await this.atomicPhase_(async (manager) => {
|
||||
const levelRepository = manager.getRepository(InventoryLevel)
|
||||
* Deletes inventory levels by inventory Item ID.
|
||||
* @param inventoryItemId - The ID or IDs of the inventory item to delete inventory levels for.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async deleteByInventoryItemId(
|
||||
inventoryItemId: string | string[],
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<void> {
|
||||
const ids = Array.isArray(inventoryItemId)
|
||||
? inventoryItemId
|
||||
: [inventoryItemId]
|
||||
|
||||
await levelRepository.delete({ inventory_item_id: In(ids) })
|
||||
const manager = context.transactionManager!
|
||||
const levelRepository = manager.getRepository(InventoryLevel)
|
||||
|
||||
await this.eventBusService_
|
||||
.withTransaction(manager)
|
||||
.emit(InventoryLevelService.Events.DELETED, {
|
||||
inventory_item_id: inventoryItemId,
|
||||
})
|
||||
await levelRepository.delete({ inventory_item_id: In(ids) })
|
||||
|
||||
await this.eventBusService_?.emit?.(InventoryLevelService.Events.DELETED, {
|
||||
inventory_item_id: inventoryItemId,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -212,18 +230,22 @@ export default class InventoryLevelService extends TransactionBaseService {
|
||||
* Deletes an inventory level by ID.
|
||||
* @param inventoryLevelId - The ID or IDs of the inventory level to delete.
|
||||
*/
|
||||
async delete(inventoryLevelId: string | string[]): Promise<void> {
|
||||
const ids = Array.isArray(inventoryLevelId) ? inventoryLevelId : [inventoryLevelId]
|
||||
await this.atomicPhase_(async (manager) => {
|
||||
const levelRepository = manager.getRepository(InventoryLevel)
|
||||
@InjectEntityManager()
|
||||
async delete(
|
||||
inventoryLevelId: string | string[],
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<void> {
|
||||
const ids = Array.isArray(inventoryLevelId)
|
||||
? inventoryLevelId
|
||||
: [inventoryLevelId]
|
||||
|
||||
await levelRepository.delete({ id: In(ids) })
|
||||
const manager = context.transactionManager!
|
||||
const levelRepository = manager.getRepository(InventoryLevel)
|
||||
|
||||
await this.eventBusService_
|
||||
.withTransaction(manager)
|
||||
.emit(InventoryLevelService.Events.DELETED, {
|
||||
id: inventoryLevelId,
|
||||
})
|
||||
await levelRepository.delete({ id: In(ids) })
|
||||
|
||||
await this.eventBusService_?.emit?.(InventoryLevelService.Events.DELETED, {
|
||||
id: inventoryLevelId,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -231,17 +253,18 @@ export default class InventoryLevelService extends TransactionBaseService {
|
||||
* Deletes inventory levels by location ID.
|
||||
* @param locationId - The ID of the location to delete inventory levels for.
|
||||
*/
|
||||
async deleteByLocationId(locationId: string): Promise<void> {
|
||||
return await this.atomicPhase_(async (manager) => {
|
||||
const levelRepository = manager.getRepository(InventoryLevel)
|
||||
@InjectEntityManager()
|
||||
async deleteByLocationId(
|
||||
locationId: string,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<void> {
|
||||
const manager = context.transactionManager!
|
||||
const levelRepository = manager.getRepository(InventoryLevel)
|
||||
|
||||
await levelRepository.delete({ location_id: locationId })
|
||||
await levelRepository.delete({ location_id: locationId })
|
||||
|
||||
await this.eventBusService_
|
||||
.withTransaction(manager)
|
||||
.emit(InventoryLevelService.Events.DELETED, {
|
||||
location_id: locationId,
|
||||
})
|
||||
await this.eventBusService_?.emit?.(InventoryLevelService.Events.DELETED, {
|
||||
location_id: locationId,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -251,15 +274,17 @@ export default class InventoryLevelService extends TransactionBaseService {
|
||||
* @param locationIds - The IDs of the locations.
|
||||
* @return The total stocked quantity.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async getStockedQuantity(
|
||||
inventoryItemId: string,
|
||||
locationIds: string[] | string
|
||||
locationIds: string[] | string,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<number> {
|
||||
if (!Array.isArray(locationIds)) {
|
||||
locationIds = [locationIds]
|
||||
}
|
||||
|
||||
const manager = this.activeManager_
|
||||
const manager = context.transactionManager!
|
||||
const levelRepository = manager.getRepository(InventoryLevel)
|
||||
|
||||
const result = await levelRepository
|
||||
@@ -278,15 +303,17 @@ export default class InventoryLevelService extends TransactionBaseService {
|
||||
* @param locationIds - The IDs of the locations.
|
||||
* @return The total available quantity.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async getAvailableQuantity(
|
||||
inventoryItemId: string,
|
||||
locationIds: string[] | string
|
||||
locationIds: string[] | string,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<number> {
|
||||
if (!Array.isArray(locationIds)) {
|
||||
locationIds = [locationIds]
|
||||
}
|
||||
|
||||
const manager = this.activeManager_
|
||||
const manager = context.transactionManager!
|
||||
const levelRepository = manager.getRepository(InventoryLevel)
|
||||
|
||||
const result = await levelRepository
|
||||
@@ -305,15 +332,17 @@ export default class InventoryLevelService extends TransactionBaseService {
|
||||
* @param locationIds - The IDs of the locations.
|
||||
* @return The total reserved quantity.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async getReservedQuantity(
|
||||
inventoryItemId: string,
|
||||
locationIds: string[] | string
|
||||
locationIds: string[] | string,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<number> {
|
||||
if (!Array.isArray(locationIds)) {
|
||||
locationIds = [locationIds]
|
||||
}
|
||||
|
||||
const manager = this.activeManager_
|
||||
const manager = context.transactionManager!
|
||||
const levelRepository = manager.getRepository(InventoryLevel)
|
||||
|
||||
const result = await levelRepository
|
||||
|
||||
@@ -13,18 +13,18 @@ import {
|
||||
InventoryItemDTO,
|
||||
InventoryLevelDTO,
|
||||
ReservationItemDTO,
|
||||
TransactionBaseService,
|
||||
UpdateInventoryLevelInput,
|
||||
UpdateReservationItemInput,
|
||||
} from "@medusajs/medusa"
|
||||
import { SharedContext } from "@medusajs/types"
|
||||
import { InjectEntityManager, MedusaContext } from "@medusajs/utils"
|
||||
import { MedusaError } from "medusa-core-utils"
|
||||
|
||||
import { EntityManager } from "typeorm"
|
||||
import {
|
||||
InventoryItemService,
|
||||
InventoryLevelService,
|
||||
ReservationItemService,
|
||||
} from "./"
|
||||
import { EntityManager } from "typeorm"
|
||||
|
||||
type InjectedDependencies = {
|
||||
manager: EntityManager
|
||||
@@ -33,11 +33,9 @@ type InjectedDependencies = {
|
||||
inventoryLevelService: InventoryLevelService
|
||||
reservationItemService: ReservationItemService
|
||||
}
|
||||
export default class InventoryService
|
||||
extends TransactionBaseService
|
||||
implements IInventoryService
|
||||
{
|
||||
protected readonly eventBusService_: IEventBusService
|
||||
export default class InventoryService implements IInventoryService {
|
||||
protected readonly manager_: EntityManager
|
||||
protected readonly eventBusService_: IEventBusService | undefined
|
||||
protected readonly inventoryItemService_: InventoryItemService
|
||||
protected readonly reservationItemService_: ReservationItemService
|
||||
protected readonly inventoryLevelService_: InventoryLevelService
|
||||
@@ -53,9 +51,7 @@ export default class InventoryService
|
||||
options?: unknown,
|
||||
moduleDeclaration?: InternalModuleDeclaration
|
||||
) {
|
||||
// @ts-ignore
|
||||
super(...arguments)
|
||||
|
||||
this.manager_ = manager
|
||||
this.eventBusService_ = eventBusService
|
||||
this.inventoryItemService_ = inventoryItemService
|
||||
this.inventoryLevelService_ = inventoryLevelService
|
||||
@@ -68,13 +64,17 @@ export default class InventoryService
|
||||
* @param config - the find configuration to use
|
||||
* @return A tuple of inventory items and their total count
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async listInventoryItems(
|
||||
selector: FilterableInventoryItemProps,
|
||||
config: FindConfig<InventoryItemDTO> = { relations: [], skip: 0, take: 10 }
|
||||
config: FindConfig<InventoryItemDTO> = { relations: [], skip: 0, take: 10 },
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<[InventoryItemDTO[], number]> {
|
||||
return await this.inventoryItemService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.listAndCount(selector, config)
|
||||
return await this.inventoryItemService_.listAndCount(
|
||||
selector,
|
||||
config,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -83,13 +83,21 @@ export default class InventoryService
|
||||
* @param config - the find configuration to use
|
||||
* @return A tuple of inventory levels and their total count
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async listInventoryLevels(
|
||||
selector: FilterableInventoryLevelProps,
|
||||
config: FindConfig<InventoryLevelDTO> = { relations: [], skip: 0, take: 10 }
|
||||
config: FindConfig<InventoryLevelDTO> = {
|
||||
relations: [],
|
||||
skip: 0,
|
||||
take: 10,
|
||||
},
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<[InventoryLevelDTO[], number]> {
|
||||
return await this.inventoryLevelService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.listAndCount(selector, config)
|
||||
return await this.inventoryLevelService_.listAndCount(
|
||||
selector,
|
||||
config,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,17 +106,21 @@ export default class InventoryService
|
||||
* @param config - the find configuration to use
|
||||
* @return A tuple of reservation items and their total count
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async listReservationItems(
|
||||
selector: FilterableReservationItemProps,
|
||||
config: FindConfig<ReservationItemDTO> = {
|
||||
relations: [],
|
||||
skip: 0,
|
||||
take: 10,
|
||||
}
|
||||
},
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<[ReservationItemDTO[], number]> {
|
||||
return await this.reservationItemService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.listAndCount(selector, config)
|
||||
return await this.reservationItemService_.listAndCount(
|
||||
selector,
|
||||
config,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,13 +129,17 @@ export default class InventoryService
|
||||
* @param config - the find configuration to use
|
||||
* @return The retrieved inventory item
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async retrieveInventoryItem(
|
||||
inventoryItemId: string,
|
||||
config?: FindConfig<InventoryItemDTO>
|
||||
config?: FindConfig<InventoryItemDTO>,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<InventoryItemDTO> {
|
||||
const inventoryItem = await this.inventoryItemService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.retrieve(inventoryItemId, config)
|
||||
const inventoryItem = await this.inventoryItemService_.retrieve(
|
||||
inventoryItemId,
|
||||
config,
|
||||
context
|
||||
)
|
||||
return { ...inventoryItem }
|
||||
}
|
||||
|
||||
@@ -133,16 +149,17 @@ export default class InventoryService
|
||||
* @param locationId - the id of the location
|
||||
* @return the retrieved inventory level
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async retrieveInventoryLevel(
|
||||
inventoryItemId: string,
|
||||
locationId: string
|
||||
locationId: string,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<InventoryLevelDTO> {
|
||||
const [inventoryLevel] = await this.inventoryLevelService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.list(
|
||||
{ inventory_item_id: inventoryItemId, location_id: locationId },
|
||||
{ take: 1 }
|
||||
)
|
||||
const [inventoryLevel] = await this.inventoryLevelService_.list(
|
||||
{ inventory_item_id: inventoryItemId, location_id: locationId },
|
||||
{ take: 1 },
|
||||
context
|
||||
)
|
||||
if (!inventoryLevel) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
@@ -152,15 +169,21 @@ export default class InventoryService
|
||||
return inventoryLevel
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Retrieves a reservation item
|
||||
* @param inventoryItemId - the id of the reservation item
|
||||
* @return the retrieved reservation level
|
||||
*/
|
||||
async retrieveReservationItem(reservationId: string): Promise<ReservationItemDTO> {
|
||||
return await this.reservationItemService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.retrieve(reservationId)
|
||||
@InjectEntityManager()
|
||||
async retrieveReservationItem(
|
||||
reservationId: string,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<ReservationItemDTO> {
|
||||
return await this.reservationItemService_.retrieve(
|
||||
reservationId,
|
||||
undefined,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,19 +191,20 @@ export default class InventoryService
|
||||
* @param input - the input object
|
||||
* @return The created reservation item
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async createReservationItem(
|
||||
input: CreateReservationItemInput
|
||||
input: CreateReservationItemInput,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<ReservationItemDTO> {
|
||||
// Verify that the item is stocked at the location
|
||||
const [inventoryLevel] = await this.inventoryLevelService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.list(
|
||||
{
|
||||
inventory_item_id: input.inventory_item_id,
|
||||
location_id: input.location_id,
|
||||
},
|
||||
{ take: 1 }
|
||||
)
|
||||
const [inventoryLevel] = await this.inventoryLevelService_.list(
|
||||
{
|
||||
inventory_item_id: input.inventory_item_id,
|
||||
location_id: input.location_id,
|
||||
},
|
||||
{ take: 1 },
|
||||
context
|
||||
)
|
||||
|
||||
if (!inventoryLevel) {
|
||||
throw new MedusaError(
|
||||
@@ -189,9 +213,10 @@ export default class InventoryService
|
||||
)
|
||||
}
|
||||
|
||||
const reservationItem = await this.reservationItemService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.create(input)
|
||||
const reservationItem = await this.reservationItemService_.create(
|
||||
input,
|
||||
context
|
||||
)
|
||||
|
||||
return { ...reservationItem }
|
||||
}
|
||||
@@ -201,12 +226,15 @@ export default class InventoryService
|
||||
* @param input - the input object
|
||||
* @return The created inventory item
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async createInventoryItem(
|
||||
input: CreateInventoryItemInput
|
||||
input: CreateInventoryItemInput,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<InventoryItemDTO> {
|
||||
const inventoryItem = await this.inventoryItemService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.create(input)
|
||||
const inventoryItem = await this.inventoryItemService_.create(
|
||||
input,
|
||||
context
|
||||
)
|
||||
return { ...inventoryItem }
|
||||
}
|
||||
|
||||
@@ -215,12 +243,12 @@ export default class InventoryService
|
||||
* @param input - the input object
|
||||
* @return The created inventory level
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async createInventoryLevel(
|
||||
input: CreateInventoryLevelInput
|
||||
input: CreateInventoryLevelInput,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<InventoryLevelDTO> {
|
||||
return await this.inventoryLevelService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.create(input)
|
||||
return await this.inventoryLevelService_.create(input, context)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,13 +257,17 @@ export default class InventoryService
|
||||
* @param input - the input object
|
||||
* @return The updated inventory item
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async updateInventoryItem(
|
||||
inventoryItemId: string,
|
||||
input: Partial<CreateInventoryItemInput>
|
||||
input: Partial<CreateInventoryItemInput>,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<InventoryItemDTO> {
|
||||
const inventoryItem = await this.inventoryItemService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.update(inventoryItemId, input)
|
||||
const inventoryItem = await this.inventoryItemService_.update(
|
||||
inventoryItemId,
|
||||
input,
|
||||
context
|
||||
)
|
||||
return { ...inventoryItem }
|
||||
}
|
||||
|
||||
@@ -243,26 +275,39 @@ export default class InventoryService
|
||||
* Deletes an inventory item
|
||||
* @param inventoryItemId - the id of the inventory item to delete
|
||||
*/
|
||||
async deleteInventoryItem(inventoryItemId: string): Promise<void> {
|
||||
await this.inventoryLevelService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.deleteByInventoryItemId(inventoryItemId)
|
||||
@InjectEntityManager()
|
||||
async deleteInventoryItem(
|
||||
inventoryItemId: string,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<void> {
|
||||
await this.inventoryLevelService_.deleteByInventoryItemId(
|
||||
inventoryItemId,
|
||||
context
|
||||
)
|
||||
|
||||
return await this.inventoryItemService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.delete(inventoryItemId)
|
||||
return await this.inventoryItemService_.delete(inventoryItemId, context)
|
||||
}
|
||||
|
||||
async deleteInventoryItemLevelByLocationId(locationId: string): Promise<void> {
|
||||
return await this.inventoryLevelService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.deleteByLocationId(locationId)
|
||||
@InjectEntityManager()
|
||||
async deleteInventoryItemLevelByLocationId(
|
||||
locationId: string,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<void> {
|
||||
return await this.inventoryLevelService_.deleteByLocationId(
|
||||
locationId,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
async deleteReservationItemByLocationId(locationId: string): Promise<void> {
|
||||
return await this.reservationItemService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.deleteByLocationId(locationId)
|
||||
@InjectEntityManager()
|
||||
async deleteReservationItemByLocationId(
|
||||
locationId: string,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<void> {
|
||||
return await this.reservationItemService_.deleteByLocationId(
|
||||
locationId,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -270,24 +315,23 @@ export default class InventoryService
|
||||
* @param inventoryItemId - the id of the inventory item associated with the level
|
||||
* @param locationId - the id of the location associated with the level
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async deleteInventoryLevel(
|
||||
inventoryItemId: string,
|
||||
locationId: string
|
||||
locationId: string,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<void> {
|
||||
const [inventoryLevel] = await this.inventoryLevelService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.list(
|
||||
{ inventory_item_id: inventoryItemId, location_id: locationId },
|
||||
{ take: 1 }
|
||||
)
|
||||
const [inventoryLevel] = await this.inventoryLevelService_.list(
|
||||
{ inventory_item_id: inventoryItemId, location_id: locationId },
|
||||
{ take: 1 },
|
||||
context
|
||||
)
|
||||
|
||||
if (!inventoryLevel) {
|
||||
return
|
||||
}
|
||||
|
||||
return await this.inventoryLevelService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.delete(inventoryLevel.id)
|
||||
return await this.inventoryLevelService_.delete(inventoryLevel.id, context)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -297,17 +341,18 @@ export default class InventoryService
|
||||
* @param input - the input object
|
||||
* @return The updated inventory level
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async updateInventoryLevel(
|
||||
inventoryItemId: string,
|
||||
locationId: string,
|
||||
input: UpdateInventoryLevelInput
|
||||
input: UpdateInventoryLevelInput,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<InventoryLevelDTO> {
|
||||
const [inventoryLevel] = await this.inventoryLevelService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.list(
|
||||
{ inventory_item_id: inventoryItemId, location_id: locationId },
|
||||
{ take: 1 }
|
||||
)
|
||||
const [inventoryLevel] = await this.inventoryLevelService_.list(
|
||||
{ inventory_item_id: inventoryItemId, location_id: locationId },
|
||||
{ take: 1 },
|
||||
context
|
||||
)
|
||||
|
||||
if (!inventoryLevel) {
|
||||
throw new MedusaError(
|
||||
@@ -316,9 +361,11 @@ export default class InventoryService
|
||||
)
|
||||
}
|
||||
|
||||
return await this.inventoryLevelService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.update(inventoryLevel.id, input)
|
||||
return await this.inventoryLevelService_.update(
|
||||
inventoryLevel.id,
|
||||
input,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -327,33 +374,44 @@ export default class InventoryService
|
||||
* @param input - the input object
|
||||
* @return The updated inventory level
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async updateReservationItem(
|
||||
reservationItemId: string,
|
||||
input: UpdateReservationItemInput
|
||||
input: UpdateReservationItemInput,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<ReservationItemDTO> {
|
||||
return await this.reservationItemService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.update(reservationItemId, input)
|
||||
return await this.reservationItemService_.update(
|
||||
reservationItemId,
|
||||
input,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes reservation items by line item
|
||||
* @param lineItemId - the id of the line item associated with the reservation item
|
||||
*/
|
||||
async deleteReservationItemsByLineItem(lineItemId: string): Promise<void> {
|
||||
return await this.reservationItemService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.deleteByLineItem(lineItemId)
|
||||
@InjectEntityManager()
|
||||
async deleteReservationItemsByLineItem(
|
||||
lineItemId: string,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<void> {
|
||||
return await this.reservationItemService_.deleteByLineItem(
|
||||
lineItemId,
|
||||
context
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a reservation item
|
||||
* @param reservationItemId - the id of the reservation item to delete
|
||||
*/
|
||||
async deleteReservationItem(reservationItemId: string | string[]): Promise<void> {
|
||||
return await this.reservationItemService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.delete(reservationItemId)
|
||||
@InjectEntityManager()
|
||||
async deleteReservationItem(
|
||||
reservationItemId: string | string[],
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<void> {
|
||||
return await this.reservationItemService_.delete(reservationItemId, context)
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -364,17 +422,18 @@ export default class InventoryService
|
||||
* @return The updated inventory level
|
||||
* @throws when the inventory level is not found
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async adjustInventory(
|
||||
inventoryItemId: string,
|
||||
locationId: string,
|
||||
adjustment: number
|
||||
adjustment: number,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<InventoryLevelDTO> {
|
||||
const [inventoryLevel] = await this.inventoryLevelService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.list(
|
||||
{ inventory_item_id: inventoryItemId, location_id: locationId },
|
||||
{ take: 1 }
|
||||
)
|
||||
const [inventoryLevel] = await this.inventoryLevelService_.list(
|
||||
{ inventory_item_id: inventoryItemId, location_id: locationId },
|
||||
{ take: 1 },
|
||||
context
|
||||
)
|
||||
if (!inventoryLevel) {
|
||||
throw new MedusaError(
|
||||
MedusaError.Types.NOT_FOUND,
|
||||
@@ -382,11 +441,13 @@ export default class InventoryService
|
||||
)
|
||||
}
|
||||
|
||||
const updatedInventoryLevel = await this.inventoryLevelService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.update(inventoryLevel.id, {
|
||||
const updatedInventoryLevel = await this.inventoryLevelService_.update(
|
||||
inventoryLevel.id,
|
||||
{
|
||||
stocked_quantity: inventoryLevel.stocked_quantity + adjustment,
|
||||
})
|
||||
},
|
||||
context
|
||||
)
|
||||
|
||||
return { ...updatedInventoryLevel }
|
||||
}
|
||||
@@ -398,20 +459,27 @@ export default class InventoryService
|
||||
* @return The available quantity
|
||||
* @throws when the inventory item is not found
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async retrieveAvailableQuantity(
|
||||
inventoryItemId: string,
|
||||
locationIds: string[]
|
||||
locationIds: string[],
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<number> {
|
||||
// Throws if item does not exist
|
||||
await this.inventoryItemService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.retrieve(inventoryItemId, {
|
||||
await this.inventoryItemService_.retrieve(
|
||||
inventoryItemId,
|
||||
{
|
||||
select: ["id"],
|
||||
})
|
||||
},
|
||||
context
|
||||
)
|
||||
|
||||
const availableQuantity = await this.inventoryLevelService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.getAvailableQuantity(inventoryItemId, locationIds)
|
||||
const availableQuantity =
|
||||
await this.inventoryLevelService_.getAvailableQuantity(
|
||||
inventoryItemId,
|
||||
locationIds,
|
||||
context
|
||||
)
|
||||
|
||||
return availableQuantity
|
||||
}
|
||||
@@ -423,20 +491,27 @@ export default class InventoryService
|
||||
* @return The stocked quantity
|
||||
* @throws when the inventory item is not found
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async retrieveStockedQuantity(
|
||||
inventoryItemId: string,
|
||||
locationIds: string[]
|
||||
locationIds: string[],
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<number> {
|
||||
// Throws if item does not exist
|
||||
await this.inventoryItemService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.retrieve(inventoryItemId, {
|
||||
await this.inventoryItemService_.retrieve(
|
||||
inventoryItemId,
|
||||
{
|
||||
select: ["id"],
|
||||
})
|
||||
},
|
||||
context
|
||||
)
|
||||
|
||||
const stockedQuantity = await this.inventoryLevelService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.getStockedQuantity(inventoryItemId, locationIds)
|
||||
const stockedQuantity =
|
||||
await this.inventoryLevelService_.getStockedQuantity(
|
||||
inventoryItemId,
|
||||
locationIds,
|
||||
context
|
||||
)
|
||||
|
||||
return stockedQuantity
|
||||
}
|
||||
@@ -448,20 +523,27 @@ export default class InventoryService
|
||||
* @return The reserved quantity
|
||||
* @throws when the inventory item is not found
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async retrieveReservedQuantity(
|
||||
inventoryItemId: string,
|
||||
locationIds: string[]
|
||||
locationIds: string[],
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<number> {
|
||||
// Throws if item does not exist
|
||||
await this.inventoryItemService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.retrieve(inventoryItemId, {
|
||||
await this.inventoryItemService_.retrieve(
|
||||
inventoryItemId,
|
||||
{
|
||||
select: ["id"],
|
||||
})
|
||||
},
|
||||
context
|
||||
)
|
||||
|
||||
const reservedQuantity = await this.inventoryLevelService_
|
||||
.withTransaction(this.activeManager_)
|
||||
.getReservedQuantity(inventoryItemId, locationIds)
|
||||
const reservedQuantity =
|
||||
await this.inventoryLevelService_.getReservedQuantity(
|
||||
inventoryItemId,
|
||||
locationIds,
|
||||
context
|
||||
)
|
||||
|
||||
return reservedQuantity
|
||||
}
|
||||
@@ -473,14 +555,17 @@ export default class InventoryService
|
||||
* @param quantity - the quantity to check
|
||||
* @return Whether there is sufficient inventory
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async confirmInventory(
|
||||
inventoryItemId: string,
|
||||
locationIds: string[],
|
||||
quantity: number
|
||||
quantity: number,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<boolean> {
|
||||
const availableQuantity = await this.retrieveAvailableQuantity(
|
||||
inventoryItemId,
|
||||
locationIds
|
||||
locationIds,
|
||||
context
|
||||
)
|
||||
return availableQuantity >= quantity
|
||||
}
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
import { EntityManager, FindManyOptions } from "typeorm"
|
||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
||||
import {
|
||||
buildQuery,
|
||||
CreateReservationItemInput,
|
||||
FilterableReservationItemProps,
|
||||
FindConfig,
|
||||
IEventBusService,
|
||||
TransactionBaseService,
|
||||
UpdateReservationItemInput,
|
||||
} from "@medusajs/medusa"
|
||||
|
||||
import { ReservationItem } from "../models"
|
||||
import { SharedContext } from "@medusajs/types"
|
||||
import { InjectEntityManager, MedusaContext } from "@medusajs/utils"
|
||||
import { isDefined, MedusaError } from "medusa-core-utils"
|
||||
import { EntityManager, FindManyOptions } from "typeorm"
|
||||
import { InventoryLevelService } from "."
|
||||
import { ReservationItem } from "../models"
|
||||
|
||||
type InjectedDependencies = {
|
||||
eventBusService: IEventBusService
|
||||
@@ -19,22 +19,23 @@ type InjectedDependencies = {
|
||||
inventoryLevelService: InventoryLevelService
|
||||
}
|
||||
|
||||
export default class ReservationItemService extends TransactionBaseService {
|
||||
export default class ReservationItemService {
|
||||
static Events = {
|
||||
CREATED: "reservation-item.created",
|
||||
UPDATED: "reservation-item.updated",
|
||||
DELETED: "reservation-item.deleted",
|
||||
}
|
||||
|
||||
protected readonly eventBusService_: IEventBusService
|
||||
protected readonly manager_: EntityManager
|
||||
protected readonly eventBusService_: IEventBusService | undefined
|
||||
protected readonly inventoryLevelService_: InventoryLevelService
|
||||
|
||||
constructor({
|
||||
eventBusService,
|
||||
inventoryLevelService,
|
||||
manager,
|
||||
}: InjectedDependencies) {
|
||||
super(arguments[0])
|
||||
|
||||
this.manager_ = manager
|
||||
this.eventBusService_ = eventBusService
|
||||
this.inventoryLevelService_ = inventoryLevelService
|
||||
}
|
||||
@@ -45,11 +46,13 @@ export default class ReservationItemService extends TransactionBaseService {
|
||||
* @param config - Configuration for the query.
|
||||
* @return Array of reservation items that match the selector.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async list(
|
||||
selector: FilterableReservationItemProps = {},
|
||||
config: FindConfig<ReservationItem> = { relations: [], skip: 0, take: 10 }
|
||||
config: FindConfig<ReservationItem> = { relations: [], skip: 0, take: 10 },
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<ReservationItem[]> {
|
||||
const manager = this.activeManager_
|
||||
const manager = context.transactionManager!
|
||||
const itemRepository = manager.getRepository(ReservationItem)
|
||||
|
||||
const query = buildQuery(selector, config) as FindManyOptions
|
||||
@@ -62,11 +65,13 @@ export default class ReservationItemService extends TransactionBaseService {
|
||||
* @param config - Configuration for the query.
|
||||
* @return Array of reservation items that match the selector and the total count.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async listAndCount(
|
||||
selector: FilterableReservationItemProps = {},
|
||||
config: FindConfig<ReservationItem> = { relations: [], skip: 0, take: 10 }
|
||||
config: FindConfig<ReservationItem> = { relations: [], skip: 0, take: 10 },
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<[ReservationItem[], number]> {
|
||||
const manager = this.activeManager_
|
||||
const manager = context.transactionManager!
|
||||
const itemRepository = manager.getRepository(ReservationItem)
|
||||
|
||||
const query = buildQuery(selector, config) as FindManyOptions
|
||||
@@ -80,9 +85,11 @@ export default class ReservationItemService extends TransactionBaseService {
|
||||
* @return The reservation item with the provided id.
|
||||
* @throws If reservationItemId is not defined or if the reservation item was not found.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async retrieve(
|
||||
reservationItemId: string,
|
||||
config: FindConfig<ReservationItem> = {}
|
||||
config: FindConfig<ReservationItem> = {},
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<ReservationItem> {
|
||||
if (!isDefined(reservationItemId)) {
|
||||
throw new MedusaError(
|
||||
@@ -91,7 +98,7 @@ export default class ReservationItemService extends TransactionBaseService {
|
||||
)
|
||||
}
|
||||
|
||||
const manager = this.activeManager_
|
||||
const manager = context.transactionManager!
|
||||
const reservationItemRepository = manager.getRepository(ReservationItem)
|
||||
|
||||
const query = buildQuery(
|
||||
@@ -115,37 +122,37 @@ export default class ReservationItemService extends TransactionBaseService {
|
||||
* @param data - The reservation item data.
|
||||
* @return The created reservation item.
|
||||
*/
|
||||
async create(data: CreateReservationItemInput): Promise<ReservationItem> {
|
||||
return await this.atomicPhase_(async (manager) => {
|
||||
const itemRepository = manager.getRepository(ReservationItem)
|
||||
@InjectEntityManager()
|
||||
async create(
|
||||
data: CreateReservationItemInput,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<ReservationItem> {
|
||||
const manager = context.transactionManager!
|
||||
const itemRepository = manager.getRepository(ReservationItem)
|
||||
|
||||
const inventoryItem = itemRepository.create({
|
||||
inventory_item_id: data.inventory_item_id,
|
||||
line_item_id: data.line_item_id,
|
||||
location_id: data.location_id,
|
||||
quantity: data.quantity,
|
||||
metadata: data.metadata,
|
||||
})
|
||||
|
||||
const [newInventoryItem] = await Promise.all([
|
||||
itemRepository.save(inventoryItem),
|
||||
this.inventoryLevelService_
|
||||
.withTransaction(manager)
|
||||
.adjustReservedQuantity(
|
||||
data.inventory_item_id,
|
||||
data.location_id,
|
||||
data.quantity
|
||||
),
|
||||
])
|
||||
|
||||
await this.eventBusService_
|
||||
.withTransaction(manager)
|
||||
.emit(ReservationItemService.Events.CREATED, {
|
||||
id: newInventoryItem.id,
|
||||
})
|
||||
|
||||
return newInventoryItem
|
||||
const inventoryItem = itemRepository.create({
|
||||
inventory_item_id: data.inventory_item_id,
|
||||
line_item_id: data.line_item_id,
|
||||
location_id: data.location_id,
|
||||
quantity: data.quantity,
|
||||
metadata: data.metadata,
|
||||
})
|
||||
|
||||
const [newInventoryItem] = await Promise.all([
|
||||
itemRepository.save(inventoryItem),
|
||||
this.inventoryLevelService_.adjustReservedQuantity(
|
||||
data.inventory_item_id,
|
||||
data.location_id,
|
||||
data.quantity,
|
||||
context
|
||||
),
|
||||
])
|
||||
|
||||
await this.eventBusService_?.emit?.(ReservationItemService.Events.CREATED, {
|
||||
id: newInventoryItem.id,
|
||||
})
|
||||
|
||||
return newInventoryItem
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -154,99 +161,99 @@ export default class ReservationItemService extends TransactionBaseService {
|
||||
* @param data - The reservation item data to update.
|
||||
* @return The updated reservation item.
|
||||
*/
|
||||
@InjectEntityManager()
|
||||
async update(
|
||||
reservationItemId: string,
|
||||
data: UpdateReservationItemInput
|
||||
data: UpdateReservationItemInput,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<ReservationItem> {
|
||||
return await this.atomicPhase_(async (manager) => {
|
||||
const itemRepository = manager.getRepository(ReservationItem)
|
||||
const manager = context.transactionManager!
|
||||
const itemRepository = manager.getRepository(ReservationItem)
|
||||
|
||||
const item = await this.retrieve(reservationItemId)
|
||||
const item = await this.retrieve(reservationItemId)
|
||||
|
||||
const shouldUpdateQuantity =
|
||||
isDefined(data.quantity) && data.quantity !== item.quantity
|
||||
const shouldUpdateQuantity =
|
||||
isDefined(data.quantity) && data.quantity !== item.quantity
|
||||
|
||||
const shouldUpdateLocation =
|
||||
isDefined(data.location_id) && data.location_id !== item.location_id
|
||||
const shouldUpdateLocation =
|
||||
isDefined(data.location_id) && data.location_id !== item.location_id
|
||||
|
||||
const ops: Promise<unknown>[] = []
|
||||
const ops: Promise<unknown>[] = []
|
||||
|
||||
if (shouldUpdateLocation) {
|
||||
ops.push(
|
||||
this.inventoryLevelService_
|
||||
.withTransaction(manager)
|
||||
.adjustReservedQuantity(
|
||||
item.inventory_item_id,
|
||||
item.location_id,
|
||||
item.quantity * -1
|
||||
),
|
||||
this.inventoryLevelService_
|
||||
.withTransaction(manager)
|
||||
.adjustReservedQuantity(
|
||||
item.inventory_item_id,
|
||||
data.location_id!,
|
||||
data.quantity || item.quantity!
|
||||
)
|
||||
if (shouldUpdateLocation) {
|
||||
ops.push(
|
||||
this.inventoryLevelService_.adjustReservedQuantity(
|
||||
item.inventory_item_id,
|
||||
item.location_id,
|
||||
item.quantity * -1,
|
||||
context
|
||||
),
|
||||
this.inventoryLevelService_.adjustReservedQuantity(
|
||||
item.inventory_item_id,
|
||||
data.location_id!,
|
||||
data.quantity || item.quantity!,
|
||||
context
|
||||
)
|
||||
} else if (shouldUpdateQuantity) {
|
||||
const quantityDiff = data.quantity! - item.quantity
|
||||
ops.push(
|
||||
this.inventoryLevelService_
|
||||
.withTransaction(manager)
|
||||
.adjustReservedQuantity(
|
||||
item.inventory_item_id,
|
||||
item.location_id,
|
||||
quantityDiff
|
||||
)
|
||||
)
|
||||
} else if (shouldUpdateQuantity) {
|
||||
const quantityDiff = data.quantity! - item.quantity
|
||||
ops.push(
|
||||
this.inventoryLevelService_.adjustReservedQuantity(
|
||||
item.inventory_item_id,
|
||||
item.location_id,
|
||||
quantityDiff,
|
||||
context
|
||||
)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
const mergedItem = itemRepository.merge(item, data)
|
||||
const mergedItem = itemRepository.merge(item, data)
|
||||
|
||||
ops.push(itemRepository.save(item))
|
||||
ops.push(itemRepository.save(item))
|
||||
|
||||
await Promise.all(ops)
|
||||
await Promise.all(ops)
|
||||
|
||||
await this.eventBusService_
|
||||
.withTransaction(manager)
|
||||
.emit(ReservationItemService.Events.UPDATED, {
|
||||
id: mergedItem.id,
|
||||
})
|
||||
|
||||
return mergedItem
|
||||
await this.eventBusService_?.emit?.(ReservationItemService.Events.UPDATED, {
|
||||
id: mergedItem.id,
|
||||
})
|
||||
|
||||
return mergedItem
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes a reservation item by line item id.
|
||||
* @param lineItemId - the id of the line item to delete.
|
||||
*/
|
||||
async deleteByLineItem(lineItemId: string): Promise<void> {
|
||||
await this.atomicPhase_(async (manager) => {
|
||||
const itemRepository = manager.getRepository(ReservationItem)
|
||||
@InjectEntityManager()
|
||||
async deleteByLineItem(
|
||||
lineItemId: string,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<void> {
|
||||
const manager = context.transactionManager!
|
||||
const itemRepository = manager.getRepository(ReservationItem)
|
||||
|
||||
const items = await this.list({ line_item_id: lineItemId })
|
||||
const items = await this.list(
|
||||
{ line_item_id: lineItemId },
|
||||
undefined,
|
||||
context
|
||||
)
|
||||
|
||||
const ops: Promise<unknown>[] = []
|
||||
for (const item of items) {
|
||||
ops.push(itemRepository.softRemove({ line_item_id: lineItemId }))
|
||||
ops.push(
|
||||
this.inventoryLevelService_
|
||||
.withTransaction(manager)
|
||||
.adjustReservedQuantity(
|
||||
item.inventory_item_id,
|
||||
item.location_id,
|
||||
item.quantity * -1
|
||||
)
|
||||
const ops: Promise<unknown>[] = []
|
||||
for (const item of items) {
|
||||
ops.push(itemRepository.softRemove({ line_item_id: lineItemId }))
|
||||
ops.push(
|
||||
this.inventoryLevelService_.adjustReservedQuantity(
|
||||
item.inventory_item_id,
|
||||
item.location_id,
|
||||
item.quantity * -1,
|
||||
context
|
||||
)
|
||||
}
|
||||
await Promise.all(ops)
|
||||
)
|
||||
}
|
||||
await Promise.all(ops)
|
||||
|
||||
await this.eventBusService_
|
||||
.withTransaction(manager)
|
||||
.emit(ReservationItemService.Events.DELETED, {
|
||||
line_item_id: lineItemId,
|
||||
})
|
||||
await this.eventBusService_?.emit?.(ReservationItemService.Events.DELETED, {
|
||||
line_item_id: lineItemId,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -254,22 +261,23 @@ export default class ReservationItemService extends TransactionBaseService {
|
||||
* Deletes reservation items by location ID.
|
||||
* @param locationId - The ID of the location to delete reservations for.
|
||||
*/
|
||||
async deleteByLocationId(locationId: string): Promise<void> {
|
||||
return await this.atomicPhase_(async (manager) => {
|
||||
const itemRepository = manager.getRepository(ReservationItem)
|
||||
@InjectEntityManager()
|
||||
async deleteByLocationId(
|
||||
locationId: string,
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<void> {
|
||||
const manager = context.transactionManager!
|
||||
const itemRepository = manager.getRepository(ReservationItem)
|
||||
|
||||
await itemRepository
|
||||
.createQueryBuilder("reservation_item")
|
||||
.softDelete()
|
||||
.where("location_id = :locationId", { locationId })
|
||||
.andWhere("deleted_at IS NULL")
|
||||
.execute()
|
||||
await itemRepository
|
||||
.createQueryBuilder("reservation_item")
|
||||
.softDelete()
|
||||
.where("location_id = :locationId", { locationId })
|
||||
.andWhere("deleted_at IS NULL")
|
||||
.execute()
|
||||
|
||||
await this.eventBusService_
|
||||
.withTransaction(manager)
|
||||
.emit(ReservationItemService.Events.DELETED, {
|
||||
location_id: locationId,
|
||||
})
|
||||
await this.eventBusService_?.emit?.(ReservationItemService.Events.DELETED, {
|
||||
location_id: locationId,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -277,35 +285,32 @@ export default class ReservationItemService extends TransactionBaseService {
|
||||
* Deletes a reservation item by id.
|
||||
* @param reservationItemId - the id of the reservation item to delete.
|
||||
*/
|
||||
async delete(reservationItemId: string | string[]): Promise<void> {
|
||||
async delete(
|
||||
reservationItemId: string | string[],
|
||||
@MedusaContext() context: SharedContext = {}
|
||||
): Promise<void> {
|
||||
const ids = Array.isArray(reservationItemId)
|
||||
? reservationItemId
|
||||
: [reservationItemId]
|
||||
return await this.atomicPhase_(async (manager) => {
|
||||
const itemRepository = manager.getRepository(ReservationItem)
|
||||
const manager = context.transactionManager!
|
||||
const itemRepository = manager.getRepository(ReservationItem)
|
||||
const items = await this.list({ id: ids })
|
||||
|
||||
const items = await this.list({ id: ids })
|
||||
|
||||
await itemRepository.softRemove(items)
|
||||
|
||||
const inventoryServiceTx =
|
||||
this.inventoryLevelService_.withTransaction(manager)
|
||||
|
||||
await Promise.all(
|
||||
items.map(async (item) => {
|
||||
return inventoryServiceTx.adjustReservedQuantity(
|
||||
item.inventory_item_id,
|
||||
item.location_id,
|
||||
item.quantity * -1
|
||||
)
|
||||
})
|
||||
const promises: Promise<unknown>[] = items.map(async (item) => {
|
||||
this.inventoryLevelService_.adjustReservedQuantity(
|
||||
item.inventory_item_id,
|
||||
item.location_id,
|
||||
item.quantity * -1,
|
||||
context
|
||||
)
|
||||
})
|
||||
|
||||
await this.eventBusService_
|
||||
.withTransaction(manager)
|
||||
.emit(ReservationItemService.Events.DELETED, {
|
||||
id: reservationItemId,
|
||||
})
|
||||
promises.push(itemRepository.softRemove(items))
|
||||
|
||||
await Promise.all(promises)
|
||||
|
||||
await this.eventBusService_?.emit?.(ReservationItemService.Events.DELETED, {
|
||||
id: reservationItemId,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user