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.
29 lines
1.1 KiB
Ruby
29 lines
1.1 KiB
Ruby
require "test_helper"
|
|
|
|
class RetirementBucketEntryTest < ActiveSupport::TestCase
|
|
setup do
|
|
@entry = retirement_bucket_entries(:bob_investment)
|
|
@goal = goals(:retirement_bob)
|
|
end
|
|
|
|
test "fixture is valid" do
|
|
assert @entry.valid?, @entry.errors.full_messages.to_sentence
|
|
end
|
|
|
|
test "account is unique within a plan" do
|
|
dup = RetirementBucketEntry.new(goal_retirement: @goal, account: @entry.account)
|
|
assert_not dup.valid?
|
|
assert_includes dup.errors.attribute_names, :account_id
|
|
end
|
|
|
|
test "account must belong to the plan's family" do
|
|
other_family = Family.create!(name: "Other", currency: "USD", locale: "en", country: "US", timezone: "UTC")
|
|
foreign = Account.create!(family: other_family, accountable: Depository.new, name: "Foreign", currency: "USD", balance: 1)
|
|
|
|
entry = RetirementBucketEntry.new(goal_retirement: @goal, account: foreign)
|
|
assert_not entry.valid?
|
|
assert_includes entry.errors[:account],
|
|
I18n.t("activerecord.errors.models.retirement_bucket_entry.attributes.account.must_belong_to_family")
|
|
end
|
|
end
|