Centralize Financial Rules
The UI needs numbers, but it should not be responsible for inventing financial formulas in several different components. A rule duplicated in three files can eventually produce three different answers.
Open client/src/lib/finance.js. Keep financial operations as small named functions:
export function calculateTotals(transactions) {
return transactions.reduce(
(totals, transaction) => {
if (transaction.type === "income") totals.incomeCents += transaction.amountCents;
if (transaction.type === "expense") totals.expenseCents += transaction.amountCents;
return totals;
},
{ incomeCents: 0, expenseCents: 0 }
);
}
This function has one responsibility: add income to one bucket and expenses to another. It returns cents because cents are the application’s financial representation.
The same file contains rules for:
- converting local dates to
YYYY-MM-DD - finding the current month cursor
- choosing a default entry date
- calculating savings rate
- calculating average monthly expenses
- computing category totals and their share of total spending
- grouping transactions into monthly totals
These functions are deliberately independent of React. A pure calculation does not need a browser render to prove that 320000 + 200000 equals 520000.
That separation lets a component ask for a result rather than reimplement the formula. For example, a summary component can receive totals and render them; it does not need to know how the totals were accumulated.
Test it
Search client/src for places where the same financial formula is repeated. Replace duplicated logic with the named helper when the helper already represents that rule.
Then make a small manual check with the sample transactions:
income = 520000 cents
expenses = 136650 cents
balance = 383350 cents
Checkpoint
You can now point to one named function for each major financial rule instead of hunting through UI components for scattered calculations.