diff --git a/app/models/form/sales/pages/retirement_value_check.rb b/app/models/form/sales/pages/retirement_value_check.rb new file mode 100644 index 000000000..ae8389acf --- /dev/null +++ b/app/models/form/sales/pages/retirement_value_check.rb @@ -0,0 +1,43 @@ +class Form::Sales::Pages::RetirementValueCheck < Form::Sales::Pages::Person + def initialize(id, hsh, subsection, person_index:) + super + @depends_on = [ + { + "person_#{person_index}_retired_under_soft_min_age?" => true, + "jointpur" => joint_purchase? ? 1 : 2, + }, + ] + @person_index = person_index + @title_text = { + "translation" => "soft_validations.retirement.min.title", + "arguments" => [ + { + "key" => "retirement_age_for_person_#{person_index}", + "label" => false, + "i18n_template" => "age", + }, + ], + } + @informative_text = { + "translation" => "soft_validations.retirement.min.hint_text", + "arguments" => [ + { + "key" => "plural_gender_for_person_#{person_index}", + "label" => false, + "i18n_template" => "gender", + }, + { + "key" => "retirement_age_for_person_#{person_index}", + "label" => false, + "i18n_template" => "age", + }, + ], + } + end + + def questions + @questions ||= [ + Form::Sales::Questions::RetirementValueCheck.new(nil, nil, self, person_index: @person_index), + ] + end +end diff --git a/app/models/form/sales/questions/age1.rb b/app/models/form/sales/questions/age1.rb index 2ac7a9e3f..94d40100f 100644 --- a/app/models/form/sales/questions/age1.rb +++ b/app/models/form/sales/questions/age1.rb @@ -17,5 +17,7 @@ class Form::Sales::Questions::Age1 < ::Form::Question }, ] @check_answers_card_number = 1 + @min = 16 + @max = 110 end end diff --git a/app/models/form/sales/questions/retirement_value_check.rb b/app/models/form/sales/questions/retirement_value_check.rb new file mode 100644 index 000000000..56573490e --- /dev/null +++ b/app/models/form/sales/questions/retirement_value_check.rb @@ -0,0 +1,24 @@ +class Form::Sales::Questions::RetirementValueCheck < ::Form::Question + def initialize(id, hsh, page, person_index:) + super(id, hsh, page) + @id = "retirement_value_check" + @check_answer_label = "Retirement confirmation" + @type = "interruption_screen" + @answer_options = { + "0" => { "value" => "Yes" }, + "1" => { "value" => "No" }, + } + @hidden_in_check_answers = { + "depends_on" => [ + { + "retirement_value_check" => 0, + }, + { + "retirement_value_check" => 1, + }, + ], + } + @check_answers_card_number = person_index + @header = "Are you sure this person is retired?" + end +end diff --git a/app/models/form/sales/subsections/household_characteristics.rb b/app/models/form/sales/subsections/household_characteristics.rb index 38a71cf41..b4c8badcf 100644 --- a/app/models/form/sales/subsections/household_characteristics.rb +++ b/app/models/form/sales/subsections/household_characteristics.rb @@ -11,7 +11,11 @@ class Form::Sales::Subsections::HouseholdCharacteristics < ::Form::Subsection Form::Sales::Pages::BuyerInterview.new(nil, nil, self), Form::Sales::Pages::PrivacyNotice.new(nil, nil, self), Form::Sales::Pages::Age1.new(nil, nil, self), + Form::Sales::Pages::RetirementValueCheck.new("age_1_retirement_value_check", nil, self, person_index: 1), + Form::Sales::Pages::RetirementValueCheck.new("age_1_retirement_value_check_joint_purchase", nil, self, person_index: 1), Form::Sales::Pages::GenderIdentity1.new(nil, nil, self), + Form::Sales::Pages::RetirementValueCheck.new("gender_1_retirement_value_check", nil, self, person_index: 1), + Form::Sales::Pages::RetirementValueCheck.new("gender_1_retirement_value_check_joint_purchase", nil, self, person_index: 1), Form::Sales::Pages::Buyer1EthnicGroup.new(nil, nil, self), Form::Sales::Pages::Buyer1EthnicBackgroundBlack.new(nil, nil, self), Form::Sales::Pages::Buyer1EthnicBackgroundAsian.new(nil, nil, self), @@ -20,12 +24,17 @@ class Form::Sales::Subsections::HouseholdCharacteristics < ::Form::Subsection Form::Sales::Pages::Buyer1EthnicBackgroundWhite.new(nil, nil, self), Form::Sales::Pages::Nationality1.new(nil, nil, self), Form::Sales::Pages::Buyer1WorkingSituation.new(nil, nil, self), + Form::Sales::Pages::RetirementValueCheck.new("working_situation_1_retirement_value_check", nil, self, person_index: 1), + Form::Sales::Pages::RetirementValueCheck.new("working_situation_1_retirement_value_check_joint_purchase", nil, self, person_index: 1), Form::Sales::Pages::Buyer1IncomeValueCheck.new("working_situation_buyer_1_income_value_check", nil, self), Form::Sales::Pages::Buyer1LiveInProperty.new(nil, nil, self), Form::Sales::Pages::Buyer2RelationshipToBuyer1.new(nil, nil, self), Form::Sales::Pages::Age2.new(nil, nil, self), + Form::Sales::Pages::RetirementValueCheck.new("age_2_retirement_value_check_joint_purchase", nil, self, person_index: 2), Form::Sales::Pages::GenderIdentity2.new(nil, nil, self), + Form::Sales::Pages::RetirementValueCheck.new("gender_2_retirement_value_check_joint_purchase", nil, self, person_index: 2), Form::Sales::Pages::Buyer2WorkingSituation.new(nil, nil, self), + Form::Sales::Pages::RetirementValueCheck.new("working_situation_2_retirement_value_check_joint_purchase", nil, self, person_index: 2), Form::Sales::Pages::Buyer2LiveInProperty.new(nil, nil, self), Form::Sales::Pages::NumberOfOthersInProperty.new(nil, nil, self), Form::Sales::Pages::PersonKnown.new("person_1_known", nil, self, person_index: 2), @@ -33,41 +42,65 @@ class Form::Sales::Subsections::HouseholdCharacteristics < ::Form::Subsection Form::Sales::Pages::PersonRelationshipToBuyer1.new("person_1_relationship_to_buyer_1", nil, self, person_index: 2), Form::Sales::Pages::PersonRelationshipToBuyer1.new("person_1_relationship_to_buyer_1_joint_purchase", nil, self, person_index: 3), Form::Sales::Pages::PersonAge.new("person_1_age", nil, self, person_index: 2), + Form::Sales::Pages::RetirementValueCheck.new("age_2_retirement_value_check", nil, self, person_index: 2), Form::Sales::Pages::PersonAge.new("person_1_age_joint_purchase", nil, self, person_index: 3), + Form::Sales::Pages::RetirementValueCheck.new("age_3_retirement_value_check_joint_purchase", nil, self, person_index: 3), Form::Sales::Pages::PersonGenderIdentity.new("person_1_gender_identity", nil, self, person_index: 2), + Form::Sales::Pages::RetirementValueCheck.new("gender_2_retirement_value_check", nil, self, person_index: 2), Form::Sales::Pages::PersonGenderIdentity.new("person_1_gender_identity_joint_purchase", nil, self, person_index: 3), + Form::Sales::Pages::RetirementValueCheck.new("gender_3_retirement_value_check_joint_purchase", nil, self, person_index: 3), Form::Sales::Pages::PersonWorkingSituation.new("person_1_working_situation", nil, self, person_index: 2), + Form::Sales::Pages::RetirementValueCheck.new("working_situation_2_retirement_value_check", nil, self, person_index: 2), Form::Sales::Pages::PersonWorkingSituation.new("person_1_working_situation_joint_purchase", nil, self, person_index: 3), + Form::Sales::Pages::RetirementValueCheck.new("working_situation_3_retirement_value_check_joint_purchase", nil, self, person_index: 3), Form::Sales::Pages::PersonKnown.new("person_2_known", nil, self, person_index: 3), Form::Sales::Pages::PersonKnown.new("person_2_known_joint_purchase", nil, self, person_index: 4), Form::Sales::Pages::PersonRelationshipToBuyer1.new("person_2_relationship_to_buyer_1", nil, self, person_index: 3), Form::Sales::Pages::PersonRelationshipToBuyer1.new("person_2_relationship_to_buyer_1_joint_purchase", nil, self, person_index: 4), Form::Sales::Pages::PersonAge.new("person_2_age", nil, self, person_index: 3), + Form::Sales::Pages::RetirementValueCheck.new("age_3_retirement_value_check", nil, self, person_index: 3), Form::Sales::Pages::PersonAge.new("person_2_age_joint_purchase", nil, self, person_index: 4), + Form::Sales::Pages::RetirementValueCheck.new("age_4_retirement_value_check_joint_purchase", nil, self, person_index: 4), Form::Sales::Pages::PersonGenderIdentity.new("person_2_gender_identity", nil, self, person_index: 3), + Form::Sales::Pages::RetirementValueCheck.new("gender_3_retirement_value_check", nil, self, person_index: 3), Form::Sales::Pages::PersonGenderIdentity.new("person_2_gender_identity_joint_purchase", nil, self, person_index: 4), + Form::Sales::Pages::RetirementValueCheck.new("gender_4_retirement_value_check_joint_purchase", nil, self, person_index: 4), Form::Sales::Pages::PersonWorkingSituation.new("person_2_working_situation", nil, self, person_index: 3), + Form::Sales::Pages::RetirementValueCheck.new("working_situation_3_retirement_value_check", nil, self, person_index: 3), Form::Sales::Pages::PersonWorkingSituation.new("person_2_working_situation_joint_purchase", nil, self, person_index: 4), + Form::Sales::Pages::RetirementValueCheck.new("working_situation_4_retirement_value_check_joint_purchase", nil, self, person_index: 4), Form::Sales::Pages::PersonKnown.new("person_3_known", nil, self, person_index: 4), Form::Sales::Pages::PersonKnown.new("person_3_known_joint_purchase", nil, self, person_index: 5), Form::Sales::Pages::PersonRelationshipToBuyer1.new("person_3_relationship_to_buyer_1", nil, self, person_index: 4), Form::Sales::Pages::PersonRelationshipToBuyer1.new("person_3_relationship_to_buyer_1_joint_purchase", nil, self, person_index: 5), Form::Sales::Pages::PersonAge.new("person_3_age", nil, self, person_index: 4), + Form::Sales::Pages::RetirementValueCheck.new("age_4_retirement_value_check", nil, self, person_index: 4), Form::Sales::Pages::PersonAge.new("person_3_age_joint_purchase", nil, self, person_index: 5), + Form::Sales::Pages::RetirementValueCheck.new("age_5_retirement_value_check_joint_purchase", nil, self, person_index: 5), Form::Sales::Pages::PersonGenderIdentity.new("person_3_gender_identity", nil, self, person_index: 4), + Form::Sales::Pages::RetirementValueCheck.new("gender_4_retirement_value_check", nil, self, person_index: 4), Form::Sales::Pages::PersonGenderIdentity.new("person_3_gender_identity_joint_purchase", nil, self, person_index: 5), + Form::Sales::Pages::RetirementValueCheck.new("gender_5_retirement_value_check_joint_purchase", nil, self, person_index: 5), Form::Sales::Pages::PersonWorkingSituation.new("person_3_working_situation", nil, self, person_index: 4), + Form::Sales::Pages::RetirementValueCheck.new("working_situation_4_retirement_value_check", nil, self, person_index: 4), Form::Sales::Pages::PersonWorkingSituation.new("person_3_working_situation_joint_purchase", nil, self, person_index: 5), + Form::Sales::Pages::RetirementValueCheck.new("working_situation_5_retirement_value_check_joint_purchase", nil, self, person_index: 5), Form::Sales::Pages::PersonKnown.new("person_4_known", nil, self, person_index: 5), Form::Sales::Pages::PersonKnown.new("person_4_known_joint_purchase", nil, self, person_index: 6), Form::Sales::Pages::PersonRelationshipToBuyer1.new("person_4_relationship_to_buyer_1", nil, self, person_index: 5), Form::Sales::Pages::PersonRelationshipToBuyer1.new("person_4_relationship_to_buyer_1_joint_purchase", nil, self, person_index: 6), Form::Sales::Pages::PersonAge.new("person_4_age", nil, self, person_index: 5), + Form::Sales::Pages::RetirementValueCheck.new("age_5_retirement_value_check", nil, self, person_index: 5), Form::Sales::Pages::PersonAge.new("person_4_age_joint_purchase", nil, self, person_index: 6), + Form::Sales::Pages::RetirementValueCheck.new("age_6_retirement_value_check_joint_purchase", nil, self, person_index: 6), Form::Sales::Pages::PersonGenderIdentity.new("person_4_gender_identity", nil, self, person_index: 5), + Form::Sales::Pages::RetirementValueCheck.new("gender_5_retirement_value_check", nil, self, person_index: 5), Form::Sales::Pages::PersonGenderIdentity.new("person_4_gender_identity_joint_purchase", nil, self, person_index: 6), + Form::Sales::Pages::RetirementValueCheck.new("gender_6_retirement_value_check_joint_purchase", nil, self, person_index: 6), Form::Sales::Pages::PersonWorkingSituation.new("person_4_working_situation", nil, self, person_index: 5), + Form::Sales::Pages::RetirementValueCheck.new("working_situation_5_retirement_value_check", nil, self, person_index: 5), Form::Sales::Pages::PersonWorkingSituation.new("person_4_working_situation_joint_purchase", nil, self, person_index: 6), + Form::Sales::Pages::RetirementValueCheck.new("working_situation_6_retirement_value_check_joint_purchase", nil, self, person_index: 6), ] end end diff --git a/app/models/lettings_log.rb b/app/models/lettings_log.rb index d78495016..04b4b4ec9 100644 --- a/app/models/lettings_log.rb +++ b/app/models/lettings_log.rb @@ -456,16 +456,6 @@ class LettingsLog < Log OPTIONAL_FIELDS + dynamically_not_required end - (1..8).each do |person_num| - define_method("retirement_age_for_person_#{person_num}") do - retirement_age_for_person(person_num) - end - - define_method("plural_gender_for_person_#{person_num}") do - plural_gender_for_person(person_num) - end - end - def retirement_age_for_person(person_num) gender = public_send("sex#{person_num}".to_sym) return unless gender @@ -473,17 +463,6 @@ class LettingsLog < Log RETIREMENT_AGES[gender] end - def plural_gender_for_person(person_num) - gender = public_send("sex#{person_num}".to_sym) - return unless gender - - if %w[M X].include?(gender) - "male and non-binary people" - elsif gender == "F" - "females" - end - end - def age_known?(person_num) return false unless person_num.is_a?(Integer) diff --git a/app/models/log.rb b/app/models/log.rb index ea8a637af..d10211577 100644 --- a/app/models/log.rb +++ b/app/models/log.rb @@ -62,8 +62,29 @@ class Log < ApplicationRecord end end + (1..8).each do |person_num| + define_method("retirement_age_for_person_#{person_num}") do + retirement_age_for_person(person_num) + end + + define_method("plural_gender_for_person_#{person_num}") do + plural_gender_for_person(person_num) + end + end + private + def plural_gender_for_person(person_num) + gender = public_send("sex#{person_num}".to_sym) + return unless gender + + if %w[M X].include?(gender) + "male and non-binary people" + elsif gender == "F" + "females" + end + end + def update_status! self.status = if all_fields_completed? && errors.empty? "completed" diff --git a/app/models/sales_log.rb b/app/models/sales_log.rb index cdf2964f1..45bd9f729 100644 --- a/app/models/sales_log.rb +++ b/app/models/sales_log.rb @@ -16,6 +16,7 @@ end class SalesLog < Log include DerivedVariables::SalesLogVariables include Validations::Sales::SoftValidations + include Validations::SoftValidations self.inheritance_column = :_type_disabled @@ -33,6 +34,7 @@ class SalesLog < Log scope :search_by, ->(param) { filter_by_id(param) } OPTIONAL_FIELDS = %w[purchid].freeze + RETIREMENT_AGES = { "M" => 65, "F" => 60, "X" => 65 }.freeze def startdate saledate @@ -181,4 +183,23 @@ class SalesLog < Log self.postcode_full = upcase_and_remove_whitespace(postcode_full) process_postcode(postcode_full, "pcodenk", "is_la_inferred", "la") end + + def retirement_age_for_person(person_num) + gender = public_send("sex#{person_num}".to_sym) + return unless gender + + RETIREMENT_AGES[gender] + end + + def joint_purchase? + jointpur == 1 + end + + def not_joint_purchase? + jointpur == 2 + end + + def old_persons_shared_ownership? + type == 24 + end end diff --git a/app/models/validations/sales/household_validations.rb b/app/models/validations/sales/household_validations.rb index 6e16a0476..8ee00fdfd 100644 --- a/app/models/validations/sales/household_validations.rb +++ b/app/models/validations/sales/household_validations.rb @@ -18,6 +18,20 @@ module Validations::Sales::HouseholdValidations shared_validate_partner_count(record, 6) end + def validate_buyers_age_for_old_persons_shared_ownership(record) + if record.old_persons_shared_ownership? + if record.joint_purchase? && ages_unknown_or_under_64?(record, [1, 2]) + record.errors.add :age1, I18n.t("validations.household.old_persons_shared_ownership") + record.errors.add :age2, I18n.t("validations.household.old_persons_shared_ownership") + record.errors.add :type, I18n.t("validations.household.old_persons_shared_ownership") + end + if record.not_joint_purchase? && ages_unknown_or_under_64?(record, [1]) + record.errors.add :age1, I18n.t("validations.household.old_persons_shared_ownership") + record.errors.add :type, I18n.t("validations.household.old_persons_shared_ownership") + end + end + end + private def validate_person_age_matches_relationship(record, person_num) @@ -97,4 +111,8 @@ private def tenant_is_economic_child?(economic_status) economic_status == 9 end + + def ages_unknown_or_under_64?(record, person_indexes) + person_indexes.all? { |person_num| record["age#{person_num}"].present? && record["age#{person_num}"] < 64 || record["age#{person_num}_known"] == 1 } + end end diff --git a/app/models/validations/soft_validations.rb b/app/models/validations/soft_validations.rb index 944fff022..fc2c469ca 100644 --- a/app/models/validations/soft_validations.rb +++ b/app/models/validations/soft_validations.rb @@ -111,7 +111,7 @@ private gender = public_send("sex#{person_num}") return unless age && economic_status && gender - %w[M X].include?(gender) && tenant_is_retired?(economic_status) && age < 67 || + %w[M X].include?(gender) && tenant_is_retired?(economic_status) && age < retirement_age_for_person(person_num) || gender == "F" && tenant_is_retired?(economic_status) && age < 60 end @@ -122,7 +122,7 @@ private tenant_retired_or_prefers_not_say = tenant_is_retired?(economic_status) || tenant_prefers_not_to_say?(economic_status) return unless age && economic_status && gender - %w[M X].include?(gender) && !tenant_retired_or_prefers_not_say && age > 67 || + %w[M X].include?(gender) && !tenant_retired_or_prefers_not_say && age > retirement_age_for_person(person_num) || gender == "F" && !tenant_retired_or_prefers_not_say && age > 60 end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 73bd8bdf7..ac6a2fa7f 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -367,7 +367,8 @@ en: not_internal_transfer: "Answer cannot be ‘permanently decanted from another property owned by this landlord’ as you told us the source of referral for this tenancy was not an internal transfer" condition_effects: no_choices: "You cannot answer this question as you told us nobody in the household has a physical or mental health condition (or other illness) expected to last 12 months or more" - + old_persons_shared_ownership: "Are you sure? At least one buyer should be aged over 64 for Older persons‘ shared ownership scheme" + tenancy: length: fixed_term_not_required: "You must only answer the length of the tenancy if it's fixed-term" diff --git a/db/migrate/20230116124402_add_retirement_value_check_to_sales.rb b/db/migrate/20230116124402_add_retirement_value_check_to_sales.rb new file mode 100644 index 000000000..714c5f6b3 --- /dev/null +++ b/db/migrate/20230116124402_add_retirement_value_check_to_sales.rb @@ -0,0 +1,7 @@ +class AddRetirementValueCheckToSales < ActiveRecord::Migration[7.0] + def change + change_table :sales_logs, bulk: true do |t| + t.column :retirement_value_check, :integer + end + end +end diff --git a/db/schema.rb b/db/schema.rb index e05334946..91c6bed37 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -503,6 +503,7 @@ ActiveRecord::Schema[7.0].define(version: 2023_01_16_151942) do t.integer "hodate_check" t.bigint "bulk_upload_id" t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id" + t.integer "retirement_value_check" t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id" t.index ["managing_organisation_id"], name: "index_sales_logs_on_managing_organisation_id" t.index ["owning_organisation_id"], name: "index_sales_logs_on_owning_organisation_id" diff --git a/spec/models/form/sales/pages/retirement_value_check_spec.rb b/spec/models/form/sales/pages/retirement_value_check_spec.rb new file mode 100644 index 000000000..9c04ef25c --- /dev/null +++ b/spec/models/form/sales/pages/retirement_value_check_spec.rb @@ -0,0 +1,603 @@ +require "rails_helper" + +RSpec.describe Form::Sales::Pages::RetirementValueCheck, type: :model do + subject(:page) { described_class.new(page_id, page_definition, subsection, person_index:) } + + let(:page_definition) { nil } + let(:subsection) { instance_double(Form::Subsection) } + let(:person_index) { 1 } + + let(:page_id) { "person_1_retirement_value_check" } + + it "has correct subsection" do + expect(page.subsection).to eq(subsection) + end + + it "has the correct header" do + expect(page.header).to be_nil + end + + it "has the correct description" do + expect(page.description).to be_nil + end + + context "with joint purchase" do + context "with person 1" do + let(:person_index) { 1 } + let(:page_id) { "person_1_retirement_value_check_joint_purchase" } + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[retirement_value_check]) + end + + it "has the correct id" do + expect(page.id).to eq("person_1_retirement_value_check_joint_purchase") + end + + it "has correct depends_on" do + expect(page.depends_on).to eq([{ "person_1_retired_under_soft_min_age?" => true, "jointpur" => 1 }]) + end + + it "has correct title_text" do + expect(page.title_text).to eq({ + "translation" => "soft_validations.retirement.min.title", + "arguments" => [ + { + "key" => "retirement_age_for_person_1", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + + it "has correct informative_text" do + expect(page.informative_text).to eq({ + "translation" => "soft_validations.retirement.min.hint_text", + "arguments" => [ + { + "key" => "plural_gender_for_person_1", + "label" => false, + "i18n_template" => "gender", + }, + { + "key" => "retirement_age_for_person_1", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + end + + context "with person 2" do + let(:person_index) { 2 } + let(:page_id) { "person_2_retirement_value_check_joint_purchase" } + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[retirement_value_check]) + end + + it "has the correct id" do + expect(page.id).to eq("person_2_retirement_value_check_joint_purchase") + end + + it "has correct depends_on" do + expect(page.depends_on).to eq([{ "person_2_retired_under_soft_min_age?" => true, "jointpur" => 1 }]) + end + + it "has correct title_text" do + expect(page.title_text).to eq({ + "translation" => "soft_validations.retirement.min.title", + "arguments" => [ + { + "key" => "retirement_age_for_person_2", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + + it "has correct informative_text" do + expect(page.informative_text).to eq({ + "translation" => "soft_validations.retirement.min.hint_text", + "arguments" => [ + { + "key" => "plural_gender_for_person_2", + "label" => false, + "i18n_template" => "gender", + }, + { + "key" => "retirement_age_for_person_2", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + end + + context "with person 3" do + let(:person_index) { 3 } + let(:page_id) { "person_3_retirement_value_check_joint_purchase" } + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[retirement_value_check]) + end + + it "has the correct id" do + expect(page.id).to eq("person_3_retirement_value_check_joint_purchase") + end + + it "has correct depends_on" do + expect(page.depends_on).to eq([{ "person_3_retired_under_soft_min_age?" => true, "jointpur" => 1 }]) + end + + it "has correct title_text" do + expect(page.title_text).to eq({ + "translation" => "soft_validations.retirement.min.title", + "arguments" => [ + { + "key" => "retirement_age_for_person_3", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + + it "has correct informative_text" do + expect(page.informative_text).to eq({ + "translation" => "soft_validations.retirement.min.hint_text", + "arguments" => [ + { + "key" => "plural_gender_for_person_3", + "label" => false, + "i18n_template" => "gender", + }, + { + "key" => "retirement_age_for_person_3", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + end + + context "with person 4" do + let(:person_index) { 4 } + let(:page_id) { "person_4_retirement_value_check_joint_purchase" } + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[retirement_value_check]) + end + + it "has the correct id" do + expect(page.id).to eq("person_4_retirement_value_check_joint_purchase") + end + + it "has correct depends_on" do + expect(page.depends_on).to eq([{ "person_4_retired_under_soft_min_age?" => true, "jointpur" => 1 }]) + end + + it "has correct title_text" do + expect(page.title_text).to eq({ + "translation" => "soft_validations.retirement.min.title", + "arguments" => [ + { + "key" => "retirement_age_for_person_4", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + + it "has correct informative_text" do + expect(page.informative_text).to eq({ + "translation" => "soft_validations.retirement.min.hint_text", + "arguments" => [ + { + "key" => "plural_gender_for_person_4", + "label" => false, + "i18n_template" => "gender", + }, + { + "key" => "retirement_age_for_person_4", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + end + + context "with person 5" do + let(:person_index) { 5 } + let(:page_id) { "person_5_retirement_value_check_joint_purchase" } + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[retirement_value_check]) + end + + it "has the correct id" do + expect(page.id).to eq("person_5_retirement_value_check_joint_purchase") + end + + it "has correct depends_on" do + expect(page.depends_on).to eq([{ "person_5_retired_under_soft_min_age?" => true, "jointpur" => 1 }]) + end + + it "has correct title_text" do + expect(page.title_text).to eq({ + "translation" => "soft_validations.retirement.min.title", + "arguments" => [ + { + "key" => "retirement_age_for_person_5", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + + it "has correct informative_text" do + expect(page.informative_text).to eq({ + "translation" => "soft_validations.retirement.min.hint_text", + "arguments" => [ + { + "key" => "plural_gender_for_person_5", + "label" => false, + "i18n_template" => "gender", + }, + { + "key" => "retirement_age_for_person_5", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + end + + context "with person 6" do + let(:person_index) { 6 } + let(:page_id) { "person_6_retirement_value_check_joint_purchase" } + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[retirement_value_check]) + end + + it "has the correct id" do + expect(page.id).to eq("person_6_retirement_value_check_joint_purchase") + end + + it "has correct depends_on" do + expect(page.depends_on).to eq([{ "person_6_retired_under_soft_min_age?" => true, "jointpur" => 1 }]) + end + + it "has correct title_text" do + expect(page.title_text).to eq({ + "translation" => "soft_validations.retirement.min.title", + "arguments" => [ + { + "key" => "retirement_age_for_person_6", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + + it "has correct informative_text" do + expect(page.informative_text).to eq({ + "translation" => "soft_validations.retirement.min.hint_text", + "arguments" => [ + { + "key" => "plural_gender_for_person_6", + "label" => false, + "i18n_template" => "gender", + }, + { + "key" => "retirement_age_for_person_6", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + end + end + + context "without joint purchase" do + context "with person 1" do + let(:person_index) { 1 } + let(:page_id) { "person_1_retirement_value_check" } + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[retirement_value_check]) + end + + it "has the correct id" do + expect(page.id).to eq("person_1_retirement_value_check") + end + + it "has correct depends_on" do + expect(page.depends_on).to eq([{ "person_1_retired_under_soft_min_age?" => true, "jointpur" => 2 }]) + end + + it "has correct title_text" do + expect(page.title_text).to eq({ + "translation" => "soft_validations.retirement.min.title", + "arguments" => [ + { + "key" => "retirement_age_for_person_1", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + + it "has correct informative_text" do + expect(page.informative_text).to eq({ + "translation" => "soft_validations.retirement.min.hint_text", + "arguments" => [ + { + "key" => "plural_gender_for_person_1", + "label" => false, + "i18n_template" => "gender", + }, + { + "key" => "retirement_age_for_person_1", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + end + + context "with person 2" do + let(:person_index) { 2 } + let(:page_id) { "person_2_retirement_value_check" } + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[retirement_value_check]) + end + + it "has the correct id" do + expect(page.id).to eq("person_2_retirement_value_check") + end + + it "has correct depends_on" do + expect(page.depends_on).to eq([{ "person_2_retired_under_soft_min_age?" => true, "jointpur" => 2 }]) + end + + it "has correct title_text" do + expect(page.title_text).to eq({ + "translation" => "soft_validations.retirement.min.title", + "arguments" => [ + { + "key" => "retirement_age_for_person_2", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + + it "has correct informative_text" do + expect(page.informative_text).to eq({ + "translation" => "soft_validations.retirement.min.hint_text", + "arguments" => [ + { + "key" => "plural_gender_for_person_2", + "label" => false, + "i18n_template" => "gender", + }, + { + "key" => "retirement_age_for_person_2", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + end + + context "with person 3" do + let(:person_index) { 2 } + let(:page_id) { "person_3_retirement_value_check" } + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[retirement_value_check]) + end + + it "has the correct id" do + expect(page.id).to eq("person_3_retirement_value_check") + end + + it "has correct depends_on" do + expect(page.depends_on).to eq([{ "person_2_retired_under_soft_min_age?" => true, "jointpur" => 2 }]) + end + + it "has correct title_text" do + expect(page.title_text).to eq({ + "translation" => "soft_validations.retirement.min.title", + "arguments" => [ + { + "key" => "retirement_age_for_person_2", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + + it "has correct informative_text" do + expect(page.informative_text).to eq({ + "translation" => "soft_validations.retirement.min.hint_text", + "arguments" => [ + { + "key" => "plural_gender_for_person_2", + "label" => false, + "i18n_template" => "gender", + }, + { + "key" => "retirement_age_for_person_2", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + end + + context "with person 4" do + let(:person_index) { 3 } + let(:page_id) { "person_4_retirement_value_check" } + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[retirement_value_check]) + end + + it "has the correct id" do + expect(page.id).to eq("person_4_retirement_value_check") + end + + it "has correct depends_on" do + expect(page.depends_on).to eq([{ "person_3_retired_under_soft_min_age?" => true, "jointpur" => 2 }]) + end + + it "has correct title_text" do + expect(page.title_text).to eq({ + "translation" => "soft_validations.retirement.min.title", + "arguments" => [ + { + "key" => "retirement_age_for_person_3", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + + it "has correct informative_text" do + expect(page.informative_text).to eq({ + "translation" => "soft_validations.retirement.min.hint_text", + "arguments" => [ + { + "key" => "plural_gender_for_person_3", + "label" => false, + "i18n_template" => "gender", + }, + { + "key" => "retirement_age_for_person_3", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + end + + context "with person 5" do + let(:person_index) { 4 } + let(:page_id) { "person_5_retirement_value_check" } + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[retirement_value_check]) + end + + it "has the correct id" do + expect(page.id).to eq("person_5_retirement_value_check") + end + + it "has correct depends_on" do + expect(page.depends_on).to eq([{ "person_4_retired_under_soft_min_age?" => true, "jointpur" => 2 }]) + end + + it "has correct title_text" do + expect(page.title_text).to eq({ + "translation" => "soft_validations.retirement.min.title", + "arguments" => [ + { + "key" => "retirement_age_for_person_4", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + + it "has correct informative_text" do + expect(page.informative_text).to eq({ + "translation" => "soft_validations.retirement.min.hint_text", + "arguments" => [ + { + "key" => "plural_gender_for_person_4", + "label" => false, + "i18n_template" => "gender", + }, + { + "key" => "retirement_age_for_person_4", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + end + + context "with person 6" do + let(:person_index) { 5 } + let(:page_id) { "person_6_retirement_value_check" } + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[retirement_value_check]) + end + + it "has the correct id" do + expect(page.id).to eq("person_6_retirement_value_check") + end + + it "has correct depends_on" do + expect(page.depends_on).to eq([{ "person_5_retired_under_soft_min_age?" => true, "jointpur" => 2 }]) + end + + it "has correct title_text" do + expect(page.title_text).to eq({ + "translation" => "soft_validations.retirement.min.title", + "arguments" => [ + { + "key" => "retirement_age_for_person_5", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + + it "has correct informative_text" do + expect(page.informative_text).to eq({ + "translation" => "soft_validations.retirement.min.hint_text", + "arguments" => [ + { + "key" => "plural_gender_for_person_5", + "label" => false, + "i18n_template" => "gender", + }, + { + "key" => "retirement_age_for_person_5", + "label" => false, + "i18n_template" => "age", + }, + ], + }) + end + end + end +end diff --git a/spec/models/form/sales/questions/age1_spec.rb b/spec/models/form/sales/questions/age1_spec.rb index b5ab5d44b..33fe91c82 100644 --- a/spec/models/form/sales/questions/age1_spec.rb +++ b/spec/models/form/sales/questions/age1_spec.rb @@ -55,4 +55,12 @@ RSpec.describe Form::Sales::Questions::Age1, type: :model do it "has the correct check_answers_card_number" do expect(question.check_answers_card_number).to eq(1) end + + it "has the correct min" do + expect(question.min).to eq(16) + end + + it "has the correct max" do + expect(question.max).to eq(110) + end end diff --git a/spec/models/form/sales/questions/retirement_value_check_spec.rb b/spec/models/form/sales/questions/retirement_value_check_spec.rb new file mode 100644 index 000000000..318faa5d9 --- /dev/null +++ b/spec/models/form/sales/questions/retirement_value_check_spec.rb @@ -0,0 +1,61 @@ +require "rails_helper" + +RSpec.describe Form::Sales::Questions::RetirementValueCheck, type: :model do + subject(:question) { described_class.new(question_id, question_definition, page, person_index: 1) } + + let(:question_id) { nil } + let(:question_definition) { nil } + let(:page) { instance_double(Form::Page) } + + it "has correct page" do + expect(question.page).to eq(page) + end + + it "has the correct id" do + expect(question.id).to eq("retirement_value_check") + end + + it "has the correct header" do + expect(question.header).to eq("Are you sure this person is retired?") + end + + it "has the correct check_answer_label" do + expect(question.check_answer_label).to eq("Retirement confirmation") + end + + it "has the correct type" do + expect(question.type).to eq("interruption_screen") + end + + it "is not marked as derived" do + expect(question.derived?).to be false + end + + it "has the correct hint" do + expect(question.hint_text).to be_nil + end + + it "has a correct check_answers_card_number" do + expect(question.check_answers_card_number).to eq(1) + end + + it "has the correct answer_options" do + expect(question.answer_options).to eq({ + "0" => { "value" => "Yes" }, + "1" => { "value" => "No" }, + }) + end + + it "has the correct hidden_in_check_answers" do + expect(question.hidden_in_check_answers).to eq({ + "depends_on" => [ + { + "retirement_value_check" => 0, + }, + { + "retirement_value_check" => 1, + }, + ], + }) + end +end diff --git a/spec/models/form/sales/subsections/household_characteristics_spec.rb b/spec/models/form/sales/subsections/household_characteristics_spec.rb index 15c8be02f..34b1a7536 100644 --- a/spec/models/form/sales/subsections/household_characteristics_spec.rb +++ b/spec/models/form/sales/subsections/household_characteristics_spec.rb @@ -17,7 +17,11 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model buyer_interview privacy_notice buyer_1_age + age_1_retirement_value_check + age_1_retirement_value_check_joint_purchase buyer_1_gender_identity + gender_1_retirement_value_check + gender_1_retirement_value_check_joint_purchase buyer_1_ethnic_group buyer_1_ethnic_background_black buyer_1_ethnic_background_asian @@ -26,12 +30,17 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model buyer_1_ethnic_background_white buyer_1_nationality buyer_1_working_situation + working_situation_1_retirement_value_check + working_situation_1_retirement_value_check_joint_purchase working_situation_buyer_1_income_value_check buyer_1_live_in_property buyer_2_relationship_to_buyer_1 buyer_2_age + age_2_retirement_value_check_joint_purchase buyer_2_gender_identity + gender_2_retirement_value_check_joint_purchase buyer_2_working_situation + working_situation_2_retirement_value_check_joint_purchase buyer_2_live_in_property number_of_others_in_property person_1_known @@ -39,41 +48,65 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model person_1_relationship_to_buyer_1 person_1_relationship_to_buyer_1_joint_purchase person_1_age + age_2_retirement_value_check person_1_age_joint_purchase + age_3_retirement_value_check_joint_purchase person_1_gender_identity + gender_2_retirement_value_check person_1_gender_identity_joint_purchase + gender_3_retirement_value_check_joint_purchase person_1_working_situation + working_situation_2_retirement_value_check person_1_working_situation_joint_purchase + working_situation_3_retirement_value_check_joint_purchase person_2_known person_2_known_joint_purchase person_2_relationship_to_buyer_1 person_2_relationship_to_buyer_1_joint_purchase person_2_age + age_3_retirement_value_check person_2_age_joint_purchase + age_4_retirement_value_check_joint_purchase person_2_gender_identity + gender_3_retirement_value_check person_2_gender_identity_joint_purchase + gender_4_retirement_value_check_joint_purchase person_2_working_situation + working_situation_3_retirement_value_check person_2_working_situation_joint_purchase + working_situation_4_retirement_value_check_joint_purchase person_3_known person_3_known_joint_purchase person_3_relationship_to_buyer_1 person_3_relationship_to_buyer_1_joint_purchase person_3_age + age_4_retirement_value_check person_3_age_joint_purchase + age_5_retirement_value_check_joint_purchase person_3_gender_identity + gender_4_retirement_value_check person_3_gender_identity_joint_purchase + gender_5_retirement_value_check_joint_purchase person_3_working_situation + working_situation_4_retirement_value_check person_3_working_situation_joint_purchase + working_situation_5_retirement_value_check_joint_purchase person_4_known person_4_known_joint_purchase person_4_relationship_to_buyer_1 person_4_relationship_to_buyer_1_joint_purchase person_4_age + age_5_retirement_value_check person_4_age_joint_purchase + age_6_retirement_value_check_joint_purchase person_4_gender_identity + gender_5_retirement_value_check person_4_gender_identity_joint_purchase + gender_6_retirement_value_check_joint_purchase person_4_working_situation + working_situation_5_retirement_value_check person_4_working_situation_joint_purchase + working_situation_6_retirement_value_check_joint_purchase ], ) end diff --git a/spec/models/form_handler_spec.rb b/spec/models/form_handler_spec.rb index 1e0483fbc..c272ac4a9 100644 --- a/spec/models/form_handler_spec.rb +++ b/spec/models/form_handler_spec.rb @@ -52,14 +52,14 @@ RSpec.describe FormHandler do it "is able to load a current sales form" do form = form_handler.get_form("current_sales") expect(form).to be_a(Form) - expect(form.pages.count).to eq(149) + expect(form.pages.count).to eq(182) expect(form.name).to eq("2022_2023_sales") end it "is able to load a previous sales form" do form = form_handler.get_form("previous_sales") expect(form).to be_a(Form) - expect(form.pages.count).to eq(149) + expect(form.pages.count).to eq(182) expect(form.name).to eq("2021_2022_sales") end end diff --git a/spec/models/validations/sales/household_validations_spec.rb b/spec/models/validations/sales/household_validations_spec.rb index bdfb01ea4..61a204878 100644 --- a/spec/models/validations/sales/household_validations_spec.rb +++ b/spec/models/validations/sales/household_validations_spec.rb @@ -164,5 +164,120 @@ RSpec.describe Validations::Sales::HouseholdValidations do expect(record.errors["ecstat2"]) .to include(match I18n.t("validations.household.ecstat.student_16_19.cannot_be_student.child_not_16_19")) end + + context "when it is a joint purchase and both buyers are over 64" do + let(:record) { FactoryBot.build(:sales_log, jointpur: 1, age1: 65, age2: 66, type: 24) } + + it "does not add an error" do + household_validator.validate_buyers_age_for_old_persons_shared_ownership(record) + + expect(record.errors).not_to be_present + end + end + + context "when it is a joint purchase and first buyer is over 64" do + let(:record) { FactoryBot.build(:sales_log, jointpur: 1, age1: 65, age2: 40, type: 24) } + + it "does not add an error" do + household_validator.validate_buyers_age_for_old_persons_shared_ownership(record) + + expect(record.errors).not_to be_present + end + end + + context "when it is a joint purchase and second buyer is over 64" do + let(:record) { FactoryBot.build(:sales_log, jointpur: 1, age1: 43, age2: 64, type: 24) } + + it "does not add an error" do + household_validator.validate_buyers_age_for_old_persons_shared_ownership(record) + + expect(record.errors).not_to be_present + end + end + + context "when it is a joint purchase and neither of the buyers are over 64" do + let(:record) { FactoryBot.build(:sales_log, jointpur: 1, age1: 43, age2: 33, type: 24) } + + it "adds an error" do + household_validator.validate_buyers_age_for_old_persons_shared_ownership(record) + + expect(record.errors["age1"]) + .to include(match I18n.t("validations.household.old_persons_shared_ownership")) + expect(record.errors["age2"]) + .to include(match I18n.t("validations.household.old_persons_shared_ownership")) + expect(record.errors["type"]) + .to include(match I18n.t("validations.household.old_persons_shared_ownership")) + end + end + + context "when it is a joint purchase and first buyer is under 64 and the second buyers' age is unknown" do + let(:record) { FactoryBot.build(:sales_log, jointpur: 1, age1: 43, age2_known: 1, type: 24) } + + it "adds an error" do + household_validator.validate_buyers_age_for_old_persons_shared_ownership(record) + + expect(record.errors["age1"]) + .to include(match I18n.t("validations.household.old_persons_shared_ownership")) + expect(record.errors["age2"]) + .to include(match I18n.t("validations.household.old_persons_shared_ownership")) + expect(record.errors["type"]) + .to include(match I18n.t("validations.household.old_persons_shared_ownership")) + end + end + + context "when it is a joint purchase and neither of the buyers ages are known" do + let(:record) { FactoryBot.build(:sales_log, jointpur: 1, age1_known: 1, age2_known: 1, type: 24) } + + it "adds an error" do + household_validator.validate_buyers_age_for_old_persons_shared_ownership(record) + + expect(record.errors["age1"]) + .to include(match I18n.t("validations.household.old_persons_shared_ownership")) + expect(record.errors["age2"]) + .to include(match I18n.t("validations.household.old_persons_shared_ownership")) + expect(record.errors["type"]) + .to include(match I18n.t("validations.household.old_persons_shared_ownership")) + end + end + + context "when it is not a joint purchase and the buyer is over 64" do + let(:record) { FactoryBot.build(:sales_log, jointpur: 2, age1: 70, type: 24) } + + it "does not add an error" do + household_validator.validate_buyers_age_for_old_persons_shared_ownership(record) + + expect(record.errors).not_to be_present + end + end + + context "when it is not a joint purchase and the buyer is under 64" do + let(:record) { FactoryBot.build(:sales_log, jointpur: 2, age1: 20, type: 24) } + + it "adds an error" do + household_validator.validate_buyers_age_for_old_persons_shared_ownership(record) + + expect(record.errors["age1"]) + .to include(match I18n.t("validations.household.old_persons_shared_ownership")) + expect(record.errors["age2"]) + .to be_empty + expect(record.errors["type"]) + .to include(match I18n.t("validations.household.old_persons_shared_ownership")) + end + end + + context "when it is not a joint purchase and the buyers age is not known" do + let(:record) { FactoryBot.build(:sales_log, jointpur: 2, age1_known: 1, type: 24) } + + it "adds an error" do + household_validator.validate_buyers_age_for_old_persons_shared_ownership(record) + + expect(record.errors["age1"]) + .to include(match I18n.t("validations.household.old_persons_shared_ownership")) + expect(record.errors["age2"]) + .to be_empty + expect(record.errors["type"]) + .to include(match I18n.t("validations.household.old_persons_shared_ownership")) + end + end end end