mirror of
https://github.com/we-promise/sure.git
synced 2026-05-30 07:49:01 +00:00
Data plane for Retirement v2 (no FIRE math yet — that is PR3). Five migrations + four AR models, wired to Goal::Retirement. Models: - PensionSource — state/workplace/other source with country, pension system, tax treatment, payout shape (string-backed + inclusion validations rather than PG enums, so v2 can add countries without ALTER TYPE). monetize :amount; end_age required for fixed-term. - Goal::RetirementStatement — append-only audit journal. default_scope excludes soft-deleted rows; soft_replace! does soft-delete + insert; points_delta drives the "—"/signed Δ column; monetize against projected_currency. - Goal::RetirementAdjustment — signed today's-money deltas to the spending target, ordered, applicable_at?(age). - RetirementBucketEntry — account selection join, unique per plan, same-family guard. Goal::Retirement gains the four associations + bucket_accounts and an ADJUSTMENTS_LIMIT (10) cap. retirement_params jsonb added to goals for PR3 plan settings. Namespaced fixture classes mapped via set_fixture_class so the goal_retirement association resolves. Minimal fixtures + model tests (112 runs green, incl. goal/family/controller regression sweep). No new gems.
38 lines
1.2 KiB
Ruby
38 lines
1.2 KiB
Ruby
require "test_helper"
|
|
|
|
class Goal::RetirementStatementTest < ActiveSupport::TestCase
|
|
setup do
|
|
@statement = goal_retirement_statements(:grv_2025)
|
|
end
|
|
|
|
test "fixture is valid" do
|
|
assert @statement.valid?, @statement.errors.full_messages.to_sentence
|
|
end
|
|
|
|
test "default scope excludes soft-deleted rows" do
|
|
@statement.update_column(:deleted, true)
|
|
assert_not Goal::RetirementStatement.exists?(@statement.id)
|
|
assert Goal::RetirementStatement.unscoped.exists?(@statement.id)
|
|
end
|
|
|
|
test "points_delta is nil for earliest, signed for later" do
|
|
assert_nil goal_retirement_statements(:grv_2023).points_delta
|
|
assert_in_delta 2.50, goal_retirement_statements(:grv_2025).points_delta, 0.001
|
|
end
|
|
|
|
test "soft_replace! soft-deletes self and inserts replacement" do
|
|
new_stmt = nil
|
|
assert_difference -> { Goal::RetirementStatement.unscoped.count }, 1 do
|
|
new_stmt = @statement.soft_replace!(projected_monthly_amount: 1600)
|
|
end
|
|
|
|
assert @statement.reload.deleted
|
|
assert_equal 1600, new_stmt.projected_monthly_amount.to_i
|
|
assert_not new_stmt.deleted
|
|
end
|
|
|
|
test "money uses projected_currency" do
|
|
assert_equal Money.new(1510, "EUR"), @statement.projected_monthly_amount_money
|
|
end
|
|
end
|