Adds a toggle to mark accounts as excluded from all financial reports
while keeping them active and visible individually.
- Migration: add exclude_from_reports boolean column to accounts
- Model: included_in_reports scope
- BalanceSheet: filter excluded from ClassificationGroup and AccountGroup totals,
HistoricalAccountScope, AccountRow flag
- IncomeStatement: exclude via SQL fragments in Totals, FamilyStats, CategoryStats
- InvestmentStatement/Budget: chain included_in_reports scope
- ReportsController: filter in breakdown view, export queries, trades
- AccountsController: toggle_exclude_from_reports action + route
- UI: DS::Toggle in account form, eye-off indicator in sidebar, menu toggle items
- Locale: all labels in en.yml
- Tests: model scope, controller toggle, income statement/balance sheet filtering
- 5070 tests pass (0 failures, 0 regressions)
* perf(dashboard): streamline investment activity totals
* fix(dashboard): skip empty investment totals cache writes
Short-circuit empty investment account totals before cache fetch and move the new SQL query capture regression helper into test/support.
* refactor(dashboard): address review on investment totals query
- Drop defensive ArgumentError guards in InvestmentStatement::Totals#initialize.
The sole caller (totals_query) always passes correct types, and the
empty_result early-return already handles the zero-accounts case.
- Remove the redundant accounts JOIN and its family_id/status filters from the
aggregation SQL. account_ids is already scoped to the family's visible
(draft/active) investment accounts, so the join back to accounts is
unnecessary work in the query plan. Drop the now-unused family_id param.
- Add a regression assertion that the aggregate no longer joins accounts.
* feat(reports): add Period Return card to Investment Performance tab
Surfaces market-only return (absolute + %) for the selected period using
net_market_flows from the balances table, excluding contributions and
withdrawals. Appears in both the interactive report and the print view.
* docs: remove TODOS.md; fold FX fallback caveat into PR description
The single V2 item (Period Return's 1:1 FX fallback on missing rates) is
now documented under Known Limitations in the PR description, so a tracked
file in the repo root is redundant.
* fix(investment_statement): align start_value denominator scope and FX handling
Add status filter to match absolute_return, and move FX conversion into
SQL so pre-period balances are found even when an account's currency was
changed after balances were recorded.
- Refactored `persist_holdings` to separate and conditionally upsert holdings with and without cost_basis.
- Updated `avg_cost` logic to treat 0 cost_basis as unknown and return nil when cost_basis cannot be determined.
- Modified trend and investment calculation to exclude holdings with unknown cost_basis.
- Adjusted `average_cost` formatting to handle nil values in API responses and views.
- Added comprehensive tests to ensure cost_basis preservation and fallback behavior.
- Localized `unknown` label for display when cost_basis is unavailable.
Co-authored-by: Josh Waldrep <joshua.waldrep5+github@gmail.com>