diff --git a/app/models/form/lettings/pages/person_lead_partner.rb b/app/models/form/lettings/pages/person_lead_partner.rb new file mode 100644 index 000000000..30613d976 --- /dev/null +++ b/app/models/form/lettings/pages/person_lead_partner.rb @@ -0,0 +1,12 @@ +class Form::Lettings::Pages::PersonLeadPartner < ::Form::Page + def initialize(id, hsh, subsection, person_index:) + super(id, hsh, subsection) + @id = "person_#{person_index}_lead_partner" + @depends_on = [{ "details_known_#{person_index}" => 0 }] + @person_index = person_index + end + + def questions + @questions ||= [Form::Lettings::Questions::PersonPartner.new(nil, nil, self, person_index: @person_index)] + end +end diff --git a/app/models/form/lettings/pages/rent_4_weekly.rb b/app/models/form/lettings/pages/rent_4_weekly.rb index aa6441f6e..4bfaf28ff 100644 --- a/app/models/form/lettings/pages/rent_4_weekly.rb +++ b/app/models/form/lettings/pages/rent_4_weekly.rb @@ -3,10 +3,7 @@ class Form::Lettings::Pages::Rent4Weekly < ::Form::Page super @id = "rent_4_weekly" @copy_key = "lettings.income_and_benefits.rent_and_charges" - @depends_on = [ - { "household_charge" => 0, "rent_and_charges_paid_every_4_weeks?" => true, "is_carehome?" => false }, - { "household_charge" => nil, "rent_and_charges_paid_every_4_weeks?" => true, "is_carehome?" => false }, - ] + @depends_on = depends_on end def questions @@ -18,4 +15,18 @@ class Form::Lettings::Pages::Rent4Weekly < ::Form::Page Form::Lettings::Questions::Tcharge4Weekly.new(nil, nil, self), ] end + + def depends_on + if form.start_year_2025_or_later? + [ + { "household_charge" => 0, "rent_and_charges_paid_every_4_weeks?" => true }, + { "household_charge" => nil, "rent_and_charges_paid_every_4_weeks?" => true }, + ] + else + [ + { "household_charge" => 0, "rent_and_charges_paid_every_4_weeks?" => true, "is_carehome?" => false }, + { "household_charge" => nil, "rent_and_charges_paid_every_4_weeks?" => true, "is_carehome?" => false }, + ] + end + end end diff --git a/app/models/form/lettings/pages/rent_bi_weekly.rb b/app/models/form/lettings/pages/rent_bi_weekly.rb index 7eab8daf4..aad9e9312 100644 --- a/app/models/form/lettings/pages/rent_bi_weekly.rb +++ b/app/models/form/lettings/pages/rent_bi_weekly.rb @@ -3,10 +3,7 @@ class Form::Lettings::Pages::RentBiWeekly < ::Form::Page super @id = "rent_bi_weekly" @copy_key = "lettings.income_and_benefits.rent_and_charges" - @depends_on = [ - { "household_charge" => nil, "rent_and_charges_paid_every_2_weeks?" => true, "is_carehome?" => false }, - { "household_charge" => 0, "rent_and_charges_paid_every_2_weeks?" => true, "is_carehome?" => false }, - ] + @depends_on = depends_on end def questions @@ -18,4 +15,18 @@ class Form::Lettings::Pages::RentBiWeekly < ::Form::Page Form::Lettings::Questions::TchargeBiWeekly.new(nil, nil, self), ] end + + def depends_on + if form.start_year_2025_or_later? + [ + { "household_charge" => nil, "rent_and_charges_paid_every_2_weeks?" => true }, + { "household_charge" => 0, "rent_and_charges_paid_every_2_weeks?" => true }, + ] + else + [ + { "household_charge" => nil, "rent_and_charges_paid_every_2_weeks?" => true, "is_carehome?" => false }, + { "household_charge" => 0, "rent_and_charges_paid_every_2_weeks?" => true, "is_carehome?" => false }, + ] + end + end end diff --git a/app/models/form/lettings/pages/rent_monthly.rb b/app/models/form/lettings/pages/rent_monthly.rb index 9a3cd6a7e..1fcc21b17 100644 --- a/app/models/form/lettings/pages/rent_monthly.rb +++ b/app/models/form/lettings/pages/rent_monthly.rb @@ -3,10 +3,7 @@ class Form::Lettings::Pages::RentMonthly < ::Form::Page super @id = "rent_monthly" @copy_key = "lettings.income_and_benefits.rent_and_charges" - @depends_on = [ - { "household_charge" => nil, "rent_and_charges_paid_monthly?" => true, "is_carehome?" => false }, - { "household_charge" => 0, "rent_and_charges_paid_monthly?" => true, "is_carehome?" => false }, - ] + @depends_on = depends_on end def questions @@ -18,4 +15,18 @@ class Form::Lettings::Pages::RentMonthly < ::Form::Page Form::Lettings::Questions::TchargeMonthly.new(nil, nil, self), ] end + + def depends_on + if form.start_year_2025_or_later? + [ + { "household_charge" => nil, "rent_and_charges_paid_monthly?" => true }, + { "household_charge" => 0, "rent_and_charges_paid_monthly?" => true }, + ] + else + [ + { "household_charge" => nil, "rent_and_charges_paid_monthly?" => true, "is_carehome?" => false }, + { "household_charge" => 0, "rent_and_charges_paid_monthly?" => true, "is_carehome?" => false }, + ] + end + end end diff --git a/app/models/form/lettings/pages/rent_weekly.rb b/app/models/form/lettings/pages/rent_weekly.rb index 86106cfe3..b40641ebe 100644 --- a/app/models/form/lettings/pages/rent_weekly.rb +++ b/app/models/form/lettings/pages/rent_weekly.rb @@ -3,10 +3,7 @@ class Form::Lettings::Pages::RentWeekly < ::Form::Page super @id = "rent_weekly" @copy_key = "lettings.income_and_benefits.rent_and_charges" - @depends_on = [ - { "rent_and_charges_paid_weekly?" => true, "household_charge" => 0, "is_carehome?" => false }, - { "rent_and_charges_paid_weekly?" => true, "household_charge" => nil, "is_carehome?" => false }, - ] + @depends_on = depends_on end def questions @@ -18,4 +15,18 @@ class Form::Lettings::Pages::RentWeekly < ::Form::Page Form::Lettings::Questions::TchargeWeekly.new(nil, nil, self), ] end + + def depends_on + if form.start_year_2025_or_later? + [ + { "rent_and_charges_paid_weekly?" => true, "household_charge" => 0 }, + { "rent_and_charges_paid_weekly?" => true, "household_charge" => nil }, + ] + else + [ + { "rent_and_charges_paid_weekly?" => true, "household_charge" => 0, "is_carehome?" => false }, + { "rent_and_charges_paid_weekly?" => true, "household_charge" => nil, "is_carehome?" => false }, + ] + end + end end diff --git a/app/models/form/lettings/questions/person_partner.rb b/app/models/form/lettings/questions/person_partner.rb new file mode 100644 index 000000000..25c2d72c1 --- /dev/null +++ b/app/models/form/lettings/questions/person_partner.rb @@ -0,0 +1,30 @@ +class Form::Lettings::Questions::PersonPartner < ::Form::Question + def initialize(id, hsh, page, person_index:) + super(id, hsh, page) + @id = "relat#{person_index}" + @type = "radio" + @check_answers_card_number = person_index + @answer_options = answer_options + @person_index = person_index + @question_number = question_number + end + + def answer_options + { + "P" => { "value" => "Yes" }, + "X" => { "value" => "No" }, + "R" => { "value" => "Tenant prefers not to say" }, + } + end + + def question_number + base_question_number = case form.start_date.year + when 2023 + 30 + else + 29 + end + + base_question_number + (4 * @person_index) + end +end diff --git a/app/models/form/lettings/subsections/household_characteristics.rb b/app/models/form/lettings/subsections/household_characteristics.rb index 61334d84c..a454ffed5 100644 --- a/app/models/form/lettings/subsections/household_characteristics.rb +++ b/app/models/form/lettings/subsections/household_characteristics.rb @@ -32,7 +32,7 @@ class Form::Lettings::Subsections::HouseholdCharacteristics < ::Form::Subsection Form::Lettings::Pages::LeadTenantUnderRetirementValueCheck.new("working_situation_lead_tenant_under_retirement_value_check", nil, self), Form::Lettings::Pages::LeadTenantOverRetirementValueCheck.new("working_situation_lead_tenant_over_retirement_value_check", nil, self), Form::Lettings::Pages::PersonKnown.new(nil, nil, self, person_index: 2), - Form::Lettings::Pages::PersonRelationshipToLead.new(nil, nil, self, person_index: 2), + relationship_question(person_index: 2), (Form::Lettings::Pages::PartnerUnder16ValueCheck.new("relationship_2_partner_under_16_value_check", nil, self, person_index: 2) if form.start_year_2024_or_later?), (Form::Lettings::Pages::MultiplePartnersValueCheck.new("relationship_2_multiple_partners_value_check", nil, self, person_index: 2) if form.start_year_2024_or_later?), Form::Lettings::Pages::PersonAge.new(nil, nil, self, person_index: 2), @@ -52,7 +52,7 @@ class Form::Lettings::Subsections::HouseholdCharacteristics < ::Form::Subsection Form::Lettings::Pages::PersonUnderRetirementValueCheck.new("working_situation_2_under_retirement_value_check", nil, self, person_index: 2), Form::Lettings::Pages::PersonOverRetirementValueCheck.new("working_situation_2_over_retirement_value_check", nil, self, person_index: 2), Form::Lettings::Pages::PersonKnown.new(nil, nil, self, person_index: 3), - Form::Lettings::Pages::PersonRelationshipToLead.new(nil, nil, self, person_index: 3), + relationship_question(person_index: 3), (Form::Lettings::Pages::PartnerUnder16ValueCheck.new("relationship_3_partner_under_16_value_check", nil, self, person_index: 3) if form.start_year_2024_or_later?), (Form::Lettings::Pages::MultiplePartnersValueCheck.new("relationship_3_multiple_partners_value_check", nil, self, person_index: 3) if form.start_year_2024_or_later?), Form::Lettings::Pages::PersonAge.new(nil, nil, self, person_index: 3), @@ -72,7 +72,7 @@ class Form::Lettings::Subsections::HouseholdCharacteristics < ::Form::Subsection Form::Lettings::Pages::PersonUnderRetirementValueCheck.new("working_situation_3_under_retirement_value_check", nil, self, person_index: 3), Form::Lettings::Pages::PersonOverRetirementValueCheck.new("working_situation_3_over_retirement_value_check", nil, self, person_index: 3), Form::Lettings::Pages::PersonKnown.new(nil, nil, self, person_index: 4), - Form::Lettings::Pages::PersonRelationshipToLead.new(nil, nil, self, person_index: 4), + relationship_question(person_index: 4), (Form::Lettings::Pages::PartnerUnder16ValueCheck.new("relationship_4_partner_under_16_value_check", nil, self, person_index: 4) if form.start_year_2024_or_later?), (Form::Lettings::Pages::MultiplePartnersValueCheck.new("relationship_4_multiple_partners_value_check", nil, self, person_index: 4) if form.start_year_2024_or_later?), Form::Lettings::Pages::PersonAge.new(nil, nil, self, person_index: 4), @@ -92,7 +92,7 @@ class Form::Lettings::Subsections::HouseholdCharacteristics < ::Form::Subsection Form::Lettings::Pages::PersonUnderRetirementValueCheck.new("working_situation_4_under_retirement_value_check", nil, self, person_index: 4), Form::Lettings::Pages::PersonOverRetirementValueCheck.new("working_situation_4_over_retirement_value_check", nil, self, person_index: 4), Form::Lettings::Pages::PersonKnown.new(nil, nil, self, person_index: 5), - Form::Lettings::Pages::PersonRelationshipToLead.new(nil, nil, self, person_index: 5), + relationship_question(person_index: 5), (Form::Lettings::Pages::PartnerUnder16ValueCheck.new("relationship_5_partner_under_16_value_check", nil, self, person_index: 5) if form.start_year_2024_or_later?), (Form::Lettings::Pages::MultiplePartnersValueCheck.new("relationship_5_multiple_partners_value_check", nil, self, person_index: 5) if form.start_year_2024_or_later?), Form::Lettings::Pages::PersonAge.new(nil, nil, self, person_index: 5), @@ -112,7 +112,7 @@ class Form::Lettings::Subsections::HouseholdCharacteristics < ::Form::Subsection Form::Lettings::Pages::PersonUnderRetirementValueCheck.new("working_situation_5_under_retirement_value_check", nil, self, person_index: 5), Form::Lettings::Pages::PersonOverRetirementValueCheck.new("working_situation_5_over_retirement_value_check", nil, self, person_index: 5), Form::Lettings::Pages::PersonKnown.new(nil, nil, self, person_index: 6), - Form::Lettings::Pages::PersonRelationshipToLead.new(nil, nil, self, person_index: 6), + relationship_question(person_index: 6), (Form::Lettings::Pages::PartnerUnder16ValueCheck.new("relationship_6_partner_under_16_value_check", nil, self, person_index: 6) if form.start_year_2024_or_later?), (Form::Lettings::Pages::MultiplePartnersValueCheck.new("relationship_6_multiple_partners_value_check", nil, self, person_index: 6) if form.start_year_2024_or_later?), Form::Lettings::Pages::PersonAge.new(nil, nil, self, person_index: 6), @@ -132,7 +132,7 @@ class Form::Lettings::Subsections::HouseholdCharacteristics < ::Form::Subsection Form::Lettings::Pages::PersonUnderRetirementValueCheck.new("working_situation_6_under_retirement_value_check", nil, self, person_index: 6), Form::Lettings::Pages::PersonOverRetirementValueCheck.new("working_situation_6_over_retirement_value_check", nil, self, person_index: 6), Form::Lettings::Pages::PersonKnown.new(nil, nil, self, person_index: 7), - Form::Lettings::Pages::PersonRelationshipToLead.new(nil, nil, self, person_index: 7), + relationship_question(person_index: 7), (Form::Lettings::Pages::PartnerUnder16ValueCheck.new("relationship_7_partner_under_16_value_check", nil, self, person_index: 7) if form.start_year_2024_or_later?), (Form::Lettings::Pages::MultiplePartnersValueCheck.new("relationship_7_multiple_partners_value_check", nil, self, person_index: 7) if form.start_year_2024_or_later?), Form::Lettings::Pages::PersonAge.new(nil, nil, self, person_index: 7), @@ -152,7 +152,7 @@ class Form::Lettings::Subsections::HouseholdCharacteristics < ::Form::Subsection Form::Lettings::Pages::PersonUnderRetirementValueCheck.new("working_situation_7_under_retirement_value_check", nil, self, person_index: 7), Form::Lettings::Pages::PersonOverRetirementValueCheck.new("working_situation_7_over_retirement_value_check", nil, self, person_index: 7), Form::Lettings::Pages::PersonKnown.new(nil, nil, self, person_index: 8), - Form::Lettings::Pages::PersonRelationshipToLead.new(nil, nil, self, person_index: 8), + relationship_question(person_index: 8), (Form::Lettings::Pages::PartnerUnder16ValueCheck.new("relationship_8_partner_under_16_value_check", nil, self, person_index: 8) if form.start_year_2024_or_later?), (Form::Lettings::Pages::MultiplePartnersValueCheck.new("relationship_8_multiple_partners_value_check", nil, self, person_index: 8) if form.start_year_2024_or_later?), Form::Lettings::Pages::PersonAge.new(nil, nil, self, person_index: 8), @@ -173,4 +173,12 @@ class Form::Lettings::Subsections::HouseholdCharacteristics < ::Form::Subsection Form::Lettings::Pages::PersonOverRetirementValueCheck.new("working_situation_8_over_retirement_value_check", nil, self, person_index: 8), ].compact end + + def relationship_question(person_index:) + if form.start_year_2025_or_later? + Form::Lettings::Pages::PersonLeadPartner.new(nil, nil, self, person_index:) + else + Form::Lettings::Pages::PersonRelationshipToLead.new(nil, nil, self, person_index:) + end + end end diff --git a/app/models/form/lettings/subsections/income_and_benefits.rb b/app/models/form/lettings/subsections/income_and_benefits.rb index 2be2fb9a5..4ad3003cb 100644 --- a/app/models/form/lettings/subsections/income_and_benefits.rb +++ b/app/models/form/lettings/subsections/income_and_benefits.rb @@ -15,11 +15,7 @@ class Form::Lettings::Subsections::IncomeAndBenefits < ::Form::Subsection Form::Lettings::Pages::BenefitsProportion.new("benefits_proportion", nil, self), Form::Lettings::Pages::RentOrOtherCharges.new(nil, nil, self), Form::Lettings::Pages::RentPeriod.new(nil, nil, self), - Form::Lettings::Pages::CareHomeWeekly.new(nil, nil, self), - Form::Lettings::Pages::CareHomeBiWeekly.new(nil, nil, self), - Form::Lettings::Pages::CareHome4Weekly.new(nil, nil, self), - Form::Lettings::Pages::CareHomeMonthly.new(nil, nil, self), - Form::Lettings::Pages::CareHomeChargesValueCheck.new(nil, nil, self), + carehome_questions, Form::Lettings::Pages::RentWeekly.new(nil, nil, self), Form::Lettings::Pages::RentBiWeekly.new(nil, nil, self), Form::Lettings::Pages::Rent4Weekly.new(nil, nil, self), @@ -30,6 +26,20 @@ class Form::Lettings::Subsections::IncomeAndBenefits < ::Form::Subsection Form::Lettings::Pages::SupchargValueCheck.new(nil, nil, self), Form::Lettings::Pages::Outstanding.new(nil, nil, self), Form::Lettings::Pages::OutstandingAmount.new(nil, nil, self), - ].compact + ].flatten.compact + end + +private + + def carehome_questions + return [] if form.start_year_2025_or_later? + + [ + Form::Lettings::Pages::CareHomeWeekly.new(nil, nil, self), + Form::Lettings::Pages::CareHomeBiWeekly.new(nil, nil, self), + Form::Lettings::Pages::CareHome4Weekly.new(nil, nil, self), + Form::Lettings::Pages::CareHomeMonthly.new(nil, nil, self), + Form::Lettings::Pages::CareHomeChargesValueCheck.new(nil, nil, self), + ] end end diff --git a/app/models/validations/date_validations.rb b/app/models/validations/date_validations.rb index 7462290b6..f69f41cdd 100644 --- a/app/models/validations/date_validations.rb +++ b/app/models/validations/date_validations.rb @@ -2,53 +2,56 @@ module Validations::DateValidations include Validations::SharedValidations def validate_property_major_repairs(record) - date_valid?("mrcdate", record) - if record["startdate"].present? && record["mrcdate"].present? && record["startdate"] < record["mrcdate"] - record.errors.add :mrcdate, I18n.t("validations.lettings.date.mrcdate.before_tenancy_start") - end + return unless record["mrcdate"].present? && date_valid?("mrcdate", record) if is_rsnvac_first_let?(record) && record["mrcdate"].present? record.errors.add :mrcdate, I18n.t("validations.lettings.date.mrcdate.not_first_let") end + return unless record["startdate"].present? && date_valid?("startdate", record) - if record["mrcdate"].present? && record["startdate"].present? && record["startdate"].to_date - record["mrcdate"].to_date > 3650 + if record["startdate"].present? && record["mrcdate"].present? && record["startdate"] < record["mrcdate"] + record.errors.add :mrcdate, I18n.t("validations.lettings.date.mrcdate.before_tenancy_start") + record.errors.add :startdate, I18n.t("validations.lettings.date.startdate.after_major_repair_date") + end + + if record.form.start_year_2025_or_later? + if record["startdate"].to_date - 20.years > record["mrcdate"].to_date + record.errors.add :mrcdate, I18n.t("validations.lettings.date.mrcdate.twenty_years_before_tenancy_start") + record.errors.add :startdate, I18n.t("validations.lettings.date.startdate.twenty_years_after_mrc_date") + end + elsif record["startdate"].to_date - 10.years > record["mrcdate"].to_date record.errors.add :mrcdate, I18n.t("validations.lettings.date.mrcdate.ten_years_before_tenancy_start") + record.errors.add :startdate, I18n.t("validations.lettings.date.startdate.ten_years_after_mrc_date") end end def validate_property_void_date(record) - if record["voiddate"].present? && record["startdate"].present? && record["startdate"].to_date - record["voiddate"].to_date > 3650 - record.errors.add :voiddate, I18n.t("validations.lettings.date.void_date.ten_years_before_tenancy_start") - end - - if record["voiddate"].present? && record["startdate"].present? && record["startdate"].to_date < record["voiddate"].to_date - record.errors.add :voiddate, I18n.t("validations.lettings.date.void_date.before_tenancy_start") - end + return unless record["voiddate"].present? && date_valid?("voiddate", record) - if record["voiddate"].present? && record["mrcdate"].present? && record["mrcdate"].to_date < record["voiddate"].to_date + if record["mrcdate"].present? && record["mrcdate"].to_date < record["voiddate"].to_date record.errors.add :voiddate, :after_mrcdate, message: I18n.t("validations.lettings.date.void_date.after_mrcdate") record.errors.add :mrcdate, I18n.t("validations.lettings.date.mrcdate.before_void_date") end - end - - def validate_startdate(record) - return unless record.startdate && date_valid?("startdate", record) + return unless record["startdate"].present? && date_valid?("startdate", record) - if record["voiddate"].present? && record.startdate < record["voiddate"] + if record["startdate"].to_date < record["voiddate"].to_date + record.errors.add :voiddate, I18n.t("validations.lettings.date.void_date.before_tenancy_start") record.errors.add :startdate, I18n.t("validations.lettings.date.startdate.after_void_date") end - if record["mrcdate"].present? && record.startdate < record["mrcdate"] - record.errors.add :startdate, I18n.t("validations.lettings.date.startdate.after_major_repair_date") - end - - if record["voiddate"].present? && record["startdate"].to_date - record["voiddate"].to_date > 3650 + if record.form.start_year_2025_or_later? + if record["startdate"].to_date - 20.years > record["voiddate"].to_date + record.errors.add :voiddate, I18n.t("validations.lettings.date.void_date.twenty_years_before_tenancy_start") + record.errors.add :startdate, I18n.t("validations.lettings.date.startdate.twenty_years_after_void_date") + end + elsif record["startdate"].to_date - 10.years > record["voiddate"].to_date + record.errors.add :voiddate, I18n.t("validations.lettings.date.void_date.ten_years_before_tenancy_start") record.errors.add :startdate, I18n.t("validations.lettings.date.startdate.ten_years_after_void_date") end + end - if record["mrcdate"].present? && record["startdate"].to_date - record["mrcdate"].to_date > 3650 - record.errors.add :startdate, I18n.t("validations.lettings.date.startdate.ten_years_after_mrc_date") - end + def validate_startdate(record) + date_valid?("startdate", record) end private diff --git a/app/models/validations/sales/sale_information_validations.rb b/app/models/validations/sales/sale_information_validations.rb index 4b8948053..f99f6668a 100644 --- a/app/models/validations/sales/sale_information_validations.rb +++ b/app/models/validations/sales/sale_information_validations.rb @@ -144,11 +144,11 @@ module Validations::Sales::SaleInformationValidations return unless record.saledate && record.form.start_year_2024_or_later? return unless record.discount && record.value && record.la - if record.london_property? && record.discount_value > 136_400 + if record.london_property? && record.discount_value > 137_400 %i[discount value la postcode_full uprn].each do |field| record.errors.add field, I18n.t("validations.sales.sale_information.#{field}.value_over_discounted_london_max", discount_value: record.field_formatted_as_currency("discount_value")) end - elsif record.property_not_in_london? && record.discount_value > 102_400 + elsif record.property_not_in_london? && record.discount_value > 103_400 %i[discount value la postcode_full uprn].each do |field| record.errors.add field, I18n.t("validations.sales.sale_information.#{field}.value_over_discounted_max", discount_value: record.field_formatted_as_currency("discount_value")) end diff --git a/app/models/validations/shared_validations.rb b/app/models/validations/shared_validations.rb index da79599ee..7b0ecc420 100644 --- a/app/models/validations/shared_validations.rb +++ b/app/models/validations/shared_validations.rb @@ -54,14 +54,15 @@ module Validations::SharedValidations field = question.check_answer_label || question.id incorrect_accuracy = (value.to_d * 100) % (question.step * 100) != 0 - if question.step < 1 && incorrect_accuracy - record.errors.add question.id.to_sym, I18n.t("validations.shared.numeric.nearest_hundredth", field:) - elsif incorrect_accuracy || value.to_d != value.to_i # if the user enters a value in exponent notation (eg '4e1') the to_i method does not convert this to the correct value - field = question.check_answer_label || question.id - case question.step - when 1 then record.errors.add question.id.to_sym, :not_integer, message: I18n.t("validations.shared.numeric.whole_number", field:) - when 10 then record.errors.add question.id.to_sym, I18n.t("validations.shared.numeric.nearest_ten", field:) - end + next unless incorrect_accuracy + + case question.step + when 0.01 then record.errors.add question.id.to_sym, I18n.t("validations.shared.numeric.nearest_hundredth", field:) + when 0.1 then record.errors.add question.id.to_sym, I18n.t("validations.shared.numeric.nearest_tenth", field:) + when 1 then record.errors.add question.id.to_sym, :not_integer, message: I18n.t("validations.shared.numeric.whole_number", field:) + when 10 then record.errors.add question.id.to_sym, I18n.t("validations.shared.numeric.nearest_ten", field:) + else + record.errors.add question.id.to_sym, I18n.t("validations.shared.numeric.nearest_step", field:, step: question.step) end end end diff --git a/config/locales/forms/2025/lettings/household_characteristics.en.yml b/config/locales/forms/2025/lettings/household_characteristics.en.yml index b6d7ad7e9..79646b32b 100644 --- a/config/locales/forms/2025/lettings/household_characteristics.en.yml +++ b/config/locales/forms/2025/lettings/household_characteristics.en.yml @@ -84,9 +84,9 @@ en: relat2: page_header: "" - check_answer_label: "Person 2’s relationship to the lead tenant" + check_answer_label: "Person 2 lead tenant’s partner" hint_text: "" - question_text: "What is person 2’s relationship to the lead tenant?" + question_text: "Is tenant 2 the partner of tenant 1?" age2: page_header: "" @@ -119,9 +119,9 @@ en: relat3: page_header: "" - check_answer_label: "Person 3’s relationship to the lead tenant" + check_answer_label: "Person 3 lead tenant’s partner" hint_text: "" - question_text: "What is person 3’s relationship to the lead tenant?" + question_text: "Is tenant 3 the partner of tenant 1?" age3: page_header: "" @@ -154,9 +154,9 @@ en: relat4: page_header: "" - check_answer_label: "Person 4’s relationship to the lead tenant" + check_answer_label: "Person 4 lead tenant’s partner" hint_text: "" - question_text: "What is person 4’s relationship to the lead tenant?" + question_text: "Is tenant 4 the partner of tenant 1?" age4: page_header: "" @@ -189,9 +189,9 @@ en: relat5: page_header: "" - check_answer_label: "Person 5’s relationship to the lead tenant" + check_answer_label: "Person 5 lead tenant’s partner" hint_text: "" - question_text: "What is person 5’s relationship to the lead tenant?" + question_text: "Is tenant 5 the partner of tenant 1?" age5: page_header: "" @@ -224,9 +224,9 @@ en: relat6: page_header: "" - check_answer_label: "Person 6’s relationship to the lead tenant" + check_answer_label: "Person 6 lead tenant’s partner" hint_text: "" - question_text: "What is person 6’s relationship to the lead tenant?" + question_text: "Is tenant 6 the partner of tenant 1?" age6: page_header: "" @@ -259,9 +259,9 @@ en: relat7: page_header: "" - check_answer_label: "Person 7’s relationship to the lead tenant" + check_answer_label: "Person 7 lead tenant’s partner" hint_text: "" - question_text: "What is person 7’s relationship to the lead tenant?" + question_text: "Is tenant 7 the partner of tenant 1?" age7: page_header: "" @@ -294,9 +294,9 @@ en: relat8: page_header: "" - check_answer_label: "Person 8’s relationship to the lead tenant" + check_answer_label: "Person 8 lead tenant’s partner" hint_text: "" - question_text: "What is person 8’s relationship to the lead tenant?" + question_text: "Is tenant 8 the partner of tenant 1?" age8: page_header: "" diff --git a/config/locales/validations/lettings/date.en.yml b/config/locales/validations/lettings/date.en.yml index 54c53996f..1e46dba7b 100644 --- a/config/locales/validations/lettings/date.en.yml +++ b/config/locales/validations/lettings/date.en.yml @@ -7,14 +7,18 @@ en: after_major_repair_date: "Enter a tenancy start date that is after the major repair date." ten_years_after_void_date: "Enter a tenancy start date that is no more than 10 years after the void date." ten_years_after_mrc_date: "Enter a tenancy start date that is no more than 10 years after the major repairs completion date." + twenty_years_after_void_date: "Enter a tenancy start date that is no more than 20 years after the void date." + twenty_years_after_mrc_date: "Enter a tenancy start date that is no more than 20 years after the major repairs completion date." mrcdate: before_tenancy_start: "Enter a major repairs date that is before the tenancy start date." not_first_let: "Major repairs date must not be completed if the tenancy is a first let." ten_years_before_tenancy_start: "Enter a major repairs completion date that is no more than 10 years before the tenancy start date." + twenty_years_before_tenancy_start: "Enter a major repairs completion date that is no more than 20 years before the tenancy start date." before_void_date: "Major repairs date must be after the void date if provided." void_date: ten_years_before_tenancy_start: "Enter a void date no more than 10 years before the tenancy start date." + twenty_years_before_tenancy_start: "Enter a void date no more than 20 years before the tenancy start date." before_tenancy_start: "Enter a void date that is before the tenancy start date." after_mrcdate: "Void date must be before the major repairs date if provided." diff --git a/config/locales/validations/sales/sale_information.en.yml b/config/locales/validations/sales/sale_information.en.yml index ea17953fb..f29856143 100644 --- a/config/locales/validations/sales/sale_information.en.yml +++ b/config/locales/validations/sales/sale_information.en.yml @@ -47,8 +47,8 @@ en: value: discounted_ownership_value: "The mortgage%{mortgage}%{deposit_and_grant_sentence} added together is %{mortgage_deposit_and_grant_total}.

