Skip to content

Commit

Permalink
fix: trial balance sheet adjusted balance
Browse files Browse the repository at this point in the history
  • Loading branch information
abouolia committed Oct 19, 2023
1 parent 1ed1c9e commit ba00e8b
Show file tree
Hide file tree
Showing 9 changed files with 388 additions and 67 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export default class TrialBalanceSheetController extends BaseFinancialReportCont
/**
* Router constructor.
*/
router() {
public router() {
const router = Router();

router.get(
Expand All @@ -36,7 +36,7 @@ export default class TrialBalanceSheetController extends BaseFinancialReportCont
* Validation schema.
* @return {ValidationChain[]}
*/
get trialBalanceSheetValidationSchema(): ValidationChain[] {
private get trialBalanceSheetValidationSchema(): ValidationChain[] {
return [
...this.sheetNumberFormatValidationSchema,
query('basis').optional(),
Expand All @@ -59,28 +59,37 @@ export default class TrialBalanceSheetController extends BaseFinancialReportCont
/**
* Retrieve the trial balance sheet.
*/
public async trialBalanceSheet(
private async trialBalanceSheet(
req: Request,
res: Response,
next: NextFunction
) {
const { tenantId, settings } = req;
const { tenantId } = req;
let filter = this.matchedQueryData(req);

filter = {
...filter,
accountsIds: castArray(filter.accountsIds),
};

try {
const { data, query, meta } =
await this.trialBalanceSheetService.trialBalanceSheet(tenantId, filter);
const accept = this.accepts(req);
const acceptType = accept.types(['json', 'application/json+table']);

return res.status(200).send({
data: this.transfromToResponse(data),
query: this.transfromToResponse(query),
meta: this.transfromToResponse(meta),
});
if (acceptType === 'application/json+table') {
const { table, meta, query } =
await this.trialBalanceSheetService.trialBalanceSheetTable(
tenantId,
filter
);
return res.status(200).send({ table, meta, query });
} else {
const { data, query, meta } =
await this.trialBalanceSheetService.trialBalanceSheet(
tenantId,
filter
);
return res.status(200).send({ data, query, meta });
}
} catch (error) {
next(error);
}
Expand Down
2 changes: 2 additions & 0 deletions packages/server/src/interfaces/Ledger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ export interface ILedger {

getClosingBalance(): number;
getForeignClosingBalance(): number;
getClosingDebit(): number;
getClosingCredit(): number;

getContactsIds(): number[];
getAccountsIds(): number[];
Expand Down
18 changes: 17 additions & 1 deletion packages/server/src/services/Accounting/Ledger.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import moment from 'moment';
import { defaultTo, uniqBy } from 'lodash';
import { defaultTo, sumBy, uniqBy } from 'lodash';
import { IAccountTransaction, ILedger, ILedgerEntry } from '@/interfaces';

export default class Ledger implements ILedger {
Expand Down Expand Up @@ -130,6 +130,22 @@ export default class Ledger implements ILedger {
return closingBalance;
}

/**
* Retrieves the closing credit of the entries.
* @returns {number}
*/
public getClosingCredit(): number {
return sumBy(this.entries, 'credit');
}

/**
* Retrieves the closing debit of the entries.
* @returns {number}
*/
public getClosingDebit(): number {
return sumBy(this.entries, 'debit');
}

/**
* Retrieve the closing balance of the entries.
* @returns {number}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,12 @@ import {
} from '@/interfaces';
import FinancialSheet from '../FinancialSheet';
import { allPassedConditionsPass, flatToNestedArray } from 'utils';
import { TrialBalanceSheetRepository } from './TrialBalanceSheetRepository';

export default class TrialBalanceSheet extends FinancialSheet {
tenantId: number;
query: ITrialBalanceSheetQuery;
accounts: IAccount & { type: IAccountType }[];
journalFinancial: any;
baseCurrency: string;
private query: ITrialBalanceSheetQuery;
private repository: TrialBalanceSheetRepository;
private baseCurrency: string;

/**
* Constructor method.
Expand All @@ -28,20 +27,52 @@ export default class TrialBalanceSheet extends FinancialSheet {
constructor(
tenantId: number,
query: ITrialBalanceSheetQuery,
accounts: IAccount & { type: IAccountType }[],
journalFinancial: any,
repository: TrialBalanceSheetRepository,
baseCurrency: string
) {
super();

this.tenantId = tenantId;
this.query = query;
this.accounts = accounts;
this.journalFinancial = journalFinancial;
this.repository = repository;
this.numberFormat = this.query.numberFormat;
this.baseCurrency = baseCurrency;
}

/**
* Retrieves the closing credit of the given account.
* @param {number} accountId
* @returns {number}
*/
public getClosingAccountCredit(accountId: number) {
return this.repository.totalAccountsLedger
.whereAccountId(accountId)
.getClosingCredit();
}

/**
* Retrieves the closing debit of the given account.
* @param {number} accountId
* @returns {number}
*/
public getClosingAccountDebit(accountId: number) {
return this.repository.totalAccountsLedger
.whereAccountId(accountId)
.getClosingDebit();
}

/**
* Retrieves the closing total of the given account.
* @param {number} accountId
* @returns {number}
*/
public getClosingAccountTotal(accountId: number) {
const credit = this.getClosingAccountCredit(accountId);
const debit = this.getClosingAccountDebit(accountId);

return debit - credit;
}

/**
* Account mapper.
* @param {IAccount} account
Expand All @@ -50,7 +81,9 @@ export default class TrialBalanceSheet extends FinancialSheet {
private accountTransformer = (
account: IAccount & { type: IAccountType }
): ITrialBalanceAccount => {
const trial = this.journalFinancial.getTrialBalanceWithDepands(account.id);
const debit = this.getClosingAccountDebit(account.id);
const credit = this.getClosingAccountCredit(account.id);
const balance = this.getClosingAccountTotal(account.id);

return {
id: account.id,
Expand All @@ -59,14 +92,14 @@ export default class TrialBalanceSheet extends FinancialSheet {
code: account.code,
accountNormal: account.accountNormal,

credit: trial.credit,
debit: trial.debit,
balance: trial.balance,
credit,
debit,
balance,
currencyCode: this.baseCurrency,

formattedCredit: this.formatNumber(trial.credit),
formattedDebit: this.formatNumber(trial.debit),
formattedBalance: this.formatNumber(trial.balance),
formattedCredit: this.formatNumber(credit),
formattedDebit: this.formatNumber(debit),
formattedBalance: this.formatNumber(balance),
};
};

Expand Down Expand Up @@ -117,10 +150,7 @@ export default class TrialBalanceSheet extends FinancialSheet {
private filterNoneTransactions = (
accountNode: ITrialBalanceAccount
): boolean => {
const entries = this.journalFinancial.getAccountEntriesWithDepents(
accountNode.id
);
return entries.length > 0;
return false === this.repository.totalAccountsLedger.isEmpty();
};

/**
Expand Down Expand Up @@ -200,11 +230,11 @@ export default class TrialBalanceSheet extends FinancialSheet {
*/
public reportData(): ITrialBalanceSheetData {
// Don't return noting if the journal has no transactions.
if (this.journalFinancial.isEmpty()) {
if (this.repository.totalAccountsLedger.isEmpty()) {
return null;
}
// Retrieve accounts nodes.
const accounts = this.accountsSection(this.accounts);
const accounts = this.accountsSection(this.repository.accounts);

// Retrieve account node.
const total = this.tatalSection(accounts);
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import { ITrialBalanceSheetQuery } from '@/interfaces';
import Ledger from '@/services/Accounting/Ledger';
import { Knex } from 'knex';
import { isEmpty } from 'lodash';
import { Service } from 'typedi';

@Service()
export class TrialBalanceSheetRepository {
private query: ITrialBalanceSheetQuery;
private models: any;

/**
*
*/
public accounts: any;

/**
* Total closing accounts ledger.
* @param {Ledger}
*/
public totalAccountsLedger: Ledger;

/**
* Constructor method.
* @param {number} tenantId
* @param {IBalanceSheetQuery} query
*/
constructor(models: any, query: ITrialBalanceSheetQuery) {
this.query = query;
this.models = models;
}

/**
* Async initialize.
* @returns {Promise<void>}
*/
public asyncInitialize = async () => {
await this.initAccounts();
await this.initAccountsClosingTotalLedger();
};

// ----------------------------
// # Accounts
// ----------------------------
/**
* Initialize accounts.
* @returns {Promise<void>}
*/
public initAccounts = async () => {
const accounts = await this.getAccounts();

this.accounts = accounts;
};

/**
* Initialize all accounts closing total ledger.
* @return {Promise<void>}
*/
public initAccountsClosingTotalLedger = async (): Promise<void> => {
const totalByAccounts = await this.closingAccountsTotal(this.query.toDate);

this.totalAccountsLedger = Ledger.fromTransactions(totalByAccounts);
};

/**
* Retrieve accounts of the report.
* @return {Promise<IAccount[]>}
*/
private getAccounts = () => {
const { Account } = this.models;

return Account.query();
};

/**
* Retrieve the opening balance transactions of the report.
* @param {Date|string} openingDate -
*/
public closingAccountsTotal = async (openingDate: Date | string) => {
const { AccountTransaction } = this.models;

return AccountTransaction.query().onBuild((query) => {
query.sum('credit as credit');
query.sum('debit as debit');
query.groupBy('accountId');
query.select(['accountId']);

query.modify('filterDateRange', null, openingDate);
query.withGraphFetched('account');

this.commonFilterBranchesQuery(query);
});
};

/**
* Common branches filter query.
* @param {Knex.QueryBuilder} query
*/
private commonFilterBranchesQuery = (query: Knex.QueryBuilder) => {
if (!isEmpty(this.query.branchesIds)) {
query.modify('filterByBranches', this.query.branchesIds);
}
};
}
Loading

0 comments on commit ba00e8b

Please sign in to comment.