add money tracker
All checks were successful
Test and deploy staging / staging (push) Successful in 1m46s

This commit is contained in:
2026-09-23 17:02:32 +00:00
parent 753b2e5d6a
commit 0638ead87f
15 changed files with 2532 additions and 3 deletions

View File

@@ -0,0 +1,62 @@
import { describe, expect, it } from 'vitest';
import { accountBalances, balanceSeries, forecastSeries, utilityEstimate } from './charts';
describe('money tracker calculations', () => {
it('keeps balances separate across accounts and preserves transaction order', () => {
const accounts = [
{ id: 1, name: 'Cash', openingBalanceCents: 10000 },
{ id: 2, name: 'Bank', openingBalanceCents: 20000 }
];
const transactions = [
{ accountId: 1, date: '2026-01-01', amountCents: -2500 },
{ accountId: 2, date: '2026-01-02', amountCents: 5000 },
{ accountId: 1, date: '2026-01-03', amountCents: 1000 }
];
expect([...accountBalances(accounts, transactions).values()]).toEqual([8500, 25000]);
expect(balanceSeries(accounts, transactions)[0].points.map((point) => point.value)).toEqual([
10000, 7500, 8500
]);
});
it('projects only future estimates from the current balance', () => {
expect(
forecastSeries(
10000,
[
{ date: '2026-01-01', amountCents: -9999 },
{ date: '2026-10-01', amountCents: -2500 },
{ date: '2026-11-01', amountCents: 5000 }
],
'2026-09-23'
)[0].points.map((point) => point.value)
).toEqual([10000, 7500, 12500]);
});
it('compares estimated usage cost with prorated advances', () => {
const result = utilityEstimate(
[
{ kind: 'gas', date: '2026-01-01', reading: '100' },
{ kind: 'gas', date: '2026-04-01', reading: '130' }
],
'gas',
'1.2500',
2000
);
expect(result?.usage).toBe(30);
expect(result?.estimatedCents).toBe(3750);
expect(result?.advancesCents).toBeGreaterThan(5800);
expect(
utilityEstimate(
[
{ kind: 'gas', date: '2025-01-01', reading: '0' },
{ kind: 'gas', date: '2026-01-01', reading: '100' },
{ kind: 'gas', date: '2026-04-01', reading: '130' }
],
'gas',
'1.2500',
2000,
'2026-01-01'
)?.usage
).toBe(30);
});
});