Skip to content

Commit

Permalink
recursive account complete
Browse files Browse the repository at this point in the history
  • Loading branch information
TinyMurky committed Oct 11, 2024
1 parent 4f39f67 commit 40a0aad
Show file tree
Hide file tree
Showing 6 changed files with 105 additions and 20 deletions.
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "iSunFA",
"version": "0.8.2+43",
"version": "0.8.2+44",
"private": false,
"scripts": {
"dev": "next dev",
Expand Down
1 change: 1 addition & 0 deletions src/interfaces/accounting_account.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export interface IAccountForSheetDisplay {
amount: number | null;
percentage: number | null;
indent: number;
children: IAccountForSheetDisplay[];
debit?: boolean;
}

Expand Down
70 changes: 66 additions & 4 deletions src/lib/utils/account/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,17 +110,48 @@ export function updateAccountAmounts(forest: IAccountNode[], lineItemsMap: Map<n
return updatedForest;
}

/**
* Info: (20241011 - Murky)
* Start with 0 depth
*/
export function calculateMaxHeighOfNode(node: IAccountNode): number {
if (!node.children || node.children.length === 0) {
return 0;
}

let maxChildDepth = 0;
node.children.forEach((child) => {
maxChildDepth = Math.max(maxChildDepth, calculateMaxHeighOfNode(child));
});

return maxChildDepth + 1;
}

export function addAccountNodeToMapRecursively(
accountMap: Map<string, { accountNode: IAccountNode; percentage: number }>,
account: IAccountNode,
rootAmount: number
rootAmount: number,
currentDepth: number,
maxHeight?: number
) {
const newAccountNode = { ...account, children: [] };
// Info: (20241011 - Murky) 倒數第二層可以保有自己的child
const isSecondLastLayer = maxHeight === 1;
const newAccountNode = isSecondLastLayer ? account : { ...account, children: [] };
const percentage = rootAmount === 0 ? 0 : account.amount / rootAmount; // Info: (20240702 - Murky) Calculate percentage
accountMap.set(account.code, { accountNode: newAccountNode, percentage });

account.children.forEach((child) => {
addAccountNodeToMapRecursively(accountMap, child, rootAmount);
const maxHeightOfChild = calculateMaxHeighOfNode(child);
addAccountNodeToMapRecursively(
accountMap,
child,
rootAmount,
currentDepth + 1,
maxHeightOfChild
);
});

return false;
}

export function transformForestToMap(
Expand All @@ -129,12 +160,30 @@ export function transformForestToMap(
const accountMap = new Map<string, { accountNode: IAccountNode; percentage: number }>();

forest.forEach((accountNode) => {
addAccountNodeToMapRecursively(accountMap, accountNode, accountNode.amount);
const maxHeight = calculateMaxHeighOfNode(accountNode);
addAccountNodeToMapRecursively(accountMap, accountNode, accountNode.amount, 0, maxHeight);
});

return accountMap;
}

export function iAccountNode2IAccountForSheetDisplay(
accountNode: IAccountNode,
percentage: number,
children?: IAccountForSheetDisplay[]
): IAccountForSheetDisplay {
const iAccountForSheetDisplay: IAccountForSheetDisplay = {
code: accountNode.code,
name: accountNode.name,
amount: accountNode.amount,
indent: accountNode.level,
debit: accountNode.debit,
percentage,
children: children || [],
};
return iAccountForSheetDisplay;
}

export function mappingAccountToSheetDisplay(
accountMap: Map<string, { accountNode: IAccountNode; percentage: number }>,
sheetMappingRow: {
Expand Down Expand Up @@ -162,15 +211,28 @@ export function mappingAccountToSheetDisplay(
indent: row.indent,
debit: undefined,
percentage: 0,
children: [],
});
} else {
const hasChildren = account.accountNode.children.length > 0;
const children = hasChildren
? account.accountNode.children.map((child) => {
const childAccount = accountMap.get(child.code)!;
// Info: (20241011 - Murky) 最多只有兩層,所以最底不會再有children
return iAccountNode2IAccountForSheetDisplay(
childAccount.accountNode,
childAccount.percentage
);
})
: [];
sheetDisplay.push({
code: row.code,
name: row.name,
amount: account.accountNode.amount,
indent: row.indent,
debit: account.accountNode.debit,
percentage: account.percentage,
children,
});
}
});
Expand Down
1 change: 0 additions & 1 deletion src/lib/utils/report/balance_sheet_generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,6 @@ export default class BalanceSheetGenerator extends FinancialReportGenerator {
const accountForest = await this.generateFinancialReportTree(curPeriod);
BalanceSheetGenerator.calculateLiabilityAndEquity(accountForest);
const accountMap = transformForestToMap(accountForest);

return accountMap;
}

Expand Down
11 changes: 11 additions & 0 deletions src/lib/utils/report/cash_flow_statement_generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -194,6 +194,7 @@ export default class CashFlowStatementGenerator extends FinancialReportGenerator
indent: level,
debit,
percentage: null,
children: [],
};

const newReportSheetMapping = new Map<string, IAccountForSheetDisplay>([
Expand Down Expand Up @@ -247,6 +248,7 @@ export default class CashFlowStatementGenerator extends FinancialReportGenerator
amount: sum,
indent: 0,
percentage: null,
children: [],
});

