import { Inject, Injectable } from '@nestjs/common'; import { Knex } from 'knex'; import { IVendorCreditCreatedPayload, IVendorCreditCreatingPayload, } from '@/modules/VendorCredit/types/VendorCredit.types'; import { VendorCredit } from '../models/VendorCredit'; import { Vendor } from '@/modules/Vendors/models/Vendor'; import { events } from '@/common/events/events'; import { EventEmitter2 } from '@nestjs/event-emitter'; import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service'; import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service'; import { VendorCreditDTOTransformService } from './VendorCreditDTOTransform.service'; import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel'; import { CreateVendorCreditDto } from '../dtos/VendorCredit.dto'; @Injectable() export class CreateVendorCreditService { /** * @param {UnitOfWork} uow - The unit of work service. * @param {ItemsEntriesService} itemsEntriesService - The items entries service. * @param {EventEmitter2} eventPublisher - The event emitter service. * @param {typeof VendorCredit} vendorCreditModel - The vendor credit model. * @param {typeof Vendor} vendorModel - The vendor model. */ constructor( private readonly uow: UnitOfWork, private readonly itemsEntriesService: ItemsEntriesService, private readonly eventPublisher: EventEmitter2, private readonly vendorCreditDTOTransformService: VendorCreditDTOTransformService, @Inject(VendorCredit.name) private readonly vendorCreditModel: TenantModelProxy, @Inject(Vendor.name) private readonly vendorModel: TenantModelProxy, ) {} /** * Creates a new vendor credit. * @param {IVendorCreditCreateDTO} vendorCreditCreateDTO - * @param {Knex.Transaction} trx - */ public newVendorCredit = async ( vendorCreditCreateDTO: CreateVendorCreditDto, trx?: Knex.Transaction, ) => { // Triggers `onVendorCreditCreate` event. await this.eventPublisher.emitAsync(events.vendorCredit.onCreate, { vendorCreditCreateDTO, }); // Retrieve the given vendor or throw not found service error. const vendor = await this.vendorModel() .query() .findById(vendorCreditCreateDTO.vendorId) .throwIfNotFound(); // Validate items should be sellable items. await this.itemsEntriesService.validateNonSellableEntriesItems( vendorCreditCreateDTO.entries, ); // Transforms the credit DTO to storage layer. const vendorCreditModel = await this.vendorCreditDTOTransformService.transformCreateEditDTOToModel( vendorCreditCreateDTO, vendor.currencyCode, ); // Saves the vendor credit transactions under UOW environment. return this.uow.withTransaction(async (trx: Knex.Transaction) => { // Triggers `onVendorCreditCreating` event. await this.eventPublisher.emitAsync(events.vendorCredit.onCreating, { vendorCreditCreateDTO, trx, } as IVendorCreditCreatingPayload); // Saves the vendor credit graph. const vendorCredit = await this.vendorCreditModel() .query(trx) .upsertGraphAndFetch({ ...vendorCreditModel, }); // Triggers `onVendorCreditCreated` event. await this.eventPublisher.emitAsync(events.vendorCredit.onCreated, { vendorCredit, vendorCreditCreateDTO, trx, } as IVendorCreditCreatedPayload); return vendorCredit; }, trx); }; }