mirror of
https://github.com/we-promise/sure.git
synced 2026-05-29 23:39:03 +00:00
Polish retirement feature: Custom calculator, grouped select, auto-detect, UK progress
- Extract Custom pension calculator class (was mapped to Base, which raises NotImplementedError — now explicit and safe) - Remove if/custom short-circuit from estimated_monthly_pension — all systems go through pension_calculator uniformly - Add PENSION_SYSTEM_GROUPS constant for grouped UI select and COUNTRY_TO_PENSION_SYSTEM + suggest_pension_system(country) for auto-detection - Setup action pre-selects pension system and country from family profile - Form dropdown now uses grouped_options_for_select grouped by region - Show page displays UK State Pension qualifying-years progress bar for uk_sp - Add pension_system_groups i18n keys in EN/DE/ES/FR - Add UK progress i18n keys (uk_progress_title, uk_qualifying_years, uk_years_remaining) in all four locales - Add 5 calculator unit tests (DE, US, UK, FR, ES) and update schema.rb to reflect GeneralizePensionSystems migration (pension_params JSONB, data JSONB, current_points nullable, old DE-specific columns removed) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -9,7 +9,9 @@ class RetirementController < ApplicationController
|
||||
def setup
|
||||
@retirement_config = Current.family.retirement_config || Current.family.build_retirement_config(
|
||||
birth_year: 1990,
|
||||
currency: Current.family.currency
|
||||
currency: Current.family.currency,
|
||||
country: Current.family.country,
|
||||
pension_system: RetirementConfig.suggest_pension_system(Current.family.country)
|
||||
)
|
||||
end
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class RetirementConfig < ApplicationRecord
|
||||
PENSION_SYSTEMS = {
|
||||
"custom" => { calculator: "RetirementConfig::PensionCalculator::Base" },
|
||||
"custom" => { calculator: "RetirementConfig::PensionCalculator::Custom" },
|
||||
"de_grv" => { calculator: "RetirementConfig::PensionCalculator::DeGrv" },
|
||||
"us_ss" => { calculator: "RetirementConfig::PensionCalculator::UsSocialSecurity" },
|
||||
"uk_sp" => { calculator: "RetirementConfig::PensionCalculator::UkStatePension" },
|
||||
@@ -8,8 +8,27 @@ class RetirementConfig < ApplicationRecord
|
||||
"es_ss" => { calculator: "RetirementConfig::PensionCalculator::EsSocialSecurity" }
|
||||
}.freeze
|
||||
|
||||
PENSION_SYSTEM_GROUPS = {
|
||||
"europe" => %w[de_grv fr_regime es_ss],
|
||||
"united_kingdom" => %w[uk_sp],
|
||||
"north_america" => %w[us_ss],
|
||||
"other" => %w[custom]
|
||||
}.freeze
|
||||
|
||||
COUNTRY_TO_PENSION_SYSTEM = {
|
||||
"DE" => "de_grv", "AT" => "de_grv",
|
||||
"US" => "us_ss", "CA" => "us_ss",
|
||||
"GB" => "uk_sp",
|
||||
"FR" => "fr_regime",
|
||||
"ES" => "es_ss"
|
||||
}.freeze
|
||||
|
||||
SAFE_WITHDRAWAL_RATE = 0.04
|
||||
|
||||
def self.suggest_pension_system(country)
|
||||
COUNTRY_TO_PENSION_SYSTEM.fetch(country.to_s.upcase, "custom")
|
||||
end
|
||||
|
||||
belongs_to :family
|
||||
has_many :pension_entries, dependent: :destroy
|
||||
|
||||
@@ -36,12 +55,7 @@ class RetirementConfig < ApplicationRecord
|
||||
current_age >= retirement_age
|
||||
end
|
||||
|
||||
# Delegates pension estimation to the active calculator
|
||||
def estimated_monthly_pension
|
||||
if pension_system == "custom"
|
||||
return latest_pension_entry&.projected_monthly_pension || 0
|
||||
end
|
||||
|
||||
pension_calculator.estimated_monthly_pension
|
||||
end
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
class RetirementConfig
|
||||
module PensionCalculator
|
||||
class Custom < Base
|
||||
def estimated_monthly_pension
|
||||
latest_entry&.projected_monthly_pension || 0
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -45,7 +45,15 @@
|
||||
<div>
|
||||
<label for="retirement_config_pension_system" class="block text-sm font-medium text-secondary mb-1"><%= t(".pension_system") %></label>
|
||||
<%= f.select :pension_system,
|
||||
RetirementConfig::PENSION_SYSTEMS.keys.map { |k| [t("retirement.pension_systems.#{k}", default: k.humanize), k] },
|
||||
grouped_options_for_select(
|
||||
RetirementConfig::PENSION_SYSTEM_GROUPS.map do |group_key, systems|
|
||||
[
|
||||
t("retirement.pension_system_groups.#{group_key}"),
|
||||
systems.map { |k| [ t("retirement.pension_systems.#{k}", default: k.humanize), k ] }
|
||||
]
|
||||
end,
|
||||
f.object&.pension_system
|
||||
),
|
||||
{},
|
||||
class: "form-select w-full rounded-lg border border-secondary bg-container text-sm text-primary px-3 py-2",
|
||||
data: { pension_system_target: "select", action: "change->pension-system#toggle" } %>
|
||||
|
||||
@@ -135,6 +135,27 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%# System-specific progress (UK State Pension) %>
|
||||
<% if @retirement_config.pension_system == "uk_sp" %>
|
||||
<% qualifying_years = @retirement_config.pension_param("qualifying_years").to_i %>
|
||||
<% target_years = 35 %>
|
||||
<div class="bg-container shadow-border-xs rounded-lg p-6 mb-8">
|
||||
<h2 class="text-lg font-medium text-primary mb-4"><%= t(".uk_progress_title") %></h2>
|
||||
<div class="space-y-3">
|
||||
<div class="flex justify-between text-sm">
|
||||
<span class="text-secondary"><%= t(".uk_qualifying_years") %></span>
|
||||
<span class="text-primary font-medium"><%= qualifying_years %> / <%= target_years %></span>
|
||||
</div>
|
||||
<div class="w-full bg-surface-inset rounded-full h-3">
|
||||
<div class="bg-primary h-3 rounded-full transition-all" style="width: <%= [ (qualifying_years.to_f / target_years * 100), 100 ].min.round %>%"></div>
|
||||
</div>
|
||||
<p class="text-xs text-secondary">
|
||||
<%= t(".uk_years_remaining", count: [ target_years - qualifying_years, 0 ].max) %>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
<%# Pension History %>
|
||||
<div class="bg-container shadow-border-xs rounded-lg p-6">
|
||||
<h2 class="text-lg font-medium text-primary mb-4"><%= t(".pension_history") %></h2>
|
||||
|
||||
@@ -41,6 +41,12 @@ de:
|
||||
no_entries: Noch keine Renteneinträge vorhanden
|
||||
no_entries_hint: Füge Einträge aus deiner Renteninformation hinzu, um deinen Rentenfortschritt zu verfolgen
|
||||
setup_required: Bitte richte zuerst die Ruhestandsplanung ein
|
||||
uk_progress_title: Rentenanspruch Fortschritt
|
||||
uk_qualifying_years: Anspruchsjahre (NI)
|
||||
uk_years_remaining:
|
||||
zero: Alle Anspruchsjahre erreicht — volle State Pension!
|
||||
one: "Noch %{count} Jahr für die volle State Pension"
|
||||
other: "Noch %{count} Jahre für die volle State Pension"
|
||||
form_fields: &retirement_form_fields_de
|
||||
personal_section: Persönliche Angaben
|
||||
birth_year: Geburtsjahr
|
||||
@@ -98,6 +104,11 @@ de:
|
||||
pension_entry_added: Renteneintrag erfolgreich hinzugefügt
|
||||
destroy_pension_entry:
|
||||
pension_entry_removed: Renteneintrag entfernt
|
||||
pension_system_groups:
|
||||
europe: Europa
|
||||
united_kingdom: Vereinigtes Königreich
|
||||
north_america: Nordamerika
|
||||
other: Sonstiges
|
||||
pension_systems:
|
||||
de_grv: Deutsche Gesetzliche Rentenversicherung (GRV)
|
||||
us_ss: US-Sozialversicherung
|
||||
|
||||
@@ -41,6 +41,12 @@ en:
|
||||
no_entries: No pension entries yet
|
||||
no_entries_hint: Add entries from your pension statements to track your progress
|
||||
setup_required: Please set up retirement planning first
|
||||
uk_progress_title: State Pension Progress
|
||||
uk_qualifying_years: Qualifying Years (NI)
|
||||
uk_years_remaining:
|
||||
zero: All qualifying years reached — full State Pension!
|
||||
one: "%{count} more year needed for full State Pension"
|
||||
other: "%{count} more years needed for full State Pension"
|
||||
form_fields: &retirement_form_fields_en
|
||||
personal_section: Personal Information
|
||||
birth_year: Birth Year
|
||||
@@ -98,6 +104,11 @@ en:
|
||||
pension_entry_added: Pension entry added successfully
|
||||
destroy_pension_entry:
|
||||
pension_entry_removed: Pension entry removed
|
||||
pension_system_groups:
|
||||
europe: Europe
|
||||
united_kingdom: United Kingdom
|
||||
north_america: North America
|
||||
other: Other
|
||||
pension_systems:
|
||||
de_grv: German Statutory Pension (GRV)
|
||||
us_ss: US Social Security
|
||||
|
||||
@@ -41,6 +41,12 @@ es:
|
||||
no_entries: Aún no hay entradas de pensión
|
||||
no_entries_hint: Añade entradas de tus informes de pensión para seguir tu progreso
|
||||
setup_required: Por favor configura primero la planificación de jubilación
|
||||
uk_progress_title: Progreso de Pensión Estatal
|
||||
uk_qualifying_years: Años Calificados (NI)
|
||||
uk_years_remaining:
|
||||
zero: "¡Todos los años calificados alcanzados — State Pension completa!"
|
||||
one: "%{count} año más para la State Pension completa"
|
||||
other: "%{count} años más para la State Pension completa"
|
||||
form_fields: &retirement_form_fields_es
|
||||
personal_section: Información Personal
|
||||
birth_year: Año de Nacimiento
|
||||
@@ -92,6 +98,11 @@ es:
|
||||
pension_entry_added: Entrada de pensión añadida correctamente
|
||||
destroy_pension_entry:
|
||||
pension_entry_removed: Entrada de pensión eliminada
|
||||
pension_system_groups:
|
||||
europe: Europa
|
||||
united_kingdom: Reino Unido
|
||||
north_america: Norteamérica
|
||||
other: Otros
|
||||
pension_systems:
|
||||
de_grv: Pensión Estatal Alemana (GRV)
|
||||
us_ss: Seguridad Social de EE.UU.
|
||||
|
||||
@@ -41,6 +41,12 @@ fr:
|
||||
no_entries: Aucune entrée de pension
|
||||
no_entries_hint: Ajoutez des entrées de vos relevés de pension pour suivre votre progression
|
||||
setup_required: Veuillez d'abord configurer la planification de retraite
|
||||
uk_progress_title: Progression de la Pension d'État
|
||||
uk_qualifying_years: Années de Qualification (NI)
|
||||
uk_years_remaining:
|
||||
zero: "Toutes les années atteintes — Pension d'État complète !"
|
||||
one: "%{count} an de plus pour la Pension d'État complète"
|
||||
other: "%{count} ans de plus pour la Pension d'État complète"
|
||||
form_fields: &retirement_form_fields_fr
|
||||
personal_section: Informations Personnelles
|
||||
birth_year: Année de Naissance
|
||||
@@ -92,6 +98,11 @@ fr:
|
||||
pension_entry_added: Entrée de pension ajoutée avec succès
|
||||
destroy_pension_entry:
|
||||
pension_entry_removed: Entrée de pension supprimée
|
||||
pension_system_groups:
|
||||
europe: Europe
|
||||
united_kingdom: Royaume-Uni
|
||||
north_america: Amérique du Nord
|
||||
other: Autre
|
||||
pension_systems:
|
||||
de_grv: Pension Légale Allemande (GRV)
|
||||
us_ss: Sécurité Sociale Américaine
|
||||
|
||||
9
db/schema.rb
generated
9
db/schema.rb
generated
@@ -10,7 +10,7 @@
|
||||
#
|
||||
# It's strongly recommended that you check this file into your version control system.
|
||||
|
||||
ActiveRecord::Schema[7.2].define(version: 2026_03_30_050801) do
|
||||
ActiveRecord::Schema[7.2].define(version: 2026_04_09_100000) do
|
||||
# These are extensions that must be enabled in order to support this database
|
||||
enable_extension "pgcrypto"
|
||||
enable_extension "plpgsql"
|
||||
@@ -1063,10 +1063,11 @@ ActiveRecord::Schema[7.2].define(version: 2026_03_30_050801) do
|
||||
create_table "pension_entries", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t|
|
||||
t.uuid "retirement_config_id", null: false
|
||||
t.date "recorded_at", null: false
|
||||
t.decimal "current_points", precision: 8, scale: 4, null: false
|
||||
t.decimal "current_points", precision: 8, scale: 4
|
||||
t.decimal "current_monthly_pension", precision: 19, scale: 4
|
||||
t.decimal "projected_monthly_pension", precision: 19, scale: 4
|
||||
t.text "notes"
|
||||
t.jsonb "data", null: false, default: {}
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["retirement_config_id", "recorded_at"], name: "index_pension_entries_on_retirement_config_id_and_recorded_at", unique: true
|
||||
@@ -1173,9 +1174,7 @@ ActiveRecord::Schema[7.2].define(version: 2026_03_30_050801) do
|
||||
t.decimal "inflation_pct", precision: 5, scale: 2, null: false, default: "2.0"
|
||||
t.decimal "tax_rate_pct", precision: 5, scale: 2, null: false, default: "26.38"
|
||||
t.decimal "current_monthly_savings", precision: 19, scale: 4, null: false, default: "0.0"
|
||||
t.integer "contribution_start_year"
|
||||
t.decimal "expected_annual_points", precision: 5, scale: 2
|
||||
t.decimal "rentenwert", precision: 8, scale: 2
|
||||
t.jsonb "pension_params", null: false, default: {}
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
t.index ["family_id"], name: "index_retirement_configs_on_family_id", unique: true
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
require "test_helper"
|
||||
|
||||
class RetirementConfig::PensionCalculator::DeGrvTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
@config = retirement_configs(:dylan_retirement)
|
||||
@calculator = RetirementConfig::PensionCalculator::DeGrv.new(@config)
|
||||
end
|
||||
|
||||
test "uses projected_monthly_pension from latest entry when available" do
|
||||
result = @calculator.estimated_monthly_pension
|
||||
assert_equal 1850.0, result
|
||||
end
|
||||
|
||||
test "calculates from points and rentenwert when no entry present" do
|
||||
@config.pension_entries.delete_all
|
||||
@config.instance_variable_set(:@latest_pension_entry, nil)
|
||||
@config.pension_params = { "expected_annual_points" => 1.0, "rentenwert" => 39.32 }
|
||||
|
||||
result = @calculator.estimated_monthly_pension
|
||||
expected = (0 + 1.0 * @config.years_to_retirement) * 39.32
|
||||
assert_in_delta expected, result, 0.01
|
||||
end
|
||||
|
||||
test "falls back to default rentenwert when not in pension_params" do
|
||||
@config.pension_entries.delete_all
|
||||
@config.instance_variable_set(:@latest_pension_entry, nil)
|
||||
@config.pension_params = { "expected_annual_points" => 1.0 }
|
||||
|
||||
result = @calculator.estimated_monthly_pension
|
||||
expected = (0 + 1.0 * @config.years_to_retirement) * RetirementConfig::PensionCalculator::DeGrv::DEFAULT_RENTENWERT
|
||||
assert_in_delta expected, result, 0.01
|
||||
end
|
||||
|
||||
test "is points_based" do
|
||||
assert @calculator.points_based?
|
||||
end
|
||||
|
||||
test "param_definitions returns expected keys" do
|
||||
keys = RetirementConfig::PensionCalculator::DeGrv.param_definitions.map { |d| d[:key] }
|
||||
assert_includes keys, "expected_annual_points"
|
||||
assert_includes keys, "rentenwert"
|
||||
assert_includes keys, "contribution_start_year"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,39 @@
|
||||
require "test_helper"
|
||||
|
||||
class RetirementConfig::PensionCalculator::EsSocialSecurityTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
@config = retirement_configs(:us_retirement)
|
||||
@config.pension_system = "es_ss"
|
||||
@config.pension_params = { "estimated_monthly_pension" => 1400.0, "contribution_years" => 30 }
|
||||
@calculator = RetirementConfig::PensionCalculator::EsSocialSecurity.new(@config)
|
||||
end
|
||||
|
||||
test "returns estimated_monthly_pension from pension_params" do
|
||||
assert_equal 1400.0, @calculator.estimated_monthly_pension
|
||||
end
|
||||
|
||||
test "returns 0 when no pension configured and no entry" do
|
||||
@config.pension_params = {}
|
||||
assert_equal 0, @calculator.estimated_monthly_pension
|
||||
end
|
||||
|
||||
test "uses projected_monthly_pension from entry when available" do
|
||||
entry = @config.pension_entries.build(
|
||||
recorded_at: Date.current,
|
||||
projected_monthly_pension: 1500.0
|
||||
)
|
||||
entry.save!
|
||||
calc = RetirementConfig::PensionCalculator::EsSocialSecurity.new(@config)
|
||||
assert_equal 1500.0, calc.estimated_monthly_pension
|
||||
end
|
||||
|
||||
test "is not points_based" do
|
||||
assert_not @calculator.points_based?
|
||||
end
|
||||
|
||||
test "param_definitions includes contribution_years and estimated_monthly_pension" do
|
||||
keys = RetirementConfig::PensionCalculator::EsSocialSecurity.param_definitions.map { |d| d[:key] }
|
||||
assert_includes keys, "contribution_years"
|
||||
assert_includes keys, "estimated_monthly_pension"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,39 @@
|
||||
require "test_helper"
|
||||
|
||||
class RetirementConfig::PensionCalculator::FrRegimeGeneralTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
@config = retirement_configs(:us_retirement)
|
||||
@config.pension_system = "fr_regime"
|
||||
@config.pension_params = { "estimated_monthly_pension" => 1600.0, "trimestres" => 120 }
|
||||
@calculator = RetirementConfig::PensionCalculator::FrRegimeGeneral.new(@config)
|
||||
end
|
||||
|
||||
test "returns estimated_monthly_pension from pension_params" do
|
||||
assert_equal 1600.0, @calculator.estimated_monthly_pension
|
||||
end
|
||||
|
||||
test "returns 0 when no pension configured and no entry" do
|
||||
@config.pension_params = {}
|
||||
assert_equal 0, @calculator.estimated_monthly_pension
|
||||
end
|
||||
|
||||
test "uses projected_monthly_pension from entry when available" do
|
||||
entry = @config.pension_entries.build(
|
||||
recorded_at: Date.current,
|
||||
projected_monthly_pension: 1700.0
|
||||
)
|
||||
entry.save!
|
||||
calc = RetirementConfig::PensionCalculator::FrRegimeGeneral.new(@config)
|
||||
assert_equal 1700.0, calc.estimated_monthly_pension
|
||||
end
|
||||
|
||||
test "is not points_based" do
|
||||
assert_not @calculator.points_based?
|
||||
end
|
||||
|
||||
test "param_definitions includes trimestres and estimated_monthly_pension" do
|
||||
keys = RetirementConfig::PensionCalculator::FrRegimeGeneral.param_definitions.map { |d| d[:key] }
|
||||
assert_includes keys, "trimestres"
|
||||
assert_includes keys, "estimated_monthly_pension"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,45 @@
|
||||
require "test_helper"
|
||||
|
||||
class RetirementConfig::PensionCalculator::UkStatePensionTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
@config = retirement_configs(:us_retirement)
|
||||
@config.pension_system = "uk_sp"
|
||||
@config.pension_params = { "qualifying_years" => 35, "full_weekly_rate" => 221.20 }
|
||||
@calculator = RetirementConfig::PensionCalculator::UkStatePension.new(@config)
|
||||
end
|
||||
|
||||
test "calculates full pension for 35 qualifying years" do
|
||||
result = @calculator.estimated_monthly_pension
|
||||
expected = (35.0 / 35.0) * 221.20 * 52 / 12
|
||||
assert_in_delta expected, result, 0.01
|
||||
end
|
||||
|
||||
test "calculates partial pension for fewer qualifying years" do
|
||||
@config.pension_params = { "qualifying_years" => 20, "full_weekly_rate" => 221.20 }
|
||||
result = @calculator.estimated_monthly_pension
|
||||
expected = (20.0 / 35.0) * 221.20 * 52 / 12
|
||||
assert_in_delta expected, result, 0.01
|
||||
end
|
||||
|
||||
test "returns 0 when no qualifying years" do
|
||||
@config.pension_params = { "qualifying_years" => 0 }
|
||||
assert_equal 0, @calculator.estimated_monthly_pension
|
||||
end
|
||||
|
||||
test "falls back to default weekly rate" do
|
||||
@config.pension_params = { "qualifying_years" => 35 }
|
||||
result = @calculator.estimated_monthly_pension
|
||||
expected = 1.0 * RetirementConfig::PensionCalculator::UkStatePension::FULL_WEEKLY_RATE * 52 / 12
|
||||
assert_in_delta expected, result, 0.01
|
||||
end
|
||||
|
||||
test "is not points_based" do
|
||||
assert_not @calculator.points_based?
|
||||
end
|
||||
|
||||
test "param_definitions includes qualifying_years and full_weekly_rate" do
|
||||
keys = RetirementConfig::PensionCalculator::UkStatePension.param_definitions.map { |d| d[:key] }
|
||||
assert_includes keys, "qualifying_years"
|
||||
assert_includes keys, "full_weekly_rate"
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,38 @@
|
||||
require "test_helper"
|
||||
|
||||
class RetirementConfig::PensionCalculator::UsSocialSecurityTest < ActiveSupport::TestCase
|
||||
setup do
|
||||
@config = retirement_configs(:us_retirement)
|
||||
@calculator = RetirementConfig::PensionCalculator::UsSocialSecurity.new(@config)
|
||||
end
|
||||
|
||||
test "returns estimated_monthly_benefit from pension_params" do
|
||||
result = @calculator.estimated_monthly_pension
|
||||
assert_equal 2800.0, result
|
||||
end
|
||||
|
||||
test "returns 0 when no benefit configured and no entry" do
|
||||
@config.pension_params = {}
|
||||
result = @calculator.estimated_monthly_pension
|
||||
assert_equal 0, result
|
||||
end
|
||||
|
||||
test "uses projected_monthly_pension from entry when available" do
|
||||
entry = @config.pension_entries.build(
|
||||
recorded_at: Date.current,
|
||||
projected_monthly_pension: 3000.0
|
||||
)
|
||||
entry.save!
|
||||
calc = RetirementConfig::PensionCalculator::UsSocialSecurity.new(@config)
|
||||
assert_equal 3000.0, calc.estimated_monthly_pension
|
||||
end
|
||||
|
||||
test "is not points_based" do
|
||||
assert_not @calculator.points_based?
|
||||
end
|
||||
|
||||
test "param_definitions includes estimated_monthly_benefit" do
|
||||
keys = RetirementConfig::PensionCalculator::UsSocialSecurity.param_definitions.map { |d| d[:key] }
|
||||
assert_includes keys, "estimated_monthly_benefit"
|
||||
end
|
||||
end
|
||||
Reference in New Issue
Block a user