fix(retirement): allow null target_amount for retirement plans

for_owner bootstraps a Goal::Retirement before any target exists, but
goals.target_amount was NOT NULL at the DB level — the target_amount_required?
hook only dropped the AR validation. Creating a plan for a user with no
existing record (the demo user, caught in a live browser smoke) raised
PG::NotNullViolation. Tests missed it because for_owner(family_admin)
finds the retirement_bob fixture and never inserts.

Relaxes the column to nullable and re-asserts the guarantee for savings
goals via a type-aware check (type <> 'Goal' OR target_amount IS NOT NULL),
so base Goal rows still require a target at the DB level. Adds tests that
exercise the create path (a user with no fixture plan).
This commit is contained in:
Guillem Arias
2026-05-29 10:53:00 +02:00
parent 26bb333c34
commit 47f441afbc
3 changed files with 40 additions and 2 deletions

View File

@@ -74,6 +74,26 @@ class Goal::RetirementTest < ActiveSupport::TestCase
assert retirement.valid?, retirement.errors.full_messages.to_sentence
end
test "for_owner bootstraps a valid plan without a target_amount" do
# family_member has no retirement fixture, so this exercises the
# create path (family_admin would just find retirement_bob).
member = users(:family_member)
plan = Goal::Retirement.for_owner(member)
assert plan.persisted?
assert_nil plan.target_amount
assert_equal member.id, plan.user_id
assert_equal member.family_id, plan.family_id
end
test "for_owner is idempotent (one plan per user)" do
member = users(:family_member)
first = Goal::Retirement.for_owner(member)
second = Goal::Retirement.for_owner(member)
assert_equal first.id, second.id
end
test "has pension sources, statements, adjustments, and bucket accounts" do
plan = goals(:retirement_bob)
assert_includes plan.pension_sources, pension_sources(:de_grv_bob)