From 1cbc1c056ff28120a48fb158b619cde38e8c4f99 Mon Sep 17 00:00:00 2001 From: Ahmed Bouhuolia Date: Mon, 10 Jun 2024 08:08:47 +0200 Subject: [PATCH] feat: general ledger filter nodes --- .../GeneralLedger/GeneralLedger.ts | 41 ++++--------- .../GeneralLedger/GeneralLedgerRepository.ts | 57 ++++++++++++++++++- 2 files changed, 67 insertions(+), 31 deletions(-) diff --git a/packages/server/src/services/FinancialStatements/GeneralLedger/GeneralLedger.ts b/packages/server/src/services/FinancialStatements/GeneralLedger/GeneralLedger.ts index e797085a4..5ae2bba76 100644 --- a/packages/server/src/services/FinancialStatements/GeneralLedger/GeneralLedger.ts +++ b/packages/server/src/services/FinancialStatements/GeneralLedger/GeneralLedger.ts @@ -261,18 +261,8 @@ export default class GeneralLedgerSheet extends R.compose( if (isEmpty(this.query.accountsIds)) { return true; } - // Returns true if the given account id included in the filter. - const isIncluded = this.query.accountsIds.includes(accountId); - - const parentAccountIds = - this.repository.accountsGraph.dependantsOf(accountId); - - // Returns true if one of the parent account id exists in the filter. - const accountIdInChildren = R.any( - (parentAccountId) => R.includes(parentAccountId, this.query.accountsIds), - parentAccountIds - ); - return isIncluded || accountIdInChildren; + // Returns true if the given account id includes transactions. + return this.repository.accountNodesIncludeTransactions.includes(accountId); }; /** @@ -290,12 +280,7 @@ export default class GeneralLedgerSheet extends R.compose( const closingBalanceSubaccounts = this.accountClosingBalanceWithSubaccountsTotal(account.id); - return R.compose( - R.when( - () => this.isAccountNodeIncludesClosingSubaccounts(account.id), - R.assoc('closingBalanceSubaccounts', closingBalanceSubaccounts) - ) - )({ + const initialNode = { id: account.id, name: account.name, code: account.code, @@ -304,7 +289,14 @@ export default class GeneralLedgerSheet extends R.compose( openingBalance, transactions, closingBalance, - }); + }; + + return R.compose( + R.when( + () => this.isAccountNodeIncludesClosingSubaccounts(account.id), + R.assoc('closingBalanceSubaccounts', closingBalanceSubaccounts) + ) + )(initialNode); }; /** @@ -356,16 +348,7 @@ export default class GeneralLedgerSheet extends R.compose( return true; } // Returns true if the given account id exists in the filter. - const isIncluded = this.query.accountsIds?.includes(node.id); - - const parentAccountIds = this.repository.accountsGraph.dependantsOf( - node.id - ); - // Returns true if one of th parent account ids exist in the filter. - const oneParentAccountIdExistInFilter = parentAccountIds.some((id) => - this.query.accountsIds?.includes(id) - ); - return isIncluded || oneParentAccountIdExistInFilter; + return this.repository.accountNodeInclude?.includes(node.id); }); }; diff --git a/packages/server/src/services/FinancialStatements/GeneralLedger/GeneralLedgerRepository.ts b/packages/server/src/services/FinancialStatements/GeneralLedger/GeneralLedgerRepository.ts index 9d51a9806..875b4fefa 100644 --- a/packages/server/src/services/FinancialStatements/GeneralLedger/GeneralLedgerRepository.ts +++ b/packages/server/src/services/FinancialStatements/GeneralLedger/GeneralLedgerRepository.ts @@ -1,4 +1,5 @@ import moment from 'moment'; +import * as R from 'ramda'; import { IAccount, IAccountTransaction, @@ -9,6 +10,7 @@ import { import Ledger from '@/services/Accounting/Ledger'; import { transformToMap } from '@/utils'; import { Tenant } from '@/system/models'; +import { flatten, isEmpty, uniq } from 'lodash'; export class GeneralLedgerRepository { public filter: IGeneralLedgerSheetQuery; @@ -30,6 +32,9 @@ export class GeneralLedgerRepository { public tenantId: number; public tenant: ITenant; + public accountNodesIncludeTransactions: Array = []; + public accountNodeInclude: Array = []; + /** * Constructor method. * @param models @@ -54,8 +59,10 @@ export class GeneralLedgerRepository { await this.initAccounts(); await this.initAccountsGraph(); await this.initContacts(); - await this.initTransactions(); await this.initAccountsOpeningBalance(); + this.initAccountNodesIncludeTransactions(); + await this.initTransactions(); + this.initAccountNodesIncluded(); } /** @@ -102,7 +109,12 @@ export class GeneralLedgerRepository { toDate: this.filter.toDate, branchesIds: this.filter.branchesIds, }) - .orderBy('date', 'ASC'); + .orderBy('date', 'ASC') + .onBuild((query) => { + if (this.filter.accountsIds?.length > 0) { + query.whereIn('accountId', this.accountNodesIncludeTransactions); + } + }); // Transform array transactions to journal collection. this.transactionsLedger = Ledger.fromTransactions(this.transactions); } @@ -124,4 +136,45 @@ export class GeneralLedgerRepository { this.openingBalanceTransactions ); } + + /** + * Initialize the account nodes that should include transactions. + * @returns {void} + */ + public initAccountNodesIncludeTransactions() { + if (isEmpty(this.filter.accountsIds)) { + return; + } + const childrenNodeIds = this.filter.accountsIds?.map( + (accountId: number) => { + return this.accountsGraph.dependenciesOf(accountId); + } + ); + const nodeIds = R.concat(this.filter.accountsIds, childrenNodeIds); + + this.accountNodesIncludeTransactions = uniq(flatten(nodeIds)); + } + + /** + * Initialize the account node ids should be included, + * if the filter by acounts is presented. + * @returns {void} + */ + public initAccountNodesIncluded() { + if (isEmpty(this.filter.accountsIds)) { + return; + } + const nodeIds = this.filter.accountsIds.map((accountId) => { + const childrenIds = this.accountsGraph.dependenciesOf(accountId); + const parentIds = this.accountsGraph.dependantsOf(accountId); + + return R.concat(childrenIds, parentIds); + }); + + this.accountNodeInclude = R.compose( + R.uniq, + R.flatten, + R.concat(this.filter.accountsIds) + )(nodeIds); + } }