Files
sure/app/models/investment.rb
Geoffrey f3ed07f96b Updated list of Canadian registered accounts (#1265)
* Added FHSA, RDSP, and DPSP to app/models/investment.rb

* Update investment.rb

Signed-off-by: Geoffrey <79559478+CYBRXT@users.noreply.github.com>

* Fixed RDSP tax treatment (tax-deferred -> tax-advantaged)

Signed-off-by: Geoffrey <79559478+CYBRXT@users.noreply.github.com>

* Added non-registered account to the list (taxable)

Signed-off-by: Geoffrey <79559478+CYBRXT@users.noreply.github.com>

* Reordering

Signed-off-by: Geoffrey <79559478+CYBRXT@users.noreply.github.com>

---------

Signed-off-by: Geoffrey <79559478+CYBRXT@users.noreply.github.com>
Co-authored-by: Geoffrey <geoffrey@github.worker>
2026-03-24 09:28:38 +01:00

114 lines
6.3 KiB
Ruby

class Investment < ApplicationRecord
include Accountable
# Tax treatment categories:
# - taxable: Gains taxed when realized
# - tax_deferred: Taxes deferred until withdrawal
# - tax_exempt: Qualified gains are tax-free
# - tax_advantaged: Special tax benefits with conditions
SUBTYPES = {
# === United States ===
"brokerage" => { short: "Brokerage", long: "Brokerage", region: "us", tax_treatment: :taxable },
"401k" => { short: "401(k)", long: "401(k)", region: "us", tax_treatment: :tax_deferred },
"roth_401k" => { short: "Roth 401(k)", long: "Roth 401(k)", region: "us", tax_treatment: :tax_exempt },
"403b" => { short: "403(b)", long: "403(b)", region: "us", tax_treatment: :tax_deferred },
"457b" => { short: "457(b)", long: "457(b)", region: "us", tax_treatment: :tax_deferred },
"tsp" => { short: "TSP", long: "Thrift Savings Plan", region: "us", tax_treatment: :tax_deferred },
"ira" => { short: "IRA", long: "Traditional IRA", region: "us", tax_treatment: :tax_deferred },
"roth_ira" => { short: "Roth IRA", long: "Roth IRA", region: "us", tax_treatment: :tax_exempt },
"sep_ira" => { short: "SEP IRA", long: "SEP IRA", region: "us", tax_treatment: :tax_deferred },
"simple_ira" => { short: "SIMPLE IRA", long: "SIMPLE IRA", region: "us", tax_treatment: :tax_deferred },
"529_plan" => { short: "529 Plan", long: "529 Education Savings Plan", region: "us", tax_treatment: :tax_advantaged },
"hsa" => { short: "HSA", long: "Health Savings Account", region: "us", tax_treatment: :tax_advantaged },
"ugma" => { short: "UGMA", long: "UGMA Custodial Account", region: "us", tax_treatment: :taxable },
"utma" => { short: "UTMA", long: "UTMA Custodial Account", region: "us", tax_treatment: :taxable },
# === United Kingdom ===
"isa" => { short: "ISA", long: "Individual Savings Account", region: "uk", tax_treatment: :tax_exempt },
"lisa" => { short: "LISA", long: "Lifetime ISA", region: "uk", tax_treatment: :tax_exempt },
"sipp" => { short: "SIPP", long: "Self-Invested Personal Pension", region: "uk", tax_treatment: :tax_deferred },
"workplace_pension_uk" => { short: "Pension", long: "Workplace Pension", region: "uk", tax_treatment: :tax_deferred },
# === Canada ===
"tfsa" => { short: "TFSA", long: "Tax-Free Savings Account", region: "ca", tax_treatment: :tax_exempt },
"rrsp" => { short: "RRSP", long: "Registered Retirement Savings Plan", region: "ca", tax_treatment: :tax_deferred },
"non-registered" => { short: "Non-Registered", long: "Non-Registered Investment Account", region: "ca", tax_treatment: :taxable },
"fhsa" => { short: "FHSA", long: "First Home Savings Account", region: "ca", tax_treatment: :tax_exempt },
"rdsp" => { short: "RDSP", long: "Registered Disability Savings Plan", region: "ca", tax_treatment: :tax_advantaged },
"resp" => { short: "RESP", long: "Registered Education Savings Plan", region: "ca", tax_treatment: :tax_advantaged },
"dpsp" => { short: "DPSP", long: "Deferred Profit Sharing Plan", region: "ca", tax_treatment: :tax_deferred },
"prpp" => { short: "PRPP", long: "Pooled Registered Pension Plan", region: "ca", tax_treatment: :tax_deferred },
"lira" => { short: "LIRA", long: "Locked-In Retirement Account", region: "ca", tax_treatment: :tax_deferred },
"rrif" => { short: "RRIF", long: "Registered Retirement Income Fund", region: "ca", tax_treatment: :tax_deferred },
"lif" => { short: "LIF", long: "Life Income Fund", region: "ca", tax_treatment: :tax_deferred },
"lrif" => { short: "LRIF", long: "Locked-In Retirement Income Fund", region: "ca", tax_treatment: :tax_deferred },
"prif" => { short: "PRIF", long: "Prescribed Registered Retirement Income Fund", region: "ca", tax_treatment: :tax_deferred },
"rlif" => { short: "RLIF", long: "Restricted Life Income Fund", region: "ca", tax_treatment: :tax_deferred },
# === Australia ===
"super" => { short: "Super", long: "Superannuation", region: "au", tax_treatment: :tax_deferred },
"smsf" => { short: "SMSF", long: "Self-Managed Super Fund", region: "au", tax_treatment: :tax_deferred },
# === Europe ===
"pea" => { short: "PEA", long: "Plan d'Épargne en Actions", region: "eu", tax_treatment: :tax_advantaged },
"pillar_3a" => { short: "Pillar 3a", long: "Private Pension (Pillar 3a)", region: "eu", tax_treatment: :tax_deferred },
"riester" => { short: "Riester", long: "Riester-Rente", region: "eu", tax_treatment: :tax_deferred },
# === Generic (available everywhere) ===
"pension" => { short: "Pension", long: "Pension", region: nil, tax_treatment: :tax_deferred },
"retirement" => { short: "Retirement", long: "Retirement Account", region: nil, tax_treatment: :tax_deferred },
"mutual_fund" => { short: "Mutual Fund", long: "Mutual Fund", region: nil, tax_treatment: :taxable },
"angel" => { short: "Angel", long: "Angel Investment", region: nil, tax_treatment: :taxable },
"trust" => { short: "Trust", long: "Trust", region: nil, tax_treatment: :taxable },
"other" => { short: "Other", long: "Other Investment", region: nil, tax_treatment: :taxable }
}.freeze
def tax_treatment
SUBTYPES.dig(subtype, :tax_treatment) || :taxable
end
class << self
def color
"#1570EF"
end
def classification
"asset"
end
def icon
"chart-line"
end
def region_label_for(region)
I18n.t("accounts.subtype_regions.#{region || 'generic'}")
end
# Maps currency codes to regions for prioritizing user's likely region
CURRENCY_REGION_MAP = {
"USD" => "us",
"GBP" => "uk",
"CAD" => "ca",
"AUD" => "au",
"EUR" => "eu",
"CHF" => "eu"
}.freeze
# Returns subtypes grouped by region for use with grouped_options_for_select
# Optionally accepts currency to prioritize user's region first
def subtypes_grouped_for_select(currency: nil)
user_region = CURRENCY_REGION_MAP[currency]
grouped = SUBTYPES.group_by { |_, v| v[:region] }
# Build region order: user's region first (if known), then Generic, then others
other_regions = %w[us uk ca au eu] - [ user_region ].compact
region_order = [ user_region, nil, *other_regions ].compact.uniq
region_order.filter_map do |region|
next unless grouped[region]
[ region_label_for(region), grouped[region].map { |k, v| [ v[:long], k ] } ]
end
end
end
end