The full purchase price%{discount_sentence} is %{value_with_discount}.

These two amounts should be the same." outright_sale_value: "The mortgage%{mortgage} and cash deposit (%{deposit}) when added together is %{mortgage_and_deposit_total}.

The full purchase price is %{value}.

These two amounts should be the same." - value_over_discounted_london_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £136,400 for properties in London." - value_over_discounted_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £102,400 for properties outside of London." + value_over_discounted_london_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £137,400 for properties in London." + value_over_discounted_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £103,400 for properties outside of London." non_staircasing_mortgage: mortgage_used: "The mortgage (%{mortgage}) and cash deposit (%{deposit}) added together is %{mortgage_and_deposit_total}.

The full purchase price (%{value}) multiplied by the percentage equity stake purchased (%{equity}) is %{expected_shared_ownership_deposit_value}.

These two amounts should be the same." mortgage_not_used: "The cash deposit is %{deposit}.

The full purchase price (%{value}) multiplied by the percentage bought is %{expected_shared_ownership_deposit_value}.

These two amounts should be the same." @@ -87,8 +87,8 @@ en: mortgage_not_used_socialhomebuy: "The cash deposit (%{deposit}) and cash discount (%{cashdis}) added together is %{deposit_and_discount_total}.

The full purchase price (%{value}) multiplied by the percentage bought (%{equity}) is %{expected_shared_ownership_deposit_value}.

