mirror of
https://github.com/we-promise/sure.git
synced 2026-04-19 03:54:08 +00:00
Add tax treatment classification for investment accounts with international support (#693)
* Add tax treatment support for accounts, investments, and cryptos * Replace hardcoded region labels with I18n translations * Add I18n support for subtype labels with fallback to hardcoded values * fixed schema --------- Co-authored-by: luckyPipewrench <luckypipewrench@proton.me>
This commit is contained in:
@@ -89,4 +89,70 @@ class AccountTest < ActiveSupport::TestCase
|
||||
assert_equal "Investments", account.short_subtype_label
|
||||
assert_equal "Investments", account.long_subtype_label
|
||||
end
|
||||
|
||||
# Tax treatment tests (TaxTreatable concern)
|
||||
|
||||
test "tax_treatment delegates to accountable for Investment" do
|
||||
investment = Investment.new(subtype: "401k")
|
||||
account = @family.accounts.create!(
|
||||
name: "Test 401k",
|
||||
balance: 1000,
|
||||
currency: "USD",
|
||||
accountable: investment
|
||||
)
|
||||
|
||||
assert_equal :tax_deferred, account.tax_treatment
|
||||
assert_equal I18n.t("accounts.tax_treatments.tax_deferred"), account.tax_treatment_label
|
||||
end
|
||||
|
||||
test "tax_treatment delegates to accountable for Crypto" do
|
||||
crypto = Crypto.new(tax_treatment: :taxable)
|
||||
account = @family.accounts.create!(
|
||||
name: "Test Crypto",
|
||||
balance: 500,
|
||||
currency: "USD",
|
||||
accountable: crypto
|
||||
)
|
||||
|
||||
assert_equal :taxable, account.tax_treatment
|
||||
assert_equal I18n.t("accounts.tax_treatments.taxable"), account.tax_treatment_label
|
||||
end
|
||||
|
||||
test "tax_treatment returns nil for non-investment accounts" do
|
||||
# Depository accounts don't have tax_treatment
|
||||
assert_nil @account.tax_treatment
|
||||
assert_nil @account.tax_treatment_label
|
||||
end
|
||||
|
||||
test "tax_advantaged? returns true for tax-advantaged accounts" do
|
||||
investment = Investment.new(subtype: "401k")
|
||||
account = @family.accounts.create!(
|
||||
name: "Test 401k",
|
||||
balance: 1000,
|
||||
currency: "USD",
|
||||
accountable: investment
|
||||
)
|
||||
|
||||
assert account.tax_advantaged?
|
||||
assert_not account.taxable?
|
||||
end
|
||||
|
||||
test "tax_advantaged? returns false for taxable accounts" do
|
||||
investment = Investment.new(subtype: "brokerage")
|
||||
account = @family.accounts.create!(
|
||||
name: "Test Brokerage",
|
||||
balance: 1000,
|
||||
currency: "USD",
|
||||
accountable: investment
|
||||
)
|
||||
|
||||
assert_not account.tax_advantaged?
|
||||
assert account.taxable?
|
||||
end
|
||||
|
||||
test "taxable? returns true for accounts without tax_treatment" do
|
||||
# Depository accounts
|
||||
assert @account.taxable?
|
||||
assert_not @account.tax_advantaged?
|
||||
end
|
||||
end
|
||||
|
||||
30
test/models/crypto_test.rb
Normal file
30
test/models/crypto_test.rb
Normal file
@@ -0,0 +1,30 @@
|
||||
require "test_helper"
|
||||
|
||||
class CryptoTest < ActiveSupport::TestCase
|
||||
test "tax_treatment defaults to taxable" do
|
||||
crypto = Crypto.new
|
||||
assert_equal "taxable", crypto.tax_treatment
|
||||
end
|
||||
|
||||
test "tax_treatment can be set to tax_deferred" do
|
||||
crypto = Crypto.new(tax_treatment: :tax_deferred)
|
||||
assert_equal "tax_deferred", crypto.tax_treatment
|
||||
end
|
||||
|
||||
test "tax_treatment can be set to tax_exempt" do
|
||||
crypto = Crypto.new(tax_treatment: :tax_exempt)
|
||||
assert_equal "tax_exempt", crypto.tax_treatment
|
||||
end
|
||||
|
||||
test "tax_treatment enum provides predicate methods" do
|
||||
crypto = Crypto.new(tax_treatment: :taxable)
|
||||
assert crypto.taxable?
|
||||
assert_not crypto.tax_deferred?
|
||||
assert_not crypto.tax_exempt?
|
||||
|
||||
crypto.tax_treatment = :tax_deferred
|
||||
assert_not crypto.taxable?
|
||||
assert crypto.tax_deferred?
|
||||
assert_not crypto.tax_exempt?
|
||||
end
|
||||
end
|
||||
139
test/models/investment_test.rb
Normal file
139
test/models/investment_test.rb
Normal file
@@ -0,0 +1,139 @@
|
||||
require "test_helper"
|
||||
|
||||
class InvestmentTest < ActiveSupport::TestCase
|
||||
# Tax treatment derivation tests
|
||||
|
||||
test "tax_treatment returns tax_deferred for US retirement accounts" do
|
||||
%w[401k 403b 457b tsp ira sep_ira simple_ira].each do |subtype|
|
||||
investment = Investment.new(subtype: subtype)
|
||||
assert_equal :tax_deferred, investment.tax_treatment, "Expected #{subtype} to be tax_deferred"
|
||||
end
|
||||
end
|
||||
|
||||
test "tax_treatment returns tax_exempt for Roth accounts" do
|
||||
%w[roth_401k roth_ira].each do |subtype|
|
||||
investment = Investment.new(subtype: subtype)
|
||||
assert_equal :tax_exempt, investment.tax_treatment, "Expected #{subtype} to be tax_exempt"
|
||||
end
|
||||
end
|
||||
|
||||
test "tax_treatment returns tax_advantaged for special accounts" do
|
||||
%w[529_plan hsa].each do |subtype|
|
||||
investment = Investment.new(subtype: subtype)
|
||||
assert_equal :tax_advantaged, investment.tax_treatment, "Expected #{subtype} to be tax_advantaged"
|
||||
end
|
||||
end
|
||||
|
||||
test "tax_treatment returns taxable for standard accounts" do
|
||||
%w[brokerage mutual_fund angel trust ugma utma other].each do |subtype|
|
||||
investment = Investment.new(subtype: subtype)
|
||||
assert_equal :taxable, investment.tax_treatment, "Expected #{subtype} to be taxable"
|
||||
end
|
||||
end
|
||||
|
||||
test "tax_treatment returns taxable for nil subtype" do
|
||||
investment = Investment.new(subtype: nil)
|
||||
assert_equal :taxable, investment.tax_treatment
|
||||
end
|
||||
|
||||
test "tax_treatment returns taxable for unknown subtype" do
|
||||
investment = Investment.new(subtype: "unknown_type")
|
||||
assert_equal :taxable, investment.tax_treatment
|
||||
end
|
||||
|
||||
# UK account types
|
||||
|
||||
test "tax_treatment returns tax_exempt for UK ISA accounts" do
|
||||
%w[isa lisa].each do |subtype|
|
||||
investment = Investment.new(subtype: subtype)
|
||||
assert_equal :tax_exempt, investment.tax_treatment, "Expected #{subtype} to be tax_exempt"
|
||||
end
|
||||
end
|
||||
|
||||
test "tax_treatment returns tax_deferred for UK pension accounts" do
|
||||
%w[sipp workplace_pension_uk].each do |subtype|
|
||||
investment = Investment.new(subtype: subtype)
|
||||
assert_equal :tax_deferred, investment.tax_treatment, "Expected #{subtype} to be tax_deferred"
|
||||
end
|
||||
end
|
||||
|
||||
# Canadian account types
|
||||
|
||||
test "tax_treatment returns tax_deferred for Canadian retirement accounts" do
|
||||
%w[rrsp lira rrif].each do |subtype|
|
||||
investment = Investment.new(subtype: subtype)
|
||||
assert_equal :tax_deferred, investment.tax_treatment, "Expected #{subtype} to be tax_deferred"
|
||||
end
|
||||
end
|
||||
|
||||
test "tax_treatment returns tax_exempt for Canadian TFSA" do
|
||||
investment = Investment.new(subtype: "tfsa")
|
||||
assert_equal :tax_exempt, investment.tax_treatment
|
||||
end
|
||||
|
||||
test "tax_treatment returns tax_advantaged for Canadian RESP" do
|
||||
investment = Investment.new(subtype: "resp")
|
||||
assert_equal :tax_advantaged, investment.tax_treatment
|
||||
end
|
||||
|
||||
# Australian account types
|
||||
|
||||
test "tax_treatment returns tax_deferred for Australian super accounts" do
|
||||
%w[super smsf].each do |subtype|
|
||||
investment = Investment.new(subtype: subtype)
|
||||
assert_equal :tax_deferred, investment.tax_treatment, "Expected #{subtype} to be tax_deferred"
|
||||
end
|
||||
end
|
||||
|
||||
# European account types
|
||||
|
||||
test "tax_treatment returns tax_deferred for European pension accounts" do
|
||||
%w[pillar_3a riester].each do |subtype|
|
||||
investment = Investment.new(subtype: subtype)
|
||||
assert_equal :tax_deferred, investment.tax_treatment, "Expected #{subtype} to be tax_deferred"
|
||||
end
|
||||
end
|
||||
|
||||
test "tax_treatment returns tax_advantaged for French PEA" do
|
||||
investment = Investment.new(subtype: "pea")
|
||||
assert_equal :tax_advantaged, investment.tax_treatment
|
||||
end
|
||||
|
||||
# Generic account types
|
||||
|
||||
test "tax_treatment returns tax_deferred for generic pension and retirement" do
|
||||
%w[pension retirement].each do |subtype|
|
||||
investment = Investment.new(subtype: subtype)
|
||||
assert_equal :tax_deferred, investment.tax_treatment, "Expected #{subtype} to be tax_deferred"
|
||||
end
|
||||
end
|
||||
|
||||
# Subtype metadata tests
|
||||
|
||||
test "all subtypes have required metadata keys" do
|
||||
Investment::SUBTYPES.each do |key, metadata|
|
||||
assert metadata.key?(:short), "Subtype #{key} missing :short key"
|
||||
assert metadata.key?(:long), "Subtype #{key} missing :long key"
|
||||
assert metadata.key?(:tax_treatment), "Subtype #{key} missing :tax_treatment key"
|
||||
assert metadata.key?(:region), "Subtype #{key} missing :region key"
|
||||
end
|
||||
end
|
||||
|
||||
test "all subtypes have valid tax_treatment values" do
|
||||
valid_treatments = %i[taxable tax_deferred tax_exempt tax_advantaged]
|
||||
|
||||
Investment::SUBTYPES.each do |key, metadata|
|
||||
assert_includes valid_treatments, metadata[:tax_treatment],
|
||||
"Subtype #{key} has invalid tax_treatment: #{metadata[:tax_treatment]}"
|
||||
end
|
||||
end
|
||||
|
||||
test "all subtypes have valid region values" do
|
||||
valid_regions = [ "us", "uk", "ca", "au", "eu", nil ]
|
||||
|
||||
Investment::SUBTYPES.each do |key, metadata|
|
||||
assert_includes valid_regions, metadata[:region],
|
||||
"Subtype #{key} has invalid region: #{metadata[:region]}"
|
||||
end
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user