From 4f3230c90491fc1b404a7c2c8811d5dba4e00341 Mon Sep 17 00:00:00 2001 From: ChakibMoMi Date: Thu, 9 Apr 2026 00:37:11 +0200 Subject: [PATCH] Generalize pension system: multi-country strategy pattern - Add JSONB pension_params column to retirement_configs - Add data JSONB column to pension_entries - Create pension calculator strategy classes (Base, DeGrv, UsSocialSecurity, UkStatePension, FrRegimeGeneral, EsSocialSecurity) - Update RetirementConfig model to delegate to calculators - Make PensionEntry.current_points optional for non-points systems - Update controller strong params (pension_params: {}) - Add Stimulus pension_system_controller for dynamic form fields - Update views with per-country field groups and conditional points columns - Expand i18n (EN, DE) and add ES, FR locale files - Update fixtures and tests for new schema Addresses review feedback from jjmata on PR #1057 --- app/controllers/retirement_controller.rb | 8 +- .../controllers/pension_system_controller.js | 32 ++++++ app/models/pension_entry.rb | 9 +- app/models/retirement_config.rb | 60 ++++++----- .../pension_calculator/base.rb | 36 +++++++ .../pension_calculator/de_grv.rb | 37 +++++++ .../pension_calculator/es_social_security.rb | 21 ++++ .../pension_calculator/fr_regime_general.rb | 21 ++++ .../pension_calculator/uk_state_pension.rb | 26 +++++ .../pension_calculator/us_social_security.rb | 20 ++++ app/views/retirement/_form_fields.html.erb | 101 ++++++++++++++++-- app/views/retirement/show.html.erb | 44 +++++--- config/locales/views/retirement/de.yml | 36 +++++-- config/locales/views/retirement/en.yml | 40 +++++-- config/locales/views/retirement/es.yml | 101 ++++++++++++++++++ config/locales/views/retirement/fr.yml | 101 ++++++++++++++++++ ...260409100000_generalize_pension_systems.rb | 32 ++++++ .../controllers/retirement_controller_test.rb | 7 +- test/fixtures/retirement_configs.yml | 22 +++- test/models/pension_entry_test.rb | 4 +- 20 files changed, 675 insertions(+), 83 deletions(-) create mode 100644 app/javascript/controllers/pension_system_controller.js create mode 100644 app/models/retirement_config/pension_calculator/base.rb create mode 100644 app/models/retirement_config/pension_calculator/de_grv.rb create mode 100644 app/models/retirement_config/pension_calculator/es_social_security.rb create mode 100644 app/models/retirement_config/pension_calculator/fr_regime_general.rb create mode 100644 app/models/retirement_config/pension_calculator/uk_state_pension.rb create mode 100644 app/models/retirement_config/pension_calculator/us_social_security.rb create mode 100644 config/locales/views/retirement/es.yml create mode 100644 config/locales/views/retirement/fr.yml create mode 100644 db/migrate/20260409100000_generalize_pension_systems.rb diff --git a/app/controllers/retirement_controller.rb b/app/controllers/retirement_controller.rb index 76912297f..856c9a9da 100644 --- a/app/controllers/retirement_controller.rb +++ b/app/controllers/retirement_controller.rb @@ -80,17 +80,15 @@ class RetirementController < ApplicationController :country, :pension_system, :birth_year, :retirement_age, :target_monthly_income, :currency, :expected_return_pct, :inflation_pct, :tax_rate_pct, :current_monthly_savings, - :contribution_start_year, :expected_annual_points, :rentenwert + pension_params: {} ) end - # Params are scoped under :pension_entry because the form uses - # form_with url: ..., scope: :pension_entry. Switching to form_with model: - # would change the nesting — update this permit list accordingly. def pension_entry_params params.require(:pension_entry).permit( :recorded_at, :current_points, :current_monthly_pension, - :projected_monthly_pension, :notes + :projected_monthly_pension, :notes, + data: {} ) end end diff --git a/app/javascript/controllers/pension_system_controller.js b/app/javascript/controllers/pension_system_controller.js new file mode 100644 index 000000000..6a27dc959 --- /dev/null +++ b/app/javascript/controllers/pension_system_controller.js @@ -0,0 +1,32 @@ +import { Controller } from "@hotwired/stimulus"; + +// Toggles visibility of country-specific pension field groups +// based on the selected pension system. +// +// Usage: +//
+//