feat: refine month totals and recurring purchase entry
This commit is contained in:
1 parent
7cccd7a41a
commit
c250bbe476
30 files changed
+634
-67
No files matched your search
@@ -0,0 +1,96 @@
|
||||
# Month and purchase refinements
|
||||
|
||||
The owner requested this round on 2026-10-03, with the work queued in TODO
|
||||
before implementation. The follow-up added a visible Total-field reset bug.
|
||||
|
||||
## Actual available
|
||||
|
||||
The month header shows entered income minus actual spending beside Spent.
|
||||
This includes unassigned purchases, refunds, foreign-currency charges and the
|
||||
selected month's finance-plan slices. Unpaid recurring occurrences do not
|
||||
reduce it. Allocation and envelope carry do not enter this calculation.
|
||||
Negative values remain visible, and arithmetic and display use dataset digits.
|
||||
|
||||
Purchases before the envelope fold's start still count in Spent and Actual
|
||||
available. The month view uses the existing charge calculation for those
|
||||
months; the rollover fold continues to begin at its configured start.
|
||||
|
||||
## Display choices
|
||||
|
||||
Monthly breakdown has a Show chart checkbox. Its header and checkbox remain
|
||||
visible when the chart and detail list are hidden. Expected has an Expand /
|
||||
Collapse button and shows counts for expected, coming-up and overdue entries
|
||||
when closed. Closing it preserves any typed confirmation amount.
|
||||
|
||||
Both choices default to visible/expanded and persist across months and reloads
|
||||
in browser localStorage. This follows the theme decision: display preferences
|
||||
belong to this browser, not to the exported budget. Blocked localStorage must
|
||||
not stop the app or the controls from working. Neither choice changes money,
|
||||
occurrences or confirmation behavior.
|
||||
|
||||
## Purchase entry
|
||||
|
||||
New purchases begin with Recurring cost set to None. Their recurring option
|
||||
creates a new bill from this purchase, rather than selecting an existing bill.
|
||||
Creating a bill and its first charge remains one atomic mutation. Calendar
|
||||
slots and last-charge date requirements retain their existing rules.
|
||||
|
||||
Settings → Recurring costs includes a checkbox to allow selecting existing
|
||||
bills in Add purchase. The optional dataset boolean is
|
||||
`settings.allowExistingRecurringCost`; absent means false, so existing budgets
|
||||
adopt the new default without a migration. JSON import accepts only booleans
|
||||
when this field is present. The choice travels with a JSON export.
|
||||
|
||||
Editing a linked purchase continues to show its saved association even with
|
||||
the setting off, and choosing None can unlink it. Ordinary purchases do not
|
||||
automatically become recurring bills. This resolves the default-selection
|
||||
ambiguity in favor of an explicit recurring action.
|
||||
|
||||
The Total field has its own text state to preserve partly typed money inputs.
|
||||
Resetting the dialog now resets that text alongside the numeric draft: new
|
||||
purchases start blank and existing purchases start with their saved amount.
|
||||
The expanded new-bill form exceeded a phone viewport in a browser check. The
|
||||
purchase dialog now caps its height to the viewport and scrolls its contents,
|
||||
keeping both the first fields and Save reachable.
|
||||
|
||||
## Default currencies
|
||||
|
||||
New datasets include Japanese yen (JPY, ¥), Australian dollars (AUD, AU$),
|
||||
Canadian dollars (CAD, CA$) and Mexican pesos (MXN, MX$). Existing tables are
|
||||
not migrated: the request specified defaults, and editing an established
|
||||
table is the owner's action. Every currency still uses dataset-wide precision.
|
||||
|
||||
The build's FX targets derive from the seed table. All four have committed
|
||||
fallback rates as well as live build-time fetching. The committed rates were
|
||||
obtained from Frankfurter's DKK-base quote dated 2026-10-02 and inverted to
|
||||
DKK per unit, preserving six decimal places. Like the previous constants,
|
||||
these rows are marked manual and seed only new datasets.
|
||||
|
||||
Source: https://api.frankfurter.dev/v1/2026-10-02?base=DKK&symbols=JPY,AUD,CAD,MXN
|
||||
|
||||
The amount parser strips longer symbols before the plain dollar sign, so
|
||||
AU$, CA$ and MX$ work without leaving stray letters in the amount. An explicit
|
||||
currency code still disambiguates a symbol collision.
|
||||
|
||||
## Build stamp
|
||||
|
||||
Colophon shows the source ref and a separate build-time UTC date. An exact
|
||||
commit keeps its source link; an uncommitted checkout retains the dirty suffix.
|
||||
Source archives say source archive rather than inventing a Git ref, while
|
||||
the service worker still receives a unique cache version. Development says
|
||||
development and no build date. Browser accessors tolerate an absent process
|
||||
global, following the existing Bun environment-inlining rule.
|
||||
|
||||
## Verification
|
||||
|
||||
Regression coverage exercises the actual money calculation, purchase save /
|
||||
reopen, new recurring creation, enabled existing-bill selection, linked editing,
|
||||
display persistence, collapse/expand preserving a typed amount, Settings write
|
||||
errors, JSON preference validation, symbol parsing and new seed conversion.
|
||||
Chrome checks verify the month controls, saving and reopening a purchase,
|
||||
persisting the Settings choice to IndexedDB, creating a new bill and its first
|
||||
charge together, keeping mobile Save reachable, and production build metadata.
|
||||
Desktop and mobile captures cover light and dark themes. Screenshots establish
|
||||
layout and console behavior; visual feel still requires the owner.
|
||||
The complete suite passes 911 tests across 66 files, TypeScript is clean, and
|
||||
production builds succeed at both root and subpath base URLs with seed rates.
|
||||
Reference in new issue
Block a user