Skip to content

fix(reports): say which month the Cash Flow tiles measure, and count spending - #155

Merged
KenTaniguchi-R merged 1 commit into
mainfrom
fix/145-cash-flow-tiles
Sep 2, 2026
Merged

fix(reports): say which month the Cash Flow tiles measure, and count spending#155
KenTaniguchi-R merged 1 commit into
mainfrom
fix/145-cash-flow-tiles

Conversation

@KenTaniguchi-R

Copy link
Copy Markdown
Owner

Closes #145. Rebased onto main now that #150 has landed, so this diff is only its own change.

Supersedes #151, which GitHub auto-closed when its stacked base branch was deleted on merge and would not reopen.

The tiles are month-scoped, and said nothing about it

On Sep 2, under a chip reading Last 3 months: Total Income $0.00, Spent So Far $0.00 — beside an Income vs Expense tab reporting $33,185.24 for the same chip.

There was a guard, and it fired backwards:

secondaryLabel: isCurrentMonth ? undefined : "(current month)"
const isCurrentMonth = dateFrom <= `${currentMonth}-01` && dateTo >= `${currentMonth}-01`;

isCurrentMonth is true whenever the range merely overlaps the current month, so Jun 2 – Sep 2 counted as "the current month" and the note was hidden — in exactly the case that needed it. It also only ever marked Safe to Spend, though all four tiles are month-scoped.

What this does instead

Per the decision on the issue's "either/or": label the panel, don't push the filter into the query.

September 2026 · this month only — not affected by the date filter

Safe to Spend is income received this month, less bills still due, less what has already gone out. Over a three-month range it would be asking how much is left to spend in the past — not a number. Scoping it to the month is correct; hiding that fact was the bug. The tile also gains a line saying what it means, since an unexplained negative in red is alarming on first load.

getSafeToSpend now takes an optional month (defaulting to the current one) and returns it, so the heading names the window the query actually measured rather than deriving it separately. The inverted isCurrentMonth flag is gone from page.tsx and ReportTabs.

Two query bugs found while pinning this down

Spent So Far had the sign backwards. It selected normalizedAmount > 0; negative is a charge everywhere else in Reports. So it collected the refunds and left out every real charge — the tile read $0.00 in every month, whatever the household had spent. On August's demo data it counted 0 rows where 42 charges totalling $4,383.06 were sitting.

A household with no income category crashed the tab. sql\0`was used as a WHERE term and Postgres rejects it with 42804,argument of AND must be type boolean, not type integer. Now sql`false``.

Tests

New tests/integration/safe-to-spend.test.ts (8 tests). Fixtures derive from new Date() per CLAUDE.md, since the query resolves its own window from the calendar.

  • a charge this month is spending (was $0)
  • a refund is not spending (was counted)
  • a recurring charge belongs to Recurring Bills, not Spent So Far
  • last month's charges are not this month's
  • defaults to the current calendar month; an explicit month overrides
  • the month it reports is the month it measured
  • a household with no income category reports $0 income instead of failing

7 of the 8 were red before the fix.

Verification

Seeded September rows into demo data and read the panel live: Total Income $7,700.00, Spent So Far $120.00 (the charge counted, the $25 refund not), Safe to Spend $4,828.02 = 7,700.00 − 2,751.98 − 120.00. Rows removed afterwards.

🤖 Generated with Claude Code

…spending

The four tiles above Money Flow are a whole-calendar-month view, but they
sat under a date chip reading "Last 3 months" with nothing to say otherwise.
On Sep 2 that meant Total Income $0.00 and Spent So Far $0.00 next to an
Income vs Expense tab reporting $33,185.24 for the same chip.

There was a guard for this, and it fired backwards. `isCurrentMonth` was
true whenever the selected range merely *overlapped* the current month, so
Jun 2 – Sep 2 counted as "the current month" and the "(current month)" note
was hidden — in exactly the case a reader needed it. It also only ever
marked the Safe to Spend tile, though all four are month-scoped.

Rather than push the filter into the query, the panel now names its own
window: a "September 2026 — this month only, not affected by the date
filter" heading over the group. Safe to Spend is income received this month
less bills still due and what has already gone out; over a three-month range
it would be asking how much is left to spend in the past, which is not a
number. Scoping it to the month is right — hiding that fact was the bug.
Safe to Spend also gains a line saying what it means, since an unexplained
negative in red is alarming on first read.

Two query bugs surfaced while pinning this down:

Spent So Far selected `normalizedAmount > 0`. Negative is a charge
everywhere else in Reports, so this collected the refunds and left out every
real charge: the tile read $0.00 in every month regardless of spending. On
August's demo data it counted 0 rows where 42 charges totalling $4,383.06
were sitting.

A household with no income category hit `sql`0`` as a WHERE term and took a
Postgres 42804 (`argument of AND must be type boolean, not type integer`) —
the whole tab failed, not just the tile. It is `sql`false`` now.

`getSafeToSpend` takes an optional month (defaulting to the current one) and
reports it back, so the panel labels the window the query actually measured
instead of deriving it separately.

Verified against demo data seeded into September: Total Income $7,700.00,
Spent So Far $120.00 — the charge counted, the refund not — and Safe to
Spend $4,828.02 = 7,700.00 − 2,751.98 − 120.00.

Closes #145
@KenTaniguchi-R
KenTaniguchi-R merged commit db435bf into main Sep 2, 2026
4 of 5 checks passed
@KenTaniguchi-R
KenTaniguchi-R deleted the fix/145-cash-flow-tiles branch September 2, 2026 13:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Cash Flow tiles ignore the date filter; the "(current month)" hint is suppressed exactly when needed

1 participant