mirror of
https://github.com/we-promise/sure.git
synced 2026-06-04 18:29:02 +00:00
* fix(family): include HSA depository accounts in tax-advantaged exclusion `Family#tax_advantaged_account_ids` is the ID set the budget engine uses to exclude tax-advantaged account activity from income / expense / cashflow totals. PR #724 originated this method and explicitly listed HSA in scope ("401k, IRA, HSA, Roth IRA, etc."), but the implementation only joined `investments` and `cryptos`. `Depository::SUBTYPES["hsa"]` already exists and Plaid routes `depository.hsa` accounts to `Depository` (not `Investment`) via `PlaidAccount::TypeMappable`, so HSA cash accounts were silently absent from the filter and HSA contributions/withdrawals showed up in household expense totals. - Add `Depository::TAX_ADVANTAGED_SUBTYPES = %w[hsa]` + a `tax_treatment` instance method (mirrors `Investment#tax_treatment`). `TaxTreatable#tax_advantaged?` picks it up via the existing `respond_to?` check, so `Account#tax_advantaged?` now flips to true for HSA depositories without touching the concern. - Extract `Family#tax_advantaged_depository_account_ids` (private) that joins `depositories` and filters by `Depository::TAX_ADVANTAGED_SUBTYPES`, mirroring the existing `investment_ids` / `crypto_ids` extraction style. Append it to the union in `tax_advantaged_account_ids`. Behavior change is scoped: HSA depositories now exit the budget engine via the same path as 401k / IRA / Roth IRA. Non-HSA depositories continue to report `tax_treatment: :taxable` (was `nil`), so `Account#taxable?` returns true for them via the existing `== :taxable` clause — no expense-total change for Checking / Savings / CD / Money Market. Tests: - `test/models/account_test.rb` — rewrite "tax_treatment returns nil for non-investment accounts" (was implicitly testing the bug) into two tests: one asserting `:taxable` for non-HSA depositories and a new sibling asserting `nil` for accountables that genuinely lack `tax_treatment` (CreditCard). Add an HSA-depository test asserting `tax_advantaged?`. - `test/models/income_statement_test.rb` — new test asserting an HSA depository is included in `tax_advantaged_account_ids` and a `savings` depository is not. No schema migration, no controller change, no provider integration change. * [200~fix(family): return nil for non-HSA depository tax_treatment
50 lines
1.8 KiB
Ruby
50 lines
1.8 KiB
Ruby
class Depository < ApplicationRecord
|
|
include Accountable
|
|
|
|
DEFAULT_SUBTYPE = "checking"
|
|
|
|
SUBTYPES = {
|
|
"checking" => { short: "Checking", long: "Checking" },
|
|
"savings" => { short: "Savings", long: "Savings" },
|
|
"hsa" => { short: "HSA", long: "Health Savings Account" },
|
|
"cd" => { short: "CD", long: "Certificate of Deposit" },
|
|
"money_market" => { short: "MM", long: "Money Market" }
|
|
}.freeze
|
|
|
|
# Depository subtypes that carry tax-advantaged treatment in the budget /
|
|
# cashflow / income-statement filters (`Family#tax_advantaged_account_ids`,
|
|
# `TaxTreatable#tax_advantaged?`). HSA cash sits here because Plaid routes
|
|
# `depository.hsa` to `Depository` (not `Investment`) via
|
|
# `PlaidAccount::TypeMappable`, so a real-world Plaid-linked HSA cash account
|
|
# was previously invisible to the tax-advantaged filter PR #724 introduced.
|
|
TAX_ADVANTAGED_SUBTYPES = %w[hsa].freeze
|
|
|
|
# `TaxTreatable` (the `Account` concern) reads this via `respond_to?` so
|
|
# adding it here transparently flips `Account#tax_advantaged?` for HSA
|
|
# depositories without touching the concern itself.
|
|
#
|
|
# Returns `nil` (not `:taxable`) for ordinary depository subtypes. `nil`
|
|
# already reads as taxable everywhere it matters: `TaxTreatable#taxable?`
|
|
# treats `nil` as taxable and `#tax_advantaged?` excludes it. Returning
|
|
# `nil` also keeps `tax_treatment.present?` false so the header tax badge
|
|
# (`app/views/accounts/show/_header.html.erb`) stays hidden on checking,
|
|
# savings, CD, and money-market accounts that never displayed it before.
|
|
def tax_treatment
|
|
:tax_advantaged if TAX_ADVANTAGED_SUBTYPES.include?(subtype)
|
|
end
|
|
|
|
class << self
|
|
def color
|
|
"#875BF7"
|
|
end
|
|
|
|
def classification
|
|
"asset"
|
|
end
|
|
|
|
def icon
|
|
"landmark"
|
|
end
|
|
end
|
|
end
|