These two amounts should be the same." discount: discounted_ownership_value: "The mortgage%{mortgage}%{deposit_and_grant_sentence} added together is %{mortgage_deposit_and_grant_total}.

The full purchase price%{discount_sentence} is %{value_with_discount}.

These two amounts should be the same." - value_over_discounted_london_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £136,400 for properties in London." - value_over_discounted_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £102,400 for properties outside of London." + value_over_discounted_london_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £137,400 for properties in London." + value_over_discounted_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £103,400 for properties outside of London." grant: discounted_ownership_value: "The mortgage%{mortgage}%{deposit_and_grant_sentence} added together is %{mortgage_deposit_and_grant_total}.

The full purchase price%{discount_sentence} is %{value_with_discount}.

These two amounts should be the same." out_of_range: "Loan, grants or subsidies must be between £9,000 and £16,000." @@ -119,14 +119,14 @@ en: staircase: mortgage_used_value: "You must answer either ‘yes’ or ‘no’ to the question ‘was a mortgage used’ for staircasing transactions." la: - value_over_discounted_london_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £136,400 for properties in London." - value_over_discounted_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £102,400 for properties outside of London." + value_over_discounted_london_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £137,400 for properties in London." + value_over_discounted_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £103,400 for properties outside of London." uprn: - value_over_discounted_london_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £136,400 for properties in London." - value_over_discounted_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £102,400 for properties outside of London." + value_over_discounted_london_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £137,400 for properties in London." + value_over_discounted_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £103,400 for properties outside of London." postcode_full: - value_over_discounted_london_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £136,400 for properties in London." - value_over_discounted_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £102,400 for properties outside of London." + value_over_discounted_london_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £137,400 for properties in London." + value_over_discounted_max: "The percentage discount multiplied by the purchase price is %{discount_value}. This figure should not be more than £103,400 for properties outside of London." numstair: must_be_greater_than_one: "The number of staircasing transactions must be greater than 1 when this is not the first staircasing transaction." firststair: diff --git a/config/locales/validations/shared.en.yml b/config/locales/validations/shared.en.yml index a29d2bd74..ea06636dc 100644 --- a/config/locales/validations/shared.en.yml +++ b/config/locales/validations/shared.en.yml @@ -9,7 +9,9 @@ en: above_min: "%{field} must be at least %{min}." whole_number: "%{field} must be a whole number." nearest_ten: "%{field} must be given to the nearest ten." + nearest_tenth: "%{field} must be given to the nearest tenth." nearest_hundredth: "%{field} must be given to the nearest hundredth." + nearest_step: "${field} must be given to the nearest %{step}." normal_format: "Enter a number." format: "%{field} must be a number." diff --git a/spec/models/form/lettings/pages/person_lead_partner_spec.rb b/spec/models/form/lettings/pages/person_lead_partner_spec.rb new file mode 100644 index 000000000..88aa3095d --- /dev/null +++ b/spec/models/form/lettings/pages/person_lead_partner_spec.rb @@ -0,0 +1,51 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Pages::PersonLeadPartner, type: :model do + subject(:page) { described_class.new(nil, page_definition, subsection, person_index:) } + + let(:page_definition) { nil } + let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2024, 4, 1), start_year_2025_or_later?: true)) } + let(:person_index) { 2 } + + it "has correct subsection" do + expect(page.subsection).to eq(subsection) + end + + it "has the correct description" do + expect(page.description).to be nil + end + + context "with person 2" do + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[relat2]) + end + + it "has the correct id" do + expect(page.id).to eq("person_2_lead_partner") + end + + it "has correct depends_on" do + expect(page.depends_on).to eq( + [{ "details_known_2" => 0 }], + ) + end + end + + context "with person 3" do + let(:person_index) { 3 } + + it "has correct questions" do + expect(page.questions.map(&:id)).to eq(%w[relat3]) + end + + it "has the correct id" do + expect(page.id).to eq("person_3_lead_partner") + end + + it "has correct depends_on" do + expect(page.depends_on).to eq( + [{ "details_known_3" => 0 }], + ) + end + end +end diff --git a/spec/models/form/lettings/pages/rent4_weekly_spec.rb b/spec/models/form/lettings/pages/rent4_weekly_spec.rb new file mode 100644 index 000000000..8a8527d6a --- /dev/null +++ b/spec/models/form/lettings/pages/rent4_weekly_spec.rb @@ -0,0 +1,44 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Pages::Rent4Weekly, type: :model do + subject(:page) { described_class.new(nil, page_definition, subsection) } + + let(:page_definition) { nil } + let(:start_date) { Time.zone.local(2024, 4, 1) } + let(:start_year_2025_or_later) { false } + let(:form) { instance_double(Form, start_date:) } + let(:subsection) { instance_double(Form::Subsection, form:) } + let(:person_index) { 2 } + + before do + allow(form).to receive(:start_year_2025_or_later?).and_return(start_year_2025_or_later) + end + + context "with form before 2025" do + let(:start_date) { Time.zone.local(2024, 4, 1) } + let(:start_year_2025_or_later) { false } + + it "has correct depends_on" do + expect(page.depends_on).to eq( + [ + { "rent_and_charges_paid_every_4_weeks?" => true, "household_charge" => 0, "is_carehome?" => false }, + { "rent_and_charges_paid_every_4_weeks?" => true, "household_charge" => nil, "is_carehome?" => false }, + ], + ) + end + end + + context "with form on or after 2025" do + let(:start_date) { Time.zone.local(2025, 4, 1) } + let(:start_year_2025_or_later) { true } + + it "has correct depends_on" do + expect(page.depends_on).to eq( + [ + { "rent_and_charges_paid_every_4_weeks?" => true, "household_charge" => 0 }, + { "rent_and_charges_paid_every_4_weeks?" => true, "household_charge" => nil }, + ], + ) + end + end +end diff --git a/spec/models/form/lettings/pages/rent_bi_weekly_spec.rb b/spec/models/form/lettings/pages/rent_bi_weekly_spec.rb new file mode 100644 index 000000000..a1975f766 --- /dev/null +++ b/spec/models/form/lettings/pages/rent_bi_weekly_spec.rb @@ -0,0 +1,44 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Pages::RentBiWeekly, type: :model do + subject(:page) { described_class.new(nil, page_definition, subsection) } + + let(:page_definition) { nil } + let(:start_date) { Time.zone.local(2024, 4, 1) } + let(:start_year_2025_or_later) { false } + let(:form) { instance_double(Form, start_date:) } + let(:subsection) { instance_double(Form::Subsection, form:) } + let(:person_index) { 2 } + + before do + allow(form).to receive(:start_year_2025_or_later?).and_return(start_year_2025_or_later) + end + + context "with form before 2025" do + let(:start_date) { Time.zone.local(2024, 4, 1) } + let(:start_year_2025_or_later) { false } + + it "has correct depends_on" do + expect(page.depends_on).to eq( + [ + { "rent_and_charges_paid_every_2_weeks?" => true, "household_charge" => nil, "is_carehome?" => false }, + { "rent_and_charges_paid_every_2_weeks?" => true, "household_charge" => 0, "is_carehome?" => false }, + ], + ) + end + end + + context "with form on or after 2025" do + let(:start_date) { Time.zone.local(2025, 4, 1) } + let(:start_year_2025_or_later) { true } + + it "has correct depends_on" do + expect(page.depends_on).to eq( + [ + { "rent_and_charges_paid_every_2_weeks?" => true, "household_charge" => nil }, + { "rent_and_charges_paid_every_2_weeks?" => true, "household_charge" => 0 }, + ], + ) + end + end +end diff --git a/spec/models/form/lettings/pages/rent_monthly_spec.rb b/spec/models/form/lettings/pages/rent_monthly_spec.rb new file mode 100644 index 000000000..619fc254e --- /dev/null +++ b/spec/models/form/lettings/pages/rent_monthly_spec.rb @@ -0,0 +1,44 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Pages::RentMonthly, type: :model do + subject(:page) { described_class.new(nil, page_definition, subsection) } + + let(:page_definition) { nil } + let(:start_date) { Time.zone.local(2024, 4, 1) } + let(:start_year_2025_or_later) { false } + let(:form) { instance_double(Form, start_date:) } + let(:subsection) { instance_double(Form::Subsection, form:) } + let(:person_index) { 2 } + + before do + allow(form).to receive(:start_year_2025_or_later?).and_return(start_year_2025_or_later) + end + + context "with form before 2025" do + let(:start_date) { Time.zone.local(2024, 4, 1) } + let(:start_year_2025_or_later) { false } + + it "has correct depends_on" do + expect(page.depends_on).to eq( + [ + { "rent_and_charges_paid_monthly?" => true, "household_charge" => nil, "is_carehome?" => false }, + { "rent_and_charges_paid_monthly?" => true, "household_charge" => 0, "is_carehome?" => false }, + ], + ) + end + end + + context "with form on or after 2025" do + let(:start_date) { Time.zone.local(2025, 4, 1) } + let(:start_year_2025_or_later) { true } + + it "has correct depends_on" do + expect(page.depends_on).to eq( + [ + { "rent_and_charges_paid_monthly?" => true, "household_charge" => nil }, + { "rent_and_charges_paid_monthly?" => true, "household_charge" => 0 }, + ], + ) + end + end +end diff --git a/spec/models/form/lettings/pages/rent_weekly_spec.rb b/spec/models/form/lettings/pages/rent_weekly_spec.rb new file mode 100644 index 000000000..89bbae37a --- /dev/null +++ b/spec/models/form/lettings/pages/rent_weekly_spec.rb @@ -0,0 +1,44 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Pages::RentWeekly, type: :model do + subject(:page) { described_class.new(nil, page_definition, subsection) } + + let(:page_definition) { nil } + let(:start_date) { Time.zone.local(2024, 4, 1) } + let(:start_year_2025_or_later) { false } + let(:form) { instance_double(Form, start_date:) } + let(:subsection) { instance_double(Form::Subsection, form:) } + let(:person_index) { 2 } + + before do + allow(form).to receive(:start_year_2025_or_later?).and_return(start_year_2025_or_later) + end + + context "with form before 2025" do + let(:start_date) { Time.zone.local(2024, 4, 1) } + let(:start_year_2025_or_later) { false } + + it "has correct depends_on" do + expect(page.depends_on).to eq( + [ + { "rent_and_charges_paid_weekly?" => true, "household_charge" => 0, "is_carehome?" => false }, + { "rent_and_charges_paid_weekly?" => true, "household_charge" => nil, "is_carehome?" => false }, + ], + ) + end + end + + context "with form on or after 2025" do + let(:start_date) { Time.zone.local(2025, 4, 1) } + let(:start_year_2025_or_later) { true } + + it "has correct depends_on" do + expect(page.depends_on).to eq( + [ + { "rent_and_charges_paid_weekly?" => true, "household_charge" => 0 }, + { "rent_and_charges_paid_weekly?" => true, "household_charge" => nil }, + ], + ) + end + end +end diff --git a/spec/models/form/lettings/questions/person_partner_spec.rb b/spec/models/form/lettings/questions/person_partner_spec.rb new file mode 100644 index 000000000..7e2d177bd --- /dev/null +++ b/spec/models/form/lettings/questions/person_partner_spec.rb @@ -0,0 +1,57 @@ +require "rails_helper" + +RSpec.describe Form::Lettings::Questions::PersonPartner, type: :model do + subject(:question) { described_class.new(nil, question_definition, page, person_index:) } + + let(:question_definition) { nil } + let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2025, 4, 4), start_year_2025_or_later?: true))) } + let(:person_index) { 2 } + + it "has correct page" do + expect(question.page).to eq(page) + end + + it "has the correct type" do + expect(question.type).to eq("radio") + end + + it "is not marked as derived" do + expect(question.derived?(nil)).to be false + end + + it "has the correct answer_options" do + expect(question.answer_options).to eq("P" => { "value" => "Yes" }, + "X" => { "value" => "No" }, + "R" => { "value" => "Tenant prefers not to say" }) + end + + it "has correct conditional for" do + expect(question.conditional_for).to be nil + end + + it "has the correct hidden_in_check_answers" do + expect(question.hidden_in_check_answers).to be nil + end + + context "with person 2" do + it "has the correct id" do + expect(question.id).to eq("relat2") + end + + it "has the correct check_answers_card_number" do + expect(question.check_answers_card_number).to eq(2) + end + end + + context "with person 3" do + let(:person_index) { 3 } + + it "has the correct id" do + expect(question.id).to eq("relat3") + end + + it "has the correct check_answers_card_number" do + expect(question.check_answers_card_number).to eq(3) + end + end +end diff --git a/spec/models/form/lettings/subsections/household_characteristics_spec.rb b/spec/models/form/lettings/subsections/household_characteristics_spec.rb index b45f86fce..5aab3514c 100644 --- a/spec/models/form/lettings/subsections/household_characteristics_spec.rb +++ b/spec/models/form/lettings/subsections/household_characteristics_spec.rb @@ -10,6 +10,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod before do allow(section).to receive(:form).and_return(form) + allow(form).to receive(:start_year_2025_or_later?).and_return(false) end it "has correct section" do @@ -304,6 +305,161 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod end end + context "with start year >= 2025" do + before do + allow(form).to receive(:start_year_2024_or_later?).and_return(true) + allow(form).to receive(:start_year_2025_or_later?).and_return(true) + end + + it "has correct pages" do + expect(household_characteristics.pages.map(&:id)).to eq( + %w[ + household_members + no_females_pregnant_household_lead_hhmemb_value_check + females_in_soft_age_range_in_pregnant_household_lead_hhmemb_value_check + lead_tenant_age + no_females_pregnant_household_lead_age_value_check + females_in_soft_age_range_in_pregnant_household_lead_age_value_check + age_lead_tenant_under_retirement_value_check + age_lead_tenant_over_retirement_value_check + lead_tenant_gender_identity + no_females_pregnant_household_lead_value_check + females_in_soft_age_range_in_pregnant_household_lead_value_check + gender_lead_tenant_over_retirement_value_check + lead_tenant_ethnic_group + lead_tenant_ethnic_background_arab + lead_tenant_ethnic_background_asian + lead_tenant_ethnic_background_black + lead_tenant_ethnic_background_mixed + lead_tenant_ethnic_background_white + lead_tenant_nationality + lead_tenant_working_situation + working_situation_lead_tenant_under_retirement_value_check + working_situation_lead_tenant_over_retirement_value_check + person_2_known + person_2_lead_partner + relationship_2_partner_under_16_value_check + relationship_2_multiple_partners_value_check + person_2_age + no_females_pregnant_household_person_2_age_value_check + females_in_soft_age_range_in_pregnant_household_person_2_age_value_check + age_2_under_retirement_value_check + age_2_over_retirement_value_check + age_2_partner_under_16_value_check + person_2_gender_identity + no_females_pregnant_household_person_2_value_check + females_in_soft_age_range_in_pregnant_household_person_2_value_check + gender_2_over_retirement_value_check + person_2_working_situation + working_situation_2_under_retirement_value_check + working_situation_2_over_retirement_value_check + person_3_known + person_3_lead_partner + relationship_3_partner_under_16_value_check + relationship_3_multiple_partners_value_check + person_3_age + no_females_pregnant_household_person_3_age_value_check + females_in_soft_age_range_in_pregnant_household_person_3_age_value_check + age_3_under_retirement_value_check + age_3_over_retirement_value_check + age_3_partner_under_16_value_check + person_3_gender_identity + no_females_pregnant_household_person_3_value_check + females_in_soft_age_range_in_pregnant_household_person_3_value_check + gender_3_over_retirement_value_check + person_3_working_situation + working_situation_3_under_retirement_value_check + working_situation_3_over_retirement_value_check + person_4_known + person_4_lead_partner + relationship_4_partner_under_16_value_check + relationship_4_multiple_partners_value_check + person_4_age + no_females_pregnant_household_person_4_age_value_check + females_in_soft_age_range_in_pregnant_household_person_4_age_value_check + age_4_under_retirement_value_check + age_4_over_retirement_value_check + age_4_partner_under_16_value_check + person_4_gender_identity + no_females_pregnant_household_person_4_value_check + females_in_soft_age_range_in_pregnant_household_person_4_value_check + gender_4_over_retirement_value_check + person_4_working_situation + working_situation_4_under_retirement_value_check + working_situation_4_over_retirement_value_check + person_5_known + person_5_lead_partner + relationship_5_partner_under_16_value_check + relationship_5_multiple_partners_value_check + person_5_age + no_females_pregnant_household_person_5_age_value_check + females_in_soft_age_range_in_pregnant_household_person_5_age_value_check + age_5_under_retirement_value_check + age_5_over_retirement_value_check + age_5_partner_under_16_value_check + person_5_gender_identity + no_females_pregnant_household_person_5_value_check + females_in_soft_age_range_in_pregnant_household_person_5_value_check + gender_5_over_retirement_value_check + person_5_working_situation + working_situation_5_under_retirement_value_check + working_situation_5_over_retirement_value_check + person_6_known + person_6_lead_partner + relationship_6_partner_under_16_value_check + relationship_6_multiple_partners_value_check + person_6_age + no_females_pregnant_household_person_6_age_value_check + females_in_soft_age_range_in_pregnant_household_person_6_age_value_check + age_6_under_retirement_value_check + age_6_over_retirement_value_check + age_6_partner_under_16_value_check + person_6_gender_identity + no_females_pregnant_household_person_6_value_check + females_in_soft_age_range_in_pregnant_household_person_6_value_check + gender_6_over_retirement_value_check + person_6_working_situation + working_situation_6_under_retirement_value_check + working_situation_6_over_retirement_value_check + person_7_known + person_7_lead_partner + relationship_7_partner_under_16_value_check + relationship_7_multiple_partners_value_check + person_7_age + no_females_pregnant_household_person_7_age_value_check + females_in_soft_age_range_in_pregnant_household_person_7_age_value_check + age_7_under_retirement_value_check + age_7_over_retirement_value_check + age_7_partner_under_16_value_check + person_7_gender_identity + no_females_pregnant_household_person_7_value_check + females_in_soft_age_range_in_pregnant_household_person_7_value_check + gender_7_over_retirement_value_check + person_7_working_situation + working_situation_7_under_retirement_value_check + working_situation_7_over_retirement_value_check + person_8_known + person_8_lead_partner + relationship_8_partner_under_16_value_check + relationship_8_multiple_partners_value_check + person_8_age + no_females_pregnant_household_person_8_age_value_check + females_in_soft_age_range_in_pregnant_household_person_8_age_value_check + age_8_under_retirement_value_check + age_8_over_retirement_value_check + age_8_partner_under_16_value_check + person_8_gender_identity + no_females_pregnant_household_person_8_value_check + females_in_soft_age_range_in_pregnant_household_person_8_value_check + gender_8_over_retirement_value_check + person_8_working_situation + working_situation_8_under_retirement_value_check + working_situation_8_over_retirement_value_check + ], + ) + end + end + it "has the correct id" do expect(household_characteristics.id).to eq("household_characteristics") end diff --git a/spec/models/form/lettings/subsections/income_and_benefits_spec.rb b/spec/models/form/lettings/subsections/income_and_benefits_spec.rb index 7bdc26bfa..9d78b3216 100644 --- a/spec/models/form/lettings/subsections/income_and_benefits_spec.rb +++ b/spec/models/form/lettings/subsections/income_and_benefits_spec.rb @@ -5,40 +5,77 @@ RSpec.describe Form::Lettings::Subsections::IncomeAndBenefits, type: :model do let(:subsection_id) { nil } let(:subsection_definition) { nil } - let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1)) } + let(:start_date) { Time.zone.local(2024, 4, 1) } + let(:start_year_2025_or_later) { false } + let(:form) { instance_double(Form, start_date:) } let(:section) { instance_double(Form::Lettings::Sections::RentAndCharges, form:) } + before do + allow(form).to receive(:start_year_2025_or_later?).and_return(start_year_2025_or_later) + end + it "has correct section" do expect(income_and_benefits.section).to eq(section) end - it "has correct pages" do - expect(income_and_benefits.pages.map(&:id)).to eq( - %w[ - income_known - income_amount - net_income_value_check - housing_benefit - benefits_proportion - rent_or_other_charges - rent_period - care_home_weekly - care_home_bi_weekly - care_home_4_weekly - care_home_monthly - care_home_charges_value_check - rent_weekly - rent_bi_weekly - rent_4_weekly - rent_monthly - brent_rent_value_check - scharge_value_check - pscharge_value_check - supcharg_value_check - outstanding - outstanding_amount - ], - ) + context "with 2024 form" do + it "has correct pages" do + expect(income_and_benefits.pages.map(&:id)).to eq( + %w[ + income_known + income_amount + net_income_value_check + housing_benefit + benefits_proportion + rent_or_other_charges + rent_period + care_home_weekly + care_home_bi_weekly + care_home_4_weekly + care_home_monthly + care_home_charges_value_check + rent_weekly + rent_bi_weekly + rent_4_weekly + rent_monthly + brent_rent_value_check + scharge_value_check + pscharge_value_check + supcharg_value_check + outstanding + outstanding_amount + ], + ) + end + end + + context "with 2025 form" do + let(:start_date) { Time.zone.local(2025, 4, 1) } + let(:start_year_2025_or_later) { true } + + it "has correct pages" do + expect(income_and_benefits.pages.map(&:id)).to eq( + %w[ + income_known + income_amount + net_income_value_check + housing_benefit + benefits_proportion + rent_or_other_charges + rent_period + rent_weekly + rent_bi_weekly + rent_4_weekly + rent_monthly + brent_rent_value_check + scharge_value_check + pscharge_value_check + supcharg_value_check + outstanding + outstanding_amount + ], + ) + end end it "has the correct id" do diff --git a/spec/models/validations/date_validations_spec.rb b/spec/models/validations/date_validations_spec.rb index 3ca259b16..b88a75eb2 100644 --- a/spec/models/validations/date_validations_spec.rb +++ b/spec/models/validations/date_validations_spec.rb @@ -21,22 +21,6 @@ RSpec.describe Validations::DateValidations do expect(record.errors["startdate"]).to be_empty end - it "validates that the tenancy start date is after the void date if it has a void date" do - record.startdate = Time.zone.local(2022, 1, 1) - record.voiddate = Time.zone.local(2022, 2, 1) - date_validator.validate_startdate(record) - expect(record.errors["startdate"]) - .to include(match I18n.t("validations.lettings.date.startdate.after_void_date")) - end - - it "validates that the tenancy start date is after the major repair date if it has a major repair date" do - record.startdate = Time.zone.local(2022, 1, 1) - record.mrcdate = Time.zone.local(2022, 2, 1) - date_validator.validate_startdate(record) - expect(record.errors["startdate"]) - .to include(match I18n.t("validations.lettings.date.startdate.after_major_repair_date")) - end - it "produces no error when the tenancy start date is before the end date of the chosen scheme if it has an end date" do record.startdate = Time.zone.today - 30.days record.scheme = scheme @@ -59,6 +43,8 @@ RSpec.describe Validations::DateValidations do date_validator.validate_property_major_repairs(record) expect(record.errors["mrcdate"]) .to include(match I18n.t("validations.lettings.date.mrcdate.before_tenancy_start")) + expect(record.errors["startdate"]) + .to include(match I18n.t("validations.lettings.date.startdate.after_major_repair_date")) end it "must be before the tenancy start date" do @@ -68,23 +54,44 @@ RSpec.describe Validations::DateValidations do expect(record.errors["mrcdate"]).to be_empty end - it "cannot be more than 10 years before the tenancy start date" do - record.startdate = Time.zone.local(2022, 2, 1) - record.mrcdate = Time.zone.local(2012, 1, 1) - date_validator.validate_property_major_repairs(record) - date_validator.validate_startdate(record) - expect(record.errors["mrcdate"]) - .to include(match I18n.t("validations.lettings.date.mrcdate.ten_years_before_tenancy_start")) - expect(record.errors["startdate"]) - .to include(match I18n.t("validations.lettings.date.startdate.ten_years_after_mrc_date")) + context "with 2024 logs or earlier" do + it "cannot be more than 10 years before the tenancy start date" do + record.startdate = Time.zone.local(2024, 2, 1) + record.mrcdate = Time.zone.local(2014, 1, 31) + date_validator.validate_property_major_repairs(record) + expect(record.errors["mrcdate"]) + .to include(match I18n.t("validations.lettings.date.mrcdate.ten_years_before_tenancy_start")) + expect(record.errors["startdate"]) + .to include(match I18n.t("validations.lettings.date.startdate.ten_years_after_mrc_date")) + end + + it "must be within 10 years of the tenancy start date" do + record.startdate = Time.zone.local(2024, 2, 1) + record.mrcdate = Time.zone.local(2014, 2, 1) + date_validator.validate_property_major_repairs(record) + expect(record.errors["mrcdate"]).to be_empty + expect(record.errors["startdate"]).to be_empty + end end - it "must be within 10 years of the tenancy start date" do - record.startdate = Time.zone.local(2022, 2, 1) - record.mrcdate = Time.zone.local(2012, 3, 1) - date_validator.validate_property_major_repairs(record) - expect(record.errors["mrcdate"]).to be_empty - expect(record.errors["startdate"]).to be_empty + context "with 2025 logs or later" do + it "cannot be more than 20 years before the tenancy start date" do + record.startdate = Time.zone.local(2026, 2, 1) + record.mrcdate = Time.zone.local(2006, 1, 31) + date_validator.validate_property_major_repairs(record) + expect(record.errors["mrcdate"]) + .to include(match I18n.t("validations.lettings.date.mrcdate.twenty_years_before_tenancy_start")) + expect(record.errors["startdate"]) + .to include(match I18n.t("validations.lettings.date.startdate.twenty_years_after_mrc_date")) + end + + it "must be within 20 years of the tenancy start date" do + record.startdate = Time.zone.local(2026, 2, 1) + record.mrcdate = Time.zone.local(2006, 2, 1) + date_validator.validate_property_major_repairs(record) + expect(record.errors["mrcdate"]).to be_empty + expect(record.errors["startdate"]).to be_empty + end end context "when reason for vacancy is first let of property" do @@ -130,6 +137,8 @@ RSpec.describe Validations::DateValidations do date_validator.validate_property_void_date(record) expect(record.errors["voiddate"]) .to include(match I18n.t("validations.lettings.date.void_date.before_tenancy_start")) + expect(record.errors["startdate"]) + .to include(match I18n.t("validations.lettings.date.startdate.after_void_date")) end it "must be before the tenancy start date" do @@ -139,23 +148,45 @@ RSpec.describe Validations::DateValidations do expect(record.errors["voiddate"]).to be_empty end - it "cannot be more than 10 years before the tenancy start date" do - record.startdate = Time.zone.local(2022, 2, 1) - record.voiddate = Time.zone.local(2012, 1, 1) - date_validator.validate_property_void_date(record) - date_validator.validate_startdate(record) - expect(record.errors["voiddate"]) - .to include(match I18n.t("validations.lettings.date.void_date.ten_years_before_tenancy_start")) - expect(record.errors["startdate"]) - .to include(match I18n.t("validations.lettings.date.startdate.ten_years_after_void_date")) + context "with 2024 logs or earlier" do + it "cannot be more than 10 years before the tenancy start date" do + record.startdate = Time.zone.local(2024, 2, 1) + record.voiddate = Time.zone.local(2014, 1, 31) + date_validator.validate_property_void_date(record) + expect(record.errors["voiddate"]) + .to include(match I18n.t("validations.lettings.date.void_date.ten_years_before_tenancy_start")) + expect(record.errors["startdate"]) + .to include(match I18n.t("validations.lettings.date.startdate.ten_years_after_void_date")) + end + + it "must be within 10 years of the tenancy start date" do + record.startdate = Time.zone.local(2024, 2, 1) + record.voiddate = Time.zone.local(2014, 2, 1) + date_validator.validate_property_void_date(record) + expect(record.errors["voiddate"]).to be_empty + expect(record.errors["startdate"]).to be_empty + end end - it "must be within 10 years of the tenancy start date" do - record.startdate = Time.zone.local(2022, 2, 1) - record.voiddate = Time.zone.local(2012, 3, 1) - date_validator.validate_property_void_date(record) - expect(record.errors["voiddate"]).to be_empty - expect(record.errors["startdate"]).to be_empty + context "with 2025 logs or later" do + it "cannot be more than 20 years before the tenancy start date" do + record.startdate = Time.zone.local(2026, 2, 1) + record.voiddate = Time.zone.local(2006, 1, 31) + date_validator.validate_property_void_date(record) + date_validator.validate_startdate(record) + expect(record.errors["voiddate"]) + .to include(match I18n.t("validations.lettings.date.void_date.twenty_years_before_tenancy_start")) + expect(record.errors["startdate"]) + .to include(match I18n.t("validations.lettings.date.startdate.twenty_years_after_void_date")) + end + + it "must be within 20 years of the tenancy start date" do + record.startdate = Time.zone.local(2026, 2, 1) + record.voiddate = Time.zone.local(2006, 2, 1) + date_validator.validate_property_void_date(record) + expect(record.errors["voiddate"]).to be_empty + expect(record.errors["startdate"]).to be_empty + end end context "when major repairs have been carried out" do diff --git a/spec/models/validations/sales/sale_information_validations_spec.rb b/spec/models/validations/sales/sale_information_validations_spec.rb index fabe3c8c5..da49d1936 100644 --- a/spec/models/validations/sales/sale_information_validations_spec.rb +++ b/spec/models/validations/sales/sale_information_validations_spec.rb @@ -795,17 +795,22 @@ RSpec.describe Validations::Sales::SaleInformationValidations do record.la = "E09000001" end - it "adds an error if value * discount is more than 136,400" do + it "adds an error if value * discount is more than 137,400" do + record.value = 200_000 record.discount = 80 + discount_value = "£160,000.00" sale_information_validator.validate_discount_and_value(record) - expect(record.errors["value"]).to include("The percentage discount multiplied by the purchase price is £160,000.00. This figure should not be more than £136,400 for properties in London.") - expect(record.errors["discount"]).to include("The percentage discount multiplied by the purchase price is £160,000.00. This figure should not be more than £136,400 for properties in London.") - expect(record.errors["la"]).to include("The percentage discount multiplied by the purchase price is £160,000.00. This figure should not be more than £136,400 for properties in London.") - expect(record.errors["postcode_full"]).to include("The percentage discount multiplied by the purchase price is £160,000.00. This figure should not be more than £136,400 for properties in London.") - expect(record.errors["uprn"]).to include("The percentage discount multiplied by the purchase price is £160,000.00. This figure should not be more than £136,400 for properties in London.") + expect(record.errors["value"]).to include(I18n.t("validations.sales.sale_information.value.value_over_discounted_london_max", discount_value:)) + expect(record.errors["discount"]).to include(I18n.t("validations.sales.sale_information.discount.value_over_discounted_london_max", discount_value:)) + expect(record.errors["la"]).to include(I18n.t("validations.sales.sale_information.la.value_over_discounted_london_max", discount_value:)) + expect(record.errors["postcode_full"]).to include(I18n.t("validations.sales.sale_information.postcode_full.value_over_discounted_london_max", discount_value:)) + expect(record.errors["uprn"]).to include(I18n.t("validations.sales.sale_information.uprn.value_over_discounted_london_max", discount_value:)) end - it "does not add an error value * discount is less than 136,400" do + it "does not add an error value * discount is less than 137,400" do + record.value = 200_000 + record.discount = 50 + # Discount value: 100,000 sale_information_validator.validate_discount_and_value(record) expect(record.errors["value"]).to be_empty expect(record.errors["discount"]).to be_empty @@ -820,17 +825,22 @@ RSpec.describe Validations::Sales::SaleInformationValidations do record.la = "E06000015" end - it "adds an error if value * discount is more than 136,400" do + it "adds an error if value * discount is more than 103,400" do + record.value = 200_000 record.discount = 52 + discount_value = "£104,000.00" sale_information_validator.validate_discount_and_value(record) - expect(record.errors["value"]).to include("The percentage discount multiplied by the purchase price is £104,000.00. This figure should not be more than £102,400 for properties outside of London.") - expect(record.errors["discount"]).to include("The percentage discount multiplied by the purchase price is £104,000.00. This figure should not be more than £102,400 for properties outside of London.") - expect(record.errors["la"]).to include("The percentage discount multiplied by the purchase price is £104,000.00. This figure should not be more than £102,400 for properties outside of London.") - expect(record.errors["postcode_full"]).to include("The percentage discount multiplied by the purchase price is £104,000.00. This figure should not be more than £102,400 for properties outside of London.") - expect(record.errors["uprn"]).to include("The percentage discount multiplied by the purchase price is £104,000.00. This figure should not be more than £102,400 for properties outside of London.") + expect(record.errors["value"]).to include(I18n.t("validations.sales.sale_information.value.value_over_discounted_max", discount_value:)) + expect(record.errors["discount"]).to include(I18n.t("validations.sales.sale_information.discount.value_over_discounted_max", discount_value:)) + expect(record.errors["la"]).to include(I18n.t("validations.sales.sale_information.la.value_over_discounted_max", discount_value:)) + expect(record.errors["postcode_full"]).to include(I18n.t("validations.sales.sale_information.postcode_full.value_over_discounted_max", discount_value:)) + expect(record.errors["uprn"]).to include(I18n.t("validations.sales.sale_information.uprn.value_over_discounted_max", discount_value:)) end - it "does not add an error value * discount is less than 136,400" do + it "does not add an error value * discount is less than 103,400" do + record.value = 200_000 + record.discount = 50 + # Discount value: 100,000 sale_information_validator.validate_discount_and_value(record) expect(record.errors["value"]).to be_empty expect(record.errors["discount"]).to be_empty diff --git a/spec/models/validations/shared_validations_spec.rb b/spec/models/validations/shared_validations_spec.rb index 53efc6675..2d9ec4ef3 100644 --- a/spec/models/validations/shared_validations_spec.rb +++ b/spec/models/validations/shared_validations_spec.rb @@ -116,19 +116,23 @@ RSpec.describe Validations::SharedValidations do end describe "validating level of accuracy or rounding for numeric questions" do + let(:sales_log) { build(:sales_log, :completed) } + + before do + income_question = instance_double(Form::Question, step:, type: "numeric", id: "income1", check_answer_label: "Buyer 1’s gross annual income", page: instance_double(Form::Page, routed_to?: true)) + form = instance_double(Form, numeric_questions: [income_question]) + allow(FormHandler.instance).to receive(:get_form).and_return(form) + end + context "when validating a question with a step of 1" do + let(:step) { 1 } + it "adds an error if input is a decimal" do sales_log.income1 = 30_000.5 shared_validator.validate_numeric_step(sales_log) expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.whole_number", field: "Buyer 1’s gross annual income") end - it "adds an error if the user attempts to input a number in exponent format" do - sales_log.income1 = "3e5" - shared_validator.validate_numeric_step(sales_log) - expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.whole_number", field: "Buyer 1’s gross annual income") - end - it "does not add an error if input is an integer" do sales_log.income1 = 30_000 shared_validator.validate_numeric_step(sales_log) @@ -137,80 +141,96 @@ RSpec.describe Validations::SharedValidations do end context "when validating a question with a step of 10" do - it "adds an error if input is not a multiple of ten" do - sales_log.savings = 30_005 - sales_log.jointpur = 1 - shared_validator.validate_numeric_step(sales_log) - expect(sales_log.errors[:savings]).to include I18n.t("validations.shared.numeric.nearest_ten", field: "Buyers’ total savings before any deposit paid") - end + let(:step) { 10 } - it "adds an error if the user attempts to input a number in exponent format" do - sales_log.savings = "3e5" - sales_log.jointpur = 1 + it "adds an error if input is not a multiple of ten" do + sales_log.income1 = 30_005 shared_validator.validate_numeric_step(sales_log) - expect(sales_log.errors[:savings]).to include I18n.t("validations.shared.numeric.nearest_ten", field: "Buyers’ total savings before any deposit paid") + expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.nearest_ten", field: "Buyer 1’s gross annual income") end it "does not add an error if input is a multiple of ten" do - sales_log.savings = 30_000 + sales_log.income1 = 30_000 shared_validator.validate_numeric_step(sales_log) expect(sales_log.errors).to be_empty end end context "when validating a question with a step of 0.01" do + let(:step) { 0.01 } + it "adds an error if input has more than 2 decimal places" do - sales_log.mscharge = 30.7418 + sales_log.income1 = 30_123.7418 shared_validator.validate_numeric_step(sales_log) - expect(sales_log.errors[:mscharge]).to include I18n.t("validations.shared.numeric.nearest_hundredth", field: "Monthly leasehold charges") + expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.nearest_hundredth", field: "Buyer 1’s gross annual income") end - it "does not add an error if the user attempts to input a number in exponent format" do - sales_log.mscharge = "3e1" + it "does not add an error if input has 2 or fewer decimal places" do + sales_log.income1 = 30_123.74 shared_validator.validate_numeric_step(sales_log) expect(sales_log.errors).to be_empty end + end - it "does not add an error if input has 2 or fewer decimal places" do - sales_log.mscharge = 30.74 + context "when validating a question with a step of 0.1" do + let(:step) { 0.1 } + + it "adds an error if input has more than 1 decimal place" do + sales_log.income1 = 30_123.74 + shared_validator.validate_numeric_step(sales_log) + expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.nearest_tenth", field: "Buyer 1’s gross annual income") + end + + it "does not add an error if input has 1 or fewer decimal places" do + sales_log.income1 = 30_123.8 shared_validator.validate_numeric_step(sales_log) expect(sales_log.errors).to be_empty end end - %i[sales_log lettings_log].each do |log_type| - describe "validate_owning_organisation_data_sharing_agremeent_signed" do - it "is valid if the Data Protection Confirmation is signed" do - log = build(log_type, :in_progress, owning_organisation: create(:organisation)) + context "when validating a question with an unusual step" do + let(:step) { 0.001 } - expect(log).to be_valid - end + it "adds an appropriate error if input does not match" do + sales_log.income1 = 30_123.7419 + shared_validator.validate_numeric_step(sales_log) + expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.nearest_step", field: "Buyer 1’s gross annual income", step: 0.001) + end + end + end - it "is valid when owning_organisation nil" do - log = build(log_type, owning_organisation: nil) + %i[sales_log lettings_log].each do |log_type| + describe "validate_owning_organisation_data_sharing_agremeent_signed" do + it "is valid if the Data Protection Confirmation is signed" do + log = build(log_type, :in_progress, owning_organisation: create(:organisation)) - expect(log).to be_valid - end + expect(log).to be_valid + end - it "is not valid if the Data Protection Confirmation is not signed" do - log = build(log_type, owning_organisation: create(:organisation, :without_dpc)) + it "is valid when owning_organisation nil" do + log = build(log_type, owning_organisation: nil) - expect(log).not_to be_valid - expect(log.errors[:owning_organisation_id]).to eq(["The organisation must accept the Data Sharing Agreement before it can be selected as the owning organisation."]) - end + expect(log).to be_valid + end + + it "is not valid if the Data Protection Confirmation is not signed" do + log = build(log_type, owning_organisation: create(:organisation, :without_dpc)) - context "when updating" do - let(:log) { create(log_type, :in_progress) } - let(:org_with_dpc) { create(:organisation) } - let(:org_without_dpc) { create(:organisation, :without_dpc) } + expect(log).not_to be_valid + expect(log.errors[:owning_organisation_id]).to eq(["The organisation must accept the Data Sharing Agreement before it can be selected as the owning organisation."]) + end - it "is valid when changing to another org with a signed Data Protection Confirmation" do - expect { log.owning_organisation = org_with_dpc }.not_to change(log, :valid?) - end + context "when updating" do + let(:log) { create(log_type, :in_progress) } + let(:org_with_dpc) { create(:organisation) } + let(:org_without_dpc) { create(:organisation, :without_dpc) } + + it "is valid when changing to another org with a signed Data Protection Confirmation" do + expect { log.owning_organisation = org_with_dpc }.not_to change(log, :valid?) + end - it "invalid when changing to another org without a signed Data Protection Confirmation" do - expect { log.owning_organisation = org_without_dpc }.to change(log, :valid?).from(true).to(false).and(change { log.errors[:owning_organisation_id] }.to(["The organisation must accept the Data Sharing Agreement before it can be selected as the owning organisation."])) - end + it "invalid when changing to another org without a signed Data Protection Confirmation" do + expect { log.owning_organisation = org_without_dpc }.to change(log, :valid?).from(true).to(false).and(change { log.errors[:owning_organisation_id] }.to(["The organisation must accept the Data Sharing Agreement before it can be selected as the owning organisation."])) end end end @@ -229,6 +249,12 @@ RSpec.describe Validations::SharedValidations do expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.format", field: "Buyer 1’s gross annual income") end + it "does not allow exponent format" do + sales_log.income1 = "1e4" + shared_validator.validate_numeric_input(sales_log) + expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.format", field: "Buyer 1’s gross annual income") + end + it "allows a digit" do sales_log.income1 = "300" shared_validator.validate_numeric_input(sales_log)