mirror of
https://github.com/we-promise/sure.git
synced 2026-05-30 07:49:01 +00:00
Functional data-entry surface on the (still preview) /retirement page. The polished combined-page UI is PR4; this ships plain forms + lists so a preview user can populate a plan end to end. - RetirementScoped concern: tier-1 preview gate + tier-2 family killswitch + per-owner plan bootstrap (Goal::Retirement.for_owner find-or-creates, so children always have a parent). RetirementController now uses it. - Nested controllers under Retirement::: PensionSources (full CRUD), Statements (new/create + soft-delete destroy — append-only audit), Adjustments (full CRUD), Buckets (replace-all account selection, same-family filtered). All scoped to the current user's own plan, so cross-user access is impossible by construction. - Routes nested under `resource :retirement` via `scope module:`. - Views: show page rewritten into management sections (sources, adjustments, bucket checkboxes, statement journal) + plain styled_form_with forms. Money carries privacy-sensitive. - Goal gains a target_amount_required? hook (true); Goal::Retirement overrides it false — the forecast owns the target (PR3), so a plan can exist before any target is set. - EN locale for the new surface. 111 controller+model tests green. Note: delete uses Turbo confirm for now; PR4 swaps in the skinned DS::Dialog per the design.
61 lines
2.0 KiB
Ruby
61 lines
2.0 KiB
Ruby
require "test_helper"
|
|
|
|
class Retirement::PensionSourcesControllerTest < ActionDispatch::IntegrationTest
|
|
setup do
|
|
@user = users(:family_admin)
|
|
@user.update!(preferences: (@user.preferences || {}).merge("preview_features_enabled" => true))
|
|
@user.family.update!(retirement_disabled: false)
|
|
sign_in @user
|
|
ensure_tailwind_build
|
|
@plan = Goal::Retirement.for_owner(@user)
|
|
end
|
|
|
|
def valid_params
|
|
{ name: "State", kind: "state", country: "DE", pension_system: "de_grv",
|
|
tax_treatment: "de_renten", payout_shape: "monthly_for_life",
|
|
start_age: 67, amount: 1500, currency: "EUR" }
|
|
end
|
|
|
|
test "redirects when preview features disabled" do
|
|
@user.update!(preferences: (@user.preferences || {}).merge("preview_features_enabled" => false))
|
|
get new_retirement_pension_source_url
|
|
assert_redirected_to root_path
|
|
end
|
|
|
|
test "404 when family retirement disabled" do
|
|
@user.family.update!(retirement_disabled: true)
|
|
get new_retirement_pension_source_url
|
|
assert_response :not_found
|
|
end
|
|
|
|
test "new renders the form" do
|
|
get new_retirement_pension_source_url
|
|
assert_response :success
|
|
end
|
|
|
|
test "edit renders the form" do
|
|
get edit_retirement_pension_source_url(pension_sources(:de_grv_bob))
|
|
assert_response :success
|
|
end
|
|
|
|
test "create adds a source to the owner's plan" do
|
|
assert_difference -> { @plan.pension_sources.count }, 1 do
|
|
post retirement_pension_sources_url, params: { pension_source: valid_params }
|
|
end
|
|
assert_redirected_to retirement_path
|
|
end
|
|
|
|
test "invalid create re-renders unprocessable" do
|
|
post retirement_pension_sources_url, params: { pension_source: valid_params.merge(name: "") }
|
|
assert_response :unprocessable_entity
|
|
end
|
|
|
|
test "destroy removes a source" do
|
|
source = @plan.pension_sources.create!(valid_params)
|
|
assert_difference -> { @plan.pension_sources.count }, -1 do
|
|
delete retirement_pension_source_url(source)
|
|
end
|
|
assert_redirected_to retirement_path
|
|
end
|
|
end
|