return indirectOperatingCashFlow;
Expand Down Expand Up @@ -311,6 +313,7 @@ export default class CashFlowStatementGenerator extends FinancialReportGenerator
amount: null,
indent: 0,
percentage: null,
children: [],
});

let directCashFlow = 0;
Expand All @@ -337,6 +340,7 @@ export default class CashFlowStatementGenerator extends FinancialReportGenerator
amount: total,
indent: 1,
percentage: null,
children: [],
};

directCashFlow += total;
Expand All @@ -359,6 +363,7 @@ export default class CashFlowStatementGenerator extends FinancialReportGenerator
amount: directCashFlow,
indent: 1,
percentage: null,
children: [],
});
return reportSheetMapping;
}
Expand All @@ -374,6 +379,7 @@ export default class CashFlowStatementGenerator extends FinancialReportGenerator
amount: directCashFlow,
indent: 1,
percentage: null,
children: [],
});
return reportSheetMapping;
}
Expand Down Expand Up @@ -414,6 +420,7 @@ export default class CashFlowStatementGenerator extends FinancialReportGenerator
amount: 0,
indent: 0,
percentage: null,
children: [],
});

result.set(SPECIAL_ACCOUNTS.CASH_INCREASE_THIS_PERIOD.code, {
Expand All @@ -422,6 +429,7 @@ export default class CashFlowStatementGenerator extends FinancialReportGenerator
amount: cashFlowFromOperating,
indent: 0,
percentage: null,
children: [],
});

result.set(SPECIAL_ACCOUNTS.CASH_AMOUNT_IN_BEGINNING.code, {
Expand All @@ -430,6 +438,7 @@ export default class CashFlowStatementGenerator extends FinancialReportGenerator
amount: startCashBalance,
indent: 0,
percentage: null,
children: [],
});

result.set(SPECIAL_ACCOUNTS.CASH_AMOUNT_IN_END.code, {
Expand All @@ -438,6 +447,7 @@ export default class CashFlowStatementGenerator extends FinancialReportGenerator
amount: endCashBalance,
indent: 0,
percentage: null,
children: [],
});
return result;
}
Expand All @@ -457,6 +467,7 @@ export default class CashFlowStatementGenerator extends FinancialReportGenerator
amount: 0,
indent: account.indent,
percentage: 0,
children: [],
};
});
return result;
Expand Down
40 changes: 26 additions & 14 deletions src/lib/utils/report/financial_report_generator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -144,22 +144,20 @@ export default abstract class FinancialReportGenerator extends ReportGenerator {
return lineItemsFromDB;
}

public async generateIAccountReadyForFrontendArray(): Promise<IAccountReadyForFrontend[]> {
private combineTwoFSReportArray(
curPeriodContent: IAccountForSheetDisplay[],
prePeriodContent: IAccountForSheetDisplay[]
) {
const curPeriodAccountReadyForFrontendArray: IAccountReadyForFrontend[] = [];

this.curPeriodContent = await this.generateFinancialReportArray(true);

this.prePeriodContent = await this.generateFinancialReportArray(false);

if (
this.curPeriodContent &&
this.prePeriodContent &&
this.curPeriodContent.length > 0 &&
this.prePeriodContent.length > 0 &&
this.curPeriodContent.length === this.prePeriodContent.length
curPeriodContent &&
prePeriodContent &&
curPeriodContent.length > 0 &&
prePeriodContent.length > 0 &&
curPeriodContent.length === prePeriodContent.length
) {
this.curPeriodContent.forEach((curPeriodAccount, index) => {
const lastPeriodAccount = this.prePeriodContent[index];
curPeriodContent.forEach((curPeriodAccount, index) => {
const lastPeriodAccount = prePeriodContent[index];
const curPeriodAmount = curPeriodAccount.amount || 0;
const prePeriodAmount = lastPeriodAccount.amount || 0;
const curPeriodAmountString = formatNumberSeparateByComma(curPeriodAmount);
Expand All @@ -171,6 +169,11 @@ export default abstract class FinancialReportGenerator extends ReportGenerator {
? Math.round(lastPeriodAccount.percentage * 100)
: 0;

const children = this.combineTwoFSReportArray(
curPeriodAccount.children,
lastPeriodAccount.children
);

const curPeriodPercentageString = numberBeDashIfFalsy(curPeriodPercentage);
const prePeriodPercentageString = numberBeDashIfFalsy(prePeriodPercentage);
const accountReadyForFrontend: IAccountReadyForFrontend = {
Expand All @@ -185,12 +188,21 @@ export default abstract class FinancialReportGenerator extends ReportGenerator {
prePeriodAmountString,
prePeriodPercentageString,
indent: curPeriodAccount.indent,
children: [],
children,
};
curPeriodAccountReadyForFrontendArray.push(accountReadyForFrontend);
});
}
return curPeriodAccountReadyForFrontendArray;
}

public async generateIAccountReadyForFrontendArray(): Promise<IAccountReadyForFrontend[]> {
this.curPeriodContent = await this.generateFinancialReportArray(true);

this.prePeriodContent = await this.generateFinancialReportArray(false);

const curPeriodAccountReadyForFrontendArray: IAccountReadyForFrontend[] =
this.combineTwoFSReportArray(this.curPeriodContent, this.prePeriodContent);
return curPeriodAccountReadyForFrontendArray;
}

Expand Down

0 comments on commit 40a0aad

Please sign in to comment.