mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 22:00:31 +00:00
refactor: wip to nestjs
This commit is contained in:
@@ -0,0 +1,155 @@
|
||||
import { Knex } from 'knex';
|
||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import {
|
||||
ISaleInvoiceWriteoffCreatePayload,
|
||||
ISaleInvoiceWriteoffDTO,
|
||||
ISaleInvoiceWrittenOffCanceledPayload,
|
||||
ISaleInvoiceWrittenOffCancelPayload,
|
||||
} from '../SaleInvoice.types';
|
||||
import { ERRORS } from '../constants';
|
||||
import { UnitOfWork } from '../../Tenancy/TenancyDB/UnitOfWork.service';
|
||||
import { CommandSaleInvoiceValidators } from './CommandSaleInvoiceValidators.service';
|
||||
import { SaleInvoice } from '../models/SaleInvoice';
|
||||
import { events } from '@/common/events/events';
|
||||
import { ServiceError } from '../../Items/ServiceError';
|
||||
|
||||
@Injectable()
|
||||
export class WriteoffSaleInvoice {
|
||||
constructor(
|
||||
private readonly eventPublisher: EventEmitter2,
|
||||
private readonly uow: UnitOfWork,
|
||||
private readonly validators: CommandSaleInvoiceValidators,
|
||||
|
||||
@Inject(SaleInvoice.name)
|
||||
private readonly saleInvoiceModel: typeof SaleInvoice,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Writes-off the sale invoice on bad debt expense account.
|
||||
* @param {number} saleInvoiceId
|
||||
* @param {ISaleInvoiceWriteoffDTO} writeoffDTO
|
||||
* @return {Promise<ISaleInvoice>}
|
||||
*/
|
||||
public writeOff = async (
|
||||
saleInvoiceId: number,
|
||||
writeoffDTO: ISaleInvoiceWriteoffDTO,
|
||||
): Promise<SaleInvoice> => {
|
||||
const saleInvoice = await this.saleInvoiceModel
|
||||
.query()
|
||||
.findById(saleInvoiceId)
|
||||
.throwIfNotFound();
|
||||
|
||||
// Validates the given invoice existance.
|
||||
this.validators.validateInvoiceExistance(saleInvoice);
|
||||
|
||||
// Validate the sale invoice whether already written-off.
|
||||
this.validateSaleInvoiceAlreadyWrittenoff(saleInvoice);
|
||||
|
||||
// Saves the invoice write-off transaction with associated transactions
|
||||
// under unit-of-work envirmenet.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
const eventPayload = {
|
||||
// tenantId,
|
||||
saleInvoiceId,
|
||||
saleInvoice,
|
||||
writeoffDTO,
|
||||
trx,
|
||||
} as ISaleInvoiceWriteoffCreatePayload;
|
||||
|
||||
// Triggers `onSaleInvoiceWriteoff` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.saleInvoice.onWriteoff,
|
||||
eventPayload,
|
||||
);
|
||||
// Mark the sale invoice as written-off.
|
||||
const newSaleInvoice = await this.saleInvoiceModel
|
||||
.query(trx)
|
||||
.patch({
|
||||
writtenoffExpenseAccountId: writeoffDTO.expenseAccountId,
|
||||
writtenoffAmount: saleInvoice.dueAmount,
|
||||
writtenoffAt: new Date(),
|
||||
})
|
||||
.findById(saleInvoiceId);
|
||||
|
||||
// Triggers `onSaleInvoiceWrittenoff` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.saleInvoice.onWrittenoff,
|
||||
eventPayload,
|
||||
);
|
||||
return newSaleInvoice;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Cancels the written-off sale invoice.
|
||||
* @param {number} tenantId
|
||||
* @param {number} saleInvoiceId
|
||||
* @returns {Promise<ISaleInvoice>}
|
||||
*/
|
||||
public cancelWrittenoff = async (
|
||||
saleInvoiceId: number,
|
||||
): Promise<SaleInvoice> => {
|
||||
// Validate the sale invoice existance.
|
||||
|
||||
// Retrieve the sale invoice or throw not found service error.
|
||||
const saleInvoice = await this.saleInvoiceModel
|
||||
.query()
|
||||
.findById(saleInvoiceId);
|
||||
|
||||
// Validate the sale invoice existance.
|
||||
this.validators.validateInvoiceExistance(saleInvoice);
|
||||
|
||||
// Validate the sale invoice whether already written-off.
|
||||
this.validateSaleInvoiceNotWrittenoff(saleInvoice);
|
||||
|
||||
// Cancels the invoice written-off and removes the associated transactions.
|
||||
return this.uow.withTransaction(async (trx: Knex.Transaction) => {
|
||||
// Triggers `onSaleInvoiceWrittenoffCancel` event.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.saleInvoice.onWrittenoffCancel,
|
||||
{
|
||||
saleInvoice,
|
||||
trx,
|
||||
} as ISaleInvoiceWrittenOffCancelPayload,
|
||||
);
|
||||
// Mark the sale invoice as written-off.
|
||||
const newSaleInvoice = await SaleInvoice.query(trx)
|
||||
.patch({
|
||||
writtenoffAmount: null,
|
||||
writtenoffAt: null,
|
||||
})
|
||||
.findById(saleInvoiceId);
|
||||
|
||||
// Triggers `onSaleInvoiceWrittenoffCanceled`.
|
||||
await this.eventPublisher.emitAsync(
|
||||
events.saleInvoice.onWrittenoffCanceled,
|
||||
{
|
||||
saleInvoice,
|
||||
trx,
|
||||
} as ISaleInvoiceWrittenOffCanceledPayload,
|
||||
);
|
||||
return newSaleInvoice;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* Should sale invoice not be written-off.
|
||||
* @param {SaleInvoice} saleInvoice
|
||||
*/
|
||||
private validateSaleInvoiceNotWrittenoff(saleInvoice: SaleInvoice) {
|
||||
if (!saleInvoice.isWrittenoff) {
|
||||
throw new ServiceError(ERRORS.SALE_INVOICE_NOT_WRITTEN_OFF);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Should sale invoice already written-off.
|
||||
* @param {SaleInvoice} saleInvoice
|
||||
*/
|
||||
private validateSaleInvoiceAlreadyWrittenoff(saleInvoice: SaleInvoice) {
|
||||
if (saleInvoice.isWrittenoff) {
|
||||
throw new ServiceError(ERRORS.SALE_INVOICE_ALREADY_WRITTEN_OFF);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user