mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-21 15:20:34 +00:00
feat: general ledger closing balance with accounts row
This commit is contained in:
@@ -56,7 +56,7 @@ export interface IGeneralLedgerSheetAccount {
|
|||||||
transactions: IGeneralLedgerSheetAccountTransaction[];
|
transactions: IGeneralLedgerSheetAccountTransaction[];
|
||||||
openingBalance: IGeneralLedgerSheetAccountBalance;
|
openingBalance: IGeneralLedgerSheetAccountBalance;
|
||||||
closingBalance: IGeneralLedgerSheetAccountBalance;
|
closingBalance: IGeneralLedgerSheetAccountBalance;
|
||||||
closingBalanceSubaccounts: IGeneralLedgerSheetAccountBalance;
|
closingBalanceSubaccounts?: IGeneralLedgerSheetAccountBalance;
|
||||||
children?: IGeneralLedgerSheetAccount[];
|
children?: IGeneralLedgerSheetAccount[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -117,10 +117,12 @@ export default class GeneralLedgerSheet extends R.compose(
|
|||||||
amount,
|
amount,
|
||||||
runningBalance,
|
runningBalance,
|
||||||
|
|
||||||
formattedAmount: this.formatNumber(amount),
|
formattedAmount: this.formatNumber(amount, { excerptZero: false }),
|
||||||
formattedCredit: this.formatNumber(entry.credit),
|
formattedCredit: this.formatNumber(entry.credit, { excerptZero: false }),
|
||||||
formattedDebit: this.formatNumber(entry.debit),
|
formattedDebit: this.formatNumber(entry.debit, { excerptZero: false }),
|
||||||
formattedRunningBalance: this.formatNumber(runningBalance),
|
formattedRunningBalance: this.formatNumber(runningBalance, {
|
||||||
|
excerptZero: false,
|
||||||
|
}),
|
||||||
|
|
||||||
currencyCode: this.baseCurrency,
|
currencyCode: this.baseCurrency,
|
||||||
} as IGeneralLedgerSheetAccountTransaction;
|
} as IGeneralLedgerSheetAccountTransaction;
|
||||||
@@ -141,16 +143,20 @@ export default class GeneralLedgerSheet extends R.compose(
|
|||||||
|
|
||||||
return entries
|
return entries
|
||||||
.reduce((prev: Array<[number, ILedgerEntry]>, current: ILedgerEntry) => {
|
.reduce((prev: Array<[number, ILedgerEntry]>, current: ILedgerEntry) => {
|
||||||
|
const prevEntry = last(prev);
|
||||||
|
const prevRunningBalance = head(prevEntry) as number;
|
||||||
const amount = this.getEntryRunningBalance(
|
const amount = this.getEntryRunningBalance(
|
||||||
current,
|
current,
|
||||||
openingBalance,
|
openingBalance,
|
||||||
head(last(prev)) as number
|
prevRunningBalance
|
||||||
);
|
);
|
||||||
return new Array([amount, current]);
|
return [...prev, [amount, current]];
|
||||||
}, [])
|
}, [])
|
||||||
.map(([runningBalance, entry]: [number, ILedgerEntry]) =>
|
.map((entryPair: [number, ILedgerEntry]) => {
|
||||||
this.entryMapper(entry, runningBalance)
|
const [runningBalance, entry] = entryPair;
|
||||||
);
|
|
||||||
|
return this.entryMapper(entry, runningBalance);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -224,8 +230,6 @@ export default class GeneralLedgerSheet extends R.compose(
|
|||||||
const depsAccountsIds =
|
const depsAccountsIds =
|
||||||
this.repository.accountsGraph.dependenciesOf(accountId);
|
this.repository.accountsGraph.dependenciesOf(accountId);
|
||||||
|
|
||||||
console.log([...depsAccountsIds, accountId]);
|
|
||||||
|
|
||||||
const openingBalance = this.repository.openingBalanceTransactionsLedger
|
const openingBalance = this.repository.openingBalanceTransactionsLedger
|
||||||
.whereAccountsIds([...depsAccountsIds, accountId])
|
.whereAccountsIds([...depsAccountsIds, accountId])
|
||||||
.getClosingBalance();
|
.getClosingBalance();
|
||||||
@@ -241,7 +245,7 @@ export default class GeneralLedgerSheet extends R.compose(
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
* Retrieves the closing balance with subaccounts total node.
|
||||||
* @param {number} accountId
|
* @param {number} accountId
|
||||||
* @returns {IGeneralLedgerSheetAccountBalance}
|
* @returns {IGeneralLedgerSheetAccountBalance}
|
||||||
*/
|
*/
|
||||||
@@ -256,6 +260,31 @@ export default class GeneralLedgerSheet extends R.compose(
|
|||||||
return { amount, formattedAmount, currencyCode, date };
|
return { amount, formattedAmount, currencyCode, date };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines whether the closing balance subaccounts node should be exist.
|
||||||
|
* @param {number} accountId
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
private isAccountNodeIncludesClosingSubaccounts = (accountId: number) => {
|
||||||
|
// Retrun early if there is no accounts in the filter so
|
||||||
|
// return closing subaccounts in all cases.
|
||||||
|
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;
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retreive general ledger accounts sections.
|
* Retreive general ledger accounts sections.
|
||||||
* @param {IAccount} account
|
* @param {IAccount} account
|
||||||
@@ -271,7 +300,12 @@ export default class GeneralLedgerSheet extends R.compose(
|
|||||||
const closingBalanceSubaccounts =
|
const closingBalanceSubaccounts =
|
||||||
this.accountClosingBalanceWithSubaccountsTotal(account.id);
|
this.accountClosingBalanceWithSubaccountsTotal(account.id);
|
||||||
|
|
||||||
return {
|
return R.compose(
|
||||||
|
R.when(
|
||||||
|
() => this.isAccountNodeIncludesClosingSubaccounts(account.id),
|
||||||
|
R.assoc('closingBalanceSubaccounts', closingBalanceSubaccounts)
|
||||||
|
)
|
||||||
|
)({
|
||||||
id: account.id,
|
id: account.id,
|
||||||
name: account.name,
|
name: account.name,
|
||||||
code: account.code,
|
code: account.code,
|
||||||
@@ -280,8 +314,7 @@ export default class GeneralLedgerSheet extends R.compose(
|
|||||||
openingBalance,
|
openingBalance,
|
||||||
transactions,
|
transactions,
|
||||||
closingBalance,
|
closingBalance,
|
||||||
closingBalanceSubaccounts,
|
});
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -310,19 +343,42 @@ export default class GeneralLedgerSheet extends R.compose(
|
|||||||
* @param {IGeneralLedgerSheetAccount[]} nodes
|
* @param {IGeneralLedgerSheetAccount[]} nodes
|
||||||
* @returns {IGeneralLedgerSheetAccount[]}
|
* @returns {IGeneralLedgerSheetAccount[]}
|
||||||
*/
|
*/
|
||||||
private filterAccountNodes = (
|
private filterAccountNodesByTransactionsFilter = (
|
||||||
nodes: IGeneralLedgerSheetAccount[]
|
nodes: IGeneralLedgerSheetAccount[]
|
||||||
): IGeneralLedgerSheetAccount[] => {
|
): IGeneralLedgerSheetAccount[] => {
|
||||||
return this.filterNodesDeep(
|
return this.filterNodesDeep(
|
||||||
nodes,
|
nodes,
|
||||||
(generalLedgerAccount: IGeneralLedgerSheetAccount) =>
|
(account: IGeneralLedgerSheetAccount) =>
|
||||||
!(
|
!(account.transactions.length === 0 && this.query.noneTransactions)
|
||||||
generalLedgerAccount.transactions.length === 0 &&
|
|
||||||
this.query.noneTransactions
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters account nodes by the acounts filter.
|
||||||
|
* @param {IAccount[]} nodes
|
||||||
|
* @returns {IAccount[]}
|
||||||
|
*/
|
||||||
|
private filterAccountNodesByAccountsFilter = (
|
||||||
|
nodes: IAccount[]
|
||||||
|
): IAccount[] => {
|
||||||
|
return this.filterNodesDeep(nodes, (node: IGeneralLedgerSheetAccount) => {
|
||||||
|
if (R.isEmpty(this.query.accountsIds)) {
|
||||||
|
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;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves mapped accounts with general ledger transactions and
|
* Retrieves mapped accounts with general ledger transactions and
|
||||||
* opeing/closing balance.
|
* opeing/closing balance.
|
||||||
@@ -331,8 +387,11 @@ export default class GeneralLedgerSheet extends R.compose(
|
|||||||
*/
|
*/
|
||||||
private accountsWalker(accounts: IAccount[]): IGeneralLedgerSheetAccount[] {
|
private accountsWalker(accounts: IAccount[]): IGeneralLedgerSheetAccount[] {
|
||||||
return R.compose(
|
return R.compose(
|
||||||
this.filterAccountNodes,
|
R.defaultTo([]),
|
||||||
|
this.filterAccountNodesByTransactionsFilter,
|
||||||
this.accountNodesDeepMap,
|
this.accountNodesDeepMap,
|
||||||
|
R.defaultTo([]),
|
||||||
|
this.filterAccountNodesByAccountsFilter,
|
||||||
this.nestedAccountsNode
|
this.nestedAccountsNode
|
||||||
)(accounts);
|
)(accounts);
|
||||||
}
|
}
|
||||||
@@ -342,6 +401,7 @@ export default class GeneralLedgerSheet extends R.compose(
|
|||||||
* @return {IGeneralLedgerSheetAccount[]}
|
* @return {IGeneralLedgerSheetAccount[]}
|
||||||
*/
|
*/
|
||||||
public reportData(): IGeneralLedgerSheetAccount[] {
|
public reportData(): IGeneralLedgerSheetAccount[] {
|
||||||
|
console.log(this.repository.accounts);
|
||||||
return this.accountsWalker(this.repository.accounts);
|
return this.accountsWalker(this.repository.accounts);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -71,7 +71,9 @@ export class GeneralLedgerRepository {
|
|||||||
* Initialize the accounts.
|
* Initialize the accounts.
|
||||||
*/
|
*/
|
||||||
public async initAccounts() {
|
public async initAccounts() {
|
||||||
this.accounts = await this.repositories.accountRepository.all();
|
this.accounts = await this.repositories.accountRepository
|
||||||
|
.all()
|
||||||
|
.orderBy('name', 'ASC');
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -94,11 +96,13 @@ export class GeneralLedgerRepository {
|
|||||||
* Initialize the G/L transactions from/to the given date.
|
* Initialize the G/L transactions from/to the given date.
|
||||||
*/
|
*/
|
||||||
public async initTransactions() {
|
public async initTransactions() {
|
||||||
this.transactions = await this.repositories.transactionsRepository.journal({
|
this.transactions = await this.repositories.transactionsRepository
|
||||||
|
.journal({
|
||||||
fromDate: this.filter.fromDate,
|
fromDate: this.filter.fromDate,
|
||||||
toDate: this.filter.toDate,
|
toDate: this.filter.toDate,
|
||||||
branchesIds: this.filter.branchesIds,
|
branchesIds: this.filter.branchesIds,
|
||||||
});
|
})
|
||||||
|
.orderBy('date', 'ASC');
|
||||||
// Transform array transactions to journal collection.
|
// Transform array transactions to journal collection.
|
||||||
this.transactionsLedger = Ledger.fromTransactions(this.transactions);
|
this.transactionsLedger = Ledger.fromTransactions(this.transactions);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -272,10 +272,14 @@ export class GeneralLedgerTable extends R.compose(
|
|||||||
const closingBalanceWithSubaccounts =
|
const closingBalanceWithSubaccounts =
|
||||||
this.closingBalanceWithSubaccountsMapper(account);
|
this.closingBalanceWithSubaccountsMapper(account);
|
||||||
|
|
||||||
|
// Appends the closing balance with sub-accounts row if the account
|
||||||
|
// has children accounts and the node is define.
|
||||||
|
const isAppendClosingSubaccounts = () =>
|
||||||
|
account.children?.length > 0 && !!account.closingBalanceSubaccounts;
|
||||||
|
|
||||||
const children = R.compose(
|
const children = R.compose(
|
||||||
// Appends the closing balance with sub-accounts row if the account has children accounts.
|
|
||||||
R.when(
|
R.when(
|
||||||
() => account.children?.length > 0,
|
isAppendClosingSubaccounts,
|
||||||
R.append(closingBalanceWithSubaccounts)
|
R.append(closingBalanceWithSubaccounts)
|
||||||
),
|
),
|
||||||
R.concat(R.defaultTo([], transactions)),
|
R.concat(R.defaultTo([], transactions)),
|
||||||
|
|||||||
Reference in New Issue
Block a user