From d530ac23d603b99603e367bf1fe37e1ba517b9ef Mon Sep 17 00:00:00 2001 From: Philip Korsholm <88927411+pKorsholm@users.noreply.github.com> Date: Tue, 2 Aug 2022 16:56:57 +0700 Subject: [PATCH] Feat(medusa): Convert inventory service to ts (#1937) Fixes CORE-350 --- packages/medusa/src/services/inventory.js | 88 --------------------- packages/medusa/src/services/inventory.ts | 94 +++++++++++++++++++++++ 2 files changed, 94 insertions(+), 88 deletions(-) delete mode 100644 packages/medusa/src/services/inventory.js create mode 100644 packages/medusa/src/services/inventory.ts diff --git a/packages/medusa/src/services/inventory.js b/packages/medusa/src/services/inventory.js deleted file mode 100644 index aa6b8f7921..0000000000 --- a/packages/medusa/src/services/inventory.js +++ /dev/null @@ -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} 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 diff --git a/packages/medusa/src/services/inventory.ts b/packages/medusa/src/services/inventory.ts new file mode 100644 index 0000000000..e3d2c13d09 --- /dev/null +++ b/packages/medusa/src/services/inventory.ts @@ -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 { + 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 { + 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 { + // 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