Files
sure/app/javascript
Juan José Mata 73abe473b7 Add cumulative spending chart dashboard widget (#3404)
* Add cumulative spending chart dashboard widget

New dashboard section showing the selected month's running spending total
against the previous month's full curve on a shared day-of-month axis,
inspired by Copilot Money's Spending card.

- IncomeStatement#daily_expense_series: per-day expense totals in family
  currency, same scoping as the other income statement totals (visible,
  posted, budget-included transactions; report-included accounts; daily
  exchange-rate conversion)
- PagesController: spending_trend section with month picker (clamped like
  money_flow), cumulative series builder, delta vs. previous month
- spending-chart Stimulus controller (D3): previous month in gray, current
  month in green with a today marker, gridlines with compact currency
  labels, shared tooltip
- i18n (en) and model/controller tests

* Address PR review: locale-safe axis labels, currency/rate-aware cache key

- X-axis tick labels are now rendered server-side (I18n.l), one per axis
  day: when the previous month is longer than the selected one it owns the
  tail labels, so a tick can no longer roll past the selected month's end
  (e.g. day 31 of a February view showed "Mar 3"), and labels follow the
  app locale instead of D3's default English time-format locale.
- IncomeStatement#daily_expense_series cache key now includes the family
  currency and the latest exchange-rate timestamp, since ExchangeRate::
  Importer's upsert_all and currency changes leave entries/accounts
  untouched and previously served stale chart data.

* Fix spending trend tests: empty-state month in axis test, dropped start_date key

- Axis-label test picked a month pair with no transactions, so the widget
  rendered its empty state and there was no chart payload to parse; seed
  spending in both months under test.
- The clamp test still asserted on the payload's removed start_date key;
  assert the clamped month via the current series' first point date instead.
2026-09-06 02:18:22 +02:00
..
2025-05-20 13:31:05 -05:00