Net Worth Balance Sheet#
The balance sheet module computes a family's net worth — assets minus liabilities — both as a current snapshot and as a monthly time series for charting. It lives in the BalanceSheet namespace and is distinct from Financial Reporting (income statement / Sankey) and from the per-account Balance History system (which produces the individual Balance rows consumed here).
Entry Point: BalanceSheet#
BalanceSheet is the top-level model. It exposes:
assets/liabilities— current-snapshotClassificationGroupobjects built fromAccountTotalsnet_worth—assets.total - liabilities.totalnet_worth_series(period:)— delegates toNetWorthSeriesBuilderfor the simple dashboard time series
Both BalanceSheet and its sub-builders accept an optional user: argument so shared-account families can scope results to the accounts visible to a specific user.
Account Scoping: HistoricalAccountScope#
BalanceSheet::HistoricalAccountScope defines which accounts feed the balance sheet:
family.accounts.historical.included_in_reports[.included_in_finances_for(user)]
historical— includes both active anddisabledaccounts (i.e.,VISIBLE_STATUSES + ["disabled"]), so closed accounts still appear in historical chartsincluded_in_reports— excludes accounts where the user has setexclude_from_reports: trueincluded_in_finances_for(user)— applied only when a user is passed; filters to accounts shared with or owned by that user
Monthly Chart: NetWorthBreakdownSeriesBuilder#
BalanceSheet::NetWorthBreakdownSeriesBuilder is the primary chart-data builder. It produces a monthly series (INTERVAL = "1 month", ) with per-account-group breakdown for chart tooltips.
breakdown_series(period:) pipeline :
- Calls
Balance::ChartSeriesBuilder#balance_seriesfor all historical accounts combined — this gives the aggregate net worth line. - Calls
Balance::ChartSeriesBuilder#balance_seriesonce per(classification, accountable_type)group — one series per account type (e.g., Depository assets, Loan liabilities). - Groups are sorted: assets before liabilities, then in canonical
Accountable::TYPESorder . - Groups with all-zero values are dropped .
- Each monthly point is assembled into a
breakdown_valuehash containing:value— aggregate net worth at that datetrend— month-over-month change (current vs. previous point's value)assets/liabilities— classification subtotalsgroups— per-account-type name, color, classification, and value
Disabled accounts are handled via account_active_until_dates: a disabled account's Balance data is capped at disabled_at - 1 day so it doesn't contribute a stale zero balance to later months .
Caching: results are memoized in Rails cache keyed on (family, user, period, shares_version) with invalidate_on_data_updates: true .
Underlying SQL: Balance::ChartSeriesBuilder#
NetWorthBreakdownSeriesBuilder delegates all SQL to Balance::ChartSeriesBuilder , passing:
account_ids— the filtered account setcurrency— family currency for FX conversionperiod/interval— date range and monthly bucketingfavorable_direction—"up"for assets,"down"for liabilities (controls trend coloring)
ChartSeriesBuilder executes a lateral-join SQL query against the balances table with dual-direction FX conversion , reading end_balance for each monthly sample date. It reads from pre-computed Balance rows; it does not recalculate balances on the fly.
Controller Integration#
ReportsController constructs the builder and feeds the result into the net_worth report payload:
breakdown_series = BalanceSheet::NetWorthBreakdownSeriesBuilder
.new(Current.family, user: Current.user)
.breakdown_series(period: @period)
The payload also includes current-snapshot asset_groups and liability_groups (from BalanceSheet#assets/liabilities), and the overall trend.
Key Source Files#
| File | Role |
|---|---|
app/models/balance_sheet.rb | Top-level model; current-snapshot net worth and series delegation |
app/models/balance_sheet/net_worth_breakdown_series_builder.rb | Monthly chart series with per-type breakdown |
app/models/balance_sheet/historical_account_scope.rb | Account filtering logic for balance sheet queries |
app/models/balance/chart_series_builder.rb | SQL query engine; reads balances table with dual-direction FX LATERAL join |
app/controllers/reports_controller.rb | Assembles net worth report payload |
See also:
- Account Type Architecture — asset vs. liability classification,
Accountable::TYPESorder - Balance History System — how
Balancerows are produced (the upstream data source) - Multi-Currency Exchange Rates — FX handling in
ChartSeriesBuilder