diff --git a/app/models/validations/sales/financial_validations.rb b/app/models/validations/sales/financial_validations.rb index c1046e035..1d2ef3d6f 100644 --- a/app/models/validations/sales/financial_validations.rb +++ b/app/models/validations/sales/financial_validations.rb @@ -7,9 +7,9 @@ module Validations::Sales::FinancialValidations relevant_fields = %i[income1 ownershipsch uprn la postcode_full] if record.london_property? && !record.income1.between?(0, 90_000) - relevant_fields.each { |field| record.errors.add field, :outside_london_income_range, message: I18n.t("validations.financial.income.outside_london_income_range") } + relevant_fields.each { |field| record.errors.add field, :outside_london_income_range, message: I18n.t("validations.sales.financial.#{field}.outside_london_income_range") } elsif record.property_not_in_london? && !record.income1.between?(0, 80_000) - relevant_fields.each { |field| record.errors.add field, :outside_non_london_income_range, message: I18n.t("validations.financial.income.outside_non_london_income_range") } + relevant_fields.each { |field| record.errors.add field, :outside_non_london_income_range, message: I18n.t("validations.sales.financial.#{field}.outside_non_london_income_range") } end end @@ -18,9 +18,9 @@ module Validations::Sales::FinancialValidations relevant_fields = %i[income2 ownershipsch uprn la postcode_full] if record.london_property? && !record.income2.between?(0, 90_000) - relevant_fields.each { |field| record.errors.add field, :outside_london_income_range, message: I18n.t("validations.financial.income.outside_london_income_range") } + relevant_fields.each { |field| record.errors.add field, :outside_london_income_range, message: I18n.t("validations.sales.financial.#{field}.outside_london_income_range") } elsif record.property_not_in_london? && !record.income2.between?(0, 80_000) - relevant_fields.each { |field| record.errors.add field, :outside_non_london_income_range, message: I18n.t("validations.financial.income.outside_non_london_income_range") } + relevant_fields.each { |field| record.errors.add field, :outside_non_london_income_range, message: I18n.t("validations.sales.financial.#{field}.outside_non_london_income_range") } end end @@ -30,25 +30,26 @@ module Validations::Sales::FinancialValidations combined_income = record.income1 + record.income2 relevant_fields = %i[income1 income2 ownershipsch uprn la postcode_full] if record.london_property? && combined_income > 90_000 - relevant_fields.each { |field| record.errors.add field, :over_combined_hard_max_for_london, message: I18n.t("validations.financial.income.combined_over_hard_max_for_london") } + relevant_fields.each { |field| record.errors.add field, :over_combined_hard_max_for_london, message: I18n.t("validations.sales.financial.#{field}.combined_over_hard_max_for_london") } elsif record.property_not_in_london? && combined_income > 80_000 - relevant_fields.each { |field| record.errors.add field, :over_combined_hard_max_for_outside_london, message: I18n.t("validations.financial.income.combined_over_hard_max_for_outside_london") } + relevant_fields.each { |field| record.errors.add field, :over_combined_hard_max_for_outside_london, message: I18n.t("validations.sales.financial.#{field}.combined_over_hard_max_for_outside_london") } end end def validate_mortgage(record) - record.errors.add :mortgage, :cannot_be_0, message: I18n.t("validations.financial.mortgage") if record.mortgage_used? && record.mortgage&.zero? + record.errors.add :mortgage, :cannot_be_0, message: I18n.t("validations.sales.financial.mortgage.mortgage_zero") if record.mortgage_used? && record.mortgage&.zero? end def validate_monthly_leasehold_charges(record) - record.errors.add :mscharge, I18n.t("validations.financial.monthly_leasehold_charges.not_zero") if record.mscharge&.zero? + record.errors.add :mscharge, I18n.t("validations.sales.financial.mscharge.monthly_leasehold_charges.not_zero") if record.mscharge&.zero? end def validate_percentage_bought_not_greater_than_percentage_owned(record) return unless record.stairbought && record.stairowned if record.stairbought > record.stairowned - record.errors.add :stairowned, I18n.t("validations.financial.staircasing.percentage_bought_must_be_greater_than_percentage_owned", buyer_now_owns: record.joint_purchase? ? "buyers now own" : "buyer now owns") + joint_purchase_id = record.joint_purchase? ? "joint_purchase" : "not_joint_purchase" + record.errors.add :stairowned, I18n.t("validations.sales.financial.stairowned.percentage_bought_must_be_greater_than_percentage_owned.#{joint_purchase_id}") end end @@ -57,8 +58,8 @@ module Validations::Sales::FinancialValidations return unless record.saledate && record.form.start_year_2024_or_later? if record.stairbought == record.stairowned - record.errors.add :stairbought, I18n.t("validations.financial.staircasing.percentage_bought_equal_percentage_owned", stairbought: sprintf("%g", record.stairbought), stairowned: sprintf("%g", record.stairowned)) - record.errors.add :stairowned, I18n.t("validations.financial.staircasing.percentage_bought_equal_percentage_owned", stairbought: sprintf("%g", record.stairbought), stairowned: sprintf("%g", record.stairowned)) + record.errors.add :stairbought, I18n.t("validations.sales.financial.stairbought.percentage_bought_equal_percentage_owned", stairbought: sprintf("%g", record.stairbought), stairowned: sprintf("%g", record.stairowned)) + record.errors.add :stairowned, I18n.t("validations.sales.financial.stairowned.percentage_bought_equal_percentage_owned", stairbought: sprintf("%g", record.stairbought), stairowned: sprintf("%g", record.stairowned)) end end @@ -72,8 +73,8 @@ module Validations::Sales::FinancialValidations end if threshold && record.stairbought < threshold - record.errors.add :stairbought, I18n.t("validations.financial.staircasing.percentage_bought_must_be_at_least_threshold", threshold:) - record.errors.add :type, I18n.t("validations.setup.type.percentage_bought_must_be_at_least_threshold", threshold:) + record.errors.add :stairbought, I18n.t("validations.sales.financial.stairbought.percentage_bought_must_be_at_least_threshold", threshold:) + record.errors.add :type, I18n.t("validations.sales.financial.type.percentage_bought_must_be_at_least_threshold", threshold:) end end @@ -81,8 +82,8 @@ module Validations::Sales::FinancialValidations return unless record.income2 && record.ecstat2 if record.income2.positive? && is_economic_status_child?(record.ecstat2) && record.form.start_date.year >= 2023 - record.errors.add :ecstat2, I18n.t("validations.financial.income.child_has_income") - record.errors.add :income2, I18n.t("validations.financial.income.child_has_income") + record.errors.add :ecstat2, I18n.t("validations.sales.financial.ecstat2.child_has_income") + record.errors.add :income2, I18n.t("validations.sales.financial.income2.child_has_income") end end @@ -94,12 +95,12 @@ module Validations::Sales::FinancialValidations return unless (range = ranges[record.type]) if record.equity < range.min - record.errors.add :type, I18n.t("validations.financial.equity.under_min", min_equity: range.min) - record.errors.add :equity, :under_min, message: I18n.t("validations.financial.equity.under_min", min_equity: range.min) + record.errors.add :type, I18n.t("validations.sales.financial.type.equity_under_min", min_equity: range.min) + record.errors.add :equity, :under_min, message: I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: range.min) elsif !record.is_resale? && record.equity > range.max - record.errors.add :type, I18n.t("validations.financial.equity.over_max", max_equity: range.max) - record.errors.add :equity, :over_max, message: I18n.t("validations.financial.equity.over_max", max_equity: range.max) - record.errors.add :resale, I18n.t("validations.financial.equity.over_max", max_equity: range.max) + record.errors.add :type, I18n.t("validations.sales.financial.type.equity_over_max", max_equity: range.max) + record.errors.add :equity, :over_max, message: I18n.t("validations.sales.financial.equity.equity_over_max", max_equity: range.max) + record.errors.add :resale, I18n.t("validations.sales.financial.resale.equity_over_max", max_equity: range.max) end end @@ -109,9 +110,10 @@ module Validations::Sales::FinancialValidations if record.equity > record.stairowned - record.stairbought formatted_equity = sprintf("%g", record.equity) - record.errors.add :equity, I18n.t("validations.financial.equity.over_stairowned_minus_stairbought", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought, buyer_owns: record.joint_purchase? ? "buyers own" : "buyer owns") - record.errors.add :stairowned, I18n.t("validations.financial.equity.over_stairowned_minus_stairbought", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought, buyer_owns: record.joint_purchase? ? "buyers own" : "buyer owns") - record.errors.add :stairbought, I18n.t("validations.financial.equity.over_stairowned_minus_stairbought", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought, buyer_owns: record.joint_purchase? ? "buyers own" : "buyer owns") + joint_purchase_id = record.joint_purchase? ? "joint_purchase" : "not_joint_purchase" + record.errors.add :equity, I18n.t("validations.sales.financial.equity.equity_over_stairowned_minus_stairbought.#{joint_purchase_id}", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought) + record.errors.add :stairowned, I18n.t("validations.sales.financial.stairowned.equity_over_stairowned_minus_stairbought.#{joint_purchase_id}", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought) + record.errors.add :stairbought, I18n.t("validations.sales.financial.stairbought.equity_over_stairowned_minus_stairbought.#{joint_purchase_id}", equity: formatted_equity, staircase_difference: record.stairowned - record.stairbought) end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 8cf9634b5..1c8f49dfb 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -258,8 +258,6 @@ en: setup: saledate: year_not_two_or_four_digits: "Sale completion year must be 2 or 4 digits." - type: - percentage_bought_must_be_at_least_threshold: "The minimum increase in equity while staircasing is %{threshold}% for this shared ownership type." startdate: before_scheme_end_date: "The tenancy start date must be before the end date for this supported housing scheme." owning_organisation: @@ -285,28 +283,14 @@ en: one_three_bedroom_single_tenant_shared: "A shared house with fewer than two tenants must have 1 to 3 bedrooms." financial: - income: - outside_london_income_range: "Income must be between £0 and £90,000 for properties within a London local authority." - outside_non_london_income_range: "Income must be between £0 and £80,000 for properties in a non-London local authority." - combined_over_hard_max_for_london: "Combined income must be £90,000 or lower for properties within a London local authority." - combined_over_hard_max_for_outside_london: "Combined income must be £80,000 or lower for properties outside London local authorities." - child_has_income: "Child's income must be £0." charges: missing_charges: "Please enter the %{sentence_fragment}. If there is no %{sentence_fragment}, please enter '0'." carehome: not_provided: "Enter how much rent and other charges the household pays %{period}." cash_discount_invalid: "Cash discount must be £0 - £999,999." - staircasing: - percentage_bought_must_be_greater_than_percentage_owned: "Total percentage %{buyer_now_owns} must be more than percentage bought in this transaction." - percentage_bought_must_be_at_least_threshold: "The minimum increase in equity while staircasing is %{threshold}%." - percentage_bought_equal_percentage_owned: "The percentage bought is %{stairbought}% and the percentage owned in total is %{stairowned}%. These figures cannot be the same." - monthly_leasehold_charges: - not_zero: "Monthly leasehold charges cannot be £0 if the property has monthly charges." - equity: - under_min: "The minimum initial equity stake for this type of shared ownership sale is %{min_equity}%." - over_max: "The maximum initial equity stake is %{max_equity}%." - over_stairowned_minus_stairbought: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the %{buyer_owns} minus the percentage bought." - mortgage: "Mortgage value cannot be £0 if a mortgage was used for the purchase of this property." + mortgage_used: + year: "You must answer either ‘yes’ or ‘no’ to the question ‘was a mortgage used’ for the selected year." + staircasing: "You must answer either ‘yes’ or ‘no’ to the question ‘was a mortgage used’ for staircasing transactions." shared_ownership_deposit: "The %{mortgage_deposit_and_discount_error_fields} added together is %{mortgage_deposit_and_discount_total}. The value times the equity percentage is %{value_times_equity}. These figures should be the same." household: diff --git a/config/locales/validations/sales/financial.en.yml b/config/locales/validations/sales/financial.en.yml new file mode 100644 index 000000000..efd257ea5 --- /dev/null +++ b/config/locales/validations/sales/financial.en.yml @@ -0,0 +1,81 @@ +en: + validations: + sales: + financial: + ownershipsch: + outside_london_income_range: "Income must be between £0 and £90,000 for properties within a London local authority." + outside_non_london_income_range: "Income must be between £0 and £80,000 for properties in a non-London local authority." + combined_over_hard_max_for_london: "Combined income must be £90,000 or lower for properties within a London local authority." + combined_over_hard_max_for_outside_london: "Combined income must be £80,000 or lower for properties outside London local authorities." + + uprn: + outside_london_income_range: "Income must be between £0 and £90,000 for properties within a London local authority." + outside_non_london_income_range: "Income must be between £0 and £80,000 for properties in a non-London local authority." + combined_over_hard_max_for_london: "Combined income must be £90,000 or lower for properties within a London local authority." + combined_over_hard_max_for_outside_london: "Combined income must be £80,000 or lower for properties outside London local authorities." + + la: + outside_london_income_range: "Income must be between £0 and £90,000 for properties within a London local authority." + outside_non_london_income_range: "Income must be between £0 and £80,000 for properties in a non-London local authority." + combined_over_hard_max_for_london: "Combined income must be £90,000 or lower for properties within a London local authority." + combined_over_hard_max_for_outside_london: "Combined income must be £80,000 or lower for properties outside London local authorities." + + postcode_full: + outside_london_income_range: "Income must be between £0 and £90,000 for properties within a London local authority." + outside_non_london_income_range: "Income must be between £0 and £80,000 for properties in a non-London local authority." + combined_over_hard_max_for_london: "Combined income must be £90,000 or lower for properties within a London local authority." + combined_over_hard_max_for_outside_london: "Combined income must be £80,000 or lower for properties outside London local authorities." + + income1: + outside_london_income_range: "Income must be between £0 and £90,000 for properties within a London local authority." + outside_non_london_income_range: "Income must be between £0 and £80,000 for properties in a non-London local authority." + combined_over_hard_max_for_london: "Combined income must be £90,000 or lower for properties within a London local authority." + combined_over_hard_max_for_outside_london: "Combined income must be £80,000 or lower for properties outside London local authorities." + + income2: + outside_london_income_range: "Income must be between £0 and £90,000 for properties within a London local authority." + outside_non_london_income_range: "Income must be between £0 and £80,000 for properties in a non-London local authority." + combined_over_hard_max_for_london: "Combined income must be £90,000 or lower for properties within a London local authority." + combined_over_hard_max_for_outside_london: "Combined income must be £80,000 or lower for properties outside London local authorities." + child_has_income: "Child's income must be £0." + + ecstat2: + child_has_income: "Child's income must be £0." + + mortgage: + mortgage_zero: "Mortgage value cannot be £0 if a mortgage was used for the purchase of this property." + + mscharge: + monthly_leasehold_charges: + not_zero: "Monthly leasehold charges cannot be £0 if the property has monthly charges." + + resale: + equity_over_max: "The maximum initial equity stake is %{max_equity}%." + + type: + equity_under_min: "The minimum initial equity stake for this type of shared ownership sale is %{min_equity}%." + equity_over_max: "The maximum initial equity stake is %{max_equity}%." + percentage_bought_must_be_at_least_threshold: "The minimum increase in equity while staircasing is %{threshold}% for this shared ownership type." + + equity: + equity_under_min: "The minimum initial equity stake for this type of shared ownership sale is %{min_equity}%." + equity_over_max: "The maximum initial equity stake is %{max_equity}%." + equity_over_stairowned_minus_stairbought: + joint_purchase: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyers own minus the percentage bought." + not_joint_purchase: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyer owns minus the percentage bought." + + stairowned: + equity_over_stairowned_minus_stairbought: + joint_purchase: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyers own minus the percentage bought." + not_joint_purchase: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyer owns minus the percentage bought." + percentage_bought_must_be_greater_than_percentage_owned: + joint_purchase: "Total percentage buyers now own must be more than percentage bought in this transaction." + not_joint_purchase: "Total percentage buyer now owns must be more than percentage bought in this transaction." + percentage_bought_equal_percentage_owned: "The percentage bought is %{stairbought}% and the percentage owned in total is %{stairowned}%. These figures cannot be the same." + + stairbought: + equity_over_stairowned_minus_stairbought: + joint_purchase: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyers own minus the percentage bought." + not_joint_purchase: "The initial equity stake is %{equity}% and the percentage owned in total minus the percentage bought is %{staircase_difference}%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyer owns minus the percentage bought." + percentage_bought_must_be_at_least_threshold: "The minimum increase in equity while staircasing is %{threshold}%." + percentage_bought_equal_percentage_owned: "The percentage bought is %{stairbought}% and the percentage owned in total is %{stairowned}%. These figures cannot be the same." diff --git a/spec/models/validations/sales/financial_validations_spec.rb b/spec/models/validations/sales/financial_validations_spec.rb index b0e80303a..7b7749003 100644 --- a/spec/models/validations/sales/financial_validations_spec.rb +++ b/spec/models/validations/sales/financial_validations_spec.rb @@ -16,19 +16,19 @@ RSpec.describe Validations::Sales::FinancialValidations do it "adds errors if buyer 1 has income over 80,000" do record.income1 = 85_000 financial_validator.validate_income1(record) - expect(record.errors["income1"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range")) - expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range")) - expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range")) - expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range")) + expect(record.errors["income1"]).to include(match I18n.t("validations.sales.financial.income1.outside_non_london_income_range")) + expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.sales.financial.ownershipsch.outside_non_london_income_range")) + expect(record.errors["la"]).to include(match I18n.t("validations.sales.financial.la.outside_non_london_income_range")) + expect(record.errors["postcode_full"]).to include(match I18n.t("validations.sales.financial.postcode_full.outside_non_london_income_range")) end it "adds errors if buyer 2 has income over 80,000" do record.income2 = 85_000 financial_validator.validate_income2(record) - expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range")) - expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range")) - expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range")) - expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range")) + expect(record.errors["income2"]).to include(match I18n.t("validations.sales.financial.income2.outside_non_london_income_range")) + expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.sales.financial.ownershipsch.outside_non_london_income_range")) + expect(record.errors["la"]).to include(match I18n.t("validations.sales.financial.la.outside_non_london_income_range")) + expect(record.errors["postcode_full"]).to include(match I18n.t("validations.sales.financial.postcode_full.outside_non_london_income_range")) end it "does not add errors if buyer 1 has income above 0 and below 80_000" do @@ -46,27 +46,27 @@ RSpec.describe Validations::Sales::FinancialValidations do it "adds errors if buyer 1 has income below 0" do record.income1 = -500 financial_validator.validate_income1(record) - expect(record.errors["income1"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range")) - expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range")) - expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range")) - expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range")) + expect(record.errors["income1"]).to include(match I18n.t("validations.sales.financial.income1.outside_non_london_income_range")) + expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.sales.financial.ownershipsch.outside_non_london_income_range")) + expect(record.errors["la"]).to include(match I18n.t("validations.sales.financial.la.outside_non_london_income_range")) + expect(record.errors["postcode_full"]).to include(match I18n.t("validations.sales.financial.postcode_full.outside_non_london_income_range")) end it "adds errors if buyer 2 has income below 0" do record.income2 = -5 financial_validator.validate_income2(record) - expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range")) - expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range")) - expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range")) - expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.outside_non_london_income_range")) + expect(record.errors["income2"]).to include(match I18n.t("validations.sales.financial.income2.outside_non_london_income_range")) + expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.sales.financial.ownershipsch.outside_non_london_income_range")) + expect(record.errors["la"]).to include(match I18n.t("validations.sales.financial.la.outside_non_london_income_range")) + expect(record.errors["postcode_full"]).to include(match I18n.t("validations.sales.financial.postcode_full.outside_non_london_income_range")) end it "adds errors when combined income is over 80_000" do record.income1 = 45_000 record.income2 = 40_000 financial_validator.validate_combined_income(record) - expect(record.errors["income1"]).to include(match I18n.t("validations.financial.income.combined_over_hard_max_for_outside_london")) - expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.combined_over_hard_max_for_outside_london")) + expect(record.errors["income1"]).to include(match I18n.t("validations.sales.financial.income1.combined_over_hard_max_for_outside_london")) + expect(record.errors["income2"]).to include(match I18n.t("validations.sales.financial.income2.combined_over_hard_max_for_outside_london")) end it "does not add errors when combined income is under 80_000" do @@ -85,19 +85,19 @@ RSpec.describe Validations::Sales::FinancialValidations do it "adds errors if buyer 1 has income over 90,000" do record.income1 = 95_000 financial_validator.validate_income1(record) - expect(record.errors["income1"]).to include(match I18n.t("validations.financial.income.outside_london_income_range")) - expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.outside_london_income_range")) - expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.outside_london_income_range")) - expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.outside_london_income_range")) + expect(record.errors["income1"]).to include(match I18n.t("validations.sales.financial.income1.outside_london_income_range")) + expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.sales.financial.ownershipsch.outside_london_income_range")) + expect(record.errors["la"]).to include(match I18n.t("validations.sales.financial.la.outside_london_income_range")) + expect(record.errors["postcode_full"]).to include(match I18n.t("validations.sales.financial.postcode_full.outside_london_income_range")) end it "adds errors if buyer 2 has income over 90,000" do record.income2 = 95_000 financial_validator.validate_income2(record) - expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.outside_london_income_range")) - expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.outside_london_income_range")) - expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.outside_london_income_range")) - expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.outside_london_income_range")) + expect(record.errors["income2"]).to include(match I18n.t("validations.sales.financial.income2.outside_london_income_range")) + expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.sales.financial.ownershipsch.outside_london_income_range")) + expect(record.errors["la"]).to include(match I18n.t("validations.sales.financial.la.outside_london_income_range")) + expect(record.errors["postcode_full"]).to include(match I18n.t("validations.sales.financial.postcode_full.outside_london_income_range")) end it "does not add errors if buyer 1 has income above 0 and below 90_000" do @@ -115,27 +115,27 @@ RSpec.describe Validations::Sales::FinancialValidations do it "adds errors if buyer 1 has income below 0" do record.income1 = -500 financial_validator.validate_income1(record) - expect(record.errors["income1"]).to include(match I18n.t("validations.financial.income.outside_london_income_range")) - expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.outside_london_income_range")) - expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.outside_london_income_range")) - expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.outside_london_income_range")) + expect(record.errors["income1"]).to include(match I18n.t("validations.sales.financial.income1.outside_london_income_range")) + expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.sales.financial.ownershipsch.outside_london_income_range")) + expect(record.errors["la"]).to include(match I18n.t("validations.sales.financial.la.outside_london_income_range")) + expect(record.errors["postcode_full"]).to include(match I18n.t("validations.sales.financial.postcode_full.outside_london_income_range")) end it "adds errors if buyer 2 has income below 0" do record.income2 = -2 financial_validator.validate_income2(record) - expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.outside_london_income_range")) - expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.financial.income.outside_london_income_range")) - expect(record.errors["la"]).to include(match I18n.t("validations.financial.income.outside_london_income_range")) - expect(record.errors["postcode_full"]).to include(match I18n.t("validations.financial.income.outside_london_income_range")) + expect(record.errors["income2"]).to include(match I18n.t("validations.sales.financial.income2.outside_london_income_range")) + expect(record.errors["ownershipsch"]).to include(match I18n.t("validations.sales.financial.ownershipsch.outside_london_income_range")) + expect(record.errors["la"]).to include(match I18n.t("validations.sales.financial.la.outside_london_income_range")) + expect(record.errors["postcode_full"]).to include(match I18n.t("validations.sales.financial.postcode_full.outside_london_income_range")) end it "adds errors when combined income is over 90_000" do record.income1 = 55_000 record.income2 = 40_000 financial_validator.validate_combined_income(record) - expect(record.errors["income1"]).to include(match I18n.t("validations.financial.income.combined_over_hard_max_for_london")) - expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.combined_over_hard_max_for_london")) + expect(record.errors["income1"]).to include(match I18n.t("validations.sales.financial.income1.combined_over_hard_max_for_london")) + expect(record.errors["income2"]).to include(match I18n.t("validations.sales.financial.income2.combined_over_hard_max_for_london")) end it "does not add errors when combined income is under 90_000" do @@ -154,7 +154,7 @@ RSpec.describe Validations::Sales::FinancialValidations do record.mortgageused = 1 record.mortgage = 0 financial_validator.validate_mortgage(record) - expect(record.errors[:mortgage]).to include I18n.t("validations.financial.mortgage") + expect(record.errors[:mortgage]).to include I18n.t("validations.sales.financial.mortgage.mortgage_zero") end it "does not add an error is the mortgage is positive" do @@ -187,7 +187,7 @@ RSpec.describe Validations::Sales::FinancialValidations do record.stairowned = 40 record.jointpur = 1 financial_validator.validate_percentage_bought_not_greater_than_percentage_owned(record) - expect(record.errors["stairowned"]).to include("Total percentage buyers now own must be more than percentage bought in this transaction.") + expect(record.errors["stairowned"]).to include(I18n.t("validations.sales.financial.stairowned.percentage_bought_must_be_greater_than_percentage_owned.joint_purchase")) end it "adds an error to stairowned and not stairbought if the percentage bought is more than the percentage owned for non joint purchase" do @@ -195,7 +195,7 @@ RSpec.describe Validations::Sales::FinancialValidations do record.stairowned = 40 record.jointpur = 2 financial_validator.validate_percentage_bought_not_greater_than_percentage_owned(record) - expect(record.errors["stairowned"]).to include("Total percentage buyer now owns must be more than percentage bought in this transaction.") + expect(record.errors["stairowned"]).to include(I18n.t("validations.sales.financial.stairowned.percentage_bought_must_be_greater_than_percentage_owned.not_joint_purchase")) end end @@ -205,7 +205,6 @@ RSpec.describe Validations::Sales::FinancialValidations do context "with 24/25 logs" do before do record.saledate = Time.zone.local(2024, 4, 3) - record.save!(validate: false) end it "does not add an error if the percentage bought is less than the percentage owned" do @@ -219,8 +218,8 @@ RSpec.describe Validations::Sales::FinancialValidations do record.stairbought = 30 record.stairowned = 30 financial_validator.validate_percentage_bought_not_equal_percentage_owned(record) - expect(record.errors["stairowned"]).to include("The percentage bought is 30% and the percentage owned in total is 30%. These figures cannot be the same.") - expect(record.errors["stairbought"]).to include("The percentage bought is 30% and the percentage owned in total is 30%. These figures cannot be the same.") + expect(record.errors["stairowned"]).to eq([I18n.t("validations.sales.financial.stairowned.percentage_bought_equal_percentage_owned", stairbought: 30, stairowned: 30)]) + expect(record.errors["stairbought"]).to eq([I18n.t("validations.sales.financial.stairbought.percentage_bought_equal_percentage_owned", stairbought: 30, stairowned: 30)]) end it "does not add an error to stairowned and not stairbought if the percentage bought is more than the percentage owned" do @@ -234,7 +233,6 @@ RSpec.describe Validations::Sales::FinancialValidations do context "with 23/24 logs" do before do record.saledate = Time.zone.local(2023, 4, 3) - record.save!(validate: false) end it "does not add an error if the percentage bought is equal to the percentage owned" do @@ -258,7 +256,7 @@ RSpec.describe Validations::Sales::FinancialValidations do it "adds an error if monthly leasehold charges are zero" do record.mscharge = 0 financial_validator.validate_monthly_leasehold_charges(record) - expect(record.errors[:mscharge]).to include I18n.t("validations.financial.monthly_leasehold_charges.not_zero") + expect(record.errors[:mscharge]).to include I18n.t("validations.sales.financial.mscharge.monthly_leasehold_charges.not_zero") end end @@ -270,8 +268,8 @@ RSpec.describe Validations::Sales::FinancialValidations do [2, 16, 18, 24].each do |type| record.type = type financial_validator.validate_percentage_bought_at_least_threshold(record) - expect(record.errors["stairbought"]).to eq(["The minimum increase in equity while staircasing is 10%."]) - expect(record.errors["type"]).to eq(["The minimum increase in equity while staircasing is 10% for this shared ownership type."]) + expect(record.errors["stairbought"]).to eq([I18n.t("validations.sales.financial.stairbought.percentage_bought_must_be_at_least_threshold", threshold: 10)]) + expect(record.errors["type"]).to eq([I18n.t("validations.sales.financial.type.percentage_bought_must_be_at_least_threshold", threshold: 10)]) record.errors.clear end @@ -279,8 +277,8 @@ RSpec.describe Validations::Sales::FinancialValidations do [28, 30, 31, 32].each do |type| record.type = type financial_validator.validate_percentage_bought_at_least_threshold(record) - expect(record.errors["stairbought"]).to eq(["The minimum increase in equity while staircasing is 1%."]) - expect(record.errors["type"]).to eq(["The minimum increase in equity while staircasing is 1% for this shared ownership type."]) + expect(record.errors["stairbought"]).to eq([I18n.t("validations.sales.financial.stairbought.percentage_bought_must_be_at_least_threshold", threshold: 1)]) + expect(record.errors["type"]).to eq([I18n.t("validations.sales.financial.type.percentage_bought_must_be_at_least_threshold", threshold: 1)]) record.errors.clear end end @@ -331,8 +329,8 @@ RSpec.describe Validations::Sales::FinancialValidations do it "adds errors if buyer 2 has an income" do record.income2 = 40_000 financial_validator.validate_child_income(record) - expect(record.errors["ecstat2"]).to include(match I18n.t("validations.financial.income.child_has_income")) - expect(record.errors["income2"]).to include(match I18n.t("validations.financial.income.child_has_income")) + expect(record.errors["ecstat2"]).to include(match I18n.t("validations.sales.financial.ecstat2.child_has_income")) + expect(record.errors["income2"]).to include(match I18n.t("validations.sales.financial.income2.child_has_income")) end end end @@ -347,16 +345,16 @@ RSpec.describe Validations::Sales::FinancialValidations do record.type = 2 record.equity = 1 financial_validator.validate_equity_in_range_for_year_and_type(record) - expect(record.errors["equity"]).to include(match I18n.t("validations.financial.equity.under_min", min_equity: 25)) - expect(record.errors["type"]).to include(match I18n.t("validations.financial.equity.under_min", min_equity: 25)) + expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: 25)) + expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_under_min", min_equity: 25)) end it "adds an error for type 30, equity below min with the correct percentage" do record.type = 30 record.equity = 1 financial_validator.validate_equity_in_range_for_year_and_type(record) - expect(record.errors["equity"]).to include(match I18n.t("validations.financial.equity.under_min", min_equity: 10)) - expect(record.errors["type"]).to include(match I18n.t("validations.financial.equity.under_min", min_equity: 10)) + expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: 10)) + expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_under_min", min_equity: 10)) end it "does not add an error for equity in range with the correct percentage" do @@ -370,8 +368,8 @@ RSpec.describe Validations::Sales::FinancialValidations do record.type = 2 record.equity = 90 financial_validator.validate_equity_in_range_for_year_and_type(record) - expect(record.errors["equity"]).to include(match I18n.t("validations.financial.equity.over_max", max_equity: 75)) - expect(record.errors["type"]).to include(match I18n.t("validations.financial.equity.over_max", max_equity: 75)) + expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_over_max", max_equity: 75)) + expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_over_max", max_equity: 75)) end it "does not add an error if it's a resale" do @@ -390,16 +388,16 @@ RSpec.describe Validations::Sales::FinancialValidations do record.type = 2 record.equity = 1 financial_validator.validate_equity_in_range_for_year_and_type(record) - expect(record.errors["equity"]).to include(match I18n.t("validations.financial.equity.under_min", min_equity: 25)) - expect(record.errors["type"]).to include(match I18n.t("validations.financial.equity.under_min", min_equity: 25)) + expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: 25)) + expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_under_min", min_equity: 25)) end it "adds an error for type 30, equity below min with the correct percentage" do record.type = 30 record.equity = 1 financial_validator.validate_equity_in_range_for_year_and_type(record) - expect(record.errors["equity"]).to include(match I18n.t("validations.financial.equity.under_min", min_equity: 10)) - expect(record.errors["type"]).to include(match I18n.t("validations.financial.equity.under_min", min_equity: 10)) + expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_under_min", min_equity: 10)) + expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_under_min", min_equity: 10)) end it "does not add an error for equity in range with the correct percentage" do @@ -413,8 +411,8 @@ RSpec.describe Validations::Sales::FinancialValidations do record.type = 2 record.equity = 90 financial_validator.validate_equity_in_range_for_year_and_type(record) - expect(record.errors["equity"]).to include(match I18n.t("validations.financial.equity.over_max", max_equity: 75)) - expect(record.errors["type"]).to include(match I18n.t("validations.financial.equity.over_max", max_equity: 75)) + expect(record.errors["equity"]).to include(match I18n.t("validations.sales.financial.equity.equity_over_max", max_equity: 75)) + expect(record.errors["type"]).to include(match I18n.t("validations.sales.financial.type.equity_over_max", max_equity: 75)) end end end @@ -443,9 +441,9 @@ RSpec.describe Validations::Sales::FinancialValidations do record.equity = 2 record.jointpur = 1 financial_validator.validate_equity_less_than_staircase_difference(record) - expect(record.errors["equity"]).to include("The initial equity stake is 2% and the percentage owned in total minus the percentage bought is 1%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyers own minus the percentage bought.") - expect(record.errors["stairowned"]).to include("The initial equity stake is 2% and the percentage owned in total minus the percentage bought is 1%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyers own minus the percentage bought.") - expect(record.errors["stairbought"]).to include("The initial equity stake is 2% and the percentage owned in total minus the percentage bought is 1%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyers own minus the percentage bought.") + expect(record.errors["equity"]).to include(I18n.t("validations.sales.financial.equity.equity_over_stairowned_minus_stairbought.joint_purchase", equity: 2, staircase_difference: 1)) + expect(record.errors["stairowned"]).to include(I18n.t("validations.sales.financial.stairowned.equity_over_stairowned_minus_stairbought.joint_purchase", equity: 2, staircase_difference: 1)) + expect(record.errors["stairbought"]).to include(I18n.t("validations.sales.financial.stairbought.equity_over_stairowned_minus_stairbought.joint_purchase", equity: 2, staircase_difference: 1)) end it "adds errors if equity is more than stairowned - stairbought for non joint purchase" do @@ -454,9 +452,9 @@ RSpec.describe Validations::Sales::FinancialValidations do record.equity = 2 record.jointpur = 2 financial_validator.validate_equity_less_than_staircase_difference(record) - expect(record.errors["equity"]).to include("The initial equity stake is 2% and the percentage owned in total minus the percentage bought is 1%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyer owns minus the percentage bought.") - expect(record.errors["stairowned"]).to include("The initial equity stake is 2% and the percentage owned in total minus the percentage bought is 1%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyer owns minus the percentage bought.") - expect(record.errors["stairbought"]).to include("The initial equity stake is 2% and the percentage owned in total minus the percentage bought is 1%. In a staircasing transaction, the equity stake purchased cannot be larger than the percentage the buyer owns minus the percentage bought.") + expect(record.errors["equity"]).to include(I18n.t("validations.sales.financial.equity.equity_over_stairowned_minus_stairbought.not_joint_purchase", equity: 2, staircase_difference: 1)) + expect(record.errors["stairowned"]).to include(I18n.t("validations.sales.financial.stairowned.equity_over_stairowned_minus_stairbought.not_joint_purchase", equity: 2, staircase_difference: 1)) + expect(record.errors["stairbought"]).to include(I18n.t("validations.sales.financial.stairbought.equity_over_stairowned_minus_stairbought.not_joint_purchase", equity: 2, staircase_difference: 1)) end it "does not add errors if equity is less than stairowned - stairbought" do