refactor: extract shared backward-reconstruction logic
Extract the month-by-month backward-walk algorithm (used for both team-level cash balance and player-level debt history) into a single shared private helper `reconstructBackward()`. This eliminates code duplication while preserving behavior: - Team-level balanceHistory: maps movements through signedFlowAmount(), rounds each point, calls the shared helper - Player-level balance history: maps transactions using type.id rule, skips rounding (only rounds at final merge to avoid compounding errors), calls the shared helper Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
@@ -299,26 +299,16 @@ export class TeamsService {
|
||||
// reconstruct earlier month-end balances — this guarantees the most
|
||||
// recent point always equals team.balance by construction, regardless
|
||||
// of undocumented history.
|
||||
const descendingMovements = [...movements].sort((a, b) =>
|
||||
a.date > b.date ? -1 : a.date < b.date ? 1 : 0,
|
||||
);
|
||||
|
||||
const signedMovements = movements.map((m) => ({
|
||||
date: m.date,
|
||||
amount: this.signedFlowAmount(m),
|
||||
}));
|
||||
const currentBalance = Number(team.balance);
|
||||
let futureSum = 0;
|
||||
let movementIndex = 0;
|
||||
const balanceHistory = [...months]
|
||||
.reverse()
|
||||
.map((month) => {
|
||||
while (
|
||||
movementIndex < descendingMovements.length &&
|
||||
descendingMovements[movementIndex].date.slice(0, 7) > month
|
||||
) {
|
||||
futureSum += this.signedFlowAmount(descendingMovements[movementIndex]);
|
||||
movementIndex++;
|
||||
}
|
||||
return { month, balance: this.round(currentBalance - futureSum) };
|
||||
})
|
||||
.reverse();
|
||||
const rawBalances = this.reconstructBackward(months, currentBalance, signedMovements);
|
||||
const balanceHistory = months.map((month, index) => ({
|
||||
month,
|
||||
balance: this.round(rawBalances[index]),
|
||||
}));
|
||||
|
||||
const monthlyFlow = months.map((month) => {
|
||||
const monthMovements = movements.filter((m) => m.date.slice(0, 7) === month);
|
||||
@@ -354,6 +344,28 @@ export class TeamsService {
|
||||
return movement.type === 'expense' ? -movement.amount : movement.amount;
|
||||
}
|
||||
|
||||
private reconstructBackward(
|
||||
months: string[],
|
||||
currentValue: number,
|
||||
signedMovements: { date: string; amount: number }[],
|
||||
): number[] {
|
||||
const descending = [...signedMovements].sort((a, b) =>
|
||||
a.date > b.date ? -1 : a.date < b.date ? 1 : 0,
|
||||
);
|
||||
let futureSum = 0;
|
||||
let index = 0;
|
||||
return [...months]
|
||||
.reverse()
|
||||
.map((month) => {
|
||||
while (index < descending.length && descending[index].date.slice(0, 7) > month) {
|
||||
futureSum += descending[index].amount;
|
||||
index++;
|
||||
}
|
||||
return currentValue - futureSum;
|
||||
})
|
||||
.reverse();
|
||||
}
|
||||
|
||||
private reconstructOutstandingHistory(months: string[], players: Player[]): number[] {
|
||||
const activePlayers = players.filter((p) => p.active);
|
||||
const totals = months.map(() => 0);
|
||||
@@ -380,28 +392,12 @@ export class TeamsService {
|
||||
currentBalance: number,
|
||||
transactions: Transaction[],
|
||||
): number[] {
|
||||
const descendingMovements = transactions
|
||||
.map((t) => ({
|
||||
date: t.date,
|
||||
amount: t.type && t.type.id > 10 ? -Number(t.amount) : Number(t.amount),
|
||||
}))
|
||||
.sort((a, b) => (a.date > b.date ? -1 : a.date < b.date ? 1 : 0));
|
||||
const signedMovements = transactions.map((t) => ({
|
||||
date: t.date,
|
||||
amount: t.type && t.type.id > 10 ? -Number(t.amount) : Number(t.amount),
|
||||
}));
|
||||
|
||||
let futureSum = 0;
|
||||
let movementIndex = 0;
|
||||
return [...months]
|
||||
.reverse()
|
||||
.map((month) => {
|
||||
while (
|
||||
movementIndex < descendingMovements.length &&
|
||||
descendingMovements[movementIndex].date.slice(0, 7) > month
|
||||
) {
|
||||
futureSum += descendingMovements[movementIndex].amount;
|
||||
movementIndex++;
|
||||
}
|
||||
return currentBalance - futureSum;
|
||||
})
|
||||
.reverse();
|
||||
return this.reconstructBackward(months, currentBalance, signedMovements);
|
||||
}
|
||||
|
||||
private round(value: number): number {
|
||||
|
||||
Reference in New Issue
Block a user