Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various bug fixes #780

Merged
merged 2 commits into from
Dec 21, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
59 changes: 41 additions & 18 deletions reports/AccountReport.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,12 @@ export abstract class AccountReport extends LedgerReport {
this._dateRanges = await this._getDateRanges();
}

getRootNode(
getRootNodes(
rootType: AccountRootType,
accountTree: AccountTree
): AccountTreeNode | undefined {
): AccountTreeNode[] | undefined {
const rootNodeList = Object.values(accountTree);
return rootNodeList.find((n) => n.rootType === rootType);
return rootNodeList.filter((n) => n.rootType === rootType);
}

getEmptyRow(): ReportRow {
Expand All @@ -88,8 +88,11 @@ export abstract class AccountReport extends LedgerReport {
};
}

getTotalNode(rootNode: AccountTreeNode, name: string): AccountListNode {
const accountTree = { [rootNode.name]: rootNode };
getTotalNode(rootNodes: AccountTreeNode[], name: string): AccountListNode {
const accountTree: Tree = {};
for (const rootNode of rootNodes) {
accountTree[rootNode.name] = rootNode;
}
const leafNodes = getListOfLeafNodes(accountTree) as AccountTreeNode[];

const totalMap = leafNodes.reduce((acc, node) => {
Expand Down Expand Up @@ -236,6 +239,17 @@ export abstract class AccountReport extends LedgerReport {
return null;
}

// Fix arythmetic on dates when adding or substracting months. If the
// reference date was the last day in month, ensure that the resulting date is
// also the last day.
_fixMonthsJump(refDate: DateTime, date: DateTime): DateTime {
if (refDate.day == refDate.daysInMonth && date.day != date.daysInMonth) {
return date.set({ day: date.daysInMonth });
} else {
return date;
}
}

async _getDateRanges(): Promise<DateRange[]> {
const endpoints = await this._getFromAndToDates();
const fromDate = DateTime.fromISO(endpoints.fromDate);
Expand All @@ -252,7 +266,10 @@ export abstract class AccountReport extends LedgerReport {

const months: number = monthsMap[this.periodicity];
const dateRanges: DateRange[] = [
{ toDate, fromDate: toDate.minus({ months }) },
{
toDate,
fromDate: this._fixMonthsJump(toDate, toDate.minus({ months })),
},
];

let count = this.count ?? 1;
Expand All @@ -264,7 +281,10 @@ export abstract class AccountReport extends LedgerReport {
const lastRange = dateRanges.at(-1)!;
dateRanges.push({
toDate: lastRange.fromDate,
fromDate: lastRange.fromDate.minus({ months }),
fromDate: this._fixMonthsJump(
toDate,
lastRange.fromDate.minus({ months })
),
});
}

Expand Down Expand Up @@ -445,14 +465,15 @@ export async function getFiscalEndpoints(

const fromDate = [
fromYear,
fys.toISOString().split('T')[0].split('-').slice(1),
]
.flat()
.join('-');
(fys.getMonth() + 1).toString().padStart(2, '0'),
fys.getDate().toString().padStart(2, '0'),
].join('-');

const toDate = [toYear, fye.toISOString().split('T')[0].split('-').slice(1)]
.flat()
.join('-');
const toDate = [
toYear,
(fye.getMonth() + 1).toString().padStart(2, '0'),
fye.getDate().toString().padStart(2, '0'),
].join('-');

return { fromDate, toDate };
}
Expand Down Expand Up @@ -573,15 +594,17 @@ function getPrunedChildren(children: AccountTreeNode[]): AccountTreeNode[] {
});
}

export function convertAccountRootNodeToAccountList(
rootNode: AccountTreeNode
export function convertAccountRootNodesToAccountList(
rootNodes: AccountTreeNode[]
): AccountList {
if (!rootNode) {
if (!rootNodes || rootNodes.length == 0) {
return [];
}

const accountList: AccountList = [];
pushToAccountList(rootNode, accountList, 0);
for (const rootNode of rootNodes) {
pushToAccountList(rootNode, accountList, 0);
}
return accountList;
}

Expand Down
14 changes: 7 additions & 7 deletions reports/BalanceSheet/BalanceSheet.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
} from 'models/baseModels/Account/types';
import {
AccountReport,
convertAccountRootNodeToAccountList,
convertAccountRootNodesToAccountList,
} from 'reports/AccountReport';
import { ReportData, RootTypeRow } from 'reports/types';
import { getMapFromList } from 'utils';
Expand Down Expand Up @@ -44,15 +44,15 @@ export class BalanceSheet extends AccountReport {

const rootTypeRows: RootTypeRow[] = this.rootTypes
.map((rootType) => {
const rootNode = this.getRootNode(rootType, accountTree)!;
const rootList = convertAccountRootNodeToAccountList(rootNode);
const rootNodes = this.getRootNodes(rootType, accountTree)!;
const rootList = convertAccountRootNodesToAccountList(rootNodes);
return {
rootType,
rootNode,
rootNodes,
rows: this.getReportRowsFromAccountList(rootList),
};
})
.filter((row) => !!row.rootNode);
.filter((row) => !!row.rootNodes.length);

this.reportData = this.getReportDataFromRows(
getMapFromList(rootTypeRows, 'rootType')
Expand Down Expand Up @@ -88,8 +88,8 @@ export class BalanceSheet extends AccountReport {

reportData.push(...row.rows);

if (row.rootNode) {
const totalNode = this.getTotalNode(row.rootNode, totalName);
if (row.rootNodes.length) {
const totalNode = this.getTotalNode(row.rootNodes, totalName);
const totalRow = this.getRowFromAccountListNode(totalNode);
reportData.push(totalRow);
}
Expand Down
61 changes: 39 additions & 22 deletions reports/ProfitAndLoss/ProfitAndLoss.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import {
} from 'models/baseModels/Account/types';
import {
AccountReport,
convertAccountRootNodeToAccountList,
convertAccountRootNodesToAccountList,
} from 'reports/AccountReport';
import {
AccountListNode,
Expand Down Expand Up @@ -45,72 +45,86 @@ export class ProfitAndLoss extends AccountReport {
/**
* Income Rows
*/
const incomeRoot = this.getRootNode(
const incomeRoots = this.getRootNodes(
AccountRootTypeEnum.Income,
accountTree
)!;
const incomeList = convertAccountRootNodeToAccountList(incomeRoot);
const incomeList = convertAccountRootNodesToAccountList(incomeRoots);
const incomeRows = this.getReportRowsFromAccountList(incomeList);

/**
* Expense Rows
*/
const expenseRoot = this.getRootNode(
const expenseRoots = this.getRootNodes(
AccountRootTypeEnum.Expense,
accountTree
)!;
const expenseList = convertAccountRootNodeToAccountList(expenseRoot);
const expenseList = convertAccountRootNodesToAccountList(expenseRoots);
const expenseRows = this.getReportRowsFromAccountList(expenseList);

this.reportData = this.getReportDataFromRows(
incomeRows,
expenseRows,
incomeRoot,
expenseRoot
incomeRoots,
expenseRoots
);
this.loading = false;
}

getReportDataFromRows(
incomeRows: ReportData,
expenseRows: ReportData,
incomeRoot: AccountTreeNode | undefined,
expenseRoot: AccountTreeNode | undefined
incomeRoots: AccountTreeNode[] | undefined,
expenseRoots: AccountTreeNode[] | undefined
): ReportData {
if (incomeRoot && !expenseRoot) {
if (
incomeRoots &&
incomeRoots.length &&
!expenseRoots &&
!expenseRoots.length
) {
return this.getIncomeOrExpenseRows(
incomeRoot,
incomeRoots,
incomeRows,
t`Total Income (Credit)`
);
}

if (expenseRoot && !incomeRoot) {
if (
expenseRoots &&
expenseRoots.length &&
(!incomeRoots || !incomeRoots.length)
) {
return this.getIncomeOrExpenseRows(
expenseRoot,
expenseRoots,
expenseRows,
t`Total Income (Credit)`
);
}

if (!incomeRoot || !expenseRoot) {
if (
!incomeRoots ||
!incomeRoots.length ||
!expenseRoots ||
!expenseRoots.length
) {
return [];
}

return this.getIncomeAndExpenseRows(
incomeRows,
expenseRows,
incomeRoot,
expenseRoot
incomeRoots,
expenseRoots
);
}

getIncomeOrExpenseRows(
root: AccountTreeNode,
roots: AccountTreeNode[],
rows: ReportData,
totalRowName: string
): ReportData {
const total = this.getTotalNode(root, totalRowName);
const total = this.getTotalNode(roots, totalRowName);
const totalRow = this.getRowFromAccountListNode(total);

return [rows, totalRow].flat();
Expand All @@ -119,14 +133,17 @@ export class ProfitAndLoss extends AccountReport {
getIncomeAndExpenseRows(
incomeRows: ReportData,
expenseRows: ReportData,
incomeRoot: AccountTreeNode,
expenseRoot: AccountTreeNode
incomeRoots: AccountTreeNode[],
expenseRoots: AccountTreeNode[]
) {
const totalIncome = this.getTotalNode(incomeRoot, t`Total Income (Credit)`);
const totalIncome = this.getTotalNode(
incomeRoots,
t`Total Income (Credit)`
);
const totalIncomeRow = this.getRowFromAccountListNode(totalIncome);

const totalExpense = this.getTotalNode(
expenseRoot,
expenseRoots,
t`Total Expense (Debit)`
);
const totalExpenseRow = this.getRowFromAccountListNode(totalExpense);
Expand Down
10 changes: 5 additions & 5 deletions reports/TrialBalance/TrialBalance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import {
AccountReport,
ACC_BAL_WIDTH,
ACC_NAME_WIDTH,
convertAccountRootNodeToAccountList,
convertAccountRootNodesToAccountList,
getFiscalEndpoints,
} from 'reports/AccountReport';
import {
Expand Down Expand Up @@ -65,15 +65,15 @@ export class TrialBalance extends AccountReport {

const rootTypeRows: RootTypeRow[] = this.rootTypes
.map((rootType) => {
const rootNode = this.getRootNode(rootType, accountTree)!;
const rootList = convertAccountRootNodeToAccountList(rootNode);
const rootNodes = this.getRootNodes(rootType, accountTree)!;
const rootList = convertAccountRootNodesToAccountList(rootNodes);
return {
rootType,
rootNode,
rootNodes,
rows: this.getReportRowsFromAccountList(rootList),
};
})
.filter((row) => !!row.rootNode);
.filter((row) => !!(row.rootNodes && row.rootNodes.length));

this.reportData = await this.getReportDataFromRows(rootTypeRows);
this.loading = false;
Expand Down
2 changes: 1 addition & 1 deletion reports/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,6 @@ export type Tree = Record<string, TreeNode>;

export type RootTypeRow = {
rootType: AccountRootType;
rootNode: AccountTreeNode;
rootNodes: AccountTreeNode[];
rows: ReportData;
};
Loading