mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-18 22:00:31 +00:00
fix: Balance sheet and P/L nested accounts
This commit is contained in:
@@ -20,6 +20,8 @@ import { BalanceSheetPercentage } from './BalanceSheetPercentage';
|
|||||||
import { BalanceSheetSchema } from './BalanceSheetSchema';
|
import { BalanceSheetSchema } from './BalanceSheetSchema';
|
||||||
import { BalanceSheetBase } from './BalanceSheetBase';
|
import { BalanceSheetBase } from './BalanceSheetBase';
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
||||||
|
import { flatToNestedArray } from '@/utils';
|
||||||
|
import BalanceSheetRepository from './BalanceSheetRepository';
|
||||||
|
|
||||||
export const BalanceSheetAccounts = (Base: any) =>
|
export const BalanceSheetAccounts = (Base: any) =>
|
||||||
class extends R.compose(
|
class extends R.compose(
|
||||||
@@ -56,6 +58,11 @@ export const BalanceSheetAccounts = (Base: any) =>
|
|||||||
*/
|
*/
|
||||||
readonly i18n: any;
|
readonly i18n: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Balance sheet repository.
|
||||||
|
*/
|
||||||
|
readonly repository: BalanceSheetRepository;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the accounts node of accounts types.
|
* Retrieve the accounts node of accounts types.
|
||||||
* @param {string} accountsTypes
|
* @param {string} accountsTypes
|
||||||
@@ -78,8 +85,12 @@ export const BalanceSheetAccounts = (Base: any) =>
|
|||||||
private reportSchemaAccountNodeMapper = (
|
private reportSchemaAccountNodeMapper = (
|
||||||
account: IAccount
|
account: IAccount
|
||||||
): IBalanceSheetAccountNode => {
|
): IBalanceSheetAccountNode => {
|
||||||
|
const childrenAccountsIds = this.repository.accountsGraph.dependenciesOf(
|
||||||
|
account.id
|
||||||
|
);
|
||||||
|
const accountIds = R.uniq(R.append(account.id, childrenAccountsIds));
|
||||||
const total = this.repository.totalAccountsLedger
|
const total = this.repository.totalAccountsLedger
|
||||||
.whereAccountId(account.id)
|
.whereAccountsIds(accountIds)
|
||||||
.getClosingBalance();
|
.getClosingBalance();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -128,8 +139,19 @@ export const BalanceSheetAccounts = (Base: any) =>
|
|||||||
private getAccountsNodesByAccountTypes = (
|
private getAccountsNodesByAccountTypes = (
|
||||||
accountsTypes: string[]
|
accountsTypes: string[]
|
||||||
): IBalanceSheetAccountNode[] => {
|
): IBalanceSheetAccountNode[] => {
|
||||||
|
// Retrieves accounts from the given defined node account types.
|
||||||
const accounts = this.getAccountsByAccountTypes(accountsTypes);
|
const accounts = this.getAccountsByAccountTypes(accountsTypes);
|
||||||
return R.map(this.reportSchemaAccountNodeComposer, accounts);
|
|
||||||
|
// Converts the flatten accounts to tree.
|
||||||
|
const accountsTree = flatToNestedArray(accounts, {
|
||||||
|
id: 'id',
|
||||||
|
parentId: 'parentAccountId',
|
||||||
|
});
|
||||||
|
// Maps over the accounts tree.
|
||||||
|
return this.mapNodesDeep(
|
||||||
|
accountsTree,
|
||||||
|
this.reportSchemaAccountNodeComposer
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import * as R from 'ramda';
|
|||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
import {
|
import {
|
||||||
IAccount,
|
|
||||||
IAccountTransactionsGroupBy,
|
IAccountTransactionsGroupBy,
|
||||||
IBalanceSheetQuery,
|
IBalanceSheetQuery,
|
||||||
ILedger,
|
ILedger,
|
||||||
@@ -12,7 +11,6 @@ import { transformToMapBy } from 'utils';
|
|||||||
import Ledger from '@/services/Accounting/Ledger';
|
import Ledger from '@/services/Accounting/Ledger';
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
||||||
import { FinancialDatePeriods } from '../FinancialDatePeriods';
|
import { FinancialDatePeriods } from '../FinancialDatePeriods';
|
||||||
import { ACCOUNT_PARENT_TYPE, ACCOUNT_TYPE } from '@/data/AccountTypes';
|
|
||||||
import { BalanceSheetRepositoryNetIncome } from './BalanceSheetRepositoryNetIncome';
|
import { BalanceSheetRepositoryNetIncome } from './BalanceSheetRepositoryNetIncome';
|
||||||
|
|
||||||
@Service()
|
@Service()
|
||||||
@@ -40,6 +38,11 @@ export default class BalanceSheetRepository extends R.compose(
|
|||||||
*/
|
*/
|
||||||
public accounts: any;
|
public accounts: any;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {}
|
||||||
|
*/
|
||||||
|
public accountsGraph: any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@@ -163,6 +166,8 @@ export default class BalanceSheetRepository extends R.compose(
|
|||||||
*/
|
*/
|
||||||
public asyncInitialize = async () => {
|
public asyncInitialize = async () => {
|
||||||
await this.initAccounts();
|
await this.initAccounts();
|
||||||
|
await this.initAccountsGraph();
|
||||||
|
|
||||||
await this.initAccountsTotalLedger();
|
await this.initAccountsTotalLedger();
|
||||||
|
|
||||||
// Date periods.
|
// Date periods.
|
||||||
@@ -204,6 +209,15 @@ export default class BalanceSheetRepository extends R.compose(
|
|||||||
this.accountsByParentType = transformToMapBy(accounts, 'accountParentType');
|
this.accountsByParentType = transformToMapBy(accounts, 'accountParentType');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize accounts graph.
|
||||||
|
*/
|
||||||
|
public initAccountsGraph = async () => {
|
||||||
|
const { Account } = this.models;
|
||||||
|
|
||||||
|
this.accountsGraph = Account.toDependencyGraph(this.accounts);
|
||||||
|
};
|
||||||
|
|
||||||
// ----------------------------
|
// ----------------------------
|
||||||
// # Closing Total
|
// # Closing Total
|
||||||
// ----------------------------
|
// ----------------------------
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ import { ProfitLossSheetPreviousYear } from './ProfitLossSheetPreviousYear';
|
|||||||
import { ProfitLossSheetPreviousPeriod } from './ProfitLossSheetPreviousPeriod';
|
import { ProfitLossSheetPreviousPeriod } from './ProfitLossSheetPreviousPeriod';
|
||||||
import { FinancialDateRanges } from '../FinancialDateRanges';
|
import { FinancialDateRanges } from '../FinancialDateRanges';
|
||||||
import { ProfitLossSheetFilter } from './ProfitLossSheetFilter';
|
import { ProfitLossSheetFilter } from './ProfitLossSheetFilter';
|
||||||
|
import { flatToNestedArray } from '@/utils';
|
||||||
|
|
||||||
export default class ProfitLossSheet extends R.compose(
|
export default class ProfitLossSheet extends R.compose(
|
||||||
ProfitLossSheetPreviousYear,
|
ProfitLossSheetPreviousYear,
|
||||||
@@ -82,14 +83,22 @@ export default class ProfitLossSheet extends R.compose(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the sheet account node from the given account.
|
* Retrieve the sheet account node from the given account.
|
||||||
* @param {IAccount} account
|
* @param {IAccount} account
|
||||||
* @returns {IProfitLossSheetAccountNode}
|
* @returns {IProfitLossSheetAccountNode}
|
||||||
*/
|
*/
|
||||||
private accountNodeMapper = (
|
private accountNodeMapper = (
|
||||||
account: IAccount
|
account: IAccount
|
||||||
): IProfitLossSheetAccountNode => {
|
): IProfitLossSheetAccountNode => {
|
||||||
|
// Retrieves the children account ids of the given account id.
|
||||||
|
const childrenAccountIds = this.repository.accountsGraph.dependenciesOf(
|
||||||
|
account.id
|
||||||
|
);
|
||||||
|
// Concat the children and the given account id.
|
||||||
|
const accountIds = R.uniq(R.append(account.id, childrenAccountIds));
|
||||||
|
|
||||||
|
// Retrieves the closing balance of the account included children accounts.
|
||||||
const total = this.repository.totalAccountsLedger
|
const total = this.repository.totalAccountsLedger
|
||||||
.whereAccountId(account.id)
|
.whereAccountsIds(accountIds)
|
||||||
.getClosingBalance();
|
.getClosingBalance();
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@@ -126,18 +135,19 @@ export default class ProfitLossSheet extends R.compose(
|
|||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve report accounts nodes by the given accounts types.
|
* Retrieves report accounts nodes by the given accounts types.
|
||||||
* @param {string[]} types
|
* @param {string[]} types
|
||||||
* @returns {IBalanceSheetAccountNode}
|
* @returns {IBalanceSheetAccountNode}
|
||||||
*/
|
*/
|
||||||
private getAccountsNodesByTypes = (
|
private getAccountsNodesByTypes = (
|
||||||
types: string[]
|
types: string[]
|
||||||
): IProfitLossSheetAccountNode[] => {
|
): IProfitLossSheetAccountNode[] => {
|
||||||
return R.compose(
|
const accounts = this.repository.getAccountsByType(types);
|
||||||
R.map(this.accountNodeCompose),
|
const accountsTree = flatToNestedArray(accounts, {
|
||||||
R.flatten,
|
id: 'id',
|
||||||
R.map(this.repository.getAccountsByType)
|
parentId: 'parentAccountId',
|
||||||
)(types);
|
});
|
||||||
|
return this.mapNodesDeep(accountsTree, this.accountNodeCompose);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { defaultTo } from 'lodash';
|
import { castArray, defaultTo } from 'lodash';
|
||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import { Knex } from 'knex';
|
import { Knex } from 'knex';
|
||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
@@ -31,6 +31,11 @@ export class ProfitLossSheetRepository extends R.compose(FinancialDatePeriods)(
|
|||||||
*/
|
*/
|
||||||
public accounts: IAccount[];
|
public accounts: IAccount[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public accountsGraph: any;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transactions group type.
|
* Transactions group type.
|
||||||
* @param {IAccountTransactionsGroupBy}
|
* @param {IAccountTransactionsGroupBy}
|
||||||
@@ -135,6 +140,8 @@ export class ProfitLossSheetRepository extends R.compose(FinancialDatePeriods)(
|
|||||||
*/
|
*/
|
||||||
public asyncInitialize = async () => {
|
public asyncInitialize = async () => {
|
||||||
await this.initAccounts();
|
await this.initAccounts();
|
||||||
|
await this.initAccountsGraph();
|
||||||
|
|
||||||
await this.initAccountsTotalLedger();
|
await this.initAccountsTotalLedger();
|
||||||
|
|
||||||
// Date Periods.
|
// Date Periods.
|
||||||
@@ -177,6 +184,15 @@ export class ProfitLossSheetRepository extends R.compose(FinancialDatePeriods)(
|
|||||||
this.accountsByType = transformToMapBy(accounts, 'accountType');
|
this.accountsByType = transformToMapBy(accounts, 'accountType');
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize accounts graph.
|
||||||
|
*/
|
||||||
|
private initAccountsGraph = async () => {
|
||||||
|
const { Account } = this.models;
|
||||||
|
|
||||||
|
this.accountsGraph = Account.toDependencyGraph(this.accounts);
|
||||||
|
};
|
||||||
|
|
||||||
// ----------------------------
|
// ----------------------------
|
||||||
// # Closing Total.
|
// # Closing Total.
|
||||||
// ----------------------------
|
// ----------------------------
|
||||||
@@ -337,7 +353,18 @@ export class ProfitLossSheetRepository extends R.compose(FinancialDatePeriods)(
|
|||||||
return Account.query();
|
return Account.query();
|
||||||
};
|
};
|
||||||
|
|
||||||
public getAccountsByType = (type: string) => {
|
/**
|
||||||
return defaultTo(this.accountsByType.get(type), []);
|
*
|
||||||
|
* @param type
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
public getAccountsByType = (type: string[] | string) => {
|
||||||
|
return R.compose(
|
||||||
|
R.flatten,
|
||||||
|
R.map((accountType) =>
|
||||||
|
R.defaultTo([], this.accountsByType.get(accountType))
|
||||||
|
),
|
||||||
|
castArray
|
||||||
|
)(type);
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user