Files
bigcapital/packages/server-nest/src/modules/VendorCredit/commands/EditVendorCredit.service.ts
2024-12-29 22:55:42 +02:00

109 lines
3.7 KiB
TypeScript

import { Inject, Injectable } from '@nestjs/common';
import {
IVendorCreditEditDTO,
IVendorCreditEditedPayload,
IVendorCreditEditingPayload,
} from '../types/VendorCredit.types';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
import { ItemsEntriesService } from '@/modules/Items/ItemsEntries.service';
import { VendorCredit } from '../models/VendorCredit';
import { Contact } from '@/modules/Contacts/models/Contact';
import { events } from '@/common/events/events';
import { Knex } from 'knex';
import { VendorCreditDTOTransformService } from './VendorCreditDTOTransform.service';
@Injectable()
export class EditVendorCreditService {
/**
* @param {EventEmitter2} eventPublisher - The event emitter service.
* @param {UnitOfWork} uow - The unit of work service.
* @param {ItemsEntriesService} itemsEntriesService - The items entries service.
* @param {typeof VendorCredit} vendorCreditModel - The vendor credit model.
* @param {typeof Contact} contactModel - The contact model.
*/
constructor(
private readonly eventPublisher: EventEmitter2,
private readonly uow: UnitOfWork,
private readonly itemsEntriesService: ItemsEntriesService,
private readonly vendorCreditDTOTransform: VendorCreditDTOTransformService,
@Inject(VendorCredit.name)
private readonly vendorCreditModel: typeof VendorCredit,
@Inject(Contact.name)
private readonly contactModel: typeof Contact,
) {}
/**
* Deletes the given vendor credit.
* @param {number} vendorCreditId - Vendor credit id.
*/
public editVendorCredit = async (
vendorCreditId: number,
vendorCreditDTO: IVendorCreditEditDTO,
trx?: Knex.Transaction,
) => {
// Retrieve the vendor credit or throw not found service error.
const oldVendorCredit = await this.vendorCreditModel
.query()
.findById(vendorCreditId)
.throwIfNotFound();
// Validate customer existance.
const vendor = await this.contactModel
.query()
.modify('vendor')
.findById(vendorCreditDTO.vendorId)
.throwIfNotFound();
// Validate items ids existance.
await this.itemsEntriesService.validateItemsIdsExistance(
vendorCreditDTO.entries,
);
// Validate non-sellable entries items.
await this.itemsEntriesService.validateNonSellableEntriesItems(
vendorCreditDTO.entries,
);
// Validate the items entries existance.
await this.itemsEntriesService.validateEntriesIdsExistance(
vendorCreditId,
'VendorCredit',
vendorCreditDTO.entries,
);
// Transformes edit DTO to model storage layer.
const vendorCreditModel =
this.vendorCreditDTOTransform.transformCreateEditDTOToModel(
vendorCreditDTO,
vendor.currencyCode,
oldVendorCredit,
);
// Edits the vendor credit graph under unit-of-work envirement.
return this.uow.withTransaction(async (trx) => {
// Triggers `onVendorCreditEditing` event.
await this.eventPublisher.emitAsync(events.vendorCredit.onEditing, {
oldVendorCredit,
vendorCreditDTO,
trx,
} as IVendorCreditEditingPayload);
// Saves the vendor credit graph to the storage.
const vendorCredit = await this.vendorCreditModel
.query(trx)
.upsertGraphAndFetch({
id: vendorCreditId,
...vendorCreditModel,
});
// Triggers `onVendorCreditEdited event.
await this.eventPublisher.emitAsync(events.vendorCredit.onEdited, {
oldVendorCredit,
vendorCredit,
vendorCreditDTO,
trx,
} as IVendorCreditEditedPayload);
return vendorCredit;
}, trx);
};
}