import { Inject, Injectable } from '@nestjs/common'; import { Knex } from 'knex'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { IWarehouseDeletedPayload, IWarehouseDeletePayload, } from '../Warehouse.types'; import { WarehouseValidator } from './WarehouseValidator.service'; import { ERRORS } from '../contants'; import { Warehouse } from '../models/Warehouse.model'; import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service'; import { events } from '@/common/events/events'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; @Injectable() export class DeleteWarehouseService { /** * @param {UnitOfWork} uow - Unit of work. * @param {EventEmitter2} eventPublisher - Event emitter. * @param {WarehouseValidator} validator - Warehouse command validator. * @param {typeof Warehouse} warehouseModel - Warehouse model. */ constructor( private readonly uow: UnitOfWork, private readonly eventPublisher: EventEmitter2, private readonly validator: WarehouseValidator, @Inject(Warehouse.name) private readonly warehouseModel: TenantModelProxy, ) {} /** * Validates the given warehouse before deleting. * @param {number} warehouseId * @returns {Promise} */ public authorize = async (warehouseId: number): Promise => { await this.validator.validateWarehouseNotOnlyWarehouse(warehouseId); }; /** * Deletes specific warehouse. * @param {number} warehouseId * @returns {Promise} */ public deleteWarehouse = async (warehouseId: number): Promise => { // Retrieves the old warehouse or throw not found service error. const oldWarehouse = await this.warehouseModel() .query() .findById(warehouseId) .throwIfNotFound(); // Validates the given warehouse before deleting. await this.authorize(warehouseId); // Creates a new warehouse under unit-of-work. return this.uow.withTransaction(async (trx: Knex.Transaction) => { const eventPayload = { warehouseId, oldWarehouse, trx, } as IWarehouseDeletePayload | IWarehouseDeletedPayload; // Triggers `onWarehouseCreate`. await this.eventPublisher.emitAsync( events.warehouse.onDelete, eventPayload, ); // Deletes the given warehouse from the storage. await this.warehouseModel() .query() .findById(warehouseId) .deleteIfNoRelations({ type: ERRORS.WAREHOUSE_HAS_ASSOCIATED_TRANSACTIONS, message: 'Warehouse has associated transactions', }); // Triggers `onWarehouseCreated`. await this.eventPublisher.emitAsync( events.warehouse.onDeleted, eventPayload as IWarehouseDeletedPayload, ); }); }; }