Files
budget2.0/src/store/index.ts
T
Lucas Winther 9fe950bc7d feat(recurring): offer confirmation on next occurrence beyond the month
Gap 1 (spec §5): ExpectedBand only listed this month's occurrences, so a
lastCharge bill whose pending slot had rolled into next month (the phone-bill
flagship case) was not confirmable without navigating there first.

Extend the walk 12 months past the displayed month (occurrencesByMonth's own
upToMonth bound; foldBalances is untouched) and surface a "Coming up" group:
at most one row per recurring cost, its next unconfirmed occurrence. That row
confirms EARLY, so it records today rather than the future slot date — which
is exactly what rebases a lastCharge series — and shows both dates so the
owner can see what will be written. `today` is exported from src/store/index.ts
next to `currentMonth`, keeping the clock out of src/domain/.

expectedGroups() is the pure, exported core (pending/overdue/comingUp);
ExpectedBand renders it and still returns null when all three are empty.
2026-09-04 08:46:45 +02:00

29 lines
1.2 KiB
TypeScript

import { monthOf } from "../domain/months.ts";
import { readDataset, writeDataset } from "./db.ts";
import { createSnapshotStore } from "./snapshot.ts";
import { BAKED_FX_RATES } from "./bakedRates.ts";
import type { IsoDate } from "../domain/types.ts";
/** The current month, read at module load. The UI owns the clock; the domain does not. */
export const currentMonth = monthOf(new Date().toISOString().slice(0, 10));
/**
* Today, day-granular, read at module load. The UI owns the clock; the domain
* does not. `ExpectedBand`'s "Coming up" group needs the actual day — a
* coming-up occurrence is confirmed EARLY, so the purchase it writes must be
* dated today rather than the future slot, which is exactly what rebases a
* `lastCharge` series.
*/
export const today: IsoDate = new Date().toISOString().slice(0, 10);
export const store = createSnapshotStore(
{ read: readDataset, write: writeDataset },
currentMonth,
// First run only, so a fresh install can convert a EUR purchase on day one.
// Never a backstop for a rate the user has cleared.
BAKED_FX_RATES,
);
export * from "./snapshot.ts";
export { UnsupportedSchemaError } from "./migrations.ts";