mirror of
https://github.com/bigcapitalhq/bigcapital.git
synced 2026-02-22 15:50:32 +00:00
refactor: balance sheet to nestjs
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
import { Response } from 'express';
|
import { Response } from 'express';
|
||||||
import { castArray } from 'lodash';
|
|
||||||
import { Controller, Headers, Query, Res } from '@nestjs/common';
|
import { Controller, Headers, Query, Res } from '@nestjs/common';
|
||||||
import { IBalanceSheetQuery } from './BalanceSheet.types';
|
import { IBalanceSheetQuery } from './BalanceSheet.types';
|
||||||
import { AcceptType } from '@/constants/accept-type';
|
import { AcceptType } from '@/constants/accept-type';
|
||||||
@@ -20,18 +19,14 @@ export class BalanceSheetStatementController {
|
|||||||
@Res() res: Response,
|
@Res() res: Response,
|
||||||
@Headers('accept') acceptHeader: string,
|
@Headers('accept') acceptHeader: string,
|
||||||
) {
|
) {
|
||||||
const filter = {
|
|
||||||
...query,
|
|
||||||
accountsIds: castArray(query.accountsIds),
|
|
||||||
};
|
|
||||||
// Retrieves the json table format.
|
// Retrieves the json table format.
|
||||||
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
|
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
|
||||||
const table = await this.balanceSheetApp.table(filter);
|
const table = await this.balanceSheetApp.table(query);
|
||||||
|
|
||||||
return res.status(200).send(table);
|
return res.status(200).send(table);
|
||||||
// Retrieves the csv format.
|
// Retrieves the csv format.
|
||||||
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
|
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
|
||||||
const buffer = await this.balanceSheetApp.csv(filter);
|
const buffer = await this.balanceSheetApp.csv(query);
|
||||||
|
|
||||||
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
|
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
|
||||||
res.setHeader('Content-Type', 'text/csv');
|
res.setHeader('Content-Type', 'text/csv');
|
||||||
@@ -39,7 +34,7 @@ export class BalanceSheetStatementController {
|
|||||||
return res.send(buffer);
|
return res.send(buffer);
|
||||||
// Retrieves the xlsx format.
|
// Retrieves the xlsx format.
|
||||||
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
|
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
|
||||||
const buffer = await this.balanceSheetApp.xlsx(filter);
|
const buffer = await this.balanceSheetApp.xlsx(query);
|
||||||
|
|
||||||
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
|
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
|
||||||
res.setHeader(
|
res.setHeader(
|
||||||
@@ -49,7 +44,7 @@ export class BalanceSheetStatementController {
|
|||||||
return res.send(buffer);
|
return res.send(buffer);
|
||||||
// Retrieves the pdf format.
|
// Retrieves the pdf format.
|
||||||
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
|
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
|
||||||
const pdfContent = await this.balanceSheetApp.pdf(filter);
|
const pdfContent = await this.balanceSheetApp.pdf(query);
|
||||||
|
|
||||||
res.set({
|
res.set({
|
||||||
'Content-Type': 'application/pdf',
|
'Content-Type': 'application/pdf',
|
||||||
@@ -57,7 +52,7 @@ export class BalanceSheetStatementController {
|
|||||||
});
|
});
|
||||||
res.send(pdfContent);
|
res.send(pdfContent);
|
||||||
} else {
|
} else {
|
||||||
const sheet = await this.balanceSheetApp.sheet(filter);
|
const sheet = await this.balanceSheetApp.sheet(query);
|
||||||
|
|
||||||
return res.status(200).send(sheet);
|
return res.status(200).send(sheet);
|
||||||
}
|
}
|
||||||
@@ -43,8 +43,10 @@ export enum BALANCE_SHEET_SCHEMA_NODE_ID {
|
|||||||
export interface IBalanceSheetQuery extends IFinancialSheetBranchesQuery {
|
export interface IBalanceSheetQuery extends IFinancialSheetBranchesQuery {
|
||||||
displayColumnsType: 'total' | 'date_periods';
|
displayColumnsType: 'total' | 'date_periods';
|
||||||
displayColumnsBy: string;
|
displayColumnsBy: string;
|
||||||
|
|
||||||
fromDate: string;
|
fromDate: string;
|
||||||
toDate: string;
|
toDate: string;
|
||||||
|
|
||||||
numberFormat: INumberFormatQuery;
|
numberFormat: INumberFormatQuery;
|
||||||
noneTransactions: boolean;
|
noneTransactions: boolean;
|
||||||
noneZero: boolean;
|
noneZero: boolean;
|
||||||
@@ -19,13 +19,16 @@ import { BalanceSheetSchema } from './BalanceSheetSchema';
|
|||||||
import { BalanceSheetBase } from './BalanceSheetBase';
|
import { BalanceSheetBase } from './BalanceSheetBase';
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
||||||
import { BalanceSheetRepository } from './BalanceSheetRepository';
|
import { BalanceSheetRepository } from './BalanceSheetRepository';
|
||||||
import { Constructor } from '@/common/types/Constructor';
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
import { INumberFormatQuery } from '../../types/Report.types';
|
import { INumberFormatQuery } from '../../types/Report.types';
|
||||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||||
import { flatToNestedArray } from '@/utils/flat-to-nested-array';
|
import { flatToNestedArray } from '@/utils/flat-to-nested-array';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
|
||||||
export const BalanceSheetAccounts = <T extends Constructor>(Base: T) =>
|
export const BalanceSheetAccounts = <T extends GConstructor<FinancialSheet>>(
|
||||||
class extends R.compose(
|
Base: T,
|
||||||
|
) =>
|
||||||
|
class extends R.pipe(
|
||||||
BalanceSheetNetIncome,
|
BalanceSheetNetIncome,
|
||||||
BalanceSheetFiltering,
|
BalanceSheetFiltering,
|
||||||
BalanceSheetDatePeriods,
|
BalanceSheetDatePeriods,
|
||||||
@@ -34,7 +37,7 @@ export const BalanceSheetAccounts = <T extends Constructor>(Base: T) =>
|
|||||||
BalanceSheetPercentage,
|
BalanceSheetPercentage,
|
||||||
BalanceSheetSchema,
|
BalanceSheetSchema,
|
||||||
BalanceSheetBase,
|
BalanceSheetBase,
|
||||||
FinancialSheetStructure
|
FinancialSheetStructure,
|
||||||
)(Base) {
|
)(Base) {
|
||||||
/**
|
/**
|
||||||
* Balance sheet query.
|
* Balance sheet query.
|
||||||
@@ -70,10 +73,10 @@ export const BalanceSheetAccounts = <T extends Constructor>(Base: T) =>
|
|||||||
* @returns {IAccount[]}
|
* @returns {IAccount[]}
|
||||||
*/
|
*/
|
||||||
private getAccountsByAccountTypes = (
|
private getAccountsByAccountTypes = (
|
||||||
accountsTypes: string[]
|
accountsTypes: string[],
|
||||||
): Account[] => {
|
): Account[] => {
|
||||||
const mapAccountsByTypes = R.map((accountType) =>
|
const mapAccountsByTypes = R.map((accountType) =>
|
||||||
defaultTo(this.repository.accountsByType.get(accountType), [])
|
defaultTo(this.repository.accountsByType.get(accountType), []),
|
||||||
);
|
);
|
||||||
return R.compose(R.flatten, mapAccountsByTypes)(accountsTypes);
|
return R.compose(R.flatten, mapAccountsByTypes)(accountsTypes);
|
||||||
};
|
};
|
||||||
@@ -84,10 +87,10 @@ export const BalanceSheetAccounts = <T extends Constructor>(Base: T) =>
|
|||||||
* @returns {IBalanceSheetAccountNode}
|
* @returns {IBalanceSheetAccountNode}
|
||||||
*/
|
*/
|
||||||
private reportSchemaAccountNodeMapper = (
|
private reportSchemaAccountNodeMapper = (
|
||||||
account: Account
|
account: Account,
|
||||||
): IBalanceSheetAccountNode => {
|
): IBalanceSheetAccountNode => {
|
||||||
const childrenAccountsIds = this.repository.accountsGraph.dependenciesOf(
|
const childrenAccountsIds = this.repository.accountsGraph.dependenciesOf(
|
||||||
account.id
|
account.id,
|
||||||
);
|
);
|
||||||
const accountIds = R.uniq(R.append(account.id, childrenAccountsIds));
|
const accountIds = R.uniq(R.append(account.id, childrenAccountsIds));
|
||||||
const total = this.repository.totalAccountsLedger
|
const total = this.repository.totalAccountsLedger
|
||||||
@@ -110,22 +113,22 @@ export const BalanceSheetAccounts = <T extends Constructor>(Base: T) =>
|
|||||||
* @returns {IBalanceSheetAccountNode}
|
* @returns {IBalanceSheetAccountNode}
|
||||||
*/
|
*/
|
||||||
private reportSchemaAccountNodeComposer = (
|
private reportSchemaAccountNodeComposer = (
|
||||||
account: Account
|
account: Account,
|
||||||
): IBalanceSheetAccountNode => {
|
): IBalanceSheetAccountNode => {
|
||||||
return R.compose(
|
return R.compose(
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearActive,
|
this.query.isPreviousYearActive,
|
||||||
this.previousYearAccountNodeComposer
|
this.previousYearAccountNodeComposer,
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousPeriodActive,
|
this.query.isPreviousPeriodActive,
|
||||||
this.previousPeriodAccountNodeComposer
|
this.previousPeriodAccountNodeComposer,
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isDatePeriodsColumnsType,
|
this.query.isDatePeriodsColumnsType,
|
||||||
this.assocAccountNodeDatePeriods
|
this.assocAccountNodeDatePeriods,
|
||||||
),
|
),
|
||||||
this.reportSchemaAccountNodeMapper
|
this.reportSchemaAccountNodeMapper,
|
||||||
)(account);
|
)(account);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -138,7 +141,7 @@ export const BalanceSheetAccounts = <T extends Constructor>(Base: T) =>
|
|||||||
* @returns {IBalanceSheetAccountNode[]}
|
* @returns {IBalanceSheetAccountNode[]}
|
||||||
*/
|
*/
|
||||||
private getAccountsNodesByAccountTypes = (
|
private getAccountsNodesByAccountTypes = (
|
||||||
accountsTypes: string[]
|
accountsTypes: string[],
|
||||||
): IBalanceSheetAccountNode[] => {
|
): IBalanceSheetAccountNode[] => {
|
||||||
// Retrieves accounts from the given defined node account types.
|
// Retrieves accounts from the given defined node account types.
|
||||||
const accounts = this.getAccountsByAccountTypes(accountsTypes);
|
const accounts = this.getAccountsByAccountTypes(accountsTypes);
|
||||||
@@ -151,7 +154,7 @@ export const BalanceSheetAccounts = <T extends Constructor>(Base: T) =>
|
|||||||
// Maps over the accounts tree.
|
// Maps over the accounts tree.
|
||||||
return this.mapNodesDeep(
|
return this.mapNodesDeep(
|
||||||
accountsTree,
|
accountsTree,
|
||||||
this.reportSchemaAccountNodeComposer
|
this.reportSchemaAccountNodeComposer,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -161,7 +164,7 @@ export const BalanceSheetAccounts = <T extends Constructor>(Base: T) =>
|
|||||||
* @returns {IBalanceSheetAccountNode}
|
* @returns {IBalanceSheetAccountNode}
|
||||||
*/
|
*/
|
||||||
private reportSchemaAccountsNodeMapper = (
|
private reportSchemaAccountsNodeMapper = (
|
||||||
node: IBalanceSheetSchemaAccountNode
|
node: IBalanceSheetSchemaAccountNode,
|
||||||
): IBalanceSheetAccountsNode => {
|
): IBalanceSheetAccountsNode => {
|
||||||
const accounts = this.getAccountsNodesByAccountTypes(node.accountsTypes);
|
const accounts = this.getAccountsNodesByAccountTypes(node.accountsTypes);
|
||||||
const children = toArray(node?.children);
|
const children = toArray(node?.children);
|
||||||
@@ -182,13 +185,13 @@ export const BalanceSheetAccounts = <T extends Constructor>(Base: T) =>
|
|||||||
* @return {IBalanceSheetSchemaNode | IBalanceSheetDataNode}
|
* @return {IBalanceSheetSchemaNode | IBalanceSheetDataNode}
|
||||||
*/
|
*/
|
||||||
private reportAccountSchemaParser = (
|
private reportAccountSchemaParser = (
|
||||||
node: IBalanceSheetSchemaNode | IBalanceSheetDataNode
|
node: IBalanceSheetSchemaNode | IBalanceSheetDataNode,
|
||||||
): IBalanceSheetSchemaNode | IBalanceSheetDataNode => {
|
): IBalanceSheetSchemaNode | IBalanceSheetDataNode => {
|
||||||
return R.compose(
|
return R.compose(
|
||||||
R.when(
|
R.when(
|
||||||
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS),
|
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS),
|
||||||
this.reportSchemaAccountsNodeMapper
|
this.reportSchemaAccountsNodeMapper,
|
||||||
)
|
),
|
||||||
)(node);
|
)(node);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -198,7 +201,7 @@ export const BalanceSheetAccounts = <T extends Constructor>(Base: T) =>
|
|||||||
* @return {IBalanceSheetStructureSection[]}
|
* @return {IBalanceSheetStructureSection[]}
|
||||||
*/
|
*/
|
||||||
public accountsSchemaParser = (
|
public accountsSchemaParser = (
|
||||||
nodes: (IBalanceSheetSchemaNode | IBalanceSheetDataNode)[]
|
nodes: (IBalanceSheetSchemaNode | IBalanceSheetDataNode)[],
|
||||||
): (IBalanceSheetDataNode | IBalanceSheetSchemaNode)[] => {
|
): (IBalanceSheetDataNode | IBalanceSheetSchemaNode)[] => {
|
||||||
return this.mapNodesDeepReverse(nodes, this.reportAccountSchemaParser);
|
return this.mapNodesDeepReverse(nodes, this.reportAccountSchemaParser);
|
||||||
};
|
};
|
||||||
@@ -14,18 +14,21 @@ import { BalanceSheetSchema } from './BalanceSheetSchema';
|
|||||||
import { BalanceSheetBase } from './BalanceSheetBase';
|
import { BalanceSheetBase } from './BalanceSheetBase';
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
||||||
import { FinancialSheetStructure } from '../../common/FinancialSheetStructure';
|
import { FinancialSheetStructure } from '../../common/FinancialSheetStructure';
|
||||||
import { Constructor } from '@/common/types/Constructor';
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
import { INumberFormatQuery } from '../../types/Report.types';
|
import { INumberFormatQuery } from '../../types/Report.types';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
|
||||||
export const BalanceSheetAggregators = <T extends Constructor>(Base: T) =>
|
export const BalanceSheetAggregators = <T extends GConstructor<FinancialSheet>>(
|
||||||
class extends R.compose(
|
Base: T,
|
||||||
|
) =>
|
||||||
|
class extends R.pipe(
|
||||||
BalanceSheetDatePeriods,
|
BalanceSheetDatePeriods,
|
||||||
BalanceSheetComparsionPreviousPeriod,
|
BalanceSheetComparsionPreviousPeriod,
|
||||||
BalanceSheetComparsionPreviousYear,
|
BalanceSheetComparsionPreviousYear,
|
||||||
BalanceSheetPercentage,
|
BalanceSheetPercentage,
|
||||||
BalanceSheetSchema,
|
BalanceSheetSchema,
|
||||||
BalanceSheetBase,
|
BalanceSheetBase,
|
||||||
FinancialSheetStructure
|
FinancialSheetStructure,
|
||||||
)(Base) {
|
)(Base) {
|
||||||
/**
|
/**
|
||||||
* Balance sheet query.
|
* Balance sheet query.
|
||||||
@@ -56,21 +59,21 @@ export const BalanceSheetAggregators = <T extends Constructor>(Base: T) =>
|
|||||||
* @returns {IBalanceSheetDataNode}
|
* @returns {IBalanceSheetDataNode}
|
||||||
*/
|
*/
|
||||||
public aggregateNodeTotalMapper = (
|
public aggregateNodeTotalMapper = (
|
||||||
node: IBalanceSheetDataNode
|
node: IBalanceSheetDataNode,
|
||||||
): IBalanceSheetDataNode => {
|
): IBalanceSheetDataNode => {
|
||||||
return R.compose(
|
return R.compose(
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearActive,
|
this.query.isPreviousYearActive,
|
||||||
this.previousYearAggregateNodeComposer
|
this.previousYearAggregateNodeComposer,
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousPeriodActive,
|
this.query.isPreviousPeriodActive,
|
||||||
this.previousPeriodAggregateNodeComposer
|
this.previousPeriodAggregateNodeComposer,
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isDatePeriodsColumnsType,
|
this.query.isDatePeriodsColumnsType,
|
||||||
this.assocAggregateNodeDatePeriods
|
this.assocAggregateNodeDatePeriods,
|
||||||
)
|
),
|
||||||
)(node);
|
)(node);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -80,7 +83,7 @@ export const BalanceSheetAggregators = <T extends Constructor>(Base: T) =>
|
|||||||
* @return {IBalanceSheetAggregateNode}
|
* @return {IBalanceSheetAggregateNode}
|
||||||
*/
|
*/
|
||||||
public reportSchemaAggregateNodeMapper = (
|
public reportSchemaAggregateNodeMapper = (
|
||||||
node: IBalanceSheetSchemaAggregateNode
|
node: IBalanceSheetSchemaAggregateNode,
|
||||||
): IBalanceSheetAggregateNode => {
|
): IBalanceSheetAggregateNode => {
|
||||||
const total = this.getTotalOfNodes(node.children);
|
const total = this.getTotalOfNodes(node.children);
|
||||||
|
|
||||||
@@ -100,11 +103,11 @@ export const BalanceSheetAggregators = <T extends Constructor>(Base: T) =>
|
|||||||
* @returns {IBalanceSheetSchemaAggregateNode}
|
* @returns {IBalanceSheetSchemaAggregateNode}
|
||||||
*/
|
*/
|
||||||
public schemaAggregateNodeCompose = (
|
public schemaAggregateNodeCompose = (
|
||||||
node: IBalanceSheetSchemaAggregateNode
|
node: IBalanceSheetSchemaAggregateNode,
|
||||||
) => {
|
) => {
|
||||||
return R.compose(
|
return R.compose(
|
||||||
this.aggregateNodeTotalMapper,
|
this.aggregateNodeTotalMapper,
|
||||||
this.reportSchemaAggregateNodeMapper
|
this.reportSchemaAggregateNodeMapper,
|
||||||
)(node);
|
)(node);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -114,17 +117,17 @@ export const BalanceSheetAggregators = <T extends Constructor>(Base: T) =>
|
|||||||
* @return {IBalanceSheetDataNode}
|
* @return {IBalanceSheetDataNode}
|
||||||
*/
|
*/
|
||||||
public reportAggregateSchemaParser = (
|
public reportAggregateSchemaParser = (
|
||||||
node: IBalanceSheetSchemaNode
|
node: IBalanceSheetSchemaNode,
|
||||||
): IBalanceSheetDataNode => {
|
): IBalanceSheetDataNode => {
|
||||||
return R.compose(
|
return R.compose(
|
||||||
R.when(
|
R.when(
|
||||||
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE),
|
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.AGGREGATE),
|
||||||
this.schemaAggregateNodeCompose
|
this.schemaAggregateNodeCompose,
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS),
|
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.ACCOUNTS),
|
||||||
this.schemaAggregateNodeCompose
|
this.schemaAggregateNodeCompose,
|
||||||
)
|
),
|
||||||
)(node);
|
)(node);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -134,7 +137,7 @@ export const BalanceSheetAggregators = <T extends Constructor>(Base: T) =>
|
|||||||
* @return {IBalanceSheetStructureSection[]}
|
* @return {IBalanceSheetStructureSection[]}
|
||||||
*/
|
*/
|
||||||
public aggregatesSchemaParser = (
|
public aggregatesSchemaParser = (
|
||||||
nodes: (IBalanceSheetSchemaNode | IBalanceSheetDataNode)[]
|
nodes: (IBalanceSheetSchemaNode | IBalanceSheetDataNode)[],
|
||||||
): (IBalanceSheetDataNode | IBalanceSheetSchemaNode)[] => {
|
): (IBalanceSheetDataNode | IBalanceSheetSchemaNode)[] => {
|
||||||
return this.mapNodesDeepReverse(nodes, this.reportAggregateSchemaParser);
|
return this.mapNodesDeepReverse(nodes, this.reportAggregateSchemaParser);
|
||||||
};
|
};
|
||||||
@@ -3,9 +3,12 @@ import {
|
|||||||
IBalanceSheetDataNode,
|
IBalanceSheetDataNode,
|
||||||
IBalanceSheetSchemaNode,
|
IBalanceSheetSchemaNode,
|
||||||
} from './BalanceSheet.types';
|
} from './BalanceSheet.types';
|
||||||
import { Constructor } from '@/common/types/Constructor';
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
|
||||||
export const BalanceSheetBase = <T extends Constructor>(Base: T) =>
|
export const BalanceSheetBase = <T extends GConstructor<FinancialSheet>>(
|
||||||
|
Base: T,
|
||||||
|
) =>
|
||||||
class BalanceSheetBase extends Base {
|
class BalanceSheetBase extends Base {
|
||||||
/**
|
/**
|
||||||
* Detarmines the node type of the given schema node.
|
* Detarmines the node type of the given schema node.
|
||||||
@@ -9,14 +9,17 @@ import {
|
|||||||
} from './BalanceSheet.types';
|
} from './BalanceSheet.types';
|
||||||
import { FinancialPreviousPeriod } from '../../common/FinancialPreviousPeriod';
|
import { FinancialPreviousPeriod } from '../../common/FinancialPreviousPeriod';
|
||||||
import { FinancialHorizTotals } from '../../common/FinancialHorizTotals';
|
import { FinancialHorizTotals } from '../../common/FinancialHorizTotals';
|
||||||
import { Constructor } from '@/common/types/Constructor';
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
|
||||||
export const BalanceSheetComparsionPreviousPeriod = <T extends Constructor>(
|
export const BalanceSheetComparsionPreviousPeriod = <
|
||||||
|
T extends GConstructor<FinancialSheet>,
|
||||||
|
>(
|
||||||
Base: T,
|
Base: T,
|
||||||
) =>
|
) =>
|
||||||
class BalanceSheetComparsionPreviousPeriod extends R.compose(
|
class BalanceSheetComparsionPreviousPeriod extends R.pipe(
|
||||||
FinancialPreviousPeriod,
|
|
||||||
FinancialHorizTotals,
|
FinancialHorizTotals,
|
||||||
|
FinancialPreviousPeriod,
|
||||||
)(Base) {
|
)(Base) {
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
// # Account
|
// # Account
|
||||||
@@ -7,15 +7,22 @@ import {
|
|||||||
IBalanceSheetTotal,
|
IBalanceSheetTotal,
|
||||||
} from './BalanceSheet.types';
|
} from './BalanceSheet.types';
|
||||||
import { FinancialPreviousYear } from '../../common/FinancialPreviousYear';
|
import { FinancialPreviousYear } from '../../common/FinancialPreviousYear';
|
||||||
import { IBalanceSheetComparsions } from './BalanceSheet.types';
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
import { Constructor } from '@/common/types/Constructor';
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
||||||
|
import { BalanceSheetRepository } from './BalanceSheetRepository';
|
||||||
|
|
||||||
export const BalanceSheetComparsionPreviousYear = <T extends Constructor>(
|
export const BalanceSheetComparsionPreviousYear = <
|
||||||
|
T extends GConstructor<FinancialSheet>,
|
||||||
|
>(
|
||||||
Base: T,
|
Base: T,
|
||||||
) =>
|
) =>
|
||||||
class BalanceSheetComparsionPreviousYear extends R.compose(
|
class BalanceSheetComparsionPreviousYear extends R.pipe(
|
||||||
FinancialPreviousYear,
|
FinancialPreviousYear,
|
||||||
)(Base) {
|
)(Base) {
|
||||||
|
query: BalanceSheetQuery;
|
||||||
|
repository: BalanceSheetRepository;
|
||||||
|
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
// # Account
|
// # Account
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
@@ -8,17 +8,21 @@ import {
|
|||||||
} from './BalanceSheet.types';
|
} from './BalanceSheet.types';
|
||||||
import { FinancialDatePeriods } from '../../common/FinancialDatePeriods';
|
import { FinancialDatePeriods } from '../../common/FinancialDatePeriods';
|
||||||
import { IDateRange, IFormatNumberSettings } from '../../types/Report.types';
|
import { IDateRange, IFormatNumberSettings } from '../../types/Report.types';
|
||||||
import { Constructor } from '@/common/types/Constructor';
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Balance sheet date periods.
|
* Balance sheet date periods.
|
||||||
*/
|
*/
|
||||||
export const BalanceSheetDatePeriods = <T extends Constructor>(Base: T) =>
|
export const BalanceSheetDatePeriods = <T extends GConstructor<FinancialSheet>>(
|
||||||
class BalanceSheetDatePeriods extends R.compose(FinancialDatePeriods)(Base) {
|
Base: T,
|
||||||
|
) =>
|
||||||
|
class BalanceSheetDatePeriods extends R.pipe(FinancialDatePeriods)(Base) {
|
||||||
/**
|
/**
|
||||||
* @param {IBalanceSheetQuery}
|
* @param {IBalanceSheetQuery}
|
||||||
*/
|
*/
|
||||||
readonly query: IBalanceSheetQuery;
|
public readonly query: BalanceSheetQuery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the date periods based on the report query.
|
* Retrieves the date periods based on the report query.
|
||||||
@@ -4,15 +4,25 @@ import {
|
|||||||
IBalanceSheetDataNode,
|
IBalanceSheetDataNode,
|
||||||
BALANCE_SHEET_NODE_TYPE,
|
BALANCE_SHEET_NODE_TYPE,
|
||||||
} from './BalanceSheet.types';
|
} from './BalanceSheet.types';
|
||||||
import { Constructor } from '@/common/types/Constructor';
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
import { FinancialFilter } from '../../common/FinancialFilter';
|
import { FinancialFilter } from '../../common/FinancialFilter';
|
||||||
import { BalanceSheetBase } from './BalanceSheetBase';
|
import { BalanceSheetBase } from './BalanceSheetBase';
|
||||||
import { BalanceSheetRepository } from './BalanceSheetRepository';
|
import { BalanceSheetRepository } from './BalanceSheetRepository';
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
import { FinancialSheetStructure } from '../../common/FinancialSheetStructure';
|
||||||
|
|
||||||
export const BalanceSheetFiltering = <T extends Constructor>(Base: T) =>
|
export const BalanceSheetFiltering = <T extends GConstructor<FinancialSheet>>(
|
||||||
class extends R.pipe(FinancialFilter, BalanceSheetBase)(Base) {
|
Base: T,
|
||||||
public repository: BalanceSheetRepository;
|
) =>
|
||||||
|
class extends R.pipe(
|
||||||
|
FinancialFilter,
|
||||||
|
FinancialSheetStructure,
|
||||||
|
BalanceSheetBase,
|
||||||
|
)(Base) {
|
||||||
|
/**
|
||||||
|
* @description Repository.
|
||||||
|
*/
|
||||||
|
readonly repository: BalanceSheetRepository;
|
||||||
|
|
||||||
// -----------------------
|
// -----------------------
|
||||||
// # Account
|
// # Account
|
||||||
@@ -5,18 +5,13 @@ import { IBalanceSheetMeta, IBalanceSheetQuery } from './BalanceSheet.types';
|
|||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class BalanceSheetMetaInjectable {
|
export class BalanceSheetMetaInjectable {
|
||||||
constructor(
|
constructor(private readonly financialSheetMeta: FinancialSheetMeta) {}
|
||||||
private readonly financialSheetMeta: FinancialSheetMeta,
|
|
||||||
) {}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the balance sheet meta.
|
* Retrieves the balance sheet meta.
|
||||||
* @param {number} tenantId -
|
|
||||||
* @returns {IBalanceSheetMeta}
|
* @returns {IBalanceSheetMeta}
|
||||||
*/
|
*/
|
||||||
public async meta(
|
public async meta(query: IBalanceSheetQuery): Promise<IBalanceSheetMeta> {
|
||||||
query: IBalanceSheetQuery
|
|
||||||
): Promise<IBalanceSheetMeta> {
|
|
||||||
const commonMeta = await this.financialSheetMeta.meta();
|
const commonMeta = await this.financialSheetMeta.meta();
|
||||||
const formattedAsDate = moment(query.toDate).format('YYYY/MM/DD');
|
const formattedAsDate = moment(query.toDate).format('YYYY/MM/DD');
|
||||||
const formattedDateRange = `As ${formattedAsDate}`;
|
const formattedDateRange = `As ${formattedAsDate}`;
|
||||||
@@ -15,15 +15,19 @@ import { BalanceSheetRepository } from './BalanceSheetRepository';
|
|||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
||||||
import { BalanceSheetNetIncomePP } from './BalanceSheetNetIncomePP';
|
import { BalanceSheetNetIncomePP } from './BalanceSheetNetIncomePP';
|
||||||
import { BalanceSheetNetIncomePY } from './BalanceSheetNetIncomePY';
|
import { BalanceSheetNetIncomePY } from './BalanceSheetNetIncomePY';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
|
|
||||||
export const BalanceSheetNetIncome = (Base: any) =>
|
export const BalanceSheetNetIncome = <T extends GConstructor<FinancialSheet>>(
|
||||||
class extends R.compose(
|
Base: T,
|
||||||
|
) =>
|
||||||
|
class extends R.pipe(
|
||||||
BalanceSheetNetIncomePP,
|
BalanceSheetNetIncomePP,
|
||||||
BalanceSheetNetIncomePY,
|
BalanceSheetNetIncomePY,
|
||||||
BalanceSheetComparsionPreviousYear,
|
BalanceSheetComparsionPreviousYear,
|
||||||
BalanceSheetComparsionPreviousPeriod,
|
BalanceSheetComparsionPreviousPeriod,
|
||||||
FinancialPreviousPeriod,
|
FinancialPreviousPeriod,
|
||||||
FinancialHorizTotals
|
FinancialHorizTotals,
|
||||||
)(Base) {
|
)(Base) {
|
||||||
public repository: BalanceSheetRepository;
|
public repository: BalanceSheetRepository;
|
||||||
public query: BalanceSheetQuery;
|
public query: BalanceSheetQuery;
|
||||||
@@ -63,7 +67,7 @@ export const BalanceSheetNetIncome = (Base: any) =>
|
|||||||
* @return {IBalanceSheetAggregateNode}
|
* @return {IBalanceSheetAggregateNode}
|
||||||
*/
|
*/
|
||||||
public schemaNetIncomeNodeMapper = (
|
public schemaNetIncomeNodeMapper = (
|
||||||
node: IBalanceSheetSchemaNetIncomeNode
|
node: IBalanceSheetSchemaNetIncomeNode,
|
||||||
): IBalanceSheetNetIncomeNode => {
|
): IBalanceSheetNetIncomeNode => {
|
||||||
const total = this.getNetIncomeTotal();
|
const total = this.getNetIncomeTotal();
|
||||||
|
|
||||||
@@ -81,22 +85,22 @@ export const BalanceSheetNetIncome = (Base: any) =>
|
|||||||
* @returns {IBalanceSheetNetIncomeNode}
|
* @returns {IBalanceSheetNetIncomeNode}
|
||||||
*/
|
*/
|
||||||
public schemaNetIncomeNodeCompose = (
|
public schemaNetIncomeNodeCompose = (
|
||||||
node: IBalanceSheetSchemaNetIncomeNode
|
node: IBalanceSheetSchemaNetIncomeNode,
|
||||||
): IBalanceSheetNetIncomeNode => {
|
): IBalanceSheetNetIncomeNode => {
|
||||||
return R.compose(
|
return R.compose(
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearActive,
|
this.query.isPreviousYearActive,
|
||||||
this.previousYearNetIncomeNodeCompose
|
this.previousYearNetIncomeNodeCompose,
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousPeriodActive,
|
this.query.isPreviousPeriodActive,
|
||||||
this.previousPeriodNetIncomeNodeCompose
|
this.previousPeriodNetIncomeNodeCompose,
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isDatePeriodsColumnsType,
|
this.query.isDatePeriodsColumnsType,
|
||||||
this.assocNetIncomeDatePeriodsNode
|
this.assocNetIncomeDatePeriodsNode,
|
||||||
),
|
),
|
||||||
this.schemaNetIncomeNodeMapper
|
this.schemaNetIncomeNodeMapper,
|
||||||
)(node);
|
)(node);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -160,7 +164,7 @@ export const BalanceSheetNetIncome = (Base: any) =>
|
|||||||
public getNetIncomeDatePeriodNode = (
|
public getNetIncomeDatePeriodNode = (
|
||||||
node: IBalanceSheetNetIncomeNode,
|
node: IBalanceSheetNetIncomeNode,
|
||||||
fromDate: Date,
|
fromDate: Date,
|
||||||
toDate: Date
|
toDate: Date,
|
||||||
): IBalanceSheetTotalPeriod => {
|
): IBalanceSheetTotalPeriod => {
|
||||||
const periodTotal = this.getNetIncomeDatePeriodTotal(toDate);
|
const periodTotal = this.getNetIncomeDatePeriodTotal(toDate);
|
||||||
|
|
||||||
@@ -173,11 +177,11 @@ export const BalanceSheetNetIncome = (Base: any) =>
|
|||||||
* @returns {IBalanceSheetNetIncomeNode}
|
* @returns {IBalanceSheetNetIncomeNode}
|
||||||
*/
|
*/
|
||||||
public getNetIncomeDatePeriodsNode = (
|
public getNetIncomeDatePeriodsNode = (
|
||||||
node: IBalanceSheetNetIncomeNode
|
node: IBalanceSheetNetIncomeNode,
|
||||||
): IBalanceSheetTotalPeriod[] => {
|
): IBalanceSheetTotalPeriod[] => {
|
||||||
return this.getReportNodeDatePeriods(
|
return this.getReportNodeDatePeriods(
|
||||||
node,
|
node,
|
||||||
this.getNetIncomeDatePeriodNode
|
this.getNetIncomeDatePeriodNode,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -187,7 +191,7 @@ export const BalanceSheetNetIncome = (Base: any) =>
|
|||||||
* @returns {IBalanceSheetNetIncomeNode}
|
* @returns {IBalanceSheetNetIncomeNode}
|
||||||
*/
|
*/
|
||||||
public assocNetIncomeDatePeriodsNode = (
|
public assocNetIncomeDatePeriodsNode = (
|
||||||
node: IBalanceSheetNetIncomeNode
|
node: IBalanceSheetNetIncomeNode,
|
||||||
): IBalanceSheetNetIncomeNode => {
|
): IBalanceSheetNetIncomeNode => {
|
||||||
const datePeriods = this.getNetIncomeDatePeriodsNode(node);
|
const datePeriods = this.getNetIncomeDatePeriodsNode(node);
|
||||||
|
|
||||||
@@ -203,13 +207,13 @@ export const BalanceSheetNetIncome = (Base: any) =>
|
|||||||
* @return {IBalanceSheetDataNode}
|
* @return {IBalanceSheetDataNode}
|
||||||
*/
|
*/
|
||||||
public reportNetIncomeNodeSchemaParser = (
|
public reportNetIncomeNodeSchemaParser = (
|
||||||
schemaNode: IBalanceSheetSchemaNode
|
schemaNode: IBalanceSheetSchemaNode,
|
||||||
): IBalanceSheetDataNode => {
|
): IBalanceSheetDataNode => {
|
||||||
return R.compose(
|
return R.compose(
|
||||||
R.when(
|
R.when(
|
||||||
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.NET_INCOME),
|
this.isSchemaNodeType(BALANCE_SHEET_SCHEMA_NODE_TYPE.NET_INCOME),
|
||||||
this.schemaNetIncomeNodeCompose
|
this.schemaNetIncomeNodeCompose,
|
||||||
)
|
),
|
||||||
)(schemaNode);
|
)(schemaNode);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -219,7 +223,7 @@ export const BalanceSheetNetIncome = (Base: any) =>
|
|||||||
* @return {IBalanceSheetDataNode[]}
|
* @return {IBalanceSheetDataNode[]}
|
||||||
*/
|
*/
|
||||||
public netIncomeSchemaParser = (
|
public netIncomeSchemaParser = (
|
||||||
nodes: (IBalanceSheetSchemaNode | IBalanceSheetDataNode)[]
|
nodes: (IBalanceSheetSchemaNode | IBalanceSheetDataNode)[],
|
||||||
): IBalanceSheetDataNode[] => {
|
): IBalanceSheetDataNode[] => {
|
||||||
return this.mapNodesDeep(nodes, this.reportNetIncomeNodeSchemaParser);
|
return this.mapNodesDeep(nodes, this.reportNetIncomeNodeSchemaParser);
|
||||||
};
|
};
|
||||||
@@ -8,21 +8,25 @@ import { BalanceSheetComparsionPreviousPeriod } from './BalanceSheetComparsionPr
|
|||||||
import { FinancialPreviousPeriod } from '../../common/FinancialPreviousPeriod';
|
import { FinancialPreviousPeriod } from '../../common/FinancialPreviousPeriod';
|
||||||
import { FinancialHorizTotals } from '../../common/FinancialHorizTotals';
|
import { FinancialHorizTotals } from '../../common/FinancialHorizTotals';
|
||||||
import { BalanceSheetRepository } from './BalanceSheetRepository';
|
import { BalanceSheetRepository } from './BalanceSheetRepository';
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
|
||||||
import { BalanceSheetNetIncomePP } from './BalanceSheetNetIncomePP';
|
import { BalanceSheetNetIncomePP } from './BalanceSheetNetIncomePP';
|
||||||
import { BalanceSheetNetIncomePY } from './BalanceSheetNetIncomePY';
|
import { BalanceSheetNetIncomePY } from './BalanceSheetNetIncomePY';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
|
|
||||||
export const BalanceSheetNetIncomeDatePeriods = (Base: any) =>
|
export const BalanceSheetNetIncomeDatePeriods = <
|
||||||
class extends R.compose(
|
T extends GConstructor<FinancialSheet>,
|
||||||
|
>(
|
||||||
|
Base: T,
|
||||||
|
) =>
|
||||||
|
class extends R.pipe(
|
||||||
BalanceSheetNetIncomePP,
|
BalanceSheetNetIncomePP,
|
||||||
BalanceSheetNetIncomePY,
|
BalanceSheetNetIncomePY,
|
||||||
BalanceSheetComparsionPreviousYear,
|
BalanceSheetComparsionPreviousYear,
|
||||||
BalanceSheetComparsionPreviousPeriod,
|
BalanceSheetComparsionPreviousPeriod,
|
||||||
FinancialPreviousPeriod,
|
FinancialPreviousPeriod,
|
||||||
FinancialHorizTotals
|
FinancialHorizTotals,
|
||||||
)(Base) {
|
)(Base) {
|
||||||
private repository: BalanceSheetRepository;
|
repository: BalanceSheetRepository;
|
||||||
private query: BalanceSheetQuery;
|
|
||||||
|
|
||||||
// --------------------------------
|
// --------------------------------
|
||||||
// # Date Periods
|
// # Date Periods
|
||||||
@@ -84,7 +88,7 @@ export const BalanceSheetNetIncomeDatePeriods = (Base: any) =>
|
|||||||
private getNetIncomeDatePeriodNode = (
|
private getNetIncomeDatePeriodNode = (
|
||||||
node: IBalanceSheetNetIncomeNode,
|
node: IBalanceSheetNetIncomeNode,
|
||||||
fromDate: Date,
|
fromDate: Date,
|
||||||
toDate: Date
|
toDate: Date,
|
||||||
): IBalanceSheetTotalPeriod => {
|
): IBalanceSheetTotalPeriod => {
|
||||||
const periodTotal = this.getNetIncomeDatePeriodTotal(toDate);
|
const periodTotal = this.getNetIncomeDatePeriodTotal(toDate);
|
||||||
|
|
||||||
@@ -97,11 +101,11 @@ export const BalanceSheetNetIncomeDatePeriods = (Base: any) =>
|
|||||||
* @returns {IBalanceSheetNetIncomeNode}
|
* @returns {IBalanceSheetNetIncomeNode}
|
||||||
*/
|
*/
|
||||||
private getNetIncomeDatePeriodsNode = (
|
private getNetIncomeDatePeriodsNode = (
|
||||||
node: IBalanceSheetNetIncomeNode
|
node: IBalanceSheetNetIncomeNode,
|
||||||
): IBalanceSheetTotalPeriod[] => {
|
): IBalanceSheetTotalPeriod[] => {
|
||||||
return this.getReportNodeDatePeriods(
|
return this.getReportNodeDatePeriods(
|
||||||
node,
|
node,
|
||||||
this.getNetIncomeDatePeriodNode
|
this.getNetIncomeDatePeriodNode,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,7 +115,7 @@ export const BalanceSheetNetIncomeDatePeriods = (Base: any) =>
|
|||||||
* @returns {IBalanceSheetNetIncomeNode}
|
* @returns {IBalanceSheetNetIncomeNode}
|
||||||
*/
|
*/
|
||||||
public assocNetIncomeDatePeriodsNode = (
|
public assocNetIncomeDatePeriodsNode = (
|
||||||
node: IBalanceSheetNetIncomeNode
|
node: IBalanceSheetNetIncomeNode,
|
||||||
): IBalanceSheetNetIncomeNode => {
|
): IBalanceSheetNetIncomeNode => {
|
||||||
const datePeriods = this.getNetIncomeDatePeriodsNode(node);
|
const datePeriods = this.getNetIncomeDatePeriodsNode(node);
|
||||||
|
|
||||||
@@ -7,10 +7,16 @@ import {
|
|||||||
IBalanceSheetTotal,
|
IBalanceSheetTotal,
|
||||||
} from './BalanceSheet.types';
|
} from './BalanceSheet.types';
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
||||||
import BalanceSheetRepository from './BalanceSheetRepository';
|
import { BalanceSheetRepository } from './BalanceSheetRepository';
|
||||||
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
|
||||||
export const BalanceSheetNetIncomeDatePeriodsPP = (Base: any) =>
|
export const BalanceSheetNetIncomeDatePeriodsPP = <
|
||||||
class extends R.compose(
|
T extends GConstructor<FinancialSheet>,
|
||||||
|
>(
|
||||||
|
Base: T,
|
||||||
|
) =>
|
||||||
|
class extends R.pipe(
|
||||||
BalanceSheetComparsionPreviousPeriod,
|
BalanceSheetComparsionPreviousPeriod,
|
||||||
FinancialPreviousPeriod,
|
FinancialPreviousPeriod,
|
||||||
FinancialHorizTotals,
|
FinancialHorizTotals,
|
||||||
@@ -2,15 +2,24 @@ import * as R from 'ramda';
|
|||||||
import { BalanceSheetComparsionPreviousYear } from './BalanceSheetComparsionPreviousYear';
|
import { BalanceSheetComparsionPreviousYear } from './BalanceSheetComparsionPreviousYear';
|
||||||
import { FinancialPreviousPeriod } from '../../common/FinancialPreviousPeriod';
|
import { FinancialPreviousPeriod } from '../../common/FinancialPreviousPeriod';
|
||||||
import { FinancialHorizTotals } from '../../common/FinancialHorizTotals';
|
import { FinancialHorizTotals } from '../../common/FinancialHorizTotals';
|
||||||
import { IBalanceSheetNetIncomeNode, IBalanceSheetTotal } from './BalanceSheet.types';
|
import {
|
||||||
|
IBalanceSheetNetIncomeNode,
|
||||||
|
IBalanceSheetTotal,
|
||||||
|
} from './BalanceSheet.types';
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
||||||
import BalanceSheetRepository from './BalanceSheetRepository';
|
import { BalanceSheetRepository } from './BalanceSheetRepository';
|
||||||
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
|
||||||
export const BalanceSheetNetIncomeDatePeriodsPY = (Base: any) =>
|
export const BalanceSheetNetIncomeDatePeriodsPY = <
|
||||||
class extends R.compose(
|
T extends GConstructor<FinancialSheet>,
|
||||||
|
>(
|
||||||
|
Base: T,
|
||||||
|
) =>
|
||||||
|
class extends R.pipe(
|
||||||
BalanceSheetComparsionPreviousYear,
|
BalanceSheetComparsionPreviousYear,
|
||||||
FinancialPreviousPeriod,
|
FinancialPreviousPeriod,
|
||||||
FinancialHorizTotals
|
FinancialHorizTotals,
|
||||||
)(Base) {
|
)(Base) {
|
||||||
query: BalanceSheetQuery;
|
query: BalanceSheetQuery;
|
||||||
repository: BalanceSheetRepository;
|
repository: BalanceSheetRepository;
|
||||||
@@ -67,10 +76,10 @@ export const BalanceSheetNetIncomeDatePeriodsPY = (Base: any) =>
|
|||||||
public assocPreviousYearNetIncomeHorizTotal = R.curry(
|
public assocPreviousYearNetIncomeHorizTotal = R.curry(
|
||||||
(node: IBalanceSheetNetIncomeNode, totalNode) => {
|
(node: IBalanceSheetNetIncomeNode, totalNode) => {
|
||||||
const total = this.getPYNetIncomeDatePeriodTotal(
|
const total = this.getPYNetIncomeDatePeriodTotal(
|
||||||
totalNode.previousYearToDate.date
|
totalNode.previousYearToDate.date,
|
||||||
);
|
);
|
||||||
return R.assoc('previousYear', this.getAmountMeta(total), totalNode);
|
return R.assoc('previousYear', this.getAmountMeta(total), totalNode);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,27 +90,27 @@ export const BalanceSheetNetIncomeDatePeriodsPY = (Base: any) =>
|
|||||||
public previousYearNetIncomeHorizNodeComposer = R.curry(
|
public previousYearNetIncomeHorizNodeComposer = R.curry(
|
||||||
(
|
(
|
||||||
node: IBalanceSheetNetIncomeNode,
|
node: IBalanceSheetNetIncomeNode,
|
||||||
horiontalTotalNode: IBalanceSheetTotal
|
horiontalTotalNode: IBalanceSheetTotal,
|
||||||
): IBalanceSheetTotal => {
|
): IBalanceSheetTotal => {
|
||||||
return R.compose(
|
return R.compose(
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearPercentageActive,
|
this.query.isPreviousYearPercentageActive,
|
||||||
this.assocPreviousYearTotalPercentageNode
|
this.assocPreviousYearTotalPercentageNode,
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearChangeActive,
|
this.query.isPreviousYearChangeActive,
|
||||||
this.assocPreviousYearTotalChangeNode
|
this.assocPreviousYearTotalChangeNode,
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearActive,
|
this.query.isPreviousYearActive,
|
||||||
this.assocPreviousYearNetIncomeHorizTotal(node)
|
this.assocPreviousYearNetIncomeHorizTotal(node),
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearActive,
|
this.query.isPreviousYearActive,
|
||||||
this.assocPreviousYearHorizNodeFromToDates
|
this.assocPreviousYearHorizNodeFromToDates,
|
||||||
)
|
),
|
||||||
)(horiontalTotalNode);
|
)(horiontalTotalNode);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -110,11 +119,11 @@ export const BalanceSheetNetIncomeDatePeriodsPY = (Base: any) =>
|
|||||||
* @returns {IBalanceSheetCommonNode}
|
* @returns {IBalanceSheetCommonNode}
|
||||||
*/
|
*/
|
||||||
public assocPreviousYearNetIncomeHorizNode = (
|
public assocPreviousYearNetIncomeHorizNode = (
|
||||||
node: IBalanceSheetNetIncomeNode
|
node: IBalanceSheetNetIncomeNode,
|
||||||
): IBalanceSheetNetIncomeNode => {
|
): IBalanceSheetNetIncomeNode => {
|
||||||
const horizontalTotals = R.addIndex(R.map)(
|
const horizontalTotals = R.addIndex(R.map)(
|
||||||
this.previousYearNetIncomeHorizNodeComposer(node),
|
this.previousYearNetIncomeHorizNodeComposer(node),
|
||||||
node.horizontalTotals
|
node.horizontalTotals,
|
||||||
) as IBalanceSheetTotal[];
|
) as IBalanceSheetTotal[];
|
||||||
|
|
||||||
return R.assoc('horizontalTotals', horizontalTotals, node);
|
return R.assoc('horizontalTotals', horizontalTotals, node);
|
||||||
@@ -9,9 +9,13 @@ import { FinancialHorizTotals } from '../../common/FinancialHorizTotals';
|
|||||||
import { BalanceSheetRepository } from './BalanceSheetRepository';
|
import { BalanceSheetRepository } from './BalanceSheetRepository';
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
||||||
import { BalanceSheetNetIncomeDatePeriodsPP } from './BalanceSheetNetIncomeDatePeriodsPP';
|
import { BalanceSheetNetIncomeDatePeriodsPP } from './BalanceSheetNetIncomeDatePeriodsPP';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
|
|
||||||
export const BalanceSheetNetIncomePP = (Base: any) =>
|
export const BalanceSheetNetIncomePP = <T extends GConstructor<FinancialSheet>>(
|
||||||
class extends R.compose(
|
Base: T,
|
||||||
|
) =>
|
||||||
|
class extends R.pipe(
|
||||||
BalanceSheetNetIncomeDatePeriodsPP,
|
BalanceSheetNetIncomeDatePeriodsPP,
|
||||||
BalanceSheetComparsionPreviousPeriod,
|
BalanceSheetComparsionPreviousPeriod,
|
||||||
FinancialPreviousPeriod,
|
FinancialPreviousPeriod,
|
||||||
@@ -1,8 +1,5 @@
|
|||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import {
|
import { IBalanceSheetNetIncomeNode } from './BalanceSheet.types';
|
||||||
IBalanceSheetDataNode,
|
|
||||||
IBalanceSheetNetIncomeNode,
|
|
||||||
} from './BalanceSheet.types';
|
|
||||||
import { BalanceSheetComparsionPreviousYear } from './BalanceSheetComparsionPreviousYear';
|
import { BalanceSheetComparsionPreviousYear } from './BalanceSheetComparsionPreviousYear';
|
||||||
import { BalanceSheetComparsionPreviousPeriod } from './BalanceSheetComparsionPreviousPeriod';
|
import { BalanceSheetComparsionPreviousPeriod } from './BalanceSheetComparsionPreviousPeriod';
|
||||||
import { FinancialPreviousPeriod } from '../../common/FinancialPreviousPeriod';
|
import { FinancialPreviousPeriod } from '../../common/FinancialPreviousPeriod';
|
||||||
@@ -10,17 +7,21 @@ import { FinancialHorizTotals } from '../../common/FinancialHorizTotals';
|
|||||||
import { BalanceSheetRepository } from './BalanceSheetRepository';
|
import { BalanceSheetRepository } from './BalanceSheetRepository';
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
||||||
import { BalanceSheetNetIncomeDatePeriodsPY } from './BalanceSheetNetIncomeDatePeriodsPY';
|
import { BalanceSheetNetIncomeDatePeriodsPY } from './BalanceSheetNetIncomeDatePeriodsPY';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
|
|
||||||
export const BalanceSheetNetIncomePY = (Base: any) =>
|
export const BalanceSheetNetIncomePY = <T extends GConstructor<FinancialSheet>>(
|
||||||
class extends R.compose(
|
Base: T,
|
||||||
|
) =>
|
||||||
|
class extends R.pipe(
|
||||||
BalanceSheetNetIncomeDatePeriodsPY,
|
BalanceSheetNetIncomeDatePeriodsPY,
|
||||||
BalanceSheetComparsionPreviousYear,
|
BalanceSheetComparsionPreviousYear,
|
||||||
BalanceSheetComparsionPreviousPeriod,
|
BalanceSheetComparsionPreviousPeriod,
|
||||||
FinancialPreviousPeriod,
|
FinancialPreviousPeriod,
|
||||||
FinancialHorizTotals
|
FinancialHorizTotals,
|
||||||
)(Base) {
|
)(Base) {
|
||||||
public repository: BalanceSheetRepository;
|
// public repository: BalanceSheetRepository;
|
||||||
public query: BalanceSheetQuery;
|
// public query: BalanceSheetQuery;
|
||||||
|
|
||||||
// ------------------------------
|
// ------------------------------
|
||||||
// # Previous Year (PY)
|
// # Previous Year (PY)
|
||||||
@@ -44,7 +45,7 @@ export const BalanceSheetNetIncomePY = (Base: any) =>
|
|||||||
* @returns {IBalanceSheetAccountNode}
|
* @returns {IBalanceSheetAccountNode}
|
||||||
*/
|
*/
|
||||||
public assocPreviousYearNetIncomeNode = (
|
public assocPreviousYearNetIncomeNode = (
|
||||||
node: IBalanceSheetNetIncomeNode
|
node: IBalanceSheetNetIncomeNode,
|
||||||
): IBalanceSheetNetIncomeNode => {
|
): IBalanceSheetNetIncomeNode => {
|
||||||
const total = this.getPreviousYearNetIncome();
|
const total = this.getPreviousYearNetIncome();
|
||||||
|
|
||||||
@@ -57,23 +58,23 @@ export const BalanceSheetNetIncomePY = (Base: any) =>
|
|||||||
* @returns {IBalanceSheetAccountNode}
|
* @returns {IBalanceSheetAccountNode}
|
||||||
*/
|
*/
|
||||||
public previousYearNetIncomeNodeCompose = (
|
public previousYearNetIncomeNodeCompose = (
|
||||||
node: IBalanceSheetNetIncomeNode
|
node: IBalanceSheetNetIncomeNode,
|
||||||
): IBalanceSheetNetIncomeNode => {
|
): IBalanceSheetNetIncomeNode => {
|
||||||
return R.compose(
|
return R.compose(
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearPercentageActive,
|
this.query.isPreviousYearPercentageActive,
|
||||||
this.assocPreviousYearTotalPercentageNode
|
this.assocPreviousYearTotalPercentageNode,
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearChangeActive,
|
this.query.isPreviousYearChangeActive,
|
||||||
this.assocPreviousYearTotalChangeNode
|
this.assocPreviousYearTotalChangeNode,
|
||||||
),
|
),
|
||||||
// Associate the PY to date periods horizontal nodes.
|
// Associate the PY to date periods horizontal nodes.
|
||||||
R.when(
|
R.when(
|
||||||
this.isNodeHasHorizontalTotals,
|
this.isNodeHasHorizontalTotals,
|
||||||
this.assocPreviousYearNetIncomeHorizNode
|
this.assocPreviousYearNetIncomeHorizNode,
|
||||||
),
|
),
|
||||||
this.assocPreviousYearNetIncomeNode
|
this.assocPreviousYearNetIncomeNode,
|
||||||
)(node);
|
)(node);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -13,13 +13,10 @@ export class BalanceSheetPdfInjectable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the given balance sheet table to pdf.
|
* Converts the given balance sheet table to pdf.
|
||||||
* @param {number} tenantId - Tenant ID.
|
|
||||||
* @param {IBalanceSheetQuery} query - Balance sheet query.
|
* @param {IBalanceSheetQuery} query - Balance sheet query.
|
||||||
* @returns {Promise<Buffer>}
|
* @returns {Promise<Buffer>}
|
||||||
*/
|
*/
|
||||||
public async pdf(
|
public async pdf(query: IBalanceSheetQuery): Promise<Buffer> {
|
||||||
query: IBalanceSheetQuery,
|
|
||||||
): Promise<Buffer> {
|
|
||||||
const table = await this.balanceSheetTable.table(query);
|
const table = await this.balanceSheetTable.table(query);
|
||||||
|
|
||||||
return this.tableSheetPdf.convertToPdf(
|
return this.tableSheetPdf.convertToPdf(
|
||||||
@@ -2,9 +2,12 @@ import * as R from 'ramda';
|
|||||||
import { get } from 'lodash';
|
import { get } from 'lodash';
|
||||||
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
import { BalanceSheetQuery } from './BalanceSheetQuery';
|
||||||
import { IBalanceSheetDataNode } from './BalanceSheet.types';
|
import { IBalanceSheetDataNode } from './BalanceSheet.types';
|
||||||
import { Constructor } from '@/common/types/Constructor';
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
|
||||||
export const BalanceSheetPercentage = <T extends Constructor>(Base: T) =>
|
export const BalanceSheetPercentage = <T extends GConstructor<FinancialSheet>>(
|
||||||
|
Base: T,
|
||||||
|
) =>
|
||||||
class extends Base {
|
class extends Base {
|
||||||
readonly query: BalanceSheetQuery;
|
readonly query: BalanceSheetQuery;
|
||||||
|
|
||||||
@@ -16,18 +19,18 @@ export const BalanceSheetPercentage = <T extends Constructor>(Base: T) =>
|
|||||||
public assocReportNodeColumnPercentage = R.curry(
|
public assocReportNodeColumnPercentage = R.curry(
|
||||||
(
|
(
|
||||||
parentTotal: number,
|
parentTotal: number,
|
||||||
node: IBalanceSheetDataNode
|
node: IBalanceSheetDataNode,
|
||||||
): IBalanceSheetDataNode => {
|
): IBalanceSheetDataNode => {
|
||||||
const percentage = this.getPercentageBasis(
|
const percentage = this.getPercentageBasis(
|
||||||
parentTotal,
|
parentTotal,
|
||||||
node.total.amount
|
node.total.amount,
|
||||||
);
|
);
|
||||||
return R.assoc(
|
return R.assoc(
|
||||||
'percentageColumn',
|
'percentageColumn',
|
||||||
this.getPercentageAmountMeta(percentage),
|
this.getPercentageAmountMeta(percentage),
|
||||||
node
|
node,
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -38,18 +41,18 @@ export const BalanceSheetPercentage = <T extends Constructor>(Base: T) =>
|
|||||||
public assocReportNodeRowPercentage = R.curry(
|
public assocReportNodeRowPercentage = R.curry(
|
||||||
(
|
(
|
||||||
parentTotal: number,
|
parentTotal: number,
|
||||||
node: IBalanceSheetDataNode
|
node: IBalanceSheetDataNode,
|
||||||
): IBalanceSheetDataNode => {
|
): IBalanceSheetDataNode => {
|
||||||
const percenatage = this.getPercentageBasis(
|
const percenatage = this.getPercentageBasis(
|
||||||
parentTotal,
|
parentTotal,
|
||||||
node.total.amount
|
node.total.amount,
|
||||||
);
|
);
|
||||||
return R.assoc(
|
return R.assoc(
|
||||||
'percentageRow',
|
'percentageRow',
|
||||||
this.getPercentageAmountMeta(percenatage),
|
this.getPercentageAmountMeta(percenatage),
|
||||||
node
|
node,
|
||||||
);
|
);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -61,13 +64,13 @@ export const BalanceSheetPercentage = <T extends Constructor>(Base: T) =>
|
|||||||
public assocRowPercentageHorizTotals = R.curry(
|
public assocRowPercentageHorizTotals = R.curry(
|
||||||
(
|
(
|
||||||
parentTotal: number,
|
parentTotal: number,
|
||||||
node: IBalanceSheetDataNode
|
node: IBalanceSheetDataNode,
|
||||||
): IBalanceSheetDataNode => {
|
): IBalanceSheetDataNode => {
|
||||||
const assocRowPercen = this.assocReportNodeRowPercentage(parentTotal);
|
const assocRowPercen = this.assocReportNodeRowPercentage(parentTotal);
|
||||||
const horTotals = R.map(assocRowPercen)(node.horizontalTotals);
|
const horTotals = R.map(assocRowPercen)(node.horizontalTotals);
|
||||||
|
|
||||||
return R.assoc('horizontalTotals', horTotals, node);
|
return R.assoc('horizontalTotals', horTotals, node);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -81,10 +84,10 @@ export const BalanceSheetPercentage = <T extends Constructor>(Base: T) =>
|
|||||||
const parentTotal = get(
|
const parentTotal = get(
|
||||||
parentNode,
|
parentNode,
|
||||||
`horizontalTotals[${index}].total.amount`,
|
`horizontalTotals[${index}].total.amount`,
|
||||||
0
|
0,
|
||||||
);
|
);
|
||||||
return this.assocReportNodeColumnPercentage(parentTotal, horTotalNode);
|
return this.assocReportNodeColumnPercentage(parentTotal, horTotalNode);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -95,15 +98,15 @@ export const BalanceSheetPercentage = <T extends Constructor>(Base: T) =>
|
|||||||
public assocColumnPercentageHorizTotals = R.curry(
|
public assocColumnPercentageHorizTotals = R.curry(
|
||||||
(
|
(
|
||||||
parentNode: IBalanceSheetDataNode,
|
parentNode: IBalanceSheetDataNode,
|
||||||
node: IBalanceSheetDataNode
|
node: IBalanceSheetDataNode,
|
||||||
): IBalanceSheetDataNode => {
|
): IBalanceSheetDataNode => {
|
||||||
// Horizontal totals.
|
// Horizontal totals.
|
||||||
const assocColPerc = this.assocColumnPercentageHorizTotal(parentNode);
|
const assocColPerc = this.assocColumnPercentageHorizTotal(parentNode);
|
||||||
const horTotals = R.addIndex(R.map)(assocColPerc)(
|
const horTotals = R.addIndex(R.map)(assocColPerc)(
|
||||||
node.horizontalTotals
|
node.horizontalTotals,
|
||||||
);
|
);
|
||||||
return R.assoc('horizontalTotals', horTotals, node);
|
return R.assoc('horizontalTotals', horTotals, node);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -112,19 +115,17 @@ export const BalanceSheetPercentage = <T extends Constructor>(Base: T) =>
|
|||||||
* @param {} node
|
* @param {} node
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
public reportNodeColumnPercentageComposer = R.curry(
|
public reportNodeColumnPercentageComposer = R.curry((parentNode, node) => {
|
||||||
(parentNode, node) => {
|
|
||||||
const parentTotal = parentNode.total.amount;
|
const parentTotal = parentNode.total.amount;
|
||||||
|
|
||||||
return R.compose(
|
return R.compose(
|
||||||
R.when(
|
R.when(
|
||||||
this.isNodeHasHorizoTotals,
|
this.isNodeHasHorizoTotals,
|
||||||
this.assocColumnPercentageHorizTotals(parentNode)
|
this.assocColumnPercentageHorizTotals(parentNode),
|
||||||
),
|
),
|
||||||
this.assocReportNodeColumnPercentage(parentTotal)
|
this.assocReportNodeColumnPercentage(parentTotal),
|
||||||
)(node);
|
)(node);
|
||||||
}
|
});
|
||||||
);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
@@ -137,9 +138,9 @@ export const BalanceSheetPercentage = <T extends Constructor>(Base: T) =>
|
|||||||
return R.compose(
|
return R.compose(
|
||||||
R.when(
|
R.when(
|
||||||
this.isNodeHasHorizoTotals,
|
this.isNodeHasHorizoTotals,
|
||||||
this.assocRowPercentageHorizTotals(total)
|
this.assocRowPercentageHorizTotals(total),
|
||||||
),
|
),
|
||||||
this.assocReportNodeRowPercentage(total)
|
this.assocReportNodeRowPercentage(total),
|
||||||
)(node);
|
)(node);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -149,7 +150,7 @@ export const BalanceSheetPercentage = <T extends Constructor>(Base: T) =>
|
|||||||
private assocNodeColumnPercentageChildren = (node) => {
|
private assocNodeColumnPercentageChildren = (node) => {
|
||||||
const children = this.mapNodesDeep(
|
const children = this.mapNodesDeep(
|
||||||
node.children,
|
node.children,
|
||||||
this.reportNodeColumnPercentageComposer(node)
|
this.reportNodeColumnPercentageComposer(node),
|
||||||
);
|
);
|
||||||
return R.assoc('children', children, node);
|
return R.assoc('children', children, node);
|
||||||
};
|
};
|
||||||
@@ -166,10 +167,10 @@ export const BalanceSheetPercentage = <T extends Constructor>(Base: T) =>
|
|||||||
return R.compose(
|
return R.compose(
|
||||||
R.when(
|
R.when(
|
||||||
this.isNodeHasHorizoTotals,
|
this.isNodeHasHorizoTotals,
|
||||||
this.assocColumnPercentageHorizTotals(parentNode)
|
this.assocColumnPercentageHorizTotals(parentNode),
|
||||||
),
|
),
|
||||||
this.assocReportNodeColumnPercentage(parentTotal),
|
this.assocReportNodeColumnPercentage(parentTotal),
|
||||||
this.assocNodeColumnPercentageChildren
|
this.assocNodeColumnPercentageChildren,
|
||||||
)(node);
|
)(node);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -179,7 +180,7 @@ export const BalanceSheetPercentage = <T extends Constructor>(Base: T) =>
|
|||||||
* @returns {IBalanceSheetDataNode[]}
|
* @returns {IBalanceSheetDataNode[]}
|
||||||
*/
|
*/
|
||||||
private reportColumnsPercentageMapper = (
|
private reportColumnsPercentageMapper = (
|
||||||
nodes: IBalanceSheetDataNode[]
|
nodes: IBalanceSheetDataNode[],
|
||||||
): IBalanceSheetDataNode[] => {
|
): IBalanceSheetDataNode[] => {
|
||||||
return R.map(this.reportNodeColumnPercentageDeepMap, nodes);
|
return R.map(this.reportNodeColumnPercentageDeepMap, nodes);
|
||||||
};
|
};
|
||||||
@@ -202,12 +203,12 @@ export const BalanceSheetPercentage = <T extends Constructor>(Base: T) =>
|
|||||||
return R.compose(
|
return R.compose(
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isColumnsPercentageActive,
|
this.query.isColumnsPercentageActive,
|
||||||
this.reportColumnsPercentageMapper
|
this.reportColumnsPercentageMapper,
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isRowsPercentageActive,
|
this.query.isRowsPercentageActive,
|
||||||
this.reportRowsPercentageMapper
|
this.reportRowsPercentageMapper,
|
||||||
)
|
),
|
||||||
)(nodes);
|
)(nodes);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -216,9 +217,7 @@ export const BalanceSheetPercentage = <T extends Constructor>(Base: T) =>
|
|||||||
* @param {IBalanceSheetDataNode} node
|
* @param {IBalanceSheetDataNode} node
|
||||||
* @returns {boolean}
|
* @returns {boolean}
|
||||||
*/
|
*/
|
||||||
public isNodeHasHorizoTotals = (
|
public isNodeHasHorizoTotals = (node: IBalanceSheetDataNode): boolean => {
|
||||||
node: IBalanceSheetDataNode
|
|
||||||
): boolean => {
|
|
||||||
return (
|
return (
|
||||||
!R.isEmpty(node.horizontalTotals) && !R.isNil(node.horizontalTotals)
|
!R.isEmpty(node.horizontalTotals) && !R.isNil(node.horizontalTotals)
|
||||||
);
|
);
|
||||||
@@ -15,30 +15,28 @@ import { transformToMapBy } from '@/utils/transform-to-map-by';
|
|||||||
import { Account } from '@/modules/Accounts/models/Account.model';
|
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||||
import { AccountTransaction } from '@/modules/Accounts/models/AccountTransaction.model';
|
import { AccountTransaction } from '@/modules/Accounts/models/AccountTransaction.model';
|
||||||
|
|
||||||
|
|
||||||
@Injectable({ scope: Scope.TRANSIENT })
|
@Injectable({ scope: Scope.TRANSIENT })
|
||||||
export class BalanceSheetRepository extends R.compose(
|
export class BalanceSheetRepository extends R.compose(
|
||||||
BalanceSheetRepositoryNetIncome,
|
BalanceSheetRepositoryNetIncome,
|
||||||
FinancialDatePeriods
|
FinancialDatePeriods,
|
||||||
)(class {}) {
|
)(class {}) {
|
||||||
/**
|
/**
|
||||||
*
|
* Account model.
|
||||||
*/
|
*/
|
||||||
@Inject(Account.name)
|
@Inject(Account.name)
|
||||||
public readonly accountModel: typeof Account;
|
public readonly accountModel: typeof Account;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Account transaction model.
|
||||||
|
*/
|
||||||
@Inject(AccountTransaction.name)
|
@Inject(AccountTransaction.name)
|
||||||
public readonly accountTransactionModel: typeof AccountTransaction;
|
public readonly accountTransactionModel: typeof AccountTransaction;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {number}
|
* @description Balance sheet query.
|
||||||
*/
|
|
||||||
public readonly tenantId: number;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {BalanceSheetQuery}
|
* @param {BalanceSheetQuery}
|
||||||
*/
|
*/
|
||||||
public readonly query: BalanceSheetQuery;
|
public query: BalanceSheetQuery;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {}
|
* @param {}
|
||||||
@@ -153,14 +151,13 @@ export class BalanceSheetRepository extends R.compose(
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor method.
|
* Constructor method.
|
||||||
* @param {number} tenantId
|
|
||||||
* @param {IBalanceSheetQuery} query
|
* @param {IBalanceSheetQuery} query
|
||||||
*/
|
*/
|
||||||
public setQuery(query: IBalanceSheetQuery) {
|
public setQuery(query: IBalanceSheetQuery) {
|
||||||
this.query = new BalanceSheetQuery(query);
|
this.query = new BalanceSheetQuery(query);
|
||||||
|
|
||||||
this.transactionsGroupType = this.getGroupByFromDisplayColumnsBy(
|
this.transactionsGroupType = this.getGroupByFromDisplayColumnsBy(
|
||||||
this.query.displayColumnsBy
|
this.query.displayColumnsBy,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -248,16 +245,16 @@ export class BalanceSheetRepository extends R.compose(
|
|||||||
const periodsByAccount = await this.accountsDatePeriods(
|
const periodsByAccount = await this.accountsDatePeriods(
|
||||||
this.query.fromDate,
|
this.query.fromDate,
|
||||||
this.query.toDate,
|
this.query.toDate,
|
||||||
this.transactionsGroupType
|
this.transactionsGroupType,
|
||||||
);
|
);
|
||||||
// Retrieves opening balance of grouped transactions.
|
// Retrieves opening balance of grouped transactions.
|
||||||
const periodsOpeningByAccount = await this.closingAccountsTotal(
|
const periodsOpeningByAccount = await this.closingAccountsTotal(
|
||||||
this.query.fromDate
|
this.query.fromDate,
|
||||||
);
|
);
|
||||||
// Inject to the repository.
|
// Inject to the repository.
|
||||||
this.periodsAccountsLedger = Ledger.fromTransactions(periodsByAccount);
|
this.periodsAccountsLedger = Ledger.fromTransactions(periodsByAccount);
|
||||||
this.periodsOpeningAccountLedger = Ledger.fromTransactions(
|
this.periodsOpeningAccountLedger = Ledger.fromTransactions(
|
||||||
periodsOpeningByAccount
|
periodsOpeningByAccount,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -270,7 +267,7 @@ export class BalanceSheetRepository extends R.compose(
|
|||||||
*/
|
*/
|
||||||
public initTotalPreviousYear = async (): Promise<void> => {
|
public initTotalPreviousYear = async (): Promise<void> => {
|
||||||
const PYTotalsByAccounts = await this.closingAccountsTotal(
|
const PYTotalsByAccounts = await this.closingAccountsTotal(
|
||||||
this.query.PYToDate
|
this.query.PYToDate,
|
||||||
);
|
);
|
||||||
// Inject to the repository.
|
// Inject to the repository.
|
||||||
this.PYTotalAccountsLedger = Ledger.fromTransactions(PYTotalsByAccounts);
|
this.PYTotalAccountsLedger = Ledger.fromTransactions(PYTotalsByAccounts);
|
||||||
@@ -284,16 +281,16 @@ export class BalanceSheetRepository extends R.compose(
|
|||||||
const PYPeriodsBYAccounts = await this.accountsDatePeriods(
|
const PYPeriodsBYAccounts = await this.accountsDatePeriods(
|
||||||
this.query.PYFromDate,
|
this.query.PYFromDate,
|
||||||
this.query.PYToDate,
|
this.query.PYToDate,
|
||||||
this.transactionsGroupType
|
this.transactionsGroupType,
|
||||||
);
|
);
|
||||||
// Retrieves opening balance of grouped transactions.
|
// Retrieves opening balance of grouped transactions.
|
||||||
const periodsOpeningByAccount = await this.closingAccountsTotal(
|
const periodsOpeningByAccount = await this.closingAccountsTotal(
|
||||||
this.query.PYFromDate
|
this.query.PYFromDate,
|
||||||
);
|
);
|
||||||
// Inject to the repository.
|
// Inject to the repository.
|
||||||
this.PYPeriodsAccountsLedger = Ledger.fromTransactions(PYPeriodsBYAccounts);
|
this.PYPeriodsAccountsLedger = Ledger.fromTransactions(PYPeriodsBYAccounts);
|
||||||
this.PYPeriodsOpeningAccountLedger = Ledger.fromTransactions(
|
this.PYPeriodsOpeningAccountLedger = Ledger.fromTransactions(
|
||||||
periodsOpeningByAccount
|
periodsOpeningByAccount,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -306,7 +303,7 @@ export class BalanceSheetRepository extends R.compose(
|
|||||||
*/
|
*/
|
||||||
public initTotalPreviousPeriod = async (): Promise<void> => {
|
public initTotalPreviousPeriod = async (): Promise<void> => {
|
||||||
const PPTotalsByAccounts = await this.closingAccountsTotal(
|
const PPTotalsByAccounts = await this.closingAccountsTotal(
|
||||||
this.query.PPToDate
|
this.query.PPToDate,
|
||||||
);
|
);
|
||||||
// Inject to the repository.
|
// Inject to the repository.
|
||||||
this.PPTotalAccountsLedger = Ledger.fromTransactions(PPTotalsByAccounts);
|
this.PPTotalAccountsLedger = Ledger.fromTransactions(PPTotalsByAccounts);
|
||||||
@@ -320,16 +317,16 @@ export class BalanceSheetRepository extends R.compose(
|
|||||||
const PPPeriodsBYAccounts = await this.accountsDatePeriods(
|
const PPPeriodsBYAccounts = await this.accountsDatePeriods(
|
||||||
this.query.PPFromDate,
|
this.query.PPFromDate,
|
||||||
this.query.PPToDate,
|
this.query.PPToDate,
|
||||||
this.transactionsGroupType
|
this.transactionsGroupType,
|
||||||
);
|
);
|
||||||
// Retrieves opening balance of grouped transactions.
|
// Retrieves opening balance of grouped transactions.
|
||||||
const periodsOpeningByAccount = await this.closingAccountsTotal(
|
const periodsOpeningByAccount = await this.closingAccountsTotal(
|
||||||
this.query.PPFromDate
|
this.query.PPFromDate,
|
||||||
);
|
);
|
||||||
// Inject to the repository.
|
// Inject to the repository.
|
||||||
this.PPPeriodsAccountsLedger = Ledger.fromTransactions(PPPeriodsBYAccounts);
|
this.PPPeriodsAccountsLedger = Ledger.fromTransactions(PPPeriodsBYAccounts);
|
||||||
this.PPPeriodsOpeningAccountLedger = Ledger.fromTransactions(
|
this.PPPeriodsOpeningAccountLedger = Ledger.fromTransactions(
|
||||||
periodsOpeningByAccount
|
periodsOpeningByAccount,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -354,7 +351,7 @@ export class BalanceSheetRepository extends R.compose(
|
|||||||
public accountsDatePeriods = async (
|
public accountsDatePeriods = async (
|
||||||
fromDate: Date,
|
fromDate: Date,
|
||||||
toDate: Date,
|
toDate: Date,
|
||||||
datePeriodsType: string
|
datePeriodsType: string,
|
||||||
) => {
|
) => {
|
||||||
return this.accountTransactionModel.query().onBuild((query) => {
|
return this.accountTransactionModel.query().onBuild((query) => {
|
||||||
query.sum('credit as credit');
|
query.sum('credit as credit');
|
||||||
@@ -5,11 +5,14 @@ import { Account } from '@/modules/Accounts/models/Account.model';
|
|||||||
import { ILedger } from '@/modules/Ledger/types/Ledger.types';
|
import { ILedger } from '@/modules/Ledger/types/Ledger.types';
|
||||||
import { ACCOUNT_PARENT_TYPE } from '@/constants/accounts';
|
import { ACCOUNT_PARENT_TYPE } from '@/constants/accounts';
|
||||||
import { GConstructor } from '@/common/types/Constructor';
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
|
||||||
export const BalanceSheetRepositoryNetIncome = <T extends GConstructor>(
|
export const BalanceSheetRepositoryNetIncome = <
|
||||||
|
T extends GConstructor<FinancialSheet>,
|
||||||
|
>(
|
||||||
Base: T,
|
Base: T,
|
||||||
) =>
|
) =>
|
||||||
class extends R.compose(FinancialDatePeriods)(Base) {
|
class extends R.pipe(FinancialDatePeriods)(Base) {
|
||||||
// -----------------------
|
// -----------------------
|
||||||
// # Net Income
|
// # Net Income
|
||||||
// -----------------------
|
// -----------------------
|
||||||
@@ -5,11 +5,14 @@ import {
|
|||||||
BALANCE_SHEET_SCHEMA_NODE_TYPE,
|
BALANCE_SHEET_SCHEMA_NODE_TYPE,
|
||||||
} from './BalanceSheet.types';
|
} from './BalanceSheet.types';
|
||||||
import { FinancialSchema } from '../../common/FinancialSchema';
|
import { FinancialSchema } from '../../common/FinancialSchema';
|
||||||
import { Constructor } from '@/common/types/Constructor';
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
import { ACCOUNT_TYPE } from '@/constants/accounts';
|
import { ACCOUNT_TYPE } from '@/constants/accounts';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
|
||||||
export const BalanceSheetSchema = <T extends Constructor>(Base: T) =>
|
export const BalanceSheetSchema = <T extends GConstructor<FinancialSheet>>(
|
||||||
class extends R.compose(FinancialSchema)(Base) {
|
Base: T,
|
||||||
|
) =>
|
||||||
|
class extends R.pipe(FinancialSchema)(Base) {
|
||||||
/**
|
/**
|
||||||
* Retrieves the balance sheet schema.
|
* Retrieves the balance sheet schema.
|
||||||
* @returns
|
* @returns
|
||||||
@@ -17,7 +20,7 @@ export const BalanceSheetSchema = <T extends Constructor>(Base: T) =>
|
|||||||
getSchema = () => {
|
getSchema = () => {
|
||||||
return getBalanceSheetSchema();
|
return getBalanceSheetSchema();
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve the balance sheet report schema.
|
* Retrieve the balance sheet report schema.
|
||||||
@@ -1,15 +1,17 @@
|
|||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import * as moment from 'moment';
|
import * as moment from 'moment';
|
||||||
import {
|
import { ITableColumn, ITableColumnAccessor } from '../../types/Table.types';
|
||||||
ITableColumn,
|
|
||||||
ITableColumnAccessor,
|
|
||||||
} from '../../types/Table.types';
|
|
||||||
import { FinancialDatePeriods } from '../../common/FinancialDatePeriods';
|
import { FinancialDatePeriods } from '../../common/FinancialDatePeriods';
|
||||||
import { IDateRange } from '../CashFlow/Cashflow.types';
|
import { IDateRange } from '../CashFlow/Cashflow.types';
|
||||||
import { Constructor } from '@/common/types/Constructor';
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
|
||||||
export const BalanceSheetTableDatePeriods = <T extends Constructor>(Base: T) =>
|
export const BalanceSheetTableDatePeriods = <
|
||||||
class extends R.compose(FinancialDatePeriods)(Base) {
|
T extends GConstructor<FinancialSheet>,
|
||||||
|
>(
|
||||||
|
Base: T,
|
||||||
|
) =>
|
||||||
|
class extends R.pipe(FinancialDatePeriods)(Base) {
|
||||||
/**
|
/**
|
||||||
* Retrieves the date periods based on the report query.
|
* Retrieves the date periods based on the report query.
|
||||||
* @returns {IDateRange[]}
|
* @returns {IDateRange[]}
|
||||||
@@ -18,7 +20,7 @@ export const BalanceSheetTableDatePeriods = <T extends Constructor>(Base: T) =>
|
|||||||
return this.getDateRanges(
|
return this.getDateRanges(
|
||||||
this.query.fromDate,
|
this.query.fromDate,
|
||||||
this.query.toDate,
|
this.query.toDate,
|
||||||
this.query.displayColumnsBy
|
this.query.displayColumnsBy,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +46,7 @@ export const BalanceSheetTableDatePeriods = <T extends Constructor>(Base: T) =>
|
|||||||
R.always(this.query.isDisplayColumnsBy(type)),
|
R.always(this.query.isDisplayColumnsBy(type)),
|
||||||
formatFn,
|
formatFn,
|
||||||
],
|
],
|
||||||
conditions
|
conditions,
|
||||||
);
|
);
|
||||||
return R.compose(R.cond(conditionsPairs))(dateRange);
|
return R.compose(R.cond(conditionsPairs))(dateRange);
|
||||||
};
|
};
|
||||||
@@ -68,9 +70,9 @@ export const BalanceSheetTableDatePeriods = <T extends Constructor>(Base: T) =>
|
|||||||
key: `date-range-${index}`,
|
key: `date-range-${index}`,
|
||||||
accessor: `horizontalTotals[${index}].total.formattedAmount`,
|
accessor: `horizontalTotals[${index}].total.formattedAmount`,
|
||||||
},
|
},
|
||||||
])
|
]),
|
||||||
)([]);
|
)([]);
|
||||||
}
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -80,7 +82,7 @@ export const BalanceSheetTableDatePeriods = <T extends Constructor>(Base: T) =>
|
|||||||
public datePeriodsColumnsAccessors = (): ITableColumnAccessor[] => {
|
public datePeriodsColumnsAccessors = (): ITableColumnAccessor[] => {
|
||||||
return R.compose(
|
return R.compose(
|
||||||
R.flatten,
|
R.flatten,
|
||||||
R.addIndex(R.map)(this.datePeriodColumnsAccessor)
|
R.addIndex(R.map)(this.datePeriodColumnsAccessor),
|
||||||
)(this.datePeriods);
|
)(this.datePeriods);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -95,18 +97,18 @@ export const BalanceSheetTableDatePeriods = <T extends Constructor>(Base: T) =>
|
|||||||
*/
|
*/
|
||||||
public datePeriodChildrenColumns = (
|
public datePeriodChildrenColumns = (
|
||||||
index: number,
|
index: number,
|
||||||
dateRange: IDateRange
|
dateRange: IDateRange,
|
||||||
) => {
|
) => {
|
||||||
return R.compose(
|
return R.compose(
|
||||||
R.unless(
|
R.unless(
|
||||||
R.isEmpty,
|
R.isEmpty,
|
||||||
R.concat([
|
R.concat([
|
||||||
{ key: `total`, label: this.i18n.__('balance_sheet.total') },
|
{ key: `total`, label: this.i18n.__('balance_sheet.total') },
|
||||||
])
|
]),
|
||||||
),
|
),
|
||||||
R.concat(this.percentageColumns()),
|
R.concat(this.percentageColumns()),
|
||||||
R.concat(this.getPreviousYearHorizontalColumns(dateRange)),
|
R.concat(this.getPreviousYearHorizontalColumns(dateRange)),
|
||||||
R.concat(this.previousPeriodHorizontalColumns(dateRange))
|
R.concat(this.previousPeriodHorizontalColumns(dateRange)),
|
||||||
)([]);
|
)([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -118,7 +120,7 @@ export const BalanceSheetTableDatePeriods = <T extends Constructor>(Base: T) =>
|
|||||||
*/
|
*/
|
||||||
public datePeriodColumn = (
|
public datePeriodColumn = (
|
||||||
dateRange: IDateRange,
|
dateRange: IDateRange,
|
||||||
index: number
|
index: number,
|
||||||
): ITableColumn => {
|
): ITableColumn => {
|
||||||
return {
|
return {
|
||||||
key: `date-range-${index}`,
|
key: `date-range-${index}`,
|
||||||
@@ -13,8 +13,7 @@ export class BalanceSheetTableInjectable {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves the balance sheet in table format.
|
* Retrieves the balance sheet in table format.
|
||||||
* @param {number} tenantId
|
* @param {number} query -
|
||||||
* @param {number} query
|
|
||||||
* @returns {Promise<IBalanceSheetTable>}
|
* @returns {Promise<IBalanceSheetTable>}
|
||||||
*/
|
*/
|
||||||
public async table(filter: IBalanceSheetQuery): Promise<IBalanceSheetTable> {
|
public async table(filter: IBalanceSheetQuery): Promise<IBalanceSheetTable> {
|
||||||
@@ -4,12 +4,17 @@ import { FinancialTablePreviousPeriod } from '../../common/FinancialTablePreviou
|
|||||||
import { FinancialDateRanges } from '../../common/FinancialDateRanges';
|
import { FinancialDateRanges } from '../../common/FinancialDateRanges';
|
||||||
import { IDateRange } from '../../types/Report.types';
|
import { IDateRange } from '../../types/Report.types';
|
||||||
import { ITableColumn } from '../../types/Table.types';
|
import { ITableColumn } from '../../types/Table.types';
|
||||||
import { Constructor } from '@/common/types/Constructor';
|
import { GConstructor } from '@/common/types/Constructor';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
|
||||||
export const BalanceSheetTablePreviousPeriod = <T extends Constructor>(Base: T) =>
|
export const BalanceSheetTablePreviousPeriod = <
|
||||||
class BalanceSheetTablePreviousPeriod extends R.compose(
|
T extends GConstructor<FinancialSheet>,
|
||||||
|
>(
|
||||||
|
Base: T,
|
||||||
|
) =>
|
||||||
|
class BalanceSheetTablePreviousPeriod extends R.pipe(
|
||||||
FinancialTablePreviousPeriod,
|
FinancialTablePreviousPeriod,
|
||||||
FinancialDateRanges
|
FinancialDateRanges,
|
||||||
)(Base) {
|
)(Base) {
|
||||||
readonly query: BalanceSheetQuery;
|
readonly query: BalanceSheetQuery;
|
||||||
|
|
||||||
@@ -20,23 +25,21 @@ export const BalanceSheetTablePreviousPeriod = <T extends Constructor>(Base: T)
|
|||||||
* Retrieves the previous period columns.
|
* Retrieves the previous period columns.
|
||||||
* @returns {ITableColumn[]}
|
* @returns {ITableColumn[]}
|
||||||
*/
|
*/
|
||||||
public previousPeriodColumns = (
|
public previousPeriodColumns = (dateRange?: IDateRange): ITableColumn[] => {
|
||||||
dateRange?: IDateRange
|
|
||||||
): ITableColumn[] => {
|
|
||||||
return R.pipe(
|
return R.pipe(
|
||||||
// Previous period columns.
|
// Previous period columns.
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousPeriodActive,
|
this.query.isPreviousPeriodActive,
|
||||||
R.append(this.getPreviousPeriodTotalColumn(dateRange))
|
R.append(this.getPreviousPeriodTotalColumn(dateRange)),
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousPeriodChangeActive,
|
this.query.isPreviousPeriodChangeActive,
|
||||||
R.append(this.getPreviousPeriodChangeColumn())
|
R.append(this.getPreviousPeriodChangeColumn()),
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousPeriodPercentageActive,
|
this.query.isPreviousPeriodPercentageActive,
|
||||||
R.append(this.getPreviousPeriodPercentageColumn())
|
R.append(this.getPreviousPeriodPercentageColumn()),
|
||||||
)
|
),
|
||||||
)([]);
|
)([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -46,12 +49,12 @@ export const BalanceSheetTablePreviousPeriod = <T extends Constructor>(Base: T)
|
|||||||
* @returns {ITableColumn}
|
* @returns {ITableColumn}
|
||||||
*/
|
*/
|
||||||
public previousPeriodHorizontalColumns = (
|
public previousPeriodHorizontalColumns = (
|
||||||
dateRange: IDateRange
|
dateRange: IDateRange,
|
||||||
): ITableColumn[] => {
|
): ITableColumn[] => {
|
||||||
const PPDateRange = this.getPPDatePeriodDateRange(
|
const PPDateRange = this.getPPDatePeriodDateRange(
|
||||||
dateRange.fromDate,
|
dateRange.fromDate,
|
||||||
dateRange.toDate,
|
dateRange.toDate,
|
||||||
this.query.displayColumnsBy
|
this.query.displayColumnsBy,
|
||||||
);
|
);
|
||||||
return this.previousPeriodColumns({
|
return this.previousPeriodColumns({
|
||||||
fromDate: PPDateRange.fromDate,
|
fromDate: PPDateRange.fromDate,
|
||||||
@@ -71,16 +74,16 @@ export const BalanceSheetTablePreviousPeriod = <T extends Constructor>(Base: T)
|
|||||||
// Previous period columns.
|
// Previous period columns.
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousPeriodActive,
|
this.query.isPreviousPeriodActive,
|
||||||
R.append(this.getPreviousPeriodTotalAccessor())
|
R.append(this.getPreviousPeriodTotalAccessor()),
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousPeriodChangeActive,
|
this.query.isPreviousPeriodChangeActive,
|
||||||
R.append(this.getPreviousPeriodChangeAccessor())
|
R.append(this.getPreviousPeriodChangeAccessor()),
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousPeriodPercentageActive,
|
this.query.isPreviousPeriodPercentageActive,
|
||||||
R.append(this.getPreviousPeriodPercentageAccessor())
|
R.append(this.getPreviousPeriodPercentageAccessor()),
|
||||||
)
|
),
|
||||||
)([]);
|
)([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -90,22 +93,22 @@ export const BalanceSheetTablePreviousPeriod = <T extends Constructor>(Base: T)
|
|||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
public previousPeriodHorizColumnAccessors = (
|
public previousPeriodHorizColumnAccessors = (
|
||||||
index: number
|
index: number,
|
||||||
): ITableColumn[] => {
|
): ITableColumn[] => {
|
||||||
return R.pipe(
|
return R.pipe(
|
||||||
// Previous period columns.
|
// Previous period columns.
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousPeriodActive,
|
this.query.isPreviousPeriodActive,
|
||||||
R.append(this.getPreviousPeriodTotalHorizAccessor(index))
|
R.append(this.getPreviousPeriodTotalHorizAccessor(index)),
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousPeriodChangeActive,
|
this.query.isPreviousPeriodChangeActive,
|
||||||
R.append(this.getPreviousPeriodChangeHorizAccessor(index))
|
R.append(this.getPreviousPeriodChangeHorizAccessor(index)),
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousPeriodPercentageActive,
|
this.query.isPreviousPeriodPercentageActive,
|
||||||
R.append(this.getPreviousPeriodPercentageHorizAccessor(index))
|
R.append(this.getPreviousPeriodPercentageHorizAccessor(index)),
|
||||||
)
|
),
|
||||||
)([]);
|
)([]);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
import * as R from 'ramda';
|
import * as R from 'ramda';
|
||||||
import { IDateRange, } from '../../types/Report.types';
|
import { IDateRange } from '../../types/Report.types';
|
||||||
import { ITableColumn } from '../../types/Table.types';
|
import { ITableColumn } from '../../types/Table.types';
|
||||||
import { FinancialTablePreviousYear } from '../../common/FinancialTablePreviousYear';
|
import { FinancialTablePreviousYear } from '../../common/FinancialTablePreviousYear';
|
||||||
import { FinancialDateRanges } from '../../common/FinancialDateRanges';
|
import { FinancialDateRanges } from '../../common/FinancialDateRanges';
|
||||||
import { Constructor } from '@/common/types/Constructor';
|
import { Constructor } from '@/common/types/Constructor';
|
||||||
|
|
||||||
export const BalanceSheetTablePreviousYear = <T extends Constructor>(Base: T) =>
|
export const BalanceSheetTablePreviousYear = <T extends Constructor>(Base: T) =>
|
||||||
class extends R.compose(FinancialTablePreviousYear, FinancialDateRanges)(Base) {
|
class extends R.pipe(FinancialTablePreviousYear, FinancialDateRanges)(Base) {
|
||||||
// --------------------
|
// --------------------
|
||||||
// # Columns.
|
// # Columns.
|
||||||
// --------------------
|
// --------------------
|
||||||
@@ -15,22 +15,22 @@ export const BalanceSheetTablePreviousYear = <T extends Constructor>(Base: T) =>
|
|||||||
* @returns {ITableColumn[]}
|
* @returns {ITableColumn[]}
|
||||||
*/
|
*/
|
||||||
public getPreviousYearColumns = (
|
public getPreviousYearColumns = (
|
||||||
dateRange?: IDateRange
|
dateRange?: IDateRange,
|
||||||
): ITableColumn[] => {
|
): ITableColumn[] => {
|
||||||
return R.pipe(
|
return R.pipe(
|
||||||
// Previous year columns.
|
// Previous year columns.
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearActive,
|
this.query.isPreviousYearActive,
|
||||||
R.append(this.getPreviousYearTotalColumn(dateRange))
|
R.append(this.getPreviousYearTotalColumn(dateRange)),
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearChangeActive,
|
this.query.isPreviousYearChangeActive,
|
||||||
R.append(this.getPreviousYearChangeColumn())
|
R.append(this.getPreviousYearChangeColumn()),
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearPercentageActive,
|
this.query.isPreviousYearPercentageActive,
|
||||||
R.append(this.getPreviousYearPercentageColumn())
|
R.append(this.getPreviousYearPercentageColumn()),
|
||||||
)
|
),
|
||||||
)([]);
|
)([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -42,7 +42,7 @@ export const BalanceSheetTablePreviousYear = <T extends Constructor>(Base: T) =>
|
|||||||
public getPreviousYearHorizontalColumns = (dateRange: IDateRange) => {
|
public getPreviousYearHorizontalColumns = (dateRange: IDateRange) => {
|
||||||
const PYDateRange = this.getPreviousYearDateRange(
|
const PYDateRange = this.getPreviousYearDateRange(
|
||||||
dateRange.fromDate,
|
dateRange.fromDate,
|
||||||
dateRange.toDate
|
dateRange.toDate,
|
||||||
);
|
);
|
||||||
return this.getPreviousYearColumns(PYDateRange);
|
return this.getPreviousYearColumns(PYDateRange);
|
||||||
};
|
};
|
||||||
@@ -59,16 +59,16 @@ export const BalanceSheetTablePreviousYear = <T extends Constructor>(Base: T) =>
|
|||||||
// Previous year columns.
|
// Previous year columns.
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearActive,
|
this.query.isPreviousYearActive,
|
||||||
R.append(this.getPreviousYearTotalAccessor())
|
R.append(this.getPreviousYearTotalAccessor()),
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearChangeActive,
|
this.query.isPreviousYearChangeActive,
|
||||||
R.append(this.getPreviousYearChangeAccessor())
|
R.append(this.getPreviousYearChangeAccessor()),
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearPercentageActive,
|
this.query.isPreviousYearPercentageActive,
|
||||||
R.append(this.getPreviousYearPercentageAccessor())
|
R.append(this.getPreviousYearPercentageAccessor()),
|
||||||
)
|
),
|
||||||
)([]);
|
)([]);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -78,22 +78,22 @@ export const BalanceSheetTablePreviousYear = <T extends Constructor>(Base: T) =>
|
|||||||
* @returns {ITableColumn[]}
|
* @returns {ITableColumn[]}
|
||||||
*/
|
*/
|
||||||
public previousYearHorizontalColumnAccessors = (
|
public previousYearHorizontalColumnAccessors = (
|
||||||
index: number
|
index: number,
|
||||||
): ITableColumn[] => {
|
): ITableColumn[] => {
|
||||||
return R.pipe(
|
return R.pipe(
|
||||||
// Previous year columns.
|
// Previous year columns.
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearActive,
|
this.query.isPreviousYearActive,
|
||||||
R.append(this.getPreviousYearTotalHorizAccessor(index))
|
R.append(this.getPreviousYearTotalHorizAccessor(index)),
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearChangeActive,
|
this.query.isPreviousYearChangeActive,
|
||||||
R.append(this.getPreviousYearChangeHorizAccessor(index))
|
R.append(this.getPreviousYearChangeHorizAccessor(index)),
|
||||||
),
|
),
|
||||||
R.when(
|
R.when(
|
||||||
this.query.isPreviousYearPercentageActive,
|
this.query.isPreviousYearPercentageActive,
|
||||||
R.append(this.getPreviousYearPercentageHorizAccessor(index))
|
R.append(this.getPreviousYearPercentageHorizAccessor(index)),
|
||||||
)
|
),
|
||||||
)([]);
|
)([]);
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
13
pnpm-lock.yaml
generated
13
pnpm-lock.yaml
generated
@@ -667,6 +667,9 @@ importers:
|
|||||||
strategy:
|
strategy:
|
||||||
specifier: ^1.1.1
|
specifier: ^1.1.1
|
||||||
version: 1.1.1
|
version: 1.1.1
|
||||||
|
stripe:
|
||||||
|
specifier: ^16.10.0
|
||||||
|
version: 16.10.0
|
||||||
uniqid:
|
uniqid:
|
||||||
specifier: ^5.2.0
|
specifier: ^5.2.0
|
||||||
version: 5.4.0
|
version: 5.4.0
|
||||||
@@ -10572,7 +10575,7 @@ packages:
|
|||||||
'@storybook/client-logger': 7.6.17
|
'@storybook/client-logger': 7.6.17
|
||||||
'@storybook/core-events': 7.6.17
|
'@storybook/core-events': 7.6.17
|
||||||
'@storybook/global': 5.0.0
|
'@storybook/global': 5.0.0
|
||||||
qs: 6.12.1
|
qs: 6.13.0
|
||||||
telejson: 7.2.0
|
telejson: 7.2.0
|
||||||
tiny-invariant: 1.3.3
|
tiny-invariant: 1.3.3
|
||||||
dev: true
|
dev: true
|
||||||
@@ -10583,7 +10586,7 @@ packages:
|
|||||||
'@storybook/client-logger': 7.6.20
|
'@storybook/client-logger': 7.6.20
|
||||||
'@storybook/core-events': 7.6.20
|
'@storybook/core-events': 7.6.20
|
||||||
'@storybook/global': 5.0.0
|
'@storybook/global': 5.0.0
|
||||||
qs: 6.12.1
|
qs: 6.13.0
|
||||||
telejson: 7.2.0
|
telejson: 7.2.0
|
||||||
tiny-invariant: 1.3.3
|
tiny-invariant: 1.3.3
|
||||||
dev: true
|
dev: true
|
||||||
@@ -11169,7 +11172,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@storybook/client-logger': 7.6.17
|
'@storybook/client-logger': 7.6.17
|
||||||
memoizerific: 1.11.3
|
memoizerific: 1.11.3
|
||||||
qs: 6.12.1
|
qs: 6.13.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@storybook/router@7.6.20:
|
/@storybook/router@7.6.20:
|
||||||
@@ -11177,7 +11180,7 @@ packages:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@storybook/client-logger': 7.6.20
|
'@storybook/client-logger': 7.6.20
|
||||||
memoizerific: 1.11.3
|
memoizerific: 1.11.3
|
||||||
qs: 6.12.1
|
qs: 6.13.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@storybook/telemetry@7.2.2:
|
/@storybook/telemetry@7.2.2:
|
||||||
@@ -32929,7 +32932,7 @@ packages:
|
|||||||
http-basic: 8.1.3
|
http-basic: 8.1.3
|
||||||
http-response-object: 3.0.2
|
http-response-object: 3.0.2
|
||||||
promise: 8.3.0
|
promise: 8.3.0
|
||||||
qs: 6.12.1
|
qs: 6.13.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/thenify-all@1.6.0:
|
/thenify-all@1.6.0:
|
||||||
|
|||||||
705
temp/CashFlowStatement/CashFlow.ts
Normal file
705
temp/CashFlowStatement/CashFlow.ts
Normal file
@@ -0,0 +1,705 @@
|
|||||||
|
import * as R from 'ramda';
|
||||||
|
import { defaultTo, map, set, sumBy, isEmpty, mapValues, get } from 'lodash';
|
||||||
|
import * as mathjs from 'mathjs';
|
||||||
|
import * as moment from 'moment';
|
||||||
|
import { compose } from 'lodash/fp';
|
||||||
|
import { I18nService } from 'nestjs-i18n';
|
||||||
|
import {
|
||||||
|
ICashFlowSchemaSection,
|
||||||
|
ICashFlowStatementQuery,
|
||||||
|
ICashFlowStatementNetIncomeSection,
|
||||||
|
ICashFlowStatementAccountSection,
|
||||||
|
ICashFlowSchemaSectionAccounts,
|
||||||
|
ICashFlowStatementAccountMeta,
|
||||||
|
ICashFlowSchemaAccountRelation,
|
||||||
|
ICashFlowStatementSectionType,
|
||||||
|
ICashFlowStatementData,
|
||||||
|
ICashFlowSchemaTotalSection,
|
||||||
|
ICashFlowStatementTotalSection,
|
||||||
|
ICashFlowStatementSection,
|
||||||
|
ICashFlowCashBeginningNode,
|
||||||
|
ICashFlowStatementAggregateSection,
|
||||||
|
} from './Cashflow.types';
|
||||||
|
import { CASH_FLOW_SCHEMA } from './schema';
|
||||||
|
import { FinancialSheet } from '../../common/FinancialSheet';
|
||||||
|
import { ACCOUNT_ROOT_TYPE } from '@/constants/accounts';
|
||||||
|
import { CashFlowStatementDatePeriods } from './CashFlowDatePeriods';
|
||||||
|
import { DISPLAY_COLUMNS_BY } from './constants';
|
||||||
|
import { FinancialSheetStructure } from '../../common/FinancialSheetStructure';
|
||||||
|
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||||
|
import { ILedger } from '@/modules/Ledger/types/Ledger.types';
|
||||||
|
import { INumberFormatQuery } from '../../types/Report.types';
|
||||||
|
import { transformToMapBy } from '@/utils/transform-to-map-by';
|
||||||
|
import { accumSum } from '@/utils/accum-sum';
|
||||||
|
import { ModelObject } from 'objection';
|
||||||
|
|
||||||
|
export default class CashFlowStatement extends compose(
|
||||||
|
CashFlowStatementDatePeriods,
|
||||||
|
FinancialSheetStructure
|
||||||
|
)(FinancialSheet) {
|
||||||
|
readonly baseCurrency: string;
|
||||||
|
readonly i18n: I18nService;
|
||||||
|
readonly sectionsByIds = {};
|
||||||
|
readonly cashFlowSchemaMap: Map<string, ICashFlowSchemaSection>;
|
||||||
|
readonly cashFlowSchemaSeq: Array<string>;
|
||||||
|
readonly accountByTypeMap: Map<string, Account[]>;
|
||||||
|
readonly accountsByRootType: Map<string, Account[]>;
|
||||||
|
readonly ledger: ILedger;
|
||||||
|
readonly cashLedger: ILedger;
|
||||||
|
readonly netIncomeLedger: ILedger;
|
||||||
|
readonly query: ICashFlowStatementQuery;
|
||||||
|
readonly numberFormat: INumberFormatQuery;
|
||||||
|
readonly comparatorDateType: string;
|
||||||
|
readonly dateRangeSet: { fromDate: Date; toDate: Date }[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
accounts: Account[],
|
||||||
|
ledger: ILedger,
|
||||||
|
cashLedger: ILedger,
|
||||||
|
netIncomeLedger: ILedger,
|
||||||
|
query: ICashFlowStatementQuery,
|
||||||
|
baseCurrency: string,
|
||||||
|
i18n
|
||||||
|
) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
this.baseCurrency = baseCurrency;
|
||||||
|
this.i18n = i18n;
|
||||||
|
this.ledger = ledger;
|
||||||
|
this.cashLedger = cashLedger;
|
||||||
|
this.netIncomeLedger = netIncomeLedger;
|
||||||
|
this.accountByTypeMap = transformToMapBy(accounts, 'accountType');
|
||||||
|
this.accountsByRootType = transformToMapBy(accounts, 'accountRootType');
|
||||||
|
this.query = query;
|
||||||
|
this.numberFormat = this.query.numberFormat;
|
||||||
|
this.dateRangeSet = [];
|
||||||
|
this.comparatorDateType =
|
||||||
|
query.displayColumnsType === 'total' ? 'day' : query.displayColumnsBy;
|
||||||
|
|
||||||
|
this.initDateRangeCollection();
|
||||||
|
}
|
||||||
|
|
||||||
|
// --------------------------------------------
|
||||||
|
// # GENERAL UTILITIES
|
||||||
|
// --------------------------------------------
|
||||||
|
/**
|
||||||
|
* Retrieve the expense accounts ids.
|
||||||
|
* @return {number[]}
|
||||||
|
*/
|
||||||
|
private getAccountsIdsByType = (accountType: string): number[] => {
|
||||||
|
const expenseAccounts = this.accountsByRootType.get(accountType);
|
||||||
|
const expenseAccountsIds = map(expenseAccounts, 'id');
|
||||||
|
|
||||||
|
return expenseAccountsIds;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines the given display columns by type.
|
||||||
|
* @param {string} displayColumnsBy
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
private isDisplayColumnsBy = (displayColumnsBy: string): boolean => {
|
||||||
|
return this.query.displayColumnsType === displayColumnsBy;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adjustments the given amount.
|
||||||
|
* @param {string} direction
|
||||||
|
* @param {number} amount -
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
private amountAdjustment = (direction: 'mines' | 'plus', amount): number => {
|
||||||
|
return R.when(
|
||||||
|
R.always(R.equals(direction, 'mines')),
|
||||||
|
R.multiply(-1)
|
||||||
|
)(amount);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------
|
||||||
|
// # NET INCOME NODE
|
||||||
|
// --------------------------------------------
|
||||||
|
/**
|
||||||
|
* Retrieve the accounts net income.
|
||||||
|
* @returns {number} - Amount of net income.
|
||||||
|
*/
|
||||||
|
private getAccountsNetIncome(): number {
|
||||||
|
// Mapping income/expense accounts ids.
|
||||||
|
const incomeAccountsIds = this.getAccountsIdsByType(
|
||||||
|
ACCOUNT_ROOT_TYPE.INCOME
|
||||||
|
);
|
||||||
|
const expenseAccountsIds = this.getAccountsIdsByType(
|
||||||
|
ACCOUNT_ROOT_TYPE.EXPENSE
|
||||||
|
);
|
||||||
|
// Income closing balance.
|
||||||
|
const incomeClosingBalance = accumSum(incomeAccountsIds, (id) =>
|
||||||
|
this.netIncomeLedger.whereAccountId(id).getClosingBalance()
|
||||||
|
);
|
||||||
|
// Expense closing balance.
|
||||||
|
const expenseClosingBalance = accumSum(expenseAccountsIds, (id) =>
|
||||||
|
this.netIncomeLedger.whereAccountId(id).getClosingBalance()
|
||||||
|
);
|
||||||
|
// Net income = income - expenses.
|
||||||
|
const netIncome = incomeClosingBalance - expenseClosingBalance;
|
||||||
|
|
||||||
|
return netIncome;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the net income section from the given section schema.
|
||||||
|
* @param {ICashFlowSchemaSection} nodeSchema - Report section schema.
|
||||||
|
* @returns {ICashFlowStatementNetIncomeSection}
|
||||||
|
*/
|
||||||
|
private netIncomeSectionMapper = (
|
||||||
|
nodeSchema: ICashFlowSchemaSection
|
||||||
|
): ICashFlowStatementNetIncomeSection => {
|
||||||
|
const netIncome = this.getAccountsNetIncome();
|
||||||
|
|
||||||
|
const node = {
|
||||||
|
id: nodeSchema.id,
|
||||||
|
label: this.i18n.__(nodeSchema.label),
|
||||||
|
total: this.getAmountMeta(netIncome),
|
||||||
|
sectionType: ICashFlowStatementSectionType.NET_INCOME,
|
||||||
|
};
|
||||||
|
return R.compose(
|
||||||
|
R.when(
|
||||||
|
R.always(this.isDisplayColumnsBy(DISPLAY_COLUMNS_BY.DATE_PERIODS)),
|
||||||
|
this.assocPeriodsToNetIncomeNode
|
||||||
|
)
|
||||||
|
)(node);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------
|
||||||
|
// # ACCOUNT NODE
|
||||||
|
// --------------------------------------------
|
||||||
|
/**
|
||||||
|
* Retrieve account meta.
|
||||||
|
* @param {ICashFlowSchemaAccountRelation} relation - Account relation.
|
||||||
|
* @param {IAccount} account -
|
||||||
|
* @returns {ICashFlowStatementAccountMeta}
|
||||||
|
*/
|
||||||
|
private accountMetaMapper = (
|
||||||
|
relation: ICashFlowSchemaAccountRelation,
|
||||||
|
account: ModelObject<Account>
|
||||||
|
): ICashFlowStatementAccountMeta => {
|
||||||
|
// Retrieve the closing balance of the given account.
|
||||||
|
const getClosingBalance = (id) =>
|
||||||
|
this.ledger.whereAccountId(id).getClosingBalance();
|
||||||
|
|
||||||
|
const closingBalance = R.compose(
|
||||||
|
// Multiplies the amount by -1 in case the relation in mines.
|
||||||
|
R.curry(this.amountAdjustment)(relation.direction)
|
||||||
|
)(getClosingBalance(account.id));
|
||||||
|
|
||||||
|
const node = {
|
||||||
|
id: account.id,
|
||||||
|
code: account.code,
|
||||||
|
label: account.name,
|
||||||
|
accountType: account.accountType,
|
||||||
|
adjustmentType: relation.direction,
|
||||||
|
total: this.getAmountMeta(closingBalance),
|
||||||
|
sectionType: ICashFlowStatementSectionType.ACCOUNT,
|
||||||
|
};
|
||||||
|
return R.compose(
|
||||||
|
R.when(
|
||||||
|
R.always(this.isDisplayColumnsBy(DISPLAY_COLUMNS_BY.DATE_PERIODS)),
|
||||||
|
this.assocPeriodsToAccountNode
|
||||||
|
)
|
||||||
|
)(node);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve accounts sections by the given schema relation.
|
||||||
|
* @param {ICashFlowSchemaAccountRelation} relation
|
||||||
|
* @returns {ICashFlowStatementAccountMeta[]}
|
||||||
|
*/
|
||||||
|
private getAccountsBySchemaRelation = (
|
||||||
|
relation: ICashFlowSchemaAccountRelation
|
||||||
|
): ICashFlowStatementAccountMeta[] => {
|
||||||
|
const accounts = defaultTo(this.accountByTypeMap.get(relation.type), []);
|
||||||
|
const accountMetaMapper = R.curry(this.accountMetaMapper)(relation);
|
||||||
|
return R.map(accountMetaMapper)(accounts);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the accounts meta.
|
||||||
|
* @param {string[]} types
|
||||||
|
* @returns {ICashFlowStatementAccountMeta[]}
|
||||||
|
*/
|
||||||
|
private getAccountsBySchemaRelations = (
|
||||||
|
relations: ICashFlowSchemaAccountRelation[]
|
||||||
|
): ICashFlowStatementAccountMeta[] => {
|
||||||
|
return R.pipe(
|
||||||
|
R.append(R.map(this.getAccountsBySchemaRelation)(relations)),
|
||||||
|
R.flatten
|
||||||
|
)([]);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates the accounts total
|
||||||
|
* @param {ICashFlowStatementAccountMeta[]} accounts
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
private getAccountsMetaTotal = (
|
||||||
|
accounts: ICashFlowStatementAccountMeta[]
|
||||||
|
): number => {
|
||||||
|
return sumBy(accounts, 'total.amount');
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the accounts section from the section schema.
|
||||||
|
* @param {ICashFlowSchemaSectionAccounts} sectionSchema
|
||||||
|
* @returns {ICashFlowStatementAccountSection}
|
||||||
|
*/
|
||||||
|
private accountsSectionParser = (
|
||||||
|
sectionSchema: ICashFlowSchemaSectionAccounts
|
||||||
|
): ICashFlowStatementAccountSection => {
|
||||||
|
const { accountsRelations } = sectionSchema;
|
||||||
|
|
||||||
|
const accounts = this.getAccountsBySchemaRelations(accountsRelations);
|
||||||
|
const accountsTotal = this.getAccountsMetaTotal(accounts);
|
||||||
|
const total = this.getTotalAmountMeta(accountsTotal);
|
||||||
|
|
||||||
|
const node = {
|
||||||
|
sectionType: ICashFlowStatementSectionType.ACCOUNTS,
|
||||||
|
id: sectionSchema.id,
|
||||||
|
label: this.i18n.__(sectionSchema.label),
|
||||||
|
footerLabel: this.i18n.__(sectionSchema.footerLabel),
|
||||||
|
children: accounts,
|
||||||
|
total,
|
||||||
|
};
|
||||||
|
return R.compose(
|
||||||
|
R.when(
|
||||||
|
R.always(this.isDisplayColumnsBy(DISPLAY_COLUMNS_BY.DATE_PERIODS)),
|
||||||
|
this.assocPeriodsToAggregateNode
|
||||||
|
)
|
||||||
|
)(node);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines the schema section type.
|
||||||
|
* @param {string} type
|
||||||
|
* @param {ICashFlowSchemaSection} section
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
private isSchemaSectionType = R.curry(
|
||||||
|
(type: string, section: ICashFlowSchemaSection): boolean => {
|
||||||
|
return type === section.sectionType;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
// --------------------------------------------
|
||||||
|
// # AGGREGATE NODE
|
||||||
|
// --------------------------------------------
|
||||||
|
/**
|
||||||
|
* Aggregate schema node parser to aggregate report node.
|
||||||
|
* @param {ICashFlowSchemaSection} schemaSection
|
||||||
|
* @returns {ICashFlowStatementAggregateSection}
|
||||||
|
*/
|
||||||
|
private regularSectionParser = R.curry(
|
||||||
|
(
|
||||||
|
children,
|
||||||
|
schemaSection: ICashFlowSchemaSection
|
||||||
|
): ICashFlowStatementAggregateSection => {
|
||||||
|
const node = {
|
||||||
|
id: schemaSection.id,
|
||||||
|
label: this.i18n.__(schemaSection.label),
|
||||||
|
footerLabel: this.i18n.__(schemaSection.footerLabel),
|
||||||
|
sectionType: ICashFlowStatementSectionType.AGGREGATE,
|
||||||
|
children,
|
||||||
|
};
|
||||||
|
return R.compose(
|
||||||
|
R.when(
|
||||||
|
this.isSchemaSectionType(ICashFlowStatementSectionType.AGGREGATE),
|
||||||
|
this.assocRegularSectionTotal
|
||||||
|
),
|
||||||
|
R.when(
|
||||||
|
this.isSchemaSectionType(ICashFlowStatementSectionType.AGGREGATE),
|
||||||
|
R.when(
|
||||||
|
R.always(this.isDisplayColumnsBy(DISPLAY_COLUMNS_BY.DATE_PERIODS)),
|
||||||
|
this.assocPeriodsToAggregateNode
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)(node);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
private transformSectionsToMap = (sections: ICashFlowSchemaSection[]) => {
|
||||||
|
return this.reduceNodesDeep(
|
||||||
|
sections,
|
||||||
|
(acc, section) => {
|
||||||
|
if (section.id) {
|
||||||
|
acc[`${section.id}`] = section;
|
||||||
|
}
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
{}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------
|
||||||
|
// # TOTAL EQUATION NODE
|
||||||
|
// --------------------------------------------
|
||||||
|
|
||||||
|
private sectionsMapToTotal = (mappedSections: { [key: number]: any }) => {
|
||||||
|
return mapValues(mappedSections, (node) => get(node, 'total.amount') || 0);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Evauluate equaation string with the given scope table.
|
||||||
|
* @param {string} equation -
|
||||||
|
* @param {{ [key: string]: number }} scope -
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
private evaluateEquation = (
|
||||||
|
equation: string,
|
||||||
|
scope: { [key: string | number]: number }
|
||||||
|
): number => {
|
||||||
|
return mathjs.evaluate(equation, scope);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the total section from the eqauation parser.
|
||||||
|
* @param {ICashFlowSchemaTotalSection} sectionSchema
|
||||||
|
* @param {ICashFlowSchemaSection[]} accumulatedSections
|
||||||
|
* @returns {ICashFlowStatementTotalSection}
|
||||||
|
*/
|
||||||
|
private totalEquationSectionParser = (
|
||||||
|
accumulatedSections: ICashFlowSchemaSection[],
|
||||||
|
sectionSchema: ICashFlowSchemaTotalSection
|
||||||
|
): ICashFlowStatementTotalSection => {
|
||||||
|
const mappedSectionsById = this.transformSectionsToMap(accumulatedSections);
|
||||||
|
const nodesTotalById = this.sectionsMapToTotal(mappedSectionsById);
|
||||||
|
|
||||||
|
const total = this.evaluateEquation(sectionSchema.equation, nodesTotalById);
|
||||||
|
|
||||||
|
return R.compose(
|
||||||
|
R.when(
|
||||||
|
R.always(this.isDisplayColumnsBy(DISPLAY_COLUMNS_BY.DATE_PERIODS)),
|
||||||
|
R.curry(this.assocTotalEquationDatePeriods)(
|
||||||
|
mappedSectionsById,
|
||||||
|
sectionSchema.equation
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)({
|
||||||
|
sectionType: ICashFlowStatementSectionType.TOTAL,
|
||||||
|
id: sectionSchema.id,
|
||||||
|
label: this.i18n.__(sectionSchema.label),
|
||||||
|
total: this.getTotalAmountMeta(total),
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the beginning cash from date.
|
||||||
|
* @param {Date|string} fromDate -
|
||||||
|
* @return {Date}
|
||||||
|
*/
|
||||||
|
private beginningCashFrom = (fromDate: string | Date): Date => {
|
||||||
|
return moment(fromDate).subtract(1, 'days').toDate();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve account meta.
|
||||||
|
* @param {ICashFlowSchemaAccountRelation} relation
|
||||||
|
* @param {IAccount} account
|
||||||
|
* @returns {ICashFlowStatementAccountMeta}
|
||||||
|
*/
|
||||||
|
private cashAccountMetaMapper = (
|
||||||
|
relation: ICashFlowSchemaAccountRelation,
|
||||||
|
account: ModelObject<Account>
|
||||||
|
): ICashFlowStatementAccountMeta => {
|
||||||
|
const cashToDate = this.beginningCashFrom(this.query.fromDate);
|
||||||
|
|
||||||
|
const closingBalance = this.cashLedger
|
||||||
|
.whereToDate(cashToDate)
|
||||||
|
.whereAccountId(account.id)
|
||||||
|
.getClosingBalance();
|
||||||
|
|
||||||
|
const node = {
|
||||||
|
id: account.id,
|
||||||
|
code: account.code,
|
||||||
|
label: account.name,
|
||||||
|
accountType: account.accountType,
|
||||||
|
adjustmentType: relation.direction,
|
||||||
|
total: this.getAmountMeta(closingBalance),
|
||||||
|
sectionType: ICashFlowStatementSectionType.ACCOUNT,
|
||||||
|
};
|
||||||
|
return R.compose(
|
||||||
|
R.when(
|
||||||
|
R.always(this.isDisplayColumnsBy(DISPLAY_COLUMNS_BY.DATE_PERIODS)),
|
||||||
|
this.assocCashAtBeginningAccountDatePeriods
|
||||||
|
)
|
||||||
|
)(node);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve accounts sections by the given schema relation.
|
||||||
|
* @param {ICashFlowSchemaAccountRelation} relation
|
||||||
|
* @returns {ICashFlowStatementAccountMeta[]}
|
||||||
|
*/
|
||||||
|
private getCashAccountsBySchemaRelation = (
|
||||||
|
relation: ICashFlowSchemaAccountRelation
|
||||||
|
): ICashFlowStatementAccountMeta[] => {
|
||||||
|
const accounts = this.accountByTypeMap.get(relation.type) || [];
|
||||||
|
const accountMetaMapper = R.curry(this.cashAccountMetaMapper)(relation);
|
||||||
|
return accounts.map(accountMetaMapper);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the accounts meta.
|
||||||
|
* @param {string[]} types
|
||||||
|
* @returns {ICashFlowStatementAccountMeta[]}
|
||||||
|
*/
|
||||||
|
private getCashAccountsBySchemaRelations = (
|
||||||
|
relations: ICashFlowSchemaAccountRelation[]
|
||||||
|
): ICashFlowStatementAccountMeta[] => {
|
||||||
|
return R.concat(...R.map(this.getCashAccountsBySchemaRelation)(relations));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the cash at beginning section.
|
||||||
|
* @param {ICashFlowSchemaTotalSection} sectionSchema -
|
||||||
|
* @return {ICashFlowCashBeginningNode}
|
||||||
|
*/
|
||||||
|
private cashAtBeginningSectionParser = (
|
||||||
|
nodeSchema: ICashFlowSchemaSection
|
||||||
|
): ICashFlowCashBeginningNode => {
|
||||||
|
const { accountsRelations } = nodeSchema;
|
||||||
|
const children = this.getCashAccountsBySchemaRelations(accountsRelations);
|
||||||
|
const total = this.getAccountsMetaTotal(children);
|
||||||
|
|
||||||
|
const node = {
|
||||||
|
sectionType: ICashFlowStatementSectionType.CASH_AT_BEGINNING,
|
||||||
|
id: nodeSchema.id,
|
||||||
|
label: this.i18n.__(nodeSchema.label),
|
||||||
|
children,
|
||||||
|
total: this.getTotalAmountMeta(total),
|
||||||
|
};
|
||||||
|
return R.compose(
|
||||||
|
R.when(
|
||||||
|
R.always(this.isDisplayColumnsBy(DISPLAY_COLUMNS_BY.DATE_PERIODS)),
|
||||||
|
this.assocCashAtBeginningDatePeriods
|
||||||
|
)
|
||||||
|
)(node);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the schema section.
|
||||||
|
* @param {ICashFlowSchemaSection} schemaNode
|
||||||
|
* @returns {ICashFlowSchemaSection}
|
||||||
|
*/
|
||||||
|
private schemaSectionParser = (
|
||||||
|
schemaNode: ICashFlowSchemaSection,
|
||||||
|
children
|
||||||
|
): ICashFlowSchemaSection | ICashFlowStatementSection => {
|
||||||
|
return R.compose(
|
||||||
|
// Accounts node.
|
||||||
|
R.when(
|
||||||
|
this.isSchemaSectionType(ICashFlowStatementSectionType.ACCOUNTS),
|
||||||
|
this.accountsSectionParser
|
||||||
|
),
|
||||||
|
// Net income node.
|
||||||
|
R.when(
|
||||||
|
this.isSchemaSectionType(ICashFlowStatementSectionType.NET_INCOME),
|
||||||
|
this.netIncomeSectionMapper
|
||||||
|
),
|
||||||
|
// Cash at beginning node.
|
||||||
|
R.when(
|
||||||
|
this.isSchemaSectionType(
|
||||||
|
ICashFlowStatementSectionType.CASH_AT_BEGINNING
|
||||||
|
),
|
||||||
|
this.cashAtBeginningSectionParser
|
||||||
|
),
|
||||||
|
// Aggregate node. (that has no section type).
|
||||||
|
R.when(
|
||||||
|
this.isSchemaSectionType(ICashFlowStatementSectionType.AGGREGATE),
|
||||||
|
this.regularSectionParser(children)
|
||||||
|
)
|
||||||
|
)(schemaNode);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses the schema section.
|
||||||
|
* @param {ICashFlowSchemaSection | ICashFlowStatementSection} section
|
||||||
|
* @param {number} key
|
||||||
|
* @param {ICashFlowSchemaSection[]} parentValue
|
||||||
|
* @param {(ICashFlowSchemaSection | ICashFlowStatementSection)[]} accumulatedSections
|
||||||
|
* @returns {ICashFlowSchemaSection}
|
||||||
|
*/
|
||||||
|
private schemaSectionTotalParser = (
|
||||||
|
section: ICashFlowSchemaSection | ICashFlowStatementSection,
|
||||||
|
key: number,
|
||||||
|
parentValue: ICashFlowSchemaSection[],
|
||||||
|
context,
|
||||||
|
accumulatedSections: (ICashFlowSchemaSection | ICashFlowStatementSection)[]
|
||||||
|
): ICashFlowSchemaSection | ICashFlowStatementSection => {
|
||||||
|
return R.compose(
|
||||||
|
// Total equation section.
|
||||||
|
R.when(
|
||||||
|
this.isSchemaSectionType(ICashFlowStatementSectionType.TOTAL),
|
||||||
|
R.curry(this.totalEquationSectionParser)(accumulatedSections)
|
||||||
|
)
|
||||||
|
)(section);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schema sections parser.
|
||||||
|
* @param {ICashFlowSchemaSection[]}schema
|
||||||
|
* @returns {ICashFlowStatementSection[]}
|
||||||
|
*/
|
||||||
|
private schemaSectionsParser = (
|
||||||
|
schema: ICashFlowSchemaSection[]
|
||||||
|
): ICashFlowStatementSection[] => {
|
||||||
|
return this.mapNodesDeepReverse(schema, this.schemaSectionParser);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the `total` property to the aggregate node.
|
||||||
|
* @param {ICashFlowStatementSection} section
|
||||||
|
* @return {ICashFlowStatementSection}
|
||||||
|
*/
|
||||||
|
private assocRegularSectionTotal = (section: ICashFlowStatementSection) => {
|
||||||
|
const total = this.getAccountsMetaTotal(section.children);
|
||||||
|
return R.assoc('total', this.getTotalAmountMeta(total), section);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parses total schema nodes.
|
||||||
|
* @param {(ICashFlowSchemaSection | ICashFlowStatementSection)[]} sections
|
||||||
|
* @returns {(ICashFlowSchemaSection | ICashFlowStatementSection)[]}
|
||||||
|
*/
|
||||||
|
private totalSectionsParser = (
|
||||||
|
sections: (ICashFlowSchemaSection | ICashFlowStatementSection)[]
|
||||||
|
): (ICashFlowSchemaSection | ICashFlowStatementSection)[] => {
|
||||||
|
return this.reduceNodesDeep(
|
||||||
|
sections,
|
||||||
|
(acc, value, key, parentValue, context) => {
|
||||||
|
set(
|
||||||
|
acc,
|
||||||
|
context.path,
|
||||||
|
this.schemaSectionTotalParser(value, key, parentValue, context, acc)
|
||||||
|
);
|
||||||
|
return acc;
|
||||||
|
},
|
||||||
|
[]
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
// --------------------------------------------
|
||||||
|
// REPORT FILTERING
|
||||||
|
// --------------------------------------------
|
||||||
|
/**
|
||||||
|
* Detarmines the given section has children and not empty.
|
||||||
|
* @param {ICashFlowStatementSection} section
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
private isSectionHasChildren = (
|
||||||
|
section: ICashFlowStatementSection
|
||||||
|
): boolean => {
|
||||||
|
return !isEmpty(section.children);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines whether the section has no zero amount.
|
||||||
|
* @param {ICashFlowStatementSection} section
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
private isSectionNoneZero = (section: ICashFlowStatementSection): boolean => {
|
||||||
|
return section.total.amount !== 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines whether the parent accounts sections has children.
|
||||||
|
* @param {ICashFlowStatementSection} section
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
private isAccountsSectionHasChildren = (
|
||||||
|
section: ICashFlowStatementSection[]
|
||||||
|
): boolean => {
|
||||||
|
return R.ifElse(
|
||||||
|
this.isSchemaSectionType(ICashFlowStatementSectionType.ACCOUNTS),
|
||||||
|
this.isSectionHasChildren,
|
||||||
|
R.always(true)
|
||||||
|
)(section);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines the account section has no zero otherwise returns true.
|
||||||
|
* @param {ICashFlowStatementSection} section
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
private isAccountLeafNoneZero = (
|
||||||
|
section: ICashFlowStatementSection[]
|
||||||
|
): boolean => {
|
||||||
|
return R.ifElse(
|
||||||
|
this.isSchemaSectionType(ICashFlowStatementSectionType.ACCOUNT),
|
||||||
|
this.isSectionNoneZero,
|
||||||
|
R.always(true)
|
||||||
|
)(section);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deep filters the non-zero accounts leafs of the report sections.
|
||||||
|
* @param {ICashFlowStatementSection[]} sections
|
||||||
|
* @returns {ICashFlowStatementSection[]}
|
||||||
|
*/
|
||||||
|
private filterNoneZeroAccountsLeafs = (
|
||||||
|
sections: ICashFlowStatementSection[]
|
||||||
|
): ICashFlowStatementSection[] => {
|
||||||
|
return this.filterNodesDeep(sections, this.isAccountLeafNoneZero);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deep filter the non-children sections of the report sections.
|
||||||
|
* @param {ICashFlowStatementSection[]} sections
|
||||||
|
* @returns {ICashFlowStatementSection[]}
|
||||||
|
*/
|
||||||
|
private filterNoneChildrenSections = (
|
||||||
|
sections: ICashFlowStatementSection[]
|
||||||
|
): ICashFlowStatementSection[] => {
|
||||||
|
return this.filterNodesDeep(sections, this.isAccountsSectionHasChildren);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Filters the report data.
|
||||||
|
* @param {ICashFlowStatementSection[]} sections
|
||||||
|
* @returns {ICashFlowStatementSection[]}
|
||||||
|
*/
|
||||||
|
private filterReportData = (
|
||||||
|
sections: ICashFlowStatementSection[]
|
||||||
|
): ICashFlowStatementSection[] => {
|
||||||
|
return R.compose(
|
||||||
|
this.filterNoneChildrenSections,
|
||||||
|
this.filterNoneZeroAccountsLeafs
|
||||||
|
)(sections);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Schema parser.
|
||||||
|
* @param {ICashFlowSchemaSection[]} schema
|
||||||
|
* @returns {ICashFlowSchemaSection[]}
|
||||||
|
*/
|
||||||
|
private schemaParser = (
|
||||||
|
schema: ICashFlowSchemaSection[]
|
||||||
|
): ICashFlowSchemaSection[] => {
|
||||||
|
return R.compose(
|
||||||
|
R.when(
|
||||||
|
R.always(this.query.noneTransactions || this.query.noneZero),
|
||||||
|
this.filterReportData
|
||||||
|
),
|
||||||
|
this.totalSectionsParser,
|
||||||
|
this.schemaSectionsParser
|
||||||
|
)(schema);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the cashflow statement data.
|
||||||
|
* @return {ICashFlowStatementData}
|
||||||
|
*/
|
||||||
|
public reportData = (): ICashFlowStatementData => {
|
||||||
|
return this.schemaParser(R.clone(CASH_FLOW_SCHEMA));
|
||||||
|
};
|
||||||
|
}
|
||||||
412
temp/CashFlowStatement/CashFlowDatePeriods.ts
Normal file
412
temp/CashFlowStatement/CashFlowDatePeriods.ts
Normal file
@@ -0,0 +1,412 @@
|
|||||||
|
import * as R from 'ramda';
|
||||||
|
import { sumBy, mapValues, get } from 'lodash';
|
||||||
|
import { ACCOUNT_ROOT_TYPE } from '@/constants/accounts';
|
||||||
|
import {
|
||||||
|
ICashFlowDatePeriod,
|
||||||
|
ICashFlowStatementNetIncomeSection,
|
||||||
|
ICashFlowStatementAccountSection,
|
||||||
|
ICashFlowStatementSection,
|
||||||
|
ICashFlowSchemaTotalSection,
|
||||||
|
ICashFlowStatementTotalSection,
|
||||||
|
ICashFlowStatementQuery,
|
||||||
|
IDateRange,
|
||||||
|
} from './Cashflow.types';
|
||||||
|
import { IFormatNumberSettings } from '../../types/Report.types';
|
||||||
|
import { dateRangeFromToCollection } from '@/utils/date-range-collection';
|
||||||
|
import { accumSum } from '@/utils/accum-sum';
|
||||||
|
|
||||||
|
export const CashFlowStatementDatePeriods = (Base) =>
|
||||||
|
class extends Base {
|
||||||
|
dateRangeSet: IDateRange[];
|
||||||
|
query: ICashFlowStatementQuery;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize date range set.
|
||||||
|
*/
|
||||||
|
public initDateRangeCollection() {
|
||||||
|
this.dateRangeSet = dateRangeFromToCollection(
|
||||||
|
this.query.fromDate,
|
||||||
|
this.query.toDate,
|
||||||
|
this.comparatorDateType
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the date period meta.
|
||||||
|
* @param {number} total - Total amount.
|
||||||
|
* @param {Date} fromDate - From date.
|
||||||
|
* @param {Date} toDate - To date.
|
||||||
|
* @return {ICashFlowDatePeriod}
|
||||||
|
*/
|
||||||
|
public getDatePeriodTotalMeta = (
|
||||||
|
total: number,
|
||||||
|
fromDate: Date,
|
||||||
|
toDate: Date,
|
||||||
|
overrideSettings: IFormatNumberSettings = {}
|
||||||
|
): ICashFlowDatePeriod => {
|
||||||
|
return this.getDatePeriodMeta(total, fromDate, toDate, {
|
||||||
|
money: true,
|
||||||
|
...overrideSettings,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the date period meta.
|
||||||
|
* @param {number} total - Total amount.
|
||||||
|
* @param {Date} fromDate - From date.
|
||||||
|
* @param {Date} toDate - To date.
|
||||||
|
* @return {ICashFlowDatePeriod}
|
||||||
|
*/
|
||||||
|
public getDatePeriodMeta = (
|
||||||
|
total: number,
|
||||||
|
fromDate: Date,
|
||||||
|
toDate: Date,
|
||||||
|
overrideSettings?: IFormatNumberSettings
|
||||||
|
): ICashFlowDatePeriod => {
|
||||||
|
return {
|
||||||
|
fromDate: this.getDateMeta(fromDate),
|
||||||
|
toDate: this.getDateMeta(toDate),
|
||||||
|
total: this.getAmountMeta(total, overrideSettings),
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
// Net income --------------------
|
||||||
|
/**
|
||||||
|
* Retrieve the net income between the given date range.
|
||||||
|
* @param {Date} fromDate
|
||||||
|
* @param {Date} toDate
|
||||||
|
* @returns {number}
|
||||||
|
*/
|
||||||
|
public getNetIncomeDateRange = (fromDate: Date, toDate: Date) => {
|
||||||
|
// Mapping income/expense accounts ids.
|
||||||
|
const incomeAccountsIds = this.getAccountsIdsByType(
|
||||||
|
ACCOUNT_ROOT_TYPE.INCOME
|
||||||
|
);
|
||||||
|
const expenseAccountsIds = this.getAccountsIdsByType(
|
||||||
|
ACCOUNT_ROOT_TYPE.EXPENSE
|
||||||
|
);
|
||||||
|
// Income closing balance.
|
||||||
|
const incomeClosingBalance = accumSum(incomeAccountsIds, (id) =>
|
||||||
|
this.netIncomeLedger
|
||||||
|
.whereFromDate(fromDate)
|
||||||
|
.whereToDate(toDate)
|
||||||
|
.whereAccountId(id)
|
||||||
|
.getClosingBalance()
|
||||||
|
);
|
||||||
|
// Expense closing balance.
|
||||||
|
const expenseClosingBalance = accumSum(expenseAccountsIds, (id) =>
|
||||||
|
this.netIncomeLedger
|
||||||
|
.whereToDate(toDate)
|
||||||
|
.whereFromDate(fromDate)
|
||||||
|
.whereAccountId(id)
|
||||||
|
.getClosingBalance()
|
||||||
|
);
|
||||||
|
// Net income = income - expenses.
|
||||||
|
const netIncome = incomeClosingBalance - expenseClosingBalance;
|
||||||
|
|
||||||
|
return netIncome;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the net income of date period.
|
||||||
|
* @param {IDateRange} dateRange -
|
||||||
|
* @retrun {ICashFlowDatePeriod}
|
||||||
|
*/
|
||||||
|
public getNetIncomeDatePeriod = (dateRange): ICashFlowDatePeriod => {
|
||||||
|
const total = this.getNetIncomeDateRange(
|
||||||
|
dateRange.fromDate,
|
||||||
|
dateRange.toDate
|
||||||
|
);
|
||||||
|
return this.getDatePeriodMeta(
|
||||||
|
total,
|
||||||
|
dateRange.fromDate,
|
||||||
|
dateRange.toDate
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the net income node between the given date ranges.
|
||||||
|
* @param {Date} fromDate
|
||||||
|
* @param {Date} toDate
|
||||||
|
* @returns {ICashFlowDatePeriod[]}
|
||||||
|
*/
|
||||||
|
public getNetIncomeDatePeriods = (
|
||||||
|
section: ICashFlowStatementNetIncomeSection
|
||||||
|
): ICashFlowDatePeriod[] => {
|
||||||
|
return this.dateRangeSet.map(this.getNetIncomeDatePeriod.bind(this));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes periods property to net income section.
|
||||||
|
* @param {ICashFlowStatementNetIncomeSection} section
|
||||||
|
* @returns {ICashFlowStatementNetIncomeSection}
|
||||||
|
*/
|
||||||
|
public assocPeriodsToNetIncomeNode = (
|
||||||
|
section: ICashFlowStatementNetIncomeSection
|
||||||
|
): ICashFlowStatementNetIncomeSection => {
|
||||||
|
const incomeDatePeriods = this.getNetIncomeDatePeriods(section);
|
||||||
|
return R.assoc('periods', incomeDatePeriods, section);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Account nodes --------------------
|
||||||
|
/**
|
||||||
|
* Retrieve the account total between date range.
|
||||||
|
* @param {Date} fromDate - From date.
|
||||||
|
* @param {Date} toDate - To date.
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
public getAccountTotalDateRange = (
|
||||||
|
node: ICashFlowStatementAccountSection,
|
||||||
|
fromDate: Date,
|
||||||
|
toDate: Date
|
||||||
|
): number => {
|
||||||
|
const closingBalance = this.ledger
|
||||||
|
.whereFromDate(fromDate)
|
||||||
|
.whereToDate(toDate)
|
||||||
|
.whereAccountId(node.id)
|
||||||
|
.getClosingBalance();
|
||||||
|
|
||||||
|
return this.amountAdjustment(node.adjustmentType, closingBalance);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the given account node total date period.
|
||||||
|
* @param {ICashFlowStatementAccountSection} node -
|
||||||
|
* @param {Date} fromDate - From date.
|
||||||
|
* @param {Date} toDate - To date.
|
||||||
|
* @return {ICashFlowDatePeriod}
|
||||||
|
*/
|
||||||
|
public getAccountTotalDatePeriod = (
|
||||||
|
node: ICashFlowStatementAccountSection,
|
||||||
|
fromDate: Date,
|
||||||
|
toDate: Date
|
||||||
|
): ICashFlowDatePeriod => {
|
||||||
|
const total = this.getAccountTotalDateRange(node, fromDate, toDate);
|
||||||
|
return this.getDatePeriodMeta(total, fromDate, toDate);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the accounts date periods nodes of the give account node.
|
||||||
|
* @param {ICashFlowStatementAccountSection} node -
|
||||||
|
* @return {ICashFlowDatePeriod[]}
|
||||||
|
*/
|
||||||
|
public getAccountDatePeriods = (
|
||||||
|
node: ICashFlowStatementAccountSection
|
||||||
|
): ICashFlowDatePeriod[] => {
|
||||||
|
return this.getNodeDatePeriods(
|
||||||
|
node,
|
||||||
|
this.getAccountTotalDatePeriod.bind(this)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes `periods` property to account node.
|
||||||
|
* @param {ICashFlowStatementAccountSection} node -
|
||||||
|
* @return {ICashFlowStatementAccountSection}
|
||||||
|
*/
|
||||||
|
public assocPeriodsToAccountNode = (
|
||||||
|
node: ICashFlowStatementAccountSection
|
||||||
|
): ICashFlowStatementAccountSection => {
|
||||||
|
const datePeriods = this.getAccountDatePeriods(node);
|
||||||
|
return R.assoc('periods', datePeriods, node);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Aggregate node -------------------------
|
||||||
|
/**
|
||||||
|
* Retrieve total of the given period index for node that has children nodes.
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
public getChildrenTotalPeriodByIndex = (
|
||||||
|
node: ICashFlowStatementSection,
|
||||||
|
index: number
|
||||||
|
): number => {
|
||||||
|
return sumBy(node.children, `periods[${index}].total.amount`);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve date period meta of the given node index.
|
||||||
|
* @param {ICashFlowStatementSection} node -
|
||||||
|
* @param {number} index - Loop index.
|
||||||
|
* @param {Date} fromDate - From date.
|
||||||
|
* @param {Date} toDate - To date.
|
||||||
|
*/
|
||||||
|
public getChildrenTotalPeriodMetaByIndex(
|
||||||
|
node: ICashFlowStatementSection,
|
||||||
|
index: number,
|
||||||
|
fromDate: Date,
|
||||||
|
toDate: Date
|
||||||
|
) {
|
||||||
|
const total = this.getChildrenTotalPeriodByIndex(node, index);
|
||||||
|
return this.getDatePeriodTotalMeta(total, fromDate, toDate);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the date periods of aggregate node.
|
||||||
|
* @param {ICashFlowStatementSection} node
|
||||||
|
*/
|
||||||
|
public getAggregateNodeDatePeriods(node: ICashFlowStatementSection) {
|
||||||
|
const getChildrenTotalPeriodMetaByIndex = R.curry(
|
||||||
|
this.getChildrenTotalPeriodMetaByIndex.bind(this)
|
||||||
|
)(node);
|
||||||
|
|
||||||
|
return this.dateRangeSet.map((dateRange, index) =>
|
||||||
|
getChildrenTotalPeriodMetaByIndex(
|
||||||
|
index,
|
||||||
|
dateRange.fromDate,
|
||||||
|
dateRange.toDate
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes `periods` property to aggregate section node.
|
||||||
|
* @param {ICashFlowStatementSection} node -
|
||||||
|
* @return {ICashFlowStatementSection}
|
||||||
|
*/
|
||||||
|
public assocPeriodsToAggregateNode = (
|
||||||
|
node: ICashFlowStatementSection
|
||||||
|
): ICashFlowStatementSection => {
|
||||||
|
const datePeriods = this.getAggregateNodeDatePeriods(node);
|
||||||
|
return R.assoc('periods', datePeriods, node);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Total equation node --------------------
|
||||||
|
|
||||||
|
public sectionsMapToTotalPeriod = (
|
||||||
|
mappedSections: { [key: number]: any },
|
||||||
|
index
|
||||||
|
) => {
|
||||||
|
return mapValues(
|
||||||
|
mappedSections,
|
||||||
|
(node) => get(node, `periods[${index}].total.amount`) || 0
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the date periods of the given total equation.
|
||||||
|
* @param {ICashFlowSchemaTotalSection}
|
||||||
|
* @param {string} equation -
|
||||||
|
* @return {ICashFlowDatePeriod[]}
|
||||||
|
*/
|
||||||
|
public getTotalEquationDatePeriods = (
|
||||||
|
node: ICashFlowSchemaTotalSection,
|
||||||
|
equation: string,
|
||||||
|
nodesTable
|
||||||
|
): ICashFlowDatePeriod[] => {
|
||||||
|
return this.getNodeDatePeriods(node, (node, fromDate, toDate, index) => {
|
||||||
|
const periodScope = this.sectionsMapToTotalPeriod(nodesTable, index);
|
||||||
|
const total = this.evaluateEquation(equation, periodScope);
|
||||||
|
|
||||||
|
return this.getDatePeriodTotalMeta(total, fromDate, toDate);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associates the total periods of total equation to the ginve total node..
|
||||||
|
* @param {ICashFlowSchemaTotalSection} totalSection -
|
||||||
|
* @return {ICashFlowStatementTotalSection}
|
||||||
|
*/
|
||||||
|
public assocTotalEquationDatePeriods = (
|
||||||
|
nodesTable: any,
|
||||||
|
equation: string,
|
||||||
|
node: ICashFlowSchemaTotalSection
|
||||||
|
): ICashFlowStatementTotalSection => {
|
||||||
|
const datePeriods = this.getTotalEquationDatePeriods(
|
||||||
|
node,
|
||||||
|
equation,
|
||||||
|
nodesTable
|
||||||
|
);
|
||||||
|
|
||||||
|
return R.assoc('periods', datePeriods, node);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Cash at beginning ----------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the date preioods of the given node and accumulated function.
|
||||||
|
* @param {} node
|
||||||
|
* @param {}
|
||||||
|
* @return {}
|
||||||
|
*/
|
||||||
|
public getNodeDatePeriods = (node, callback) => {
|
||||||
|
const curriedCallback = R.curry(callback)(node);
|
||||||
|
|
||||||
|
return this.dateRangeSet.map((dateRange, index) => {
|
||||||
|
return curriedCallback(dateRange.fromDate, dateRange.toDate, index);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the account total between date range.
|
||||||
|
* @param {Date} fromDate - From date.
|
||||||
|
* @param {Date} toDate - To date.
|
||||||
|
* @return {number}
|
||||||
|
*/
|
||||||
|
public getBeginningCashAccountDateRange = (
|
||||||
|
node: ICashFlowStatementSection,
|
||||||
|
fromDate: Date,
|
||||||
|
toDate: Date
|
||||||
|
) => {
|
||||||
|
const cashToDate = this.beginningCashFrom(fromDate);
|
||||||
|
|
||||||
|
return this.cashLedger
|
||||||
|
.whereToDate(cashToDate)
|
||||||
|
.whereAccountId(node.id)
|
||||||
|
.getClosingBalance();
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the beginning cash date period.
|
||||||
|
* @param {ICashFlowStatementSection} node -
|
||||||
|
* @param {Date} fromDate - From date.
|
||||||
|
* @param {Date} toDate - To date.
|
||||||
|
* @return {ICashFlowDatePeriod}
|
||||||
|
*/
|
||||||
|
public getBeginningCashDatePeriod = (
|
||||||
|
node: ICashFlowStatementSection,
|
||||||
|
fromDate: Date,
|
||||||
|
toDate: Date
|
||||||
|
) => {
|
||||||
|
const total = this.getBeginningCashAccountDateRange(
|
||||||
|
node,
|
||||||
|
fromDate,
|
||||||
|
toDate
|
||||||
|
);
|
||||||
|
return this.getDatePeriodTotalMeta(total, fromDate, toDate);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the beginning cash account periods.
|
||||||
|
* @param {ICashFlowStatementSection} node
|
||||||
|
* @return {ICashFlowDatePeriod}
|
||||||
|
*/
|
||||||
|
public getBeginningCashAccountPeriods = (
|
||||||
|
node: ICashFlowStatementSection
|
||||||
|
): ICashFlowDatePeriod => {
|
||||||
|
return this.getNodeDatePeriods(node, this.getBeginningCashDatePeriod);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes `periods` property to cash at beginning date periods.
|
||||||
|
* @param {ICashFlowStatementSection} section -
|
||||||
|
* @return {ICashFlowStatementSection}
|
||||||
|
*/
|
||||||
|
public assocCashAtBeginningDatePeriods = (
|
||||||
|
node: ICashFlowStatementSection
|
||||||
|
): ICashFlowStatementSection => {
|
||||||
|
const datePeriods = this.getAggregateNodeDatePeriods(node);
|
||||||
|
return R.assoc('periods', datePeriods, node);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Associates `periods` propery to cash at beginning account node.
|
||||||
|
* @param {ICashFlowStatementSection} node -
|
||||||
|
* @return {ICashFlowStatementSection}
|
||||||
|
*/
|
||||||
|
public assocCashAtBeginningAccountDatePeriods = (
|
||||||
|
node: ICashFlowStatementSection
|
||||||
|
): ICashFlowStatementSection => {
|
||||||
|
const datePeriods = this.getBeginningCashAccountPeriods(node);
|
||||||
|
return R.assoc('periods', datePeriods, node);
|
||||||
|
};
|
||||||
|
};
|
||||||
163
temp/CashFlowStatement/CashFlowRepository.ts
Normal file
163
temp/CashFlowStatement/CashFlowRepository.ts
Normal file
@@ -0,0 +1,163 @@
|
|||||||
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
|
import moment from 'moment';
|
||||||
|
import { Knex } from 'knex';
|
||||||
|
import { isEmpty } from 'lodash';
|
||||||
|
import { ICashFlowStatementQuery } from './Cashflow.types';
|
||||||
|
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||||
|
import { AccountTransaction } from '@/modules/Accounts/models/AccountTransaction.model';
|
||||||
|
import { ModelObject } from 'objection';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CashFlowRepository {
|
||||||
|
constructor(
|
||||||
|
@Inject(Account.name)
|
||||||
|
private readonly accountModel: typeof Account,
|
||||||
|
|
||||||
|
@Inject(AccountTransaction.name)
|
||||||
|
private readonly accountTransactionModel: typeof AccountTransaction,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the group type from periods type.
|
||||||
|
* @param {string} displayType
|
||||||
|
* @returns {string}
|
||||||
|
*/
|
||||||
|
protected getGroupTypeFromPeriodsType(displayType: string) {
|
||||||
|
const displayTypes = {
|
||||||
|
year: 'year',
|
||||||
|
day: 'day',
|
||||||
|
month: 'month',
|
||||||
|
quarter: 'month',
|
||||||
|
week: 'day',
|
||||||
|
};
|
||||||
|
return displayTypes[displayType] || 'month';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the cashflow accounts.
|
||||||
|
* @returns {Promise<IAccount[]>}
|
||||||
|
*/
|
||||||
|
public async cashFlowAccounts(): Promise<Account[]> {
|
||||||
|
const accounts = await this.accountModel.query();
|
||||||
|
return accounts;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve total of csah at beginning transactions.
|
||||||
|
* @param {ICashFlowStatementQuery} filter -
|
||||||
|
* @return {Promise<IAccountTransaction[]>}
|
||||||
|
*/
|
||||||
|
public async cashAtBeginningTotalTransactions(
|
||||||
|
filter: ICashFlowStatementQuery,
|
||||||
|
): Promise<ModelObject<AccountTransaction>[]> {
|
||||||
|
const cashBeginningPeriod = moment(filter.fromDate)
|
||||||
|
.subtract(1, 'day')
|
||||||
|
.toDate();
|
||||||
|
|
||||||
|
const transactions = await this.accountTransactionModel
|
||||||
|
.query()
|
||||||
|
.onBuild((query) => {
|
||||||
|
query.modify('creditDebitSummation');
|
||||||
|
|
||||||
|
query.select('accountId');
|
||||||
|
query.groupBy('accountId');
|
||||||
|
|
||||||
|
query.withGraphFetched('account');
|
||||||
|
query.modify('filterDateRange', null, cashBeginningPeriod);
|
||||||
|
|
||||||
|
this.commonFilterBranchesQuery(filter, query);
|
||||||
|
});
|
||||||
|
return transactions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve accounts transactions.
|
||||||
|
* @param {ICashFlowStatementQuery} filter
|
||||||
|
* @return {Promise<IAccountTransaction>}
|
||||||
|
*/
|
||||||
|
public async getAccountsTransactions(
|
||||||
|
filter: ICashFlowStatementQuery,
|
||||||
|
): Promise<ModelObject<AccountTransaction>[]> {
|
||||||
|
const groupByDateType = this.getGroupTypeFromPeriodsType(
|
||||||
|
filter.displayColumnsBy,
|
||||||
|
);
|
||||||
|
return await this.accountTransactionModel.query().onBuild((query) => {
|
||||||
|
query.modify('creditDebitSummation');
|
||||||
|
query.modify('groupByDateFormat', groupByDateType);
|
||||||
|
|
||||||
|
query.select('accountId');
|
||||||
|
|
||||||
|
query.groupBy('accountId');
|
||||||
|
query.withGraphFetched('account');
|
||||||
|
|
||||||
|
query.modify('filterDateRange', filter.fromDate, filter.toDate);
|
||||||
|
|
||||||
|
this.commonFilterBranchesQuery(filter, query);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the net income tranasctions.
|
||||||
|
* @param {number} tenantId -
|
||||||
|
* @param {ICashFlowStatementQuery} query -
|
||||||
|
* @return {Promise<IAccountTransaction[]>}
|
||||||
|
*/
|
||||||
|
public async getNetIncomeTransactions(
|
||||||
|
filter: ICashFlowStatementQuery,
|
||||||
|
): Promise<AccountTransaction[]> {
|
||||||
|
const groupByDateType = this.getGroupTypeFromPeriodsType(
|
||||||
|
filter.displayColumnsBy,
|
||||||
|
);
|
||||||
|
return await this.accountTransactionModel.query().onBuild((query) => {
|
||||||
|
query.modify('creditDebitSummation');
|
||||||
|
query.modify('groupByDateFormat', groupByDateType);
|
||||||
|
|
||||||
|
query.select('accountId');
|
||||||
|
query.groupBy('accountId');
|
||||||
|
|
||||||
|
query.withGraphFetched('account');
|
||||||
|
query.modify('filterDateRange', filter.fromDate, filter.toDate);
|
||||||
|
|
||||||
|
this.commonFilterBranchesQuery(filter, query);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve peridos of cash at beginning transactions.
|
||||||
|
* @param {ICashFlowStatementQuery} filter -
|
||||||
|
* @return {Promise<ModelObject<AccountTransaction>[]>}
|
||||||
|
*/
|
||||||
|
public async cashAtBeginningPeriodTransactions(
|
||||||
|
filter: ICashFlowStatementQuery,
|
||||||
|
): Promise<ModelObject<AccountTransaction>[]> {
|
||||||
|
const groupByDateType = this.getGroupTypeFromPeriodsType(
|
||||||
|
filter.displayColumnsBy,
|
||||||
|
);
|
||||||
|
|
||||||
|
return await this.accountTransactionModel.query().onBuild((query) => {
|
||||||
|
query.modify('creditDebitSummation');
|
||||||
|
query.modify('groupByDateFormat', groupByDateType);
|
||||||
|
|
||||||
|
query.select('accountId');
|
||||||
|
query.groupBy('accountId');
|
||||||
|
|
||||||
|
query.withGraphFetched('account');
|
||||||
|
query.modify('filterDateRange', filter.fromDate, filter.toDate);
|
||||||
|
|
||||||
|
this.commonFilterBranchesQuery(filter, query);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common branches filter query.
|
||||||
|
* @param {Knex.QueryBuilder} query
|
||||||
|
*/
|
||||||
|
private commonFilterBranchesQuery = (
|
||||||
|
query: ICashFlowStatementQuery,
|
||||||
|
knexQuery: Knex.QueryBuilder,
|
||||||
|
) => {
|
||||||
|
if (!isEmpty(query.branchesIds)) {
|
||||||
|
knexQuery.modify('filterByBranches', query.branchesIds);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
109
temp/CashFlowStatement/CashFlowService.ts
Normal file
109
temp/CashFlowStatement/CashFlowService.ts
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
import { ModelObject } from 'objection';
|
||||||
|
import moment from 'moment';
|
||||||
|
import * as R from 'ramda';
|
||||||
|
import {
|
||||||
|
ICashFlowStatementQuery,
|
||||||
|
ICashFlowStatementDOO,
|
||||||
|
} from './Cashflow.types';
|
||||||
|
import CashFlowStatement from './CashFlow';
|
||||||
|
import { CashflowSheetMeta } from './CashflowSheetMeta';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { CashFlowRepository } from './CashFlowRepository';
|
||||||
|
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
||||||
|
import { Ledger } from '@/modules/Ledger/Ledger';
|
||||||
|
import { AccountTransaction } from '@/modules/Accounts/models/AccountTransaction.model';
|
||||||
|
import { I18nService } from 'nestjs-i18n';
|
||||||
|
import { getDefaultCashflowQuery } from './constants';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CashFlowStatementService {
|
||||||
|
/**
|
||||||
|
* @param {CashFlowRepository} cashFlowRepo - Cash flow repository.
|
||||||
|
* @param {CashflowSheetMeta} cashflowSheetMeta - Cashflow sheet meta.
|
||||||
|
* @param {TenancyContext} tenancyContext - Tenancy context.
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private readonly cashFlowRepo: CashFlowRepository,
|
||||||
|
private readonly cashflowSheetMeta: CashflowSheetMeta,
|
||||||
|
private readonly tenancyContext: TenancyContext,
|
||||||
|
private readonly i18n: I18nService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves cash at beginning transactions.
|
||||||
|
* @param {ICashFlowStatementQuery} filter - Cash flow statement query.
|
||||||
|
* @returns {Promise<ModelObject<AccountTransaction>[]>}
|
||||||
|
*/
|
||||||
|
private async cashAtBeginningTransactions(
|
||||||
|
filter: ICashFlowStatementQuery,
|
||||||
|
): Promise<ModelObject<AccountTransaction>[]> {
|
||||||
|
const appendPeriodsOperToChain = (trans) =>
|
||||||
|
R.append(
|
||||||
|
this.cashFlowRepo.cashAtBeginningPeriodTransactions(filter),
|
||||||
|
trans,
|
||||||
|
);
|
||||||
|
|
||||||
|
const promisesChain = R.pipe(
|
||||||
|
R.append(this.cashFlowRepo.cashAtBeginningTotalTransactions(filter)),
|
||||||
|
R.when(
|
||||||
|
R.always(R.equals(filter.displayColumnsType, 'date_periods')),
|
||||||
|
appendPeriodsOperToChain,
|
||||||
|
),
|
||||||
|
)([]);
|
||||||
|
const promisesResults = await Promise.all(promisesChain);
|
||||||
|
const transactions = R.flatten(promisesResults);
|
||||||
|
|
||||||
|
return transactions;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the cash flow sheet statement.
|
||||||
|
* @param {number} tenantId
|
||||||
|
* @param {ICashFlowStatementQuery} query
|
||||||
|
* @returns {Promise<ICashFlowStatementDOO>}
|
||||||
|
*/
|
||||||
|
public async cashFlow(
|
||||||
|
query: ICashFlowStatementQuery,
|
||||||
|
): Promise<ICashFlowStatementDOO> {
|
||||||
|
// Retrieve all accounts on the storage.
|
||||||
|
const accounts = await this.cashFlowRepo.cashFlowAccounts();
|
||||||
|
const tenant = await this.tenancyContext.getTenant();
|
||||||
|
|
||||||
|
const filter = {
|
||||||
|
...getDefaultCashflowQuery(),
|
||||||
|
...query,
|
||||||
|
};
|
||||||
|
// Retrieve the accounts transactions.
|
||||||
|
const transactions =
|
||||||
|
await this.cashFlowRepo.getAccountsTransactions(filter);
|
||||||
|
// Retrieve the net income transactions.
|
||||||
|
const netIncome = await this.cashFlowRepo.getNetIncomeTransactions(filter);
|
||||||
|
// Retrieve the cash at beginning transactions.
|
||||||
|
const cashAtBeginningTransactions =
|
||||||
|
await this.cashAtBeginningTransactions(filter);
|
||||||
|
|
||||||
|
// Transformes the transactions to ledgers.
|
||||||
|
const ledger = Ledger.fromTransactions(transactions);
|
||||||
|
const cashLedger = Ledger.fromTransactions(cashAtBeginningTransactions);
|
||||||
|
const netIncomeLedger = Ledger.fromTransactions(netIncome);
|
||||||
|
|
||||||
|
// Cash flow statement.
|
||||||
|
const cashFlowInstance = new CashFlowStatement(
|
||||||
|
accounts,
|
||||||
|
ledger,
|
||||||
|
cashLedger,
|
||||||
|
netIncomeLedger,
|
||||||
|
filter,
|
||||||
|
tenant.metadata.baseCurrency,
|
||||||
|
this.i18n,
|
||||||
|
);
|
||||||
|
// Retrieve the cashflow sheet meta.
|
||||||
|
const meta = await this.cashflowSheetMeta.meta(filter);
|
||||||
|
|
||||||
|
return {
|
||||||
|
data: cashFlowInstance.reportData(),
|
||||||
|
query: filter,
|
||||||
|
meta,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
374
temp/CashFlowStatement/CashFlowTable.ts
Normal file
374
temp/CashFlowStatement/CashFlowTable.ts
Normal file
@@ -0,0 +1,374 @@
|
|||||||
|
import * as R from 'ramda';
|
||||||
|
import { isEmpty, } from 'lodash';
|
||||||
|
import moment from 'moment';
|
||||||
|
import {
|
||||||
|
ICashFlowStatementSection,
|
||||||
|
ICashFlowStatementSectionType,
|
||||||
|
IDateRange,
|
||||||
|
ICashFlowStatementDOO,
|
||||||
|
} from './Cashflow.types';
|
||||||
|
import { ITableRow, ITableColumn } from '../../types/Table.types';
|
||||||
|
import { dateRangeFromToCollection } from '@/utils/date-range-collection';
|
||||||
|
import { tableRowMapper } from '../../utils/Table.utils';
|
||||||
|
import { mapValuesDeep } from '@/utils/deepdash';
|
||||||
|
|
||||||
|
enum IROW_TYPE {
|
||||||
|
AGGREGATE = 'AGGREGATE',
|
||||||
|
NET_INCOME = 'NET_INCOME',
|
||||||
|
ACCOUNTS = 'ACCOUNTS',
|
||||||
|
ACCOUNT = 'ACCOUNT',
|
||||||
|
TOTAL = 'TOTAL',
|
||||||
|
}
|
||||||
|
const DEEP_CONFIG = { childrenPath: 'children', pathFormat: 'array' };
|
||||||
|
const DISPLAY_COLUMNS_BY = {
|
||||||
|
DATE_PERIODS: 'date_periods',
|
||||||
|
TOTAL: 'total',
|
||||||
|
};
|
||||||
|
|
||||||
|
export class CashFlowTable {
|
||||||
|
private report: ICashFlowStatementDOO;
|
||||||
|
private i18n;
|
||||||
|
private dateRangeSet: IDateRange[];
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
* @param {ICashFlowStatement} reportStatement
|
||||||
|
*/
|
||||||
|
constructor(reportStatement: ICashFlowStatementDOO, i18n) {
|
||||||
|
this.report = reportStatement;
|
||||||
|
this.i18n = i18n;
|
||||||
|
this.dateRangeSet = [];
|
||||||
|
this.initDateRangeCollection();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Initialize date range set.
|
||||||
|
*/
|
||||||
|
private initDateRangeCollection() {
|
||||||
|
this.dateRangeSet = dateRangeFromToCollection(
|
||||||
|
this.report.query.fromDate,
|
||||||
|
this.report.query.toDate,
|
||||||
|
this.report.query.displayColumnsBy,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the date periods columns accessors.
|
||||||
|
*/
|
||||||
|
private datePeriodsColumnsAccessors = () => {
|
||||||
|
return this.dateRangeSet.map((dateRange: IDateRange, index) => ({
|
||||||
|
key: `date-range-${index}`,
|
||||||
|
accessor: `periods[${index}].total.formattedAmount`,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the total column accessor.
|
||||||
|
*/
|
||||||
|
private totalColumnAccessor = () => {
|
||||||
|
return [{ key: 'total', accessor: 'total.formattedAmount' }];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the common columns for all report nodes.
|
||||||
|
*/
|
||||||
|
private commonColumns = () => {
|
||||||
|
return R.compose(
|
||||||
|
R.concat([{ key: 'name', accessor: 'label' }]),
|
||||||
|
R.when(
|
||||||
|
R.always(this.isDisplayColumnsBy(DISPLAY_COLUMNS_BY.DATE_PERIODS)),
|
||||||
|
R.concat(this.datePeriodsColumnsAccessors()),
|
||||||
|
),
|
||||||
|
R.concat(this.totalColumnAccessor()),
|
||||||
|
)([]);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the table rows of regular section.
|
||||||
|
* @param {ICashFlowStatementSection} section
|
||||||
|
* @returns {ITableRow[]}
|
||||||
|
*/
|
||||||
|
private regularSectionMapper = (
|
||||||
|
section: ICashFlowStatementSection,
|
||||||
|
): ITableRow => {
|
||||||
|
const columns = this.commonColumns();
|
||||||
|
|
||||||
|
return tableRowMapper(section, columns, {
|
||||||
|
rowTypes: [IROW_TYPE.AGGREGATE],
|
||||||
|
id: section.id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the net income table rows of the section.
|
||||||
|
* @param {ICashFlowStatementSection} section
|
||||||
|
* @returns {ITableRow}
|
||||||
|
*/
|
||||||
|
private netIncomeSectionMapper = (
|
||||||
|
section: ICashFlowStatementSection,
|
||||||
|
): ITableRow => {
|
||||||
|
const columns = this.commonColumns();
|
||||||
|
|
||||||
|
return tableRowMapper(section, columns, {
|
||||||
|
rowTypes: [IROW_TYPE.NET_INCOME, IROW_TYPE.TOTAL],
|
||||||
|
id: section.id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the accounts table rows of the section.
|
||||||
|
* @param {ICashFlowStatementSection} section
|
||||||
|
* @returns {ITableRow}
|
||||||
|
*/
|
||||||
|
private accountsSectionMapper = (
|
||||||
|
section: ICashFlowStatementSection,
|
||||||
|
): ITableRow => {
|
||||||
|
const columns = this.commonColumns();
|
||||||
|
|
||||||
|
return tableRowMapper(section, columns, {
|
||||||
|
rowTypes: [IROW_TYPE.ACCOUNTS],
|
||||||
|
id: section.id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the account table row of account section.
|
||||||
|
* @param {ICashFlowStatementSection} section
|
||||||
|
* @returns {ITableRow}
|
||||||
|
*/
|
||||||
|
private accountSectionMapper = (
|
||||||
|
section: ICashFlowStatementSection,
|
||||||
|
): ITableRow => {
|
||||||
|
const columns = this.commonColumns();
|
||||||
|
|
||||||
|
return tableRowMapper(section, columns, {
|
||||||
|
rowTypes: [IROW_TYPE.ACCOUNT],
|
||||||
|
id: `account-${section.id}`,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the total table rows from the given total section.
|
||||||
|
* @param {ICashFlowStatementSection} section
|
||||||
|
* @returns {ITableRow}
|
||||||
|
*/
|
||||||
|
private totalSectionMapper = (
|
||||||
|
section: ICashFlowStatementSection,
|
||||||
|
): ITableRow => {
|
||||||
|
const columns = this.commonColumns();
|
||||||
|
|
||||||
|
return tableRowMapper(section, columns, {
|
||||||
|
rowTypes: [IROW_TYPE.TOTAL],
|
||||||
|
id: section.id,
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines the schema section type.
|
||||||
|
* @param {string} type
|
||||||
|
* @param {ICashFlowSchemaSection} section
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
private isSectionHasType = (
|
||||||
|
type: string,
|
||||||
|
section: ICashFlowStatementSection,
|
||||||
|
): boolean => {
|
||||||
|
return type === section.sectionType;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The report section mapper.
|
||||||
|
* @param {ICashFlowStatementSection} section
|
||||||
|
* @returns {ITableRow}
|
||||||
|
*/
|
||||||
|
private sectionMapper = (
|
||||||
|
section: ICashFlowStatementSection,
|
||||||
|
key: string,
|
||||||
|
parentSection: ICashFlowStatementSection,
|
||||||
|
): ITableRow => {
|
||||||
|
const isSectionHasType = R.curry(this.isSectionHasType);
|
||||||
|
|
||||||
|
return R.pipe(
|
||||||
|
R.when(
|
||||||
|
isSectionHasType(ICashFlowStatementSectionType.AGGREGATE),
|
||||||
|
this.regularSectionMapper,
|
||||||
|
),
|
||||||
|
R.when(
|
||||||
|
isSectionHasType(ICashFlowStatementSectionType.CASH_AT_BEGINNING),
|
||||||
|
this.regularSectionMapper,
|
||||||
|
),
|
||||||
|
R.when(
|
||||||
|
isSectionHasType(ICashFlowStatementSectionType.NET_INCOME),
|
||||||
|
this.netIncomeSectionMapper,
|
||||||
|
),
|
||||||
|
R.when(
|
||||||
|
isSectionHasType(ICashFlowStatementSectionType.ACCOUNTS),
|
||||||
|
this.accountsSectionMapper,
|
||||||
|
),
|
||||||
|
R.when(
|
||||||
|
isSectionHasType(ICashFlowStatementSectionType.ACCOUNT),
|
||||||
|
this.accountSectionMapper,
|
||||||
|
),
|
||||||
|
R.when(
|
||||||
|
isSectionHasType(ICashFlowStatementSectionType.TOTAL),
|
||||||
|
this.totalSectionMapper,
|
||||||
|
),
|
||||||
|
)(section);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Mappes the sections to the table rows.
|
||||||
|
* @param {ICashFlowStatementSection[]} sections
|
||||||
|
* @returns {ITableRow[]}
|
||||||
|
*/
|
||||||
|
private mapSectionsToTableRows = (
|
||||||
|
sections: ICashFlowStatementSection[],
|
||||||
|
): ITableRow[] => {
|
||||||
|
return mapValuesDeep(sections, this.sectionMapper.bind(this), DEEP_CONFIG);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends the total to section's children.
|
||||||
|
* @param {ICashFlowStatementSection} section
|
||||||
|
* @returns {ICashFlowStatementSection}
|
||||||
|
*/
|
||||||
|
private appendTotalToSectionChildren = (
|
||||||
|
section: ICashFlowStatementSection,
|
||||||
|
): ICashFlowStatementSection => {
|
||||||
|
const label = section.footerLabel
|
||||||
|
? section.footerLabel
|
||||||
|
: this.i18n.__('Total {{accountName}}', { accountName: section.label });
|
||||||
|
|
||||||
|
section.children.push({
|
||||||
|
sectionType: ICashFlowStatementSectionType.TOTAL,
|
||||||
|
label,
|
||||||
|
periods: section.periods,
|
||||||
|
total: section.total,
|
||||||
|
});
|
||||||
|
return section;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {ICashFlowStatementSection} section
|
||||||
|
* @returns {ICashFlowStatementSection}
|
||||||
|
*/
|
||||||
|
private mapSectionsToAppendTotalChildren = (
|
||||||
|
section: ICashFlowStatementSection,
|
||||||
|
): ICashFlowStatementSection => {
|
||||||
|
const isSectionHasChildren = (section) => !isEmpty(section.children);
|
||||||
|
|
||||||
|
return R.compose(
|
||||||
|
R.when(
|
||||||
|
isSectionHasChildren,
|
||||||
|
this.appendTotalToSectionChildren.bind(this),
|
||||||
|
),
|
||||||
|
)(section);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Appends total node to children section.
|
||||||
|
* @param {ICashFlowStatementSection[]} sections
|
||||||
|
* @returns {ICashFlowStatementSection[]}
|
||||||
|
*/
|
||||||
|
private appendTotalToChildren = (sections: ICashFlowStatementSection[]) => {
|
||||||
|
return mapValuesDeep(
|
||||||
|
sections,
|
||||||
|
this.mapSectionsToAppendTotalChildren.bind(this),
|
||||||
|
DEEP_CONFIG,
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the table rows of cash flow statement.
|
||||||
|
* @param {ICashFlowStatementSection[]} sections
|
||||||
|
* @returns {ITableRow[]}
|
||||||
|
*/
|
||||||
|
public tableRows = (): ITableRow[] => {
|
||||||
|
const sections = this.report.data;
|
||||||
|
|
||||||
|
return R.pipe(
|
||||||
|
this.appendTotalToChildren,
|
||||||
|
this.mapSectionsToTableRows,
|
||||||
|
)(sections);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the total columns.
|
||||||
|
* @returns {ITableColumn}
|
||||||
|
*/
|
||||||
|
private totalColumns = (): ITableColumn[] => {
|
||||||
|
return [{ key: 'total', label: this.i18n.__('Total') }];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the formatted column label from the given date range.
|
||||||
|
* @param {ICashFlowDateRange} dateRange -
|
||||||
|
* @return {string}
|
||||||
|
*/
|
||||||
|
private formatColumnLabel = (dateRange: ICashFlowDateRange) => {
|
||||||
|
const monthFormat = (range) => moment(range.toDate).format('YYYY-MM');
|
||||||
|
const yearFormat = (range) => moment(range.toDate).format('YYYY');
|
||||||
|
const dayFormat = (range) => moment(range.toDate).format('YYYY-MM-DD');
|
||||||
|
|
||||||
|
const conditions = [
|
||||||
|
['month', monthFormat],
|
||||||
|
['year', yearFormat],
|
||||||
|
['day', dayFormat],
|
||||||
|
['quarter', monthFormat],
|
||||||
|
['week', dayFormat],
|
||||||
|
];
|
||||||
|
const conditionsPairs = R.map(
|
||||||
|
([type, formatFn]) => [
|
||||||
|
R.always(this.isDisplayColumnsType(type)),
|
||||||
|
formatFn,
|
||||||
|
],
|
||||||
|
conditions,
|
||||||
|
);
|
||||||
|
|
||||||
|
return R.compose(R.cond(conditionsPairs))(dateRange);
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Date periods columns.
|
||||||
|
* @returns {ITableColumn[]}
|
||||||
|
*/
|
||||||
|
private datePeriodsColumns = (): ITableColumn[] => {
|
||||||
|
return this.dateRangeSet.map((dateRange, index) => ({
|
||||||
|
key: `date-range-${index}`,
|
||||||
|
label: this.formatColumnLabel(dateRange),
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines the given column type is the current.
|
||||||
|
* @reutrns {boolean}
|
||||||
|
*/
|
||||||
|
private isDisplayColumnsBy = (displayColumnsType: string): Boolean => {
|
||||||
|
return this.report.query.displayColumnsType === displayColumnsType;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Detarmines whether the given display columns type is the current.
|
||||||
|
* @param {string} displayColumnsBy
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
private isDisplayColumnsType = (displayColumnsBy: string): Boolean => {
|
||||||
|
return this.report.query.displayColumnsBy === displayColumnsBy;
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the table columns.
|
||||||
|
* @return {ITableColumn[]}
|
||||||
|
*/
|
||||||
|
public tableColumns = (): ITableColumn[] => {
|
||||||
|
return R.compose(
|
||||||
|
R.concat([{ key: 'name', label: this.i18n.__('Account name') }]),
|
||||||
|
R.when(
|
||||||
|
R.always(this.isDisplayColumnsBy(DISPLAY_COLUMNS_BY.DATE_PERIODS)),
|
||||||
|
R.concat(this.datePeriodsColumns()),
|
||||||
|
),
|
||||||
|
R.concat(this.totalColumns()),
|
||||||
|
)([]);
|
||||||
|
};
|
||||||
|
}
|
||||||
56
temp/CashFlowStatement/Cashflow.controller.ts
Normal file
56
temp/CashFlowStatement/Cashflow.controller.ts
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
import { Response } from 'express';
|
||||||
|
import { Controller, Get, Headers, Query, Res } from '@nestjs/common';
|
||||||
|
import { ICashFlowStatementQuery } from './Cashflow.types';
|
||||||
|
import { AcceptType } from '@/constants/accept-type';
|
||||||
|
import { CashflowSheetApplication } from './CashflowSheetApplication';
|
||||||
|
|
||||||
|
@Controller('reports/cashflow')
|
||||||
|
export class CashflowController {
|
||||||
|
constructor(private readonly cashflowSheetApp: CashflowSheetApplication) {}
|
||||||
|
|
||||||
|
@Get()
|
||||||
|
async getCashflow(
|
||||||
|
@Query() query: ICashFlowStatementQuery,
|
||||||
|
@Res() res: Response,
|
||||||
|
@Headers('accept') acceptHeader: string,
|
||||||
|
) {
|
||||||
|
// Retrieves the json table format.
|
||||||
|
if (acceptHeader.includes(AcceptType.ApplicationJsonTable)) {
|
||||||
|
const table = await this.cashflowSheetApp.table(query);
|
||||||
|
|
||||||
|
return res.status(200).send(table);
|
||||||
|
// Retrieves the csv format.
|
||||||
|
} else if (acceptHeader.includes(AcceptType.ApplicationCsv)) {
|
||||||
|
const buffer = await this.cashflowSheetApp.csv(query);
|
||||||
|
|
||||||
|
res.setHeader('Content-Disposition', 'attachment; filename=output.csv');
|
||||||
|
res.setHeader('Content-Type', 'text/csv');
|
||||||
|
|
||||||
|
return res.status(200).send(buffer);
|
||||||
|
// Retrieves the pdf format.
|
||||||
|
} else if (acceptHeader.includes(AcceptType.ApplicationXlsx)) {
|
||||||
|
const buffer = await this.cashflowSheetApp.xlsx(query);
|
||||||
|
|
||||||
|
res.setHeader('Content-Disposition', 'attachment; filename=output.xlsx');
|
||||||
|
res.setHeader(
|
||||||
|
'Content-Type',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||||
|
);
|
||||||
|
return res.send(buffer);
|
||||||
|
// Retrieves the pdf format.
|
||||||
|
} else if (acceptHeader.includes(AcceptType.ApplicationPdf)) {
|
||||||
|
const pdfContent = await this.cashflowSheetApp.pdf(query);
|
||||||
|
|
||||||
|
res.set({
|
||||||
|
'Content-Type': 'application/pdf',
|
||||||
|
'Content-Length': pdfContent.length,
|
||||||
|
});
|
||||||
|
return res.send(pdfContent);
|
||||||
|
// Retrieves the json format.
|
||||||
|
} else {
|
||||||
|
const cashflow = await this.cashflowSheetApp.sheet(query);
|
||||||
|
|
||||||
|
return res.status(200).send(cashflow);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
27
temp/CashFlowStatement/Cashflow.module.ts
Normal file
27
temp/CashFlowStatement/Cashflow.module.ts
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
import { Module } from '@nestjs/common';
|
||||||
|
import { CashflowSheetMeta } from './CashflowSheetMeta';
|
||||||
|
import { CashFlowRepository } from './CashFlowRepository';
|
||||||
|
import { CashflowTablePdfInjectable } from './CashflowTablePdfInjectable';
|
||||||
|
import { CashflowExportInjectable } from './CashflowExportInjectable';
|
||||||
|
import { CashflowController } from './Cashflow.controller';
|
||||||
|
import { FinancialSheetCommonModule } from '../../common/FinancialSheetCommon.module';
|
||||||
|
import { CashflowTableInjectable } from './CashflowTableInjectable';
|
||||||
|
import { CashFlowStatementService } from './CashFlowService';
|
||||||
|
import { TenancyContext } from '@/modules/Tenancy/TenancyContext.service';
|
||||||
|
import { CashflowSheetApplication } from './CashflowSheetApplication';
|
||||||
|
|
||||||
|
@Module({
|
||||||
|
imports: [FinancialSheetCommonModule],
|
||||||
|
providers: [
|
||||||
|
CashFlowRepository,
|
||||||
|
CashflowSheetMeta,
|
||||||
|
CashFlowStatementService,
|
||||||
|
CashflowTablePdfInjectable,
|
||||||
|
CashflowExportInjectable,
|
||||||
|
CashflowTableInjectable,
|
||||||
|
CashflowSheetApplication,
|
||||||
|
TenancyContext
|
||||||
|
],
|
||||||
|
controllers: [CashflowController],
|
||||||
|
})
|
||||||
|
export class CashflowReportModule {}
|
||||||
299
temp/CashFlowStatement/Cashflow.types.ts
Normal file
299
temp/CashFlowStatement/Cashflow.types.ts
Normal file
@@ -0,0 +1,299 @@
|
|||||||
|
import { Knex } from 'knex';
|
||||||
|
import { IFinancialSheetCommonMeta, INumberFormatQuery } from '../../types/Report.types';
|
||||||
|
import { Account } from '@/modules/Accounts/models/Account.model';
|
||||||
|
import { Ledger } from '@/modules/Ledger/Ledger';
|
||||||
|
import { IFinancialTable, ITableRow } from '../../types/Table.types';
|
||||||
|
|
||||||
|
|
||||||
|
export interface ICashFlowStatementQuery {
|
||||||
|
fromDate: Date | string;
|
||||||
|
toDate: Date | string;
|
||||||
|
displayColumnsBy: string;
|
||||||
|
displayColumnsType: string;
|
||||||
|
noneZero: boolean;
|
||||||
|
noneTransactions: boolean;
|
||||||
|
numberFormat: INumberFormatQuery;
|
||||||
|
basis: string;
|
||||||
|
|
||||||
|
branchesIds?: number[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowStatementTotal {
|
||||||
|
amount: number;
|
||||||
|
formattedAmount: string;
|
||||||
|
currencyCode: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowStatementTotalPeriod {
|
||||||
|
fromDate: Date;
|
||||||
|
toDate: Date;
|
||||||
|
total: ICashFlowStatementTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowStatementCommonSection {
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
total: ICashFlowStatementTotal;
|
||||||
|
footerLabel?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowStatementAccountMeta {
|
||||||
|
id: number;
|
||||||
|
label: string;
|
||||||
|
code: string;
|
||||||
|
total: ICashFlowStatementTotal;
|
||||||
|
accountType: string;
|
||||||
|
adjustmentType: string;
|
||||||
|
sectionType: ICashFlowStatementSectionType.ACCOUNT;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum ICashFlowStatementSectionType {
|
||||||
|
REGULAR = 'REGULAR',
|
||||||
|
AGGREGATE = 'AGGREGATE',
|
||||||
|
NET_INCOME = 'NET_INCOME',
|
||||||
|
ACCOUNT = 'ACCOUNT',
|
||||||
|
ACCOUNTS = 'ACCOUNTS',
|
||||||
|
TOTAL = 'TOTAL',
|
||||||
|
CASH_AT_BEGINNING = 'CASH_AT_BEGINNING',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowStatementAccountSection
|
||||||
|
extends ICashFlowStatementCommonSection {
|
||||||
|
sectionType: ICashFlowStatementSectionType.ACCOUNTS;
|
||||||
|
children: ICashFlowStatementAccountMeta[];
|
||||||
|
total: ICashFlowStatementTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowStatementNetIncomeSection
|
||||||
|
extends ICashFlowStatementCommonSection {
|
||||||
|
sectionType: ICashFlowStatementSectionType.NET_INCOME;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowStatementTotalSection
|
||||||
|
extends ICashFlowStatementCommonSection {
|
||||||
|
sectionType: ICashFlowStatementSectionType.TOTAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowStatementAggregateSection
|
||||||
|
extends ICashFlowStatementCommonSection {
|
||||||
|
sectionType: ICashFlowStatementSectionType.AGGREGATE;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowCashBeginningNode
|
||||||
|
extends ICashFlowStatementCommonSection {
|
||||||
|
sectionType: ICashFlowStatementSectionType.CASH_AT_BEGINNING;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ICashFlowStatementSection =
|
||||||
|
| ICashFlowStatementAccountSection
|
||||||
|
| ICashFlowStatementNetIncomeSection
|
||||||
|
| ICashFlowStatementTotalSection
|
||||||
|
| ICashFlowStatementCommonSection;
|
||||||
|
|
||||||
|
export interface ICashFlowStatementColumn {}
|
||||||
|
export interface ICashFlowStatementMeta extends IFinancialSheetCommonMeta {
|
||||||
|
formattedToDate: string;
|
||||||
|
formattedFromDate: string;
|
||||||
|
formattedDateRange: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowStatementDOO {
|
||||||
|
data: ICashFlowStatementData;
|
||||||
|
meta: ICashFlowStatementMeta;
|
||||||
|
query: ICashFlowStatementQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowStatementTable extends IFinancialTable {
|
||||||
|
meta: ICashFlowStatementMeta;
|
||||||
|
query: ICashFlowStatementQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowStatementService {
|
||||||
|
cashFlow(
|
||||||
|
tenantId: number,
|
||||||
|
query: ICashFlowStatementQuery
|
||||||
|
): Promise<ICashFlowStatementDOO>;
|
||||||
|
}
|
||||||
|
|
||||||
|
// CASH FLOW SCHEMA TYPES.
|
||||||
|
// -----------------------------
|
||||||
|
export interface ICashFlowSchemaCommonSection {
|
||||||
|
id: string;
|
||||||
|
label: string;
|
||||||
|
children: ICashFlowSchemaSection[];
|
||||||
|
footerLabel?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum CASH_FLOW_ACCOUNT_RELATION {
|
||||||
|
MINES = 'mines',
|
||||||
|
PLUS = 'plus',
|
||||||
|
}
|
||||||
|
|
||||||
|
export enum CASH_FLOW_SECTION_ID {
|
||||||
|
NET_INCOME = 'NET_INCOME',
|
||||||
|
OPERATING = 'OPERATING',
|
||||||
|
OPERATING_ACCOUNTS = 'OPERATING_ACCOUNTS',
|
||||||
|
INVESTMENT = 'INVESTMENT',
|
||||||
|
FINANCIAL = 'FINANCIAL',
|
||||||
|
|
||||||
|
NET_OPERATING = 'NET_OPERATING',
|
||||||
|
NET_INVESTMENT = 'NET_INVESTMENT',
|
||||||
|
NET_FINANCIAL = 'NET_FINANCIAL',
|
||||||
|
|
||||||
|
CASH_BEGINNING_PERIOD = 'CASH_BEGINNING_PERIOD',
|
||||||
|
CASH_END_PERIOD = 'CASH_END_PERIOD',
|
||||||
|
NET_CASH_INCREASE = 'NET_CASH_INCREASE',
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowSchemaAccountsSection
|
||||||
|
extends ICashFlowSchemaCommonSection {
|
||||||
|
sectionType: ICashFlowStatementSectionType.ACCOUNT;
|
||||||
|
accountsRelations: ICashFlowSchemaAccountRelation[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowSchemaTotalSection
|
||||||
|
extends ICashFlowStatementCommonSection {
|
||||||
|
sectionType: ICashFlowStatementSectionType.TOTAL;
|
||||||
|
equation: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export type ICashFlowSchemaSection =
|
||||||
|
| ICashFlowSchemaAccountsSection
|
||||||
|
| ICashFlowSchemaTotalSection
|
||||||
|
| ICashFlowSchemaCommonSection;
|
||||||
|
|
||||||
|
export type ICashFlowStatementData = ICashFlowSchemaSection[];
|
||||||
|
|
||||||
|
export interface ICashFlowSchemaAccountRelation {
|
||||||
|
type: string;
|
||||||
|
direction: CASH_FLOW_ACCOUNT_RELATION.PLUS;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowSchemaSectionAccounts
|
||||||
|
extends ICashFlowStatementCommonSection {
|
||||||
|
type: ICashFlowStatementSectionType.ACCOUNT;
|
||||||
|
accountsRelations: ICashFlowSchemaAccountRelation[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowSchemaSectionTotal {
|
||||||
|
type: ICashFlowStatementSectionType.TOTAL;
|
||||||
|
totalEquation: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowDatePeriod {
|
||||||
|
fromDate: ICashFlowDate;
|
||||||
|
toDate: ICashFlowDate;
|
||||||
|
total: ICashFlowStatementTotal;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowDate {
|
||||||
|
formattedDate: string;
|
||||||
|
date: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowStatement {
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
* @constructor
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
accounts: Account[],
|
||||||
|
ledger: Ledger,
|
||||||
|
cashLedger: Ledger,
|
||||||
|
netIncomeLedger: Ledger,
|
||||||
|
query: ICashFlowStatementQuery,
|
||||||
|
baseCurrency: string
|
||||||
|
): void;
|
||||||
|
|
||||||
|
reportData(): ICashFlowStatementData;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashFlowTable {
|
||||||
|
constructor(reportStatement: ICashFlowStatement): void;
|
||||||
|
tableRows(): ITableRow[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IDateRange {
|
||||||
|
fromDate: Date;
|
||||||
|
toDate: Date;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashflowTransactionSchema {
|
||||||
|
amount: number;
|
||||||
|
date: Date;
|
||||||
|
referenceNo?: string | null;
|
||||||
|
transactionNumber: string;
|
||||||
|
transactionType: string;
|
||||||
|
creditAccountId: number;
|
||||||
|
cashflowAccountId: number;
|
||||||
|
userId: number;
|
||||||
|
publishedAt?: Date | null;
|
||||||
|
branchId?: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ICashflowTransactionInput extends ICashflowTransactionSchema {}
|
||||||
|
|
||||||
|
export interface ICategorizeCashflowTransactioDTO {
|
||||||
|
date: Date;
|
||||||
|
creditAccountId: number;
|
||||||
|
referenceNo: string;
|
||||||
|
transactionNumber: string;
|
||||||
|
transactionType: string;
|
||||||
|
exchangeRate: number;
|
||||||
|
description: string;
|
||||||
|
branchId: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IUncategorizedCashflowTransaction {
|
||||||
|
id?: number;
|
||||||
|
amount: number;
|
||||||
|
date: Date;
|
||||||
|
currencyCode: string;
|
||||||
|
accountId: number;
|
||||||
|
description: string;
|
||||||
|
referenceNo: string;
|
||||||
|
categorizeRefType: string;
|
||||||
|
categorizeRefId: number;
|
||||||
|
categorized: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface CreateUncategorizedTransactionDTO {
|
||||||
|
date: Date | string;
|
||||||
|
accountId: number;
|
||||||
|
amount: number;
|
||||||
|
currencyCode: string;
|
||||||
|
payee?: string;
|
||||||
|
description?: string;
|
||||||
|
referenceNo?: string | null;
|
||||||
|
plaidTransactionId?: string | null;
|
||||||
|
pending?: boolean;
|
||||||
|
pendingPlaidTransactionId?: string | null;
|
||||||
|
batch?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IUncategorizedTransactionCreatingEventPayload {
|
||||||
|
tenantId: number;
|
||||||
|
createUncategorizedTransactionDTO: CreateUncategorizedTransactionDTO;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IUncategorizedTransactionCreatedEventPayload {
|
||||||
|
tenantId: number;
|
||||||
|
uncategorizedTransaction: any;
|
||||||
|
createUncategorizedTransactionDTO: CreateUncategorizedTransactionDTO;
|
||||||
|
trx: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPendingTransactionRemovingEventPayload {
|
||||||
|
tenantId: number;
|
||||||
|
uncategorizedTransactionId: number;
|
||||||
|
pendingTransaction: IUncategorizedCashflowTransaction;
|
||||||
|
trx?: Knex.Transaction;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IPendingTransactionRemovedEventPayload {
|
||||||
|
tenantId: number;
|
||||||
|
uncategorizedTransactionId: number;
|
||||||
|
pendingTransaction: IUncategorizedCashflowTransaction;
|
||||||
|
trx?: Knex.Transaction;
|
||||||
|
}
|
||||||
37
temp/CashFlowStatement/CashflowExportInjectable.ts
Normal file
37
temp/CashFlowStatement/CashflowExportInjectable.ts
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { CashflowTableInjectable } from './CashflowTableInjectable';
|
||||||
|
import { ICashFlowStatementQuery } from './Cashflow.types';
|
||||||
|
import { TableSheet } from '../../common/TableSheet';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CashflowExportInjectable {
|
||||||
|
constructor(private readonly cashflowSheetTable: CashflowTableInjectable) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the cashflow sheet in XLSX format.
|
||||||
|
* @param {ICashFlowStatementQuery} query - Cashflow statement query.
|
||||||
|
* @returns {Promise<Buffer>}
|
||||||
|
*/
|
||||||
|
public async xlsx(query: ICashFlowStatementQuery): Promise<Buffer> {
|
||||||
|
const table = await this.cashflowSheetTable.table(query);
|
||||||
|
|
||||||
|
const tableSheet = new TableSheet(table.table);
|
||||||
|
const tableCsv = tableSheet.convertToXLSX();
|
||||||
|
|
||||||
|
return tableSheet.convertToBuffer(tableCsv, 'xlsx');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the cashflow sheet in CSV format.
|
||||||
|
* @param {ICashFlowStatementQuery} query - Cashflow statement query.
|
||||||
|
* @returns {Promise<Buffer>}
|
||||||
|
*/
|
||||||
|
public async csv(query: ICashFlowStatementQuery): Promise<string> {
|
||||||
|
const table = await this.cashflowSheetTable.table(query);
|
||||||
|
|
||||||
|
const tableSheet = new TableSheet(table.table);
|
||||||
|
const tableCsv = tableSheet.convertToCSV();
|
||||||
|
|
||||||
|
return tableCsv;
|
||||||
|
}
|
||||||
|
}
|
||||||
66
temp/CashFlowStatement/CashflowSheetApplication.ts
Normal file
66
temp/CashFlowStatement/CashflowSheetApplication.ts
Normal file
@@ -0,0 +1,66 @@
|
|||||||
|
import { CashflowExportInjectable } from './CashflowExportInjectable';
|
||||||
|
import { ICashFlowStatementQuery } from './Cashflow.types';
|
||||||
|
import { CashFlowStatementService } from './CashFlowService';
|
||||||
|
import { CashflowTableInjectable } from './CashflowTableInjectable';
|
||||||
|
import { CashflowTablePdfInjectable } from './CashflowTablePdfInjectable';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CashflowSheetApplication {
|
||||||
|
/**
|
||||||
|
* Constructor method.
|
||||||
|
* @param {CashflowExportInjectable} cashflowExport
|
||||||
|
* @param {} cashflowSheet
|
||||||
|
* @param cashflowTable
|
||||||
|
* @param cashflowPdf
|
||||||
|
*/
|
||||||
|
constructor(
|
||||||
|
private readonly cashflowExport: CashflowExportInjectable,
|
||||||
|
private readonly cashflowSheet: CashFlowStatementService,
|
||||||
|
private readonly cashflowTable: CashflowTableInjectable,
|
||||||
|
private readonly cashflowPdf: CashflowTablePdfInjectable,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the cashflow sheet
|
||||||
|
* @param {ICashFlowStatementQuery} query - Cashflow statement query.
|
||||||
|
*/
|
||||||
|
public async sheet(query: ICashFlowStatementQuery) {
|
||||||
|
return this.cashflowSheet.cashFlow(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the cashflow sheet in table format.
|
||||||
|
* @param {ICashFlowStatementQuery} query - Cashflow statement query.
|
||||||
|
*/
|
||||||
|
public async table(query: ICashFlowStatementQuery) {
|
||||||
|
return this.cashflowTable.table(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the cashflow sheet in XLSX format.
|
||||||
|
* @param {ICashFlowStatementQuery} query - Cashflow statement query.
|
||||||
|
* @returns {Promise<Buffer>}
|
||||||
|
*/
|
||||||
|
public async xlsx(query: ICashFlowStatementQuery) {
|
||||||
|
return this.cashflowExport.xlsx(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the cashflow sheet in CSV format.
|
||||||
|
* @param {ICashFlowStatementQuery} query - Cashflow statement query.
|
||||||
|
* @returns {Promise<Buffer>}
|
||||||
|
*/
|
||||||
|
public async csv(query: ICashFlowStatementQuery): Promise<string> {
|
||||||
|
return this.cashflowExport.csv(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the cashflow sheet in pdf format.
|
||||||
|
* @param {ICashFlowStatementQuery} query - Cashflow statement query.
|
||||||
|
* @returns {Promise<Buffer>}
|
||||||
|
*/
|
||||||
|
public async pdf(query: ICashFlowStatementQuery): Promise<Buffer> {
|
||||||
|
return this.cashflowPdf.pdf(query);
|
||||||
|
}
|
||||||
|
}
|
||||||
36
temp/CashFlowStatement/CashflowSheetMeta.ts
Normal file
36
temp/CashFlowStatement/CashflowSheetMeta.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import moment from 'moment';
|
||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { FinancialSheetMeta } from '../../common/FinancialSheetMeta';
|
||||||
|
import {
|
||||||
|
ICashFlowStatementMeta,
|
||||||
|
ICashFlowStatementQuery,
|
||||||
|
} from './Cashflow.types';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CashflowSheetMeta {
|
||||||
|
constructor(private readonly financialSheetMeta: FinancialSheetMeta) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cashflow sheet meta.
|
||||||
|
* @param {ICashFlowStatementQuery} query
|
||||||
|
* @returns {Promise<ICashFlowStatementMeta>}
|
||||||
|
*/
|
||||||
|
public async meta(
|
||||||
|
query: ICashFlowStatementQuery,
|
||||||
|
): Promise<ICashFlowStatementMeta> {
|
||||||
|
const meta = await this.financialSheetMeta.meta();
|
||||||
|
const formattedToDate = moment(query.toDate).format('YYYY/MM/DD');
|
||||||
|
const formattedFromDate = moment(query.fromDate).format('YYYY/MM/DD');
|
||||||
|
const formattedDateRange = `From ${formattedFromDate} | To ${formattedToDate}`;
|
||||||
|
|
||||||
|
const sheetName = 'Statement of Cash Flow';
|
||||||
|
|
||||||
|
return {
|
||||||
|
...meta,
|
||||||
|
sheetName,
|
||||||
|
formattedToDate,
|
||||||
|
formattedFromDate,
|
||||||
|
formattedDateRange,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
36
temp/CashFlowStatement/CashflowTableInjectable.ts
Normal file
36
temp/CashFlowStatement/CashflowTableInjectable.ts
Normal file
@@ -0,0 +1,36 @@
|
|||||||
|
import { Injectable } from '@nestjs/common';
|
||||||
|
import { CashFlowTable } from './CashFlowTable';
|
||||||
|
import { CashFlowStatementService } from './CashFlowService';
|
||||||
|
import { I18nService } from 'nestjs-i18n';
|
||||||
|
import {
|
||||||
|
ICashFlowStatementQuery,
|
||||||
|
ICashFlowStatementTable,
|
||||||
|
} from './Cashflow.types';
|
||||||
|
|
||||||
|
@Injectable()
|
||||||
|
export class CashflowTableInjectable {
|
||||||
|
constructor(
|
||||||
|
private readonly cashflowSheet: CashFlowStatementService,
|
||||||
|
private readonly i18n: I18nService,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieves the cash flow table.
|
||||||
|
* @returns {Promise<ICashFlowStatementTable>}
|
||||||
|
*/
|
||||||
|
public async table(
|
||||||
|
query: ICashFlowStatementQuery,
|
||||||
|
): Promise<ICashFlowStatementTable> {
|
||||||
|
const cashflowDOO = await this.cashflowSheet.cashFlow(query);
|
||||||
|
const cashflowTable = new CashFlowTable(cashflowDOO, this.i18n);
|
||||||
|
|
||||||
|
return {
|
||||||
|
table: {
|
||||||
|
columns: cashflowTable.tableColumns(),
|
||||||
|
rows: cashflowTable.tableRows(),
|
||||||
|
},
|
||||||
|
query: cashflowDOO.query,
|
||||||
|
meta: cashflowDOO.meta,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
28
temp/CashFlowStatement/CashflowTablePdfInjectable.ts
Normal file
28
temp/CashFlowStatement/CashflowTablePdfInjectable.ts
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
import { TableSheetPdf } from '../../common/TableSheetPdf';
|
||||||
|
import { ICashFlowStatementQuery } from './Cashflow.types';
|
||||||
|
import { CashflowTableInjectable } from './CashflowTableInjectable';
|
||||||
|
import { HtmlTableCustomCss } from './constants';
|
||||||
|
|
||||||
|
export class CashflowTablePdfInjectable {
|
||||||
|
constructor(
|
||||||
|
private readonly cashflowTable: CashflowTableInjectable,
|
||||||
|
private readonly tableSheetPdf: TableSheetPdf,
|
||||||
|
) {}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Converts the given cashflow sheet table to pdf.
|
||||||
|
* @param {number} tenantId - Tenant ID.
|
||||||
|
* @param {IBalanceSheetQuery} query - Balance sheet query.
|
||||||
|
* @returns {Promise<Buffer>}
|
||||||
|
*/
|
||||||
|
public async pdf(query: ICashFlowStatementQuery): Promise<Buffer> {
|
||||||
|
const table = await this.cashflowTable.table(query);
|
||||||
|
|
||||||
|
return this.tableSheetPdf.convertToPdf(
|
||||||
|
table.table,
|
||||||
|
table.meta.sheetName,
|
||||||
|
table.meta.formattedDateRange,
|
||||||
|
HtmlTableCustomCss,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
52
temp/CashFlowStatement/constants.ts
Normal file
52
temp/CashFlowStatement/constants.ts
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
import { ICashFlowStatementQuery } from "./Cashflow.types";
|
||||||
|
|
||||||
|
export const DISPLAY_COLUMNS_BY = {
|
||||||
|
DATE_PERIODS: 'date_periods',
|
||||||
|
TOTAL: 'total',
|
||||||
|
};
|
||||||
|
|
||||||
|
export const MAP_CONFIG = { childrenPath: 'children', pathFormat: 'array' };
|
||||||
|
export const HtmlTableCustomCss = `
|
||||||
|
table tr.row-type--accounts td {
|
||||||
|
border-top: 1px solid #bbb;
|
||||||
|
}
|
||||||
|
table tr.row-id--cash-end-period td {
|
||||||
|
border-bottom: 3px double #333;
|
||||||
|
}
|
||||||
|
table tr.row-type--total {
|
||||||
|
font-weight: 600;
|
||||||
|
}
|
||||||
|
table tr.row-type--total td {
|
||||||
|
color: #000;
|
||||||
|
}
|
||||||
|
table tr.row-type--total:not(:first-child) td {
|
||||||
|
border-top: 1px solid #bbb;
|
||||||
|
}
|
||||||
|
table .column--name,
|
||||||
|
table .cell--name {
|
||||||
|
width: 400px;
|
||||||
|
}
|
||||||
|
table .column--total,
|
||||||
|
table .cell--total,
|
||||||
|
table [class*="column--date-range"],
|
||||||
|
table [class*="cell--date-range"] {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
`;
|
||||||
|
|
||||||
|
export const getDefaultCashflowQuery = (): ICashFlowStatementQuery => ({
|
||||||
|
displayColumnsType: 'total',
|
||||||
|
displayColumnsBy: 'day',
|
||||||
|
fromDate: moment().startOf('year').format('YYYY-MM-DD'),
|
||||||
|
toDate: moment().format('YYYY-MM-DD'),
|
||||||
|
numberFormat: {
|
||||||
|
precision: 2,
|
||||||
|
divideOn1000: false,
|
||||||
|
showZero: false,
|
||||||
|
formatMoney: 'total',
|
||||||
|
negativeFormat: 'mines',
|
||||||
|
},
|
||||||
|
noneZero: false,
|
||||||
|
noneTransactions: false,
|
||||||
|
basis: 'cash',
|
||||||
|
});
|
||||||
77
temp/CashFlowStatement/schema.ts
Normal file
77
temp/CashFlowStatement/schema.ts
Normal file
@@ -0,0 +1,77 @@
|
|||||||
|
import { ACCOUNT_TYPE } from '@/constants/accounts';
|
||||||
|
import {
|
||||||
|
ICashFlowSchemaSection,
|
||||||
|
CASH_FLOW_SECTION_ID,
|
||||||
|
ICashFlowStatementSectionType,
|
||||||
|
} from './Cashflow.types';
|
||||||
|
|
||||||
|
export const CASH_FLOW_SCHEMA = [
|
||||||
|
{
|
||||||
|
id: CASH_FLOW_SECTION_ID.OPERATING,
|
||||||
|
label: 'OPERATING ACTIVITIES',
|
||||||
|
sectionType: ICashFlowStatementSectionType.AGGREGATE,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: CASH_FLOW_SECTION_ID.NET_INCOME,
|
||||||
|
label: 'Net income',
|
||||||
|
sectionType: ICashFlowStatementSectionType.NET_INCOME,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: CASH_FLOW_SECTION_ID.OPERATING_ACCOUNTS,
|
||||||
|
label: 'Adjustments net income by operating activities.',
|
||||||
|
sectionType: ICashFlowStatementSectionType.ACCOUNTS,
|
||||||
|
accountsRelations: [
|
||||||
|
{ type: ACCOUNT_TYPE.ACCOUNTS_RECEIVABLE, direction: 'mines' },
|
||||||
|
{ type: ACCOUNT_TYPE.INVENTORY, direction: 'mines' },
|
||||||
|
{ type: ACCOUNT_TYPE.NON_CURRENT_ASSET, direction: 'mines' },
|
||||||
|
{ type: ACCOUNT_TYPE.ACCOUNTS_PAYABLE, direction: 'plus' },
|
||||||
|
{ type: ACCOUNT_TYPE.CREDIT_CARD, direction: 'plus' },
|
||||||
|
{ type: ACCOUNT_TYPE.TAX_PAYABLE, direction: 'plus' },
|
||||||
|
{ type: ACCOUNT_TYPE.OTHER_CURRENT_ASSET, direction: 'mines' },
|
||||||
|
{ type: ACCOUNT_TYPE.OTHER_CURRENT_LIABILITY, direction: 'plus' },
|
||||||
|
{ type: ACCOUNT_TYPE.NON_CURRENT_LIABILITY, direction: 'plus' },
|
||||||
|
],
|
||||||
|
showAlways: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
footerLabel: 'Net cash provided by operating activities',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: CASH_FLOW_SECTION_ID.INVESTMENT,
|
||||||
|
sectionType: ICashFlowStatementSectionType.ACCOUNTS,
|
||||||
|
label: 'INVESTMENT ACTIVITIES',
|
||||||
|
accountsRelations: [{ type: ACCOUNT_TYPE.FIXED_ASSET, direction: 'mines' }],
|
||||||
|
footerLabel: 'Net cash provided by investing activities',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: CASH_FLOW_SECTION_ID.FINANCIAL,
|
||||||
|
label: 'FINANCIAL ACTIVITIES',
|
||||||
|
sectionType: ICashFlowStatementSectionType.ACCOUNTS,
|
||||||
|
accountsRelations: [
|
||||||
|
{ type: ACCOUNT_TYPE.LOGN_TERM_LIABILITY, direction: 'plus' },
|
||||||
|
{ type: ACCOUNT_TYPE.EQUITY, direction: 'plus' },
|
||||||
|
],
|
||||||
|
footerLabel: 'Net cash provided by financing activities',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: CASH_FLOW_SECTION_ID.CASH_BEGINNING_PERIOD,
|
||||||
|
sectionType: ICashFlowStatementSectionType.CASH_AT_BEGINNING,
|
||||||
|
label: 'Cash at beginning of period',
|
||||||
|
accountsRelations: [
|
||||||
|
{ type: ACCOUNT_TYPE.CASH, direction: 'plus' },
|
||||||
|
{ type: ACCOUNT_TYPE.BANK, direction: 'plus' },
|
||||||
|
],
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: CASH_FLOW_SECTION_ID.NET_CASH_INCREASE,
|
||||||
|
sectionType: ICashFlowStatementSectionType.TOTAL,
|
||||||
|
equation: 'OPERATING + INVESTMENT + FINANCIAL',
|
||||||
|
label: 'NET CASH INCREASE FOR PERIOD',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: CASH_FLOW_SECTION_ID.CASH_END_PERIOD,
|
||||||
|
label: 'CASH AT END OF PERIOD',
|
||||||
|
sectionType: ICashFlowStatementSectionType.TOTAL,
|
||||||
|
equation: 'NET_CASH_INCREASE + CASH_BEGINNING_PERIOD',
|
||||||
|
},
|
||||||
|
] as ICashFlowSchemaSection[];
|
||||||
Reference in New Issue
Block a user