Skip to content

Commit

Permalink
feat: Computed Net Income under Equity in Balance Sheet report.
Browse files Browse the repository at this point in the history
  • Loading branch information
abouolia committed Oct 16, 2023
1 parent 1ed1c9e commit 846f14d
Show file tree
Hide file tree
Showing 7 changed files with 343 additions and 10 deletions.
24 changes: 21 additions & 3 deletions packages/server/src/interfaces/BalanceSheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ export enum BALANCE_SHEET_SCHEMA_NODE_TYPE {
AGGREGATE = 'AGGREGATE',
ACCOUNTS = 'ACCOUNTS',
ACCOUNT = 'ACCOUNT',
NET_INCOME = 'NET_INCOME',
}

export enum BALANCE_SHEET_NODE_TYPE {
Expand All @@ -33,6 +34,7 @@ export enum BALANCE_SHEET_SCHEMA_NODE_ID {
LOGN_TERM_LIABILITY = 'LOGN_TERM_LIABILITY',
NON_CURRENT_LIABILITY = 'NON_CURRENT_LIABILITY',
EQUITY = 'EQUITY',
NET_INCOME = 'NET_INCOME',
}

// Balance sheet query.
Expand Down Expand Up @@ -87,7 +89,6 @@ export interface IBalanceSheetDOO {
meta: IBalanceSheetMeta;
}


export interface IBalanceSheetCommonNode {
total: IBalanceSheetTotal;
horizontalTotals?: IBalanceSheetTotal[];
Expand All @@ -108,7 +109,11 @@ export interface IBalanceSheetAggregateNode extends IBalanceSheetCommonNode {
id: string;
name: string;
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE;
children?: (IBalanceSheetAggregateNode | IBalanceSheetAccountNode)[];
children?: (
| IBalanceSheetAggregateNode
| IBalanceSheetAccountNode
| IBalanceSheetNetIncomeNode
)[];
}

export interface IBalanceSheetTotal {
Expand All @@ -128,6 +133,12 @@ export interface IBalanceSheetAccountNode extends IBalanceSheetCommonNode {
children?: IBalanceSheetAccountNode[];
}

export interface IBalanceSheetNetIncomeNode extends IBalanceSheetCommonNode {
id: number;
name: string;
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.NET_INCOME;
}

export type IBalanceSheetDataNode = IBalanceSheetAggregateNode;

export interface IBalanceSheetPercentageAmount {
Expand All @@ -150,9 +161,16 @@ export interface IBalanceSheetSchemaAccountNode {
accountsTypes: string[];
}

export interface IBalanceSheetSchemaNetIncomeNode {
id: string;
name: string;
type: BALANCE_SHEET_SCHEMA_NODE_TYPE;
}

export type IBalanceSheetSchemaNode =
| IBalanceSheetSchemaAccountNode
| IBalanceSheetSchemaAggregateNode;
| IBalanceSheetSchemaAggregateNode
| IBalanceSheetSchemaNetIncomeNode;

export interface IBalanceSheetDatePeriods {
assocAccountNodeDatePeriods(node): any;
Expand Down
4 changes: 4 additions & 0 deletions packages/server/src/interfaces/Ledger.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,12 +13,16 @@ export interface ILedger {
whereCurrencyCode(currencyCode: string): ILedger;
whereBranch(branchId: number): ILedger;
whereItem(itemId: number): ILedger;
whereProject(projectId: number): ILedger;

getClosingBalance(): number;
getForeignClosingBalance(): number;

getContactsIds(): number[];
getAccountsIds(): number[];

reverse(): ILedger;
isEmpty(): boolean;
}

export interface ILedgerEntry {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,10 @@ import { FinancialSheetStructure } from '../FinancialSheetStructure';
import BalanceSheetRepository from './BalanceSheetRepository';
import { BalanceSheetQuery } from './BalanceSheetQuery';
import { BalanceSheetFiltering } from './BalanceSheetFiltering';
import { BalanceSheetNetIncome } from './BalanceSheetNetIncome';

export default class BalanceSheet extends R.compose(
BalanceSheetNetIncome,
BalanceSheetFiltering,
BalanceSheetDatePeriods,
BalanceSheetComparsionPreviousPeriod,
Expand Down Expand Up @@ -251,6 +253,10 @@ export default class BalanceSheet extends R.compose(
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS),
this.reportSchemaAccountsNodeComposer
)
R.when(
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.NET_INCOME),
this.schemaNetIncomeNodeCompose
)
)(schemaNode);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
IBalanceSheetAggregateNode,
IBalanceSheetTotal,
IBalanceSheetCommonNode,
IBalanceSheetComparsions,
} from '@/interfaces';
import { FinancialPreviousPeriod } from '../FinancialPreviousPeriod';
import { FinancialHorizTotals } from '../FinancialHorizTotals';
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,242 @@
import * as R from 'ramda';
import { sumBy, isEmpty } from 'lodash';
import {
BALANCE_SHEET_SCHEMA_NODE_TYPE,
IBalanceSheetAccountNode,
IBalanceSheetAggregateNode,
IBalanceSheetSchemaAggregateNode,
IBalanceSheetTotalPeriod,
} from '@/interfaces';
import { BalanceSheetComparsionPreviousYear } from './BalanceSheetComparsionPreviousYear';
import { BalanceSheetComparsionPreviousPeriod } from './BalanceSheetComparsionPreviousPeriod';
import { FinancialPreviousPeriod } from '../FinancialPreviousPeriod';
import { FinancialHorizTotals } from '../FinancialHorizTotals';
import BalanceSheetRepository from './BalanceSheetRepository';
import { ACCOUNT_TYPE } from '@/data/AccountTypes';

export const BalanceSheetNetIncome = (Base: any) =>
class extends R.compose(
BalanceSheetComparsionPreviousYear,
BalanceSheetComparsionPreviousPeriod,
FinancialPreviousPeriod,
FinancialHorizTotals
)(Base) {
private repository: BalanceSheetRepository;

/**
* Retrieves the closing balance of income accounts.
* @returns {number}
*/
private getIncomeTotal = () => {
const closeingBalance = this.repository.incomeLedger.getClosingBalance();

return closeingBalance;
};

/**
* Retrieves the closing balance of expenses accounts.
* @returns {number}
*/
private getExpensesTotal = () => {
const closingBalance = this.repository.expensesLedger.getClosingBalance();

return closingBalance;
};

/**
* Retrieves the total net income.
* @returns {number}
*/
protected getNetIncomeTotal = () => {
const income = this.getIncomeTotal();
const expenses = this.getExpensesTotal();

return income - expenses;
};

/**
* Mappes the aggregate schema node type.
* @param {IBalanceSheetSchemaAggregateNode} node - Schema node.
* @return {IBalanceSheetAggregateNode}
*/
protected schemaNetIncomeNodeMapper = (
node: IBalanceSheetSchemaAggregateNode
): IBalanceSheetAggregateNode => {
const total = this.getNetIncomeTotal();

return {
name: this.i18n.__(node.name),
id: node.id,
nodeType: BALANCE_SHEET_SCHEMA_NODE_TYPE.NET_INCOME,
total: this.getTotalAmountMeta(total),
children: node.children,
};
};

/**
* Mapps the net income shcema node to report node.
* @param {IBalanceSheetSchemaAggregateNode} node
* @returns
*/
protected schemaNetIncomeNodeCompose = (
node: IBalanceSheetSchemaAggregateNode
) => {
return R.compose(
R.when(
this.query.isPreviousYearActive,
this.previousYearNetIncomeNodeCompose
),
R.when(
this.query.isPreviousPeriodActive,
this.previousPeriodNetIncomeNodeCompose
),
R.when(
this.query.isDatePeriodsColumnsType,
this.assocNetIncomeDatePeriodsNode
),
this.schemaNetIncomeNodeMapper
)(node);
};

// ------------------------------
// # Previous Year (PY)
// ------------------------------
/**
* Assoc previous year on aggregate node.
* @param {IBalanceSheetAccountNode} node
* @returns {IBalanceSheetAccountNode}
*/
protected assocPreviousYearAggregateNode = (
node: IBalanceSheetAccountNode
): IBalanceSheetAccountNode => {
const total = sumBy(node.children, 'previousYear.amount');

return R.assoc('previousYear', this.getTotalAmountMeta(total), node);
};

/**
* Assoc previous year attributes to aggregate node.
* @param {IBalanceSheetAccountNode} node
* @returns {IBalanceSheetAccountNode}
*/
protected previousYearNetIncomeNodeCompose = (
node: IBalanceSheetAccountNode
): IBalanceSheetAccountNode => {
return R.compose(
R.when(
this.query.isPreviousYearPercentageActive,
this.assocPreviousYearTotalPercentageNode
),
R.when(
this.query.isPreviousYearChangeActive,
this.assocPreviousYearTotalChangeNode
),
R.when(
this.isNodeHasHorizontalTotals,
this.assocPreviousYearAggregateHorizNode
),
this.assocPreviousYearAggregateNode
)(node);
};

// -------------------------------
// # Previous Period (PP)
// -------------------------------

/**
* Previous period account node composer.
* @param {IBalanceSheetAccountNode} node
* @returns {IBalanceSheetAccountNode}
*/
protected previousPeriodNetIncomeNodeCompose = (
node: IBalanceSheetAccountNode
): IBalanceSheetAccountNode => {
return R.compose(
// R.when(
// this.isNodeHasHorizTotals,
// this.assocPreivousPeriodAccountHorizNodeComposer
// ),
R.when(
this.query.isPreviousPeriodPercentageActive,
this.assocPreviousPeriodPercentageNode
),
R.when(
this.query.isPreviousPeriodChangeActive,
this.assocPreviousPeriodChangeNode
),
R.when(
this.query.isPreviousPeriodActive,
this.assocPreviousPeriodAccountNode
)
)(node);
};

// --------------------------------
// # Date Periods
// --------------------------------
/**
* Retrieve the given net income date period total.
* @param {number} accountId
* @param {Date} toDate
* @returns {number}
*/
private getNetIncomeDatePeriodTotal = (
accountId: number,
toDate: Date
): number => {
const periodTotalBetween = this.repository.periodsAccountsLedger
.whereAccountId(accountId)
.whereToDate(toDate)
.getClosingBalance();

const periodOpening = this.repository.periodsOpeningAccountLedger
.whereAccountId(accountId)
.getClosingBalance();

return periodOpening + periodTotalBetween;
};

/**
*
* @param {IBalanceSheetAccountNode} node
* @param {Date} fromDate
* @param {Date} toDate
* @returns {IBalanceSheetAccountNode}
*/
private getNetIncomeDatePeriodNode = (
node: IBalanceSheetAccountNode,
fromDate: Date,
toDate: Date
): IBalanceSheetTotalPeriod => {
const periodTotal = this.getNetIncomeDatePeriodTotal(node.id, toDate);

return this.getDatePeriodTotalMeta(periodTotal, fromDate, toDate);
};

/**
* Retrieve total date periods of the given net income node.
* @param {IBalanceSheetAccountNode} node
* @returns {IBalanceSheetAccountNode}
*/
private getNetIncomeDatePeriodsNode = (
node: IBalanceSheetAccountNode
): IBalanceSheetTotalPeriod[] => {
return this.getReportNodeDatePeriods(
node,
this.getNetIncomeDatePeriodNode
);
};

/**
* Assoc total date periods to net income node.
* @param {IBalanceSheetAccountNode} node
* @returns {IBalanceSheetAccountNode}
*/
public assocNetIncomeDatePeriodsNode = (
node: IBalanceSheetAccountNode
): IBalanceSheetAccountNode => {
const datePeriods = this.getNetIncomeDatePeriodsNode(node);

return R.assoc('horizontalTotals', datePeriods, node);
};
};
Loading

0 comments on commit 846f14d

Please sign in to comment.