@@ -1,88 +0,0 @@
|
|||||||
import { BaseService } from "medusa-interfaces"
|
|
||||||
import { MedusaError } from "medusa-core-utils"
|
|
||||||
|
|
||||||
class InventoryService extends BaseService {
|
|
||||||
constructor({ manager, productVariantService }) {
|
|
||||||
super()
|
|
||||||
|
|
||||||
/** @private @const {EntityManager} */
|
|
||||||
this.manager_ = manager
|
|
||||||
|
|
||||||
/** @private @const {ProductVariantRepository_} */
|
|
||||||
this.productVariantService_ = productVariantService
|
|
||||||
}
|
|
||||||
|
|
||||||
withTransaction(transactionManager) {
|
|
||||||
if (!transactionManager) {
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
const cloned = new InventoryService({
|
|
||||||
manager: transactionManager,
|
|
||||||
productVariantService: this.productVariantService_,
|
|
||||||
})
|
|
||||||
|
|
||||||
cloned.transactionManager_ = transactionManager
|
|
||||||
|
|
||||||
return cloned
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Updates the inventory of a variant based on a given adjustment.
|
|
||||||
* @param {string} variantId - the id of the variant to update
|
|
||||||
* @param {number} adjustment - the number to adjust the inventory quantity by
|
|
||||||
* @return {Promise} resolves to the update result.
|
|
||||||
*/
|
|
||||||
async adjustInventory(variantId, adjustment) {
|
|
||||||
// if variantId is undefined – ergo. a custom item – then do nothing
|
|
||||||
if (typeof variantId === "undefined" || variantId === null) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
return this.atomicPhase_(async (manager) => {
|
|
||||||
const variant = await this.productVariantService_.retrieve(variantId)
|
|
||||||
// if inventory is managed then update
|
|
||||||
if (variant.manage_inventory) {
|
|
||||||
return await this.productVariantService_
|
|
||||||
.withTransaction(manager)
|
|
||||||
.update(variant, {
|
|
||||||
inventory_quantity: variant.inventory_quantity + adjustment,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* Checks if the inventory of a variant can cover a given quantity. Will
|
|
||||||
* return true if the variant doesn't have managed inventory or if the variant
|
|
||||||
* allows backorders or if the inventory quantity is greater than `quantity`.
|
|
||||||
* @param {string} variantId - the id of the variant to check
|
|
||||||
* @param {number} quantity - the number of units to check availability for
|
|
||||||
* @return {Promise<boolean>} true if the inventory covers the quantity
|
|
||||||
*/
|
|
||||||
async confirmInventory(variantId, quantity) {
|
|
||||||
// if variantId is undefined then confirm inventory as it
|
|
||||||
// is a custom item that is not managed
|
|
||||||
if (typeof variantId === "undefined" || variantId === null) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
const variant = await this.productVariantService_
|
|
||||||
.withTransaction(this.manager_)
|
|
||||||
.retrieve(variantId)
|
|
||||||
const { inventory_quantity, allow_backorder, manage_inventory } = variant
|
|
||||||
const isCovered =
|
|
||||||
!manage_inventory || allow_backorder || inventory_quantity >= quantity
|
|
||||||
|
|
||||||
if (!isCovered) {
|
|
||||||
throw new MedusaError(
|
|
||||||
MedusaError.Types.NOT_ALLOWED,
|
|
||||||
`Variant with id: ${variant.id} does not have the required inventory`,
|
|
||||||
MedusaError.Codes.INSUFFICIENT_INVENTORY
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
return isCovered
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
export default InventoryService
|
|
||||||
@@ -0,0 +1,94 @@
|
|||||||
|
import { BaseService } from "medusa-interfaces"
|
||||||
|
import { MedusaError } from "medusa-core-utils"
|
||||||
|
import { TransactionBaseService } from "../interfaces"
|
||||||
|
import { EntityManager } from "typeorm"
|
||||||
|
import ProductVariantService from "./product-variant"
|
||||||
|
import { ProductVariant } from "../models"
|
||||||
|
|
||||||
|
type InventoryServiceProps = {
|
||||||
|
manager: EntityManager
|
||||||
|
productVariantService: ProductVariantService
|
||||||
|
}
|
||||||
|
class InventoryService extends TransactionBaseService<InventoryService> {
|
||||||
|
protected readonly productVariantService_: ProductVariantService
|
||||||
|
|
||||||
|
protected manager_: EntityManager
|
||||||
|
protected transactionManager_: EntityManager | undefined
|
||||||
|
|
||||||
|
constructor({ manager, productVariantService }: InventoryServiceProps) {
|
||||||
|
super({ manager, productVariantService })
|
||||||
|
|
||||||
|
this.manager_ = manager
|
||||||
|
this.productVariantService_ = productVariantService
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Updates the inventory of a variant based on a given adjustment.
|
||||||
|
* @param variantId - the id of the variant to update
|
||||||
|
* @param adjustment - the number to adjust the inventory quantity by
|
||||||
|
* @return resolves to the update result.
|
||||||
|
*/
|
||||||
|
async adjustInventory(
|
||||||
|
variantId: string,
|
||||||
|
adjustment: number
|
||||||
|
): Promise<ProductVariant | undefined> {
|
||||||
|
if (!variantId) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
return await this.atomicPhase_(async (manager) => {
|
||||||
|
const variant = await this.productVariantService_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.retrieve(variantId)
|
||||||
|
// if inventory is managed then update
|
||||||
|
if (variant.manage_inventory) {
|
||||||
|
return await this.productVariantService_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.update(variant, {
|
||||||
|
inventory_quantity: variant.inventory_quantity + adjustment,
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
return variant
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Checks if the inventory of a variant can cover a given quantity. Will
|
||||||
|
* return true if the variant doesn't have managed inventory or if the variant
|
||||||
|
* allows backorders or if the inventory quantity is greater than `quantity`.
|
||||||
|
* @param variantId - the id of the variant to check
|
||||||
|
* @param quantity - the number of units to check availability for
|
||||||
|
* @return true if the inventory covers the quantity
|
||||||
|
*/
|
||||||
|
async confirmInventory(
|
||||||
|
variantId: string | undefined | null,
|
||||||
|
quantity: number
|
||||||
|
): Promise<boolean> {
|
||||||
|
// if variantId is undefined then confirm inventory as it
|
||||||
|
// is a custom item that is not managed
|
||||||
|
if (typeof variantId === "undefined" || variantId === null) {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return await this.atomicPhase_(async (manager) => {
|
||||||
|
const variant = await this.productVariantService_
|
||||||
|
.withTransaction(manager)
|
||||||
|
.retrieve(variantId)
|
||||||
|
const { inventory_quantity, allow_backorder, manage_inventory } = variant
|
||||||
|
const isCovered =
|
||||||
|
!manage_inventory || allow_backorder || inventory_quantity >= quantity
|
||||||
|
|
||||||
|
if (!isCovered) {
|
||||||
|
throw new MedusaError(
|
||||||
|
MedusaError.Types.NOT_ALLOWED,
|
||||||
|
`Variant with id: ${variant.id} does not have the required inventory`,
|
||||||
|
MedusaError.Codes.INSUFFICIENT_INVENTORY
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return isCovered
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default InventoryService
|
||||||
Reference in New Issue
Block a user