mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 05:40:31 +00:00
feat(nestjs): migrate to NestJS
This commit is contained in:
@@ -0,0 +1,136 @@
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { Knex } from 'knex';
|
||||
import { sumBy } from 'lodash';
|
||||
import {
|
||||
IVendorCreditApplyToBillsCreatedPayload,
|
||||
IVendorCreditApplyToInvoicesDTO,
|
||||
IVendorCreditApplyToInvoicesModel,
|
||||
} from '../types/VendorCreditApplyBills.types';
|
||||
import { ERRORS } from '../VendorCreditsApplyBills.constants';
|
||||
import { VendorCreditAppliedBill } from '../models/VendorCreditAppliedBill';
|
||||
import { VendorCredit } from '@/modules/VendorCredit/models/VendorCredit';
|
||||
import { BillPaymentValidators } from '@/modules/BillPayments/commands/BillPaymentValidators.service';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { UnitOfWork } from '@/modules/Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { Bill } from '@/modules/Bills/models/Bill';
|
||||
import { ServiceError } from '@/modules/Items/ServiceError';
|
||||
import { events } from '@/common/events/events';
|
||||
import { VendorCreditDTOTransformService } from '@/modules/VendorCredit/commands/VendorCreditDTOTransform.service';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class ApplyVendorCreditToBillsService {
|
||||
/**
|
||||
* @param {UnitOfWork} uow - The unit of work service.
|
||||
* @param {EventEmitter2} eventPublisher - The event emitter service.
|
||||
* @param {BillPaymentValidators} billPaymentValidators - The bill payment validators service.
|
||||
* @param {TenantModelProxy<typeof VendorCreditAppliedBill>} vendorCreditAppliedBillModel - The vendor credit applied bill model.
|
||||
* @param {TenantModelProxy<typeof VendorCredit>} vendorCreditModel - The vendor credit model.
|
||||
*/
|
||||
constructor(
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
private readonly billPaymentValidators: BillPaymentValidators,
|
||||
private readonly vendorCreditDTOTransform: VendorCreditDTOTransformService,
|
||||
|
||||
@Inject(VendorCreditAppliedBill.name)
|
||||
private readonly vendorCreditAppliedBillModel: TenantModelProxy<
|
||||
typeof VendorCreditAppliedBill
|
||||
>,
|
||||
|
||||
@Inject(VendorCredit.name)
|
||||
private readonly vendorCreditModel: TenantModelProxy<typeof VendorCredit>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Apply credit note to the given invoices.
|
||||
* @param {number} creditNoteId
|
||||
* @param {IApplyCreditToInvoicesDTO} applyCreditToInvoicesDTO
|
||||
*/
|
||||
public applyVendorCreditToBills = async (
|
||||
vendorCreditId: number,
|
||||
applyCreditToBillsDTO: IVendorCreditApplyToInvoicesDTO,
|
||||
): Promise<void> => {
|
||||
// Retrieves the vendor credit or throw not found service error.
|
||||
const vendorCredit = await this.vendorCreditModel()
|
||||
.query()
|
||||
.findById(vendorCreditId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Transfomes credit apply to bills DTO to model object.
|
||||
const vendorCreditAppliedModel = this.transformApplyDTOToModel(
|
||||
applyCreditToBillsDTO,
|
||||
vendorCredit,
|
||||
);
|
||||
|
||||
// Validate bills entries existance.
|
||||
const appliedBills =
|
||||
await this.billPaymentValidators.validateBillsExistance(
|
||||
vendorCreditAppliedModel.entries,
|
||||
vendorCredit.vendorId,
|
||||
);
|
||||
|
||||
// Validate bills has remaining amount to apply.
|
||||
this.validateBillsRemainingAmount(
|
||||
appliedBills,
|
||||
vendorCreditAppliedModel.amount,
|
||||
);
|
||||
// Validate vendor credit remaining credit amount.
|
||||
this.vendorCreditDTOTransform.validateCreditRemainingAmount(
|
||||
vendorCredit,
|
||||
vendorCreditAppliedModel.amount,
|
||||
);
|
||||
// Saves vendor credit applied to bills under unit-of-work envirement.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
// Inserts vendor credit applied to bills graph to the storage layer.
|
||||
const vendorCreditAppliedBills = await this.vendorCreditAppliedBillModel()
|
||||
.query(trx)
|
||||
.insertGraph(vendorCreditAppliedModel.entries);
|
||||
|
||||
// Triggers `IVendorCreditApplyToBillsCreatedPayload` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.vendorCredit.onApplyToInvoicesCreated,
|
||||
{
|
||||
trx,
|
||||
vendorCredit,
|
||||
vendorCreditAppliedBills,
|
||||
} as IVendorCreditApplyToBillsCreatedPayload,
|
||||
);
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Transformes apply DTO to model.
|
||||
* @param {IApplyCreditToInvoicesDTO} applyDTO
|
||||
* @param {ICreditNote} creditNote
|
||||
* @returns {IVendorCreditApplyToInvoicesModel}
|
||||
*/
|
||||
private transformApplyDTOToModel = (
|
||||
applyDTO: IVendorCreditApplyToInvoicesDTO,
|
||||
vendorCredit: VendorCredit,
|
||||
): IVendorCreditApplyToInvoicesModel => {
|
||||
const entries = applyDTO.entries.map((entry) => ({
|
||||
billId: entry.billId,
|
||||
amount: entry.amount,
|
||||
vendorCreditId: vendorCredit.id,
|
||||
}));
|
||||
const amount = sumBy(applyDTO.entries, 'amount');
|
||||
|
||||
return {
|
||||
amount,
|
||||
entries,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Validate bills remaining amount.
|
||||
* @param {IBill[]} bills
|
||||
* @param {number} amount
|
||||
*/
|
||||
private validateBillsRemainingAmount = (bills: Bill[], amount: number) => {
|
||||
const invalidBills = bills.filter((bill) => bill.dueAmount < amount);
|
||||
if (invalidBills.length > 0) {
|
||||
throw new ServiceError(ERRORS.BILLS_HAS_NO_REMAINING_AMOUNT);
|
||||
}
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user