mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-19 22:30:31 +00:00
feat(nestjs): migrate to NestJS
This commit is contained in:
211
packages/server/src/modules/SaleInvoices/ledger/InvoiceGL.ts
Normal file
211
packages/server/src/modules/SaleInvoices/ledger/InvoiceGL.ts
Normal file
@@ -0,0 +1,211 @@
|
||||
import * as R from 'ramda';
|
||||
import { ILedger } from '@/modules/Ledger/types/Ledger.types';
|
||||
import { AccountNormal } from '@/modules/Accounts/Accounts.types';
|
||||
import { ILedgerEntry } from '@/modules/Ledger/types/Ledger.types';
|
||||
import { ItemEntry } from '@/modules/TransactionItemEntry/models/ItemEntry';
|
||||
import { Ledger } from '@/modules/Ledger/Ledger';
|
||||
import { SaleInvoice } from '../models/SaleInvoice';
|
||||
|
||||
export class InvoiceGL {
|
||||
private saleInvoice: SaleInvoice;
|
||||
private ARAccountId: number;
|
||||
private taxPayableAccountId: number;
|
||||
private discountAccountId: number;
|
||||
private otherChargesAccountId: number;
|
||||
|
||||
/**
|
||||
* Constructor method.
|
||||
* @param {SaleInvoice} saleInvoice - Sale invoice.
|
||||
*/
|
||||
constructor(saleInvoice: SaleInvoice) {
|
||||
this.saleInvoice = saleInvoice;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the receivable account id.
|
||||
* @param {number} ARAccountId - Receivable account id.
|
||||
*/
|
||||
setARAccountId(ARAccountId: number) {
|
||||
this.ARAccountId = ARAccountId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the tax payable account id.
|
||||
* @param {number} taxPayableAccountId - Tax payable account id.
|
||||
*/
|
||||
setTaxPayableAccountId(taxPayableAccountId: number) {
|
||||
this.taxPayableAccountId = taxPayableAccountId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the discount account id.
|
||||
* @param {number} discountAccountId - Discount account id.
|
||||
*/
|
||||
setDiscountAccountId(discountAccountId: number) {
|
||||
this.discountAccountId = discountAccountId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the other charges account id.
|
||||
* @param {number} otherChargesAccountId - Other charges account id.
|
||||
*/
|
||||
setOtherChargesAccountId(otherChargesAccountId: number) {
|
||||
this.otherChargesAccountId = otherChargesAccountId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the invoice GL common entry.
|
||||
*/
|
||||
private get invoiceGLCommonEntry() {
|
||||
return {
|
||||
credit: 0,
|
||||
debit: 0,
|
||||
|
||||
currencyCode: this.saleInvoice.currencyCode,
|
||||
exchangeRate: this.saleInvoice.exchangeRate,
|
||||
|
||||
transactionType: 'SaleInvoice',
|
||||
transactionId: this.saleInvoice.id,
|
||||
|
||||
date: this.saleInvoice.invoiceDate,
|
||||
userId: this.saleInvoice.userId,
|
||||
|
||||
transactionNumber: this.saleInvoice.invoiceNo,
|
||||
referenceNumber: this.saleInvoice.referenceNo,
|
||||
|
||||
createdAt: this.saleInvoice.createdAt,
|
||||
indexGroup: 10,
|
||||
|
||||
branchId: this.saleInvoice.branchId,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve receivable entry of the invoice.
|
||||
* @returns {ILedgerEntry}
|
||||
*/
|
||||
public get invoiceReceivableEntry(): ILedgerEntry {
|
||||
const commonEntry = this.invoiceGLCommonEntry;
|
||||
|
||||
return {
|
||||
...commonEntry,
|
||||
debit: this.saleInvoice.totalLocal,
|
||||
accountId: this.ARAccountId,
|
||||
contactId: this.saleInvoice.customerId,
|
||||
accountNormal: AccountNormal.DEBIT,
|
||||
index: 1,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve item income entry of the invoice.
|
||||
* @param {ItemEntry} entry - Item entry.
|
||||
* @param {number} index - Index.
|
||||
* @returns {ILedgerEntry}
|
||||
*/
|
||||
private getInvoiceItemEntry = R.curry(
|
||||
(entry: ItemEntry, index: number): ILedgerEntry => {
|
||||
const commonEntry = this.invoiceGLCommonEntry;
|
||||
const localAmount =
|
||||
entry.totalExcludingTax * this.saleInvoice.exchangeRate;
|
||||
|
||||
return {
|
||||
...commonEntry,
|
||||
credit: localAmount,
|
||||
accountId: entry.sellAccountId,
|
||||
note: entry.description,
|
||||
index: index + 2,
|
||||
itemId: entry.itemId,
|
||||
accountNormal: AccountNormal.CREDIT,
|
||||
taxRateId: entry.taxRateId,
|
||||
taxRate: entry.taxRate,
|
||||
};
|
||||
},
|
||||
);
|
||||
|
||||
/**
|
||||
* Retreives the GL entry of tax payable.
|
||||
* @param {ItemEntry} entry - Item entry.
|
||||
* @param {number} index - Index.
|
||||
* @returns {ILedgerEntry}
|
||||
*/
|
||||
private getInvoiceTaxEntry(entry: ItemEntry, index: number): ILedgerEntry {
|
||||
const commonEntry = this.invoiceGLCommonEntry;
|
||||
|
||||
return {
|
||||
...commonEntry,
|
||||
credit: entry.taxAmount,
|
||||
accountId: this.taxPayableAccountId,
|
||||
index: index + 1,
|
||||
indexGroup: 30,
|
||||
accountNormal: AccountNormal.CREDIT,
|
||||
taxRateId: entry.taxRateId,
|
||||
taxRate: entry.taxRate,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the invoice discount GL entry.
|
||||
* @returns {ILedgerEntry}
|
||||
*/
|
||||
private get invoiceDiscountEntry(): ILedgerEntry {
|
||||
const commonEntry = this.invoiceGLCommonEntry;
|
||||
|
||||
return {
|
||||
...commonEntry,
|
||||
debit: this.saleInvoice.discountAmountLocal,
|
||||
accountId: this.discountAccountId,
|
||||
accountNormal: AccountNormal.CREDIT,
|
||||
index: 1,
|
||||
} as ILedgerEntry;
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the invoice adjustment GL entry.
|
||||
* @returns {ILedgerEntry}
|
||||
*/
|
||||
private get adjustmentEntry(): ILedgerEntry {
|
||||
const commonEntry = this.invoiceGLCommonEntry;
|
||||
const adjustmentAmount = Math.abs(this.saleInvoice.adjustmentLocal);
|
||||
|
||||
return {
|
||||
...commonEntry,
|
||||
debit: this.saleInvoice.adjustmentLocal < 0 ? adjustmentAmount : 0,
|
||||
credit: this.saleInvoice.adjustmentLocal > 0 ? adjustmentAmount : 0,
|
||||
accountId: this.otherChargesAccountId,
|
||||
accountNormal: AccountNormal.CREDIT,
|
||||
index: 1,
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the invoice GL entries.
|
||||
* @returns {ILedgerEntry[]}
|
||||
*/
|
||||
public getInvoiceGLEntries = (): ILedgerEntry[] => {
|
||||
const creditEntries = this.saleInvoice.entries.map(
|
||||
(entry, index) => this.getInvoiceItemEntry(entry, index),
|
||||
);
|
||||
const taxEntries = this.saleInvoice.entries
|
||||
.filter((entry) => entry.taxAmount > 0)
|
||||
.map((entry, index) => this.getInvoiceTaxEntry(entry, index));
|
||||
|
||||
return [
|
||||
this.invoiceReceivableEntry,
|
||||
...creditEntries,
|
||||
...taxEntries,
|
||||
this.invoiceDiscountEntry,
|
||||
this.adjustmentEntry,
|
||||
];
|
||||
};
|
||||
|
||||
/**
|
||||
* Retrieves the invoice ledger.
|
||||
* @returns {ILedger}
|
||||
*/
|
||||
public getInvoiceLedger = (): ILedger => {
|
||||
const entries = this.getInvoiceGLEntries();
|
||||
|
||||
return new Ledger(entries);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
import { Knex } from 'knex';
|
||||
import { Inject, Injectable } from '@nestjs/common';
|
||||
import { LedgerStorageService } from '../../Ledger/LedgerStorage.service';
|
||||
import { SaleInvoice } from '../models/SaleInvoice';
|
||||
import { AccountRepository } from '../../Accounts/repositories/Account.repository';
|
||||
import { InvoiceGL } from './InvoiceGL';
|
||||
import { TenantModelProxy } from '@/modules/System/models/TenantBaseModel';
|
||||
|
||||
@Injectable()
|
||||
export class SaleInvoiceGLEntries {
|
||||
constructor(
|
||||
private readonly ledegrRepository: LedgerStorageService,
|
||||
private readonly accountRepository: AccountRepository,
|
||||
|
||||
@Inject(SaleInvoice.name)
|
||||
private readonly saleInvoiceModel: TenantModelProxy<typeof SaleInvoice>,
|
||||
) {}
|
||||
|
||||
/**
|
||||
* Writes a sale invoice GL entries.
|
||||
* @param {number} saleInvoiceId - Sale invoice id.
|
||||
* @param {Knex.Transaction} trx
|
||||
*/
|
||||
public writeInvoiceGLEntries = async (
|
||||
saleInvoiceId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
const saleInvoice = await this.saleInvoiceModel()
|
||||
.query(trx)
|
||||
.findById(saleInvoiceId)
|
||||
.withGraphFetched('entries.item');
|
||||
|
||||
// Find or create the A/R account.
|
||||
const ARAccount =
|
||||
await this.accountRepository.findOrCreateAccountReceivable(
|
||||
saleInvoice.currencyCode,
|
||||
{},
|
||||
trx,
|
||||
);
|
||||
// Find or create tax payable account.
|
||||
const taxPayableAccount =
|
||||
await this.accountRepository.findOrCreateTaxPayable({}, trx);
|
||||
// Find or create the discount expense account.
|
||||
const discountAccount =
|
||||
await this.accountRepository.findOrCreateDiscountAccount({}, trx);
|
||||
// Find or create the other charges account.
|
||||
const otherChargesAccount =
|
||||
await this.accountRepository.findOrCreateOtherChargesAccount({}, trx);
|
||||
|
||||
// Retrieves the ledger of the invoice.
|
||||
const invoiceGL = new InvoiceGL(saleInvoice);
|
||||
|
||||
invoiceGL.setARAccountId(ARAccount.id);
|
||||
invoiceGL.setTaxPayableAccountId(taxPayableAccount.id);
|
||||
invoiceGL.setDiscountAccountId(discountAccount.id);
|
||||
invoiceGL.setOtherChargesAccountId(otherChargesAccount.id);
|
||||
|
||||
const ledger = invoiceGL.getInvoiceLedger();
|
||||
|
||||
// Commits the ledger entries to the storage as UOW.
|
||||
await this.ledegrRepository.commit(ledger, trx);
|
||||
};
|
||||
|
||||
/**
|
||||
* Rewrites the given invoice GL entries.
|
||||
* @param {number} tenantId
|
||||
* @param {number} saleInvoiceId
|
||||
* @param {Knex.Transaction} trx
|
||||
*/
|
||||
public rewritesInvoiceGLEntries = async (
|
||||
saleInvoiceId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
// Reverts the invoice GL entries.
|
||||
await this.revertInvoiceGLEntries(saleInvoiceId, trx);
|
||||
|
||||
// Writes the invoice GL entries.
|
||||
await this.writeInvoiceGLEntries(saleInvoiceId, trx);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reverts the given invoice GL entries.
|
||||
* @param {number} saleInvoiceId - Sale invoice id.
|
||||
* @param {Knex.Transaction} trx
|
||||
*/
|
||||
public revertInvoiceGLEntries = async (
|
||||
saleInvoiceId: number,
|
||||
trx?: Knex.Transaction,
|
||||
) => {
|
||||
await this.ledegrRepository.deleteByReference(
|
||||
saleInvoiceId,
|
||||
'SaleInvoice',
|
||||
trx,
|
||||
);
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user