Feat(medusa): Convert inventory service to ts (#1937)

Fixes CORE-350
This commit is contained in:
Philip Korsholm
2022-08-02 16:56:57 +07:00
committed by GitHub
parent 051bb16dd7
commit d530ac23d6
2 changed files with 94 additions and 88 deletions

View File

@@ -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

View File

@@ -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