Browse Source

CLDC-3693: Extract shared validations (#2744)

* Extract lettings household validation from shared validations

* Extract lettings setup validation from shared validations

* Extract only shared validations
pull/2750/head^2
Manny Dinssa 1 month ago committed by GitHub
parent
commit
61eb0057f6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      app/models/user.rb
  2. 9
      app/models/validations/household_validations.rb
  3. 8
      app/models/validations/property_validations.rb
  4. 9
      app/models/validations/sales/household_validations.rb
  5. 8
      app/models/validations/sales/property_validations.rb
  6. 8
      app/models/validations/sales/setup_validations.rb
  7. 49
      app/models/validations/setup_validations.rb
  8. 80
      app/models/validations/shared_validations.rb
  9. 35
      config/locales/en.yml
  10. 7
      config/locales/validations/lettings/household.en.yml
  11. 6
      config/locales/validations/lettings/property_information.en.yml
  12. 35
      config/locales/validations/lettings/setup.en.yml
  13. 7
      config/locales/validations/sales/property_information.en.yml
  14. 1
      config/locales/validations/sales/setup.en.yml
  15. 19
      config/locales/validations/shared.en.yml
  16. 4
      lib/tasks/generate_lettings_documentation.rake
  17. 4
      lib/tasks/generate_sales_documentation.rake
  18. 8
      spec/models/form/sales/pages/la_nominations_spec.rb
  19. 6
      spec/models/form/sales/pages/last_accommodation_la_spec.rb
  20. 6
      spec/models/form/sales/pages/last_accommodation_spec.rb
  21. 2
      spec/models/validations/date_validations_spec.rb
  22. 14
      spec/models/validations/household_validations_spec.rb
  23. 42
      spec/models/validations/setup_validations_spec.rb
  24. 34
      spec/models/validations/shared_validations_spec.rb
  25. 4
      spec/models/validations/tenancy_validations_spec.rb
  26. 2
      spec/requests/lettings_logs_controller_spec.rb

2
app/models/user.rb

@ -19,7 +19,7 @@ class User < ApplicationRecord
validates :password, presence: { if: :password_required? } validates :password, presence: { if: :password_required? }
validates :password, length: { within: Devise.password_length, allow_blank: true } validates :password, length: { within: Devise.password_length, allow_blank: true }
validates :password, confirmation: { if: :password_required? } validates :password, confirmation: { if: :password_required? }
validates :phone_extension, format: { with: /\A\d+\z/, allow_blank: true, message: I18n.t("validations.numeric.format", field: "") } validates :phone_extension, format: { with: /\A\d+\z/, allow_blank: true, message: I18n.t("validations.not_number", field: "") }
after_validation :send_data_protection_confirmation_reminder, if: :is_dpo_changed? after_validation :send_data_protection_confirmation_reminder, if: :is_dpo_changed?

9
app/models/validations/household_validations.rb

@ -52,7 +52,14 @@ module Validations::HouseholdValidations
end end
def validate_partner_count(record) def validate_partner_count(record)
shared_validate_partner_count(record, 8) return if record.form.start_year_2024_or_later?
partner_numbers = (2..8).select { |n| person_is_partner?(record["relat#{n}"]) }
if partner_numbers.count > 1
partner_numbers.each do |n|
record.errors.add "relat#{n}", I18n.t("validations.lettings.household.relat.one_partner")
end
end
end end
def validate_person_1_economic(record) def validate_person_1_economic(record)

8
app/models/validations/property_validations.rb

@ -57,4 +57,12 @@ module Validations::PropertyValidations
record.errors.add :uprn, I18n.t("validations.property.uprn.invalid") record.errors.add :uprn, I18n.t("validations.property.uprn.invalid")
end end
def validate_property_postcode(record)
postcode = record.postcode_full
if record.postcode_known? && (postcode.blank? || !postcode.match(POSTCODE_REGEXP))
error_message = I18n.t("validations.lettings.property_information.postcode_full.invalid")
record.errors.add :postcode_full, :wrong_format, message: error_message
end
end
end end

9
app/models/validations/sales/household_validations.rb

@ -2,7 +2,14 @@ module Validations::Sales::HouseholdValidations
include Validations::SharedValidations include Validations::SharedValidations
def validate_partner_count(record) def validate_partner_count(record)
shared_validate_partner_count(record, 6) return if record.form.start_year_2024_or_later?
partner_numbers = (2..6).select { |n| person_is_partner?(record["relat#{n}"]) }
if partner_numbers.count > 1
partner_numbers.each do |n|
record.errors.add "relat#{n}", I18n.t("validations.sales.household.relat.one_partner")
end
end
end end
def validate_buyers_living_in_property(record) def validate_buyers_living_in_property(record)

8
app/models/validations/sales/property_validations.rb

@ -28,4 +28,12 @@ module Validations::Sales::PropertyValidations
record.errors.add :uprn, I18n.t("validations.sales.property_information.uprn.invalid") record.errors.add :uprn, I18n.t("validations.sales.property_information.uprn.invalid")
end end
def validate_property_postcode(record)
postcode = record.postcode_full
if record.postcode_known? && (postcode.blank? || !postcode.match(POSTCODE_REGEXP))
error_message = I18n.t("validations.sales.property_information.postcode_full.invalid")
record.errors.add :postcode_full, :wrong_format, message: error_message
end
end
end end

8
app/models/validations/sales/setup_validations.rb

@ -58,6 +58,14 @@ module Validations::Sales::SetupValidations
end end
end end
def validate_owning_organisation_data_sharing_agremeent_signed(record)
return if record.skip_dpo_validation
if record.owning_organisation_id_changed? && record.owning_organisation.present? && !record.owning_organisation.data_protection_confirmed?
record.errors.add :owning_organisation_id, I18n.t("validations.sales.setup.owning_organisation.data_sharing_agreement_not_signed")
end
end
private private
def active_collection_start_date def active_collection_start_date

49
app/models/validations/setup_validations.rb

@ -72,17 +72,15 @@ module Validations::SetupValidations
end end
end end
def validate_scheme_has_confirmed_locations_validation(record) def validate_scheme(record)
return unless record.scheme return unless record.scheme
unless record.scheme.locations.confirmed.any? if record.scheme.status == :incomplete
record.errors.add :scheme_id, :no_completed_locations, message: I18n.t("validations.lettings.setup.scheme.no_completed_locations") record.errors.add :scheme_id, :incomplete, message: I18n.t("validations.lettings.setup.scheme.incomplete")
end end
end
def validate_scheme(record) if record.scheme.locations.nil? || (record.scheme.locations.present? && record.scheme.locations.confirmed.none?)
if record.scheme&.status == :incomplete record.errors.add :scheme_id, :no_completed_locations, message: I18n.t("validations.lettings.setup.scheme.no_completed_locations")
record.errors.add :scheme_id, :incomplete, message: I18n.t("validations.lettings.setup.scheme.incomplete")
end end
scheme_during_startdate_validation(record) scheme_during_startdate_validation(record)
@ -98,6 +96,35 @@ module Validations::SetupValidations
end end
end end
def location_during_startdate_validation(record)
location_inactive_status = inactive_status(record.startdate, record.location)
if location_inactive_status.present?
date, scope, deactivation_date = location_inactive_status.values_at(:date, :scope, :deactivation_date)
record.errors.add :startdate, :not_active, message: I18n.t("validations.lettings.setup.startdate.location.#{scope}.startdate", postcode: record.location.postcode, date:, deactivation_date:)
record.errors.add :location_id, :not_active, message: I18n.t("validations.lettings.setup.startdate.location.#{scope}.location_id", postcode: record.location.postcode, date:, deactivation_date:)
record.errors.add :scheme_id, :not_active, message: I18n.t("validations.lettings.setup.startdate.location.#{scope}.location_id", postcode: record.location.postcode, date:, deactivation_date:)
end
end
def scheme_during_startdate_validation(record)
scheme_inactive_status = inactive_status(record.startdate, record.scheme)
if scheme_inactive_status.present?
date, scope, deactivation_date = scheme_inactive_status.values_at(:date, :scope, :deactivation_date)
record.errors.add :startdate, I18n.t("validations.lettings.setup.startdate.scheme.#{scope}.startdate", name: record.scheme.service_name, date:, deactivation_date:)
record.errors.add :scheme_id, I18n.t("validations.lettings.setup.startdate.scheme.#{scope}.scheme_id", name: record.scheme.service_name, date:, deactivation_date:)
end
end
def tenancy_startdate_with_scheme_locations(record)
return if record.scheme.blank? || record.startdate.blank?
return if record.scheme.has_active_locations_on_date?(record.startdate)
record.errors.add :startdate, I18n.t("validations.lettings.setup.startdate.scheme.locations_inactive.startdate", name: record.scheme.service_name)
record.errors.add :scheme_id, I18n.t("validations.lettings.setup.startdate.scheme.locations_inactive.scheme_id", name: record.scheme.service_name)
end
def validate_managing_organisation_data_sharing_agremeent_signed(record) def validate_managing_organisation_data_sharing_agremeent_signed(record)
return if record.skip_dpo_validation return if record.skip_dpo_validation
@ -106,6 +133,14 @@ module Validations::SetupValidations
end end
end end
def validate_owning_organisation_data_sharing_agremeent_signed(record)
return if record.skip_dpo_validation
if record.owning_organisation_id_changed? && record.owning_organisation.present? && !record.owning_organisation.data_protection_confirmed?
record.errors.add :owning_organisation_id, I18n.t("validations.lettings.setup.owning_organisation.data_sharing_agreement_not_signed")
end
end
private private
def active_collection_start_date def active_collection_start_date

80
app/models/validations/shared_validations.rb

@ -7,12 +7,12 @@ module Validations::SharedValidations
main_field_label = main_label || main_field.to_s.humanize(capitalize: false) main_field_label = main_label || main_field.to_s.humanize(capitalize: false)
other_field_label = other_label || other_field.to_s.humanize(capitalize: false) other_field_label = other_label || other_field.to_s.humanize(capitalize: false)
if record[main_field] == value_other && record[other_field].blank? if record[main_field] == value_other && record[other_field].blank?
record.errors.add main_field.to_sym, I18n.t("validations.other_field_missing", main_field_label:, other_field_label:) record.errors.add main_field.to_sym, I18n.t("validations.shared.other_field_missing", main_field_label:, other_field_label:)
record.errors.add other_field.to_sym, I18n.t("validations.other_field_missing", main_field_label:, other_field_label:) record.errors.add other_field.to_sym, I18n.t("validations.shared.other_field_missing", main_field_label:, other_field_label:)
end end
if record[main_field] != value_other && record[other_field].present? if record[main_field] != value_other && record[other_field].present?
record.errors.add other_field.to_sym, I18n.t("validations.other_field_not_required", main_field_label:, other_field_label:) record.errors.add other_field.to_sym, I18n.t("validations.shared.other_field_not_required", main_field_label:, other_field_label:)
end end
end end
@ -22,7 +22,7 @@ module Validations::SharedValidations
next if record.send("#{question.id}_before_type_cast").to_s.match?(/\A\d+(\.\d+)?\z/) next if record.send("#{question.id}_before_type_cast").to_s.match?(/\A\d+(\.\d+)?\z/)
field = question.check_answer_label || question.id field = question.check_answer_label || question.id
record.errors.add question.id.to_sym, I18n.t("validations.numeric.format", field:) record.errors.add question.id.to_sym, I18n.t("validations.shared.numeric.format", field:)
end end
end end
@ -55,46 +55,17 @@ module Validations::SharedValidations
incorrect_accuracy = (value.to_d * 100) % (question.step * 100) != 0 incorrect_accuracy = (value.to_d * 100) % (question.step * 100) != 0
if question.step < 1 && incorrect_accuracy if question.step < 1 && incorrect_accuracy
record.errors.add question.id.to_sym, I18n.t("validations.numeric.nearest_hundredth", field:) 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 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 field = question.check_answer_label || question.id
case question.step case question.step
when 1 then record.errors.add question.id.to_sym, :not_integer, message: I18n.t("validations.numeric.whole_number", 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.numeric.nearest_ten", field:) when 10 then record.errors.add question.id.to_sym, I18n.t("validations.shared.numeric.nearest_ten", field:)
end end
end end
end end
end end
def validate_property_postcode(record)
postcode = record.postcode_full
if record.postcode_known? && (postcode.blank? || !postcode.match(POSTCODE_REGEXP))
error_message = I18n.t("validations.postcode")
record.errors.add :postcode_full, :wrong_format, message: error_message
end
end
def location_during_startdate_validation(record)
location_inactive_status = inactive_status(record.startdate, record.location)
if location_inactive_status.present?
date, scope, deactivation_date = location_inactive_status.values_at(:date, :scope, :deactivation_date)
record.errors.add :startdate, :not_active, message: I18n.t("validations.setup.startdate.location.#{scope}.startdate", postcode: record.location.postcode, date:, deactivation_date:)
record.errors.add :location_id, :not_active, message: I18n.t("validations.setup.startdate.location.#{scope}.location_id", postcode: record.location.postcode, date:, deactivation_date:)
record.errors.add :scheme_id, :not_active, message: I18n.t("validations.setup.startdate.location.#{scope}.location_id", postcode: record.location.postcode, date:, deactivation_date:)
end
end
def scheme_during_startdate_validation(record)
scheme_inactive_status = inactive_status(record.startdate, record.scheme)
if scheme_inactive_status.present?
date, scope, deactivation_date = scheme_inactive_status.values_at(:date, :scope, :deactivation_date)
record.errors.add :startdate, I18n.t("validations.setup.startdate.scheme.#{scope}.startdate", name: record.scheme.service_name, date:, deactivation_date:)
record.errors.add :scheme_id, I18n.t("validations.setup.startdate.scheme.#{scope}.scheme_id", name: record.scheme.service_name, date:, deactivation_date:)
end
end
def inactive_status(date, resource) def inactive_status(date, resource)
return if date.blank? || resource.blank? return if date.blank? || resource.blank?
@ -117,46 +88,15 @@ module Validations::SharedValidations
{ scope: status, date: date&.to_formatted_s(:govuk_date), deactivation_date: closest_reactivation&.deactivation_date&.to_formatted_s(:govuk_date) } { scope: status, date: date&.to_formatted_s(:govuk_date), deactivation_date: closest_reactivation&.deactivation_date&.to_formatted_s(:govuk_date) }
end end
def tenancy_startdate_with_scheme_locations(record)
return if record.scheme.blank? || record.startdate.blank?
return if record.scheme.has_active_locations_on_date?(record.startdate)
record.errors.add :startdate, I18n.t("validations.setup.startdate.scheme.locations_inactive.startdate", name: record.scheme.service_name)
record.errors.add :scheme_id, I18n.t("validations.setup.startdate.scheme.locations_inactive.scheme_id", name: record.scheme.service_name)
end
def shared_validate_partner_count(record, max_people)
return if record.form.start_year_2024_or_later?
partner_numbers = (2..max_people).select { |n| person_is_partner?(record["relat#{n}"]) }
if partner_numbers.count > 1
partner_numbers.each do |n|
if record.sales?
record.errors.add "relat#{n}", I18n.t("validations.sales.household.relat.one_partner")
else
record.errors.add "relat#{n}", I18n.t("validations.household.relat.one_partner")
end
end
end
end
def date_valid?(question, record) def date_valid?(question, record)
if record[question].is_a?(ActiveSupport::TimeWithZone) && record[question].year.zero? if record[question].is_a?(ActiveSupport::TimeWithZone) && record[question].year.zero?
record.errors.add question, I18n.t("validations.date.invalid_date") record.errors.add question, I18n.t("validations.shared.date.invalid_date")
false false
else else
true true
end end
end end
def validate_owning_organisation_data_sharing_agremeent_signed(record)
return if record.skip_dpo_validation
if record.owning_organisation_id_changed? && record.owning_organisation.present? && !record.owning_organisation.data_protection_confirmed?
record.errors.add :owning_organisation_id, I18n.t("validations.setup.owning_organisation.data_sharing_agreement_not_signed")
end
end
private private
def person_is_partner?(relationship) def person_is_partner?(relationship)
@ -169,9 +109,9 @@ private
max = [question.prefix, number_with_delimiter(question.max, delimiter: ","), question.suffix].join("") if question.max max = [question.prefix, number_with_delimiter(question.max, delimiter: ","), question.suffix].join("") if question.max
if min && max if min && max
record.errors.add question.id.to_sym, :outside_the_range, message: I18n.t("validations.numeric.within_range", field:, min:, max:) record.errors.add question.id.to_sym, :outside_the_range, message: I18n.t("validations.shared.numeric.within_range", field:, min:, max:)
elsif min elsif min
record.errors.add question.id.to_sym, :under_min, message: I18n.t("validations.numeric.above_min", field:, min:) record.errors.add question.id.to_sym, :under_min, message: I18n.t("validations.shared.numeric.above_min", field:, min:)
end end
end end
end end

35
config/locales/en.yml

@ -239,23 +239,12 @@ en:
merged: "That organisation has already been merged. Select a different organisation." merged: "That organisation has already been merged. Select a different organisation."
scheme_duplicates_not_resolved: "You must resolve all duplicates or indicate that there are no duplicates" scheme_duplicates_not_resolved: "You must resolve all duplicates or indicate that there are no duplicates"
not_answered: "You must answer %{question}" not_answered: "You must answer %{question}"
not_number: "%{field} must be a number."
invalid_option: "Enter a valid value for %{question}" invalid_option: "Enter a valid value for %{question}"
invalid_number: "Enter a number for %{question}" invalid_number: "Enter a number for %{question}"
no_address_found: "We could not find this address. Check the address data in your CSV file is correct and complete, or select the correct address using the CORE site." no_address_found: "We could not find this address. Check the address data in your CSV file is correct and complete, or select the correct address using the CORE site."
other_field_missing: "If %{main_field_label} is other then %{other_field_label} must be provided."
other_field_not_required: "%{other_field_label} must not be provided if %{main_field_label} was not other."
numeric:
within_range: "%{field} must be between %{min} and %{max}."
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_hundredth: "%{field} must be given to the nearest hundredth."
normal_format: "Enter a number."
format: "%{field} must be a number."
date: date:
invalid_date: "Enter a date in the correct format, for example 31 1 2024."
outside_collection_window: "Enter a date within the %{year_combo} collection year, which is between 1st April %{start_year} and 31st March %{end_year}." outside_collection_window: "Enter a date within the %{year_combo} collection year, which is between 1st April %{start_year} and 31st March %{end_year}."
postcode: "Enter a postcode in the correct format, for example AA1 1AA." postcode: "Enter a postcode in the correct format, for example AA1 1AA."
location_admin_district: "Select a local authority." location_admin_district: "Select a local authority."
@ -271,29 +260,8 @@ en:
year_not_two_or_four_digits: "Sale completion year must be 2 or 4 digits." year_not_two_or_four_digits: "Sale completion year must be 2 or 4 digits."
type: type:
percentage_bought_must_be_at_least_threshold: "The minimum increase in equity while staircasing is %{threshold}% for this shared ownership type." percentage_bought_must_be_at_least_threshold: "The minimum increase in equity while staircasing is %{threshold}% for this shared ownership type."
startdate: startdate:
before_scheme_end_date: "The tenancy start date must be before the end date for this supported housing scheme." before_scheme_end_date: "The tenancy start date must be before the end date for this supported housing scheme."
location:
deactivated:
startdate: "The location %{postcode} is inactive on this date. Enter another date or choose another location."
location_id: "This location is not active on the tenancy start date. Choose another location or edit the tenancy start date."
activating_soon:
startdate: "The location %{postcode} is not available until %{date}. Enter a tenancy start date after %{date}."
location_id: "The location %{postcode} is not available until %{date}. Select another location or edit the tenancy start date."
reactivating_soon:
startdate: "The location %{postcode} is not available until %{date}. Enter a tenancy start date after %{date}."
location_id: "The location %{postcode} is not available until %{date}. Select another location or edit the tenancy start date."
scheme:
deactivated:
startdate: "The scheme %{name} was deactivated on %{date} and was not available on the day you entered. Select another scheme or edit the tenancy start date."
scheme_id: "The scheme %{name} was deactivated on %{date} and was not available on the day you entered. Select another scheme or edit the tenancy start date."
reactivating_soon:
startdate: "The scheme %{name} is not available until %{date}. Enter a tenancy start date after %{date}."
scheme_id: "The scheme %{name} is not available until %{date}. Select another scheme or edit the tenancy start date."
locations_inactive:
startdate: "The scheme %{name} has no locations that are active on this date. Enter another date or choose another scheme."
scheme_id: "The scheme %{name} has no locations that are active on this date. Enter another date or choose another scheme."
owning_organisation: owning_organisation:
data_sharing_agreement_not_signed: "The organisation must accept the Data Sharing Agreement before it can be selected as the owning organisation." data_sharing_agreement_not_signed: "The organisation must accept the Data Sharing Agreement before it can be selected as the owning organisation."
property: property:
@ -451,7 +419,6 @@ en:
cannot_be_student: "Person cannot be a student if they are aged 16-19 but are not a child." cannot_be_student: "Person cannot be a student if they are aged 16-19 but are not a child."
relat: relat:
child_under_16_lettings: "Answer cannot be ‘partner’ as you told us person %{person_num}'s age is under 16." child_under_16_lettings: "Answer cannot be ‘partner’ as you told us person %{person_num}'s age is under 16."
one_partner: "Number of partners cannot be greater than 1."
not_student_16_19: "Answer cannot be ‘child’ as you told us the person %{person_num} is between 16 and 19 and is not a full-time student." not_student_16_19: "Answer cannot be ‘child’ as you told us the person %{person_num} is between 16 and 19 and is not a full-time student."
student_16_19: student_16_19:
cannot_be_child: cannot_be_child:

7
config/locales/validations/lettings/household.en.yml

@ -0,0 +1,7 @@
en:
validations:
lettings:
household:
relat:
one_partner: "Number of partners cannot be greater than 1."

6
config/locales/validations/lettings/property_information.en.yml

@ -0,0 +1,6 @@
en:
validations:
lettings:
property_information:
postcode_full:
invalid: "Enter a postcode in the correct format, for example AA1 1AA."

35
config/locales/validations/lettings/setup.en.yml

@ -21,12 +21,40 @@ en:
owning_organisation: "Enter a date when the owning organisation was active. %{owning_organisation} became active on %{available_from}." owning_organisation: "Enter a date when the owning organisation was active. %{owning_organisation} became active on %{available_from}."
managing_organisation: "Enter a date when the managing organisation was active. %{managing_organisation} became active on %{available_from}." managing_organisation: "Enter a date when the managing organisation was active. %{managing_organisation} became active on %{available_from}."
different_organisations: "Enter a date when the owning and managing organisations were active. %{owning_organisation} became active on %{owning_organisation_active_from}, and %{managing_organisation} became active on %{managing_organisation_active_from}." different_organisations: "Enter a date when the owning and managing organisations were active. %{owning_organisation} became active on %{owning_organisation_active_from}, and %{managing_organisation} became active on %{managing_organisation_active_from}."
location:
deactivated:
startdate: "The location %{postcode} is inactive on this date. Enter another date or choose another location."
location_id: "This location is not active on the tenancy start date. Choose another location or edit the tenancy start date."
activating_soon:
startdate: "The location %{postcode} is not available until %{date}. Enter a tenancy start date after %{date}."
location_id: "The location %{postcode} is not available until %{date}. Select another location or edit the tenancy start date."
reactivating_soon:
startdate: "The location %{postcode} is not available until %{date}. Enter a tenancy start date after %{date}."
location_id: "The location %{postcode} is not available until %{date}. Select another location or edit the tenancy start date."
scheme:
deactivated:
startdate: "The scheme %{name} was deactivated on %{date} and was not available on the day you entered. Select another scheme or edit the tenancy start date."
scheme_id: "The scheme %{name} was deactivated on %{date} and was not available on the day you entered. Select another scheme or edit the tenancy start date."
reactivating_soon:
startdate: "The scheme %{name} is not available until %{date}. Enter a tenancy start date after %{date}."
scheme_id: "The scheme %{name} is not available until %{date}. Select another scheme or edit the tenancy start date."
locations_inactive:
startdate: "The scheme %{name} has no locations that are active on this date. Enter another date or choose another scheme."
scheme_id: "The scheme %{name} has no locations that are active on this date. Enter another date or choose another scheme."
scheme:
incomplete: "This scheme is incomplete. Select another scheme or update this one."
no_completed_locations: "This scheme cannot be chosen as it has no completed locations."
location:
incomplete: "This location is incomplete. Select another location or update this one."
assigned_to: assigned_to:
invalid: "Please select the owning organisation or managing organisation that you belong to." invalid: "Please select the owning organisation or managing organisation that you belong to."
owning_organisation: owning_organisation:
invalid: "Please select the owning organisation or managing organisation that you belong to." invalid: "Please select the owning organisation or managing organisation that you belong to."
data_sharing_agreement_not_signed: "The organisation must accept the Data Sharing Agreement before it can be selected as the owning organisation."
inactive: inactive:
merged_organisation: merged_organisation:
"The owning organisation must be active on the tenancy start date. %{owning_organisation} became inactive on %{merge_date} and was replaced by %{absorbing_organisation}." "The owning organisation must be active on the tenancy start date. %{owning_organisation} became inactive on %{merge_date} and was replaced by %{absorbing_organisation}."
@ -44,10 +72,3 @@ en:
intermediate_rent_product_name: intermediate_rent_product_name:
blank: "Enter name of other intermediate rent product." blank: "Enter name of other intermediate rent product."
scheme:
incomplete: "This scheme is incomplete. Select another scheme or update this one."
no_completed_locations: "This scheme cannot be chosen as it has no completed locations."
location:
incomplete: "This location is incomplete. Select another location or update this one."

7
config/locales/validations/sales/property_information.en.yml

@ -3,11 +3,12 @@ en:
sales: sales:
property_information: property_information:
postcode_full: postcode_full:
postcode_must_match_previous: postcode_must_match_previous:
joint_purchase: "Buyers’ last accommodation and discounted ownership postcodes must match." joint_purchase: "Buyers’ last accommodation and discounted ownership postcodes must match."
not_joint_purchase: "Buyer’s last accommodation and discounted ownership postcodes must match." not_joint_purchase: "Buyer’s last accommodation and discounted ownership postcodes must match."
invalid: "Enter a postcode in the correct format, for example AA1 1AA."
ppostcode_full: ppostcode_full:
postcode_must_match_previous: postcode_must_match_previous:
joint_purchase: "Buyers’ last accommodation and discounted ownership postcodes must match." joint_purchase: "Buyers’ last accommodation and discounted ownership postcodes must match."
not_joint_purchase: "Buyer’s last accommodation and discounted ownership postcodes must match." not_joint_purchase: "Buyer’s last accommodation and discounted ownership postcodes must match."
ownershipsch: ownershipsch:
@ -15,7 +16,7 @@ en:
joint_purchase: "Buyers’ last accommodation and discounted ownership postcodes must match." joint_purchase: "Buyers’ last accommodation and discounted ownership postcodes must match."
not_joint_purchase: "Buyer’s last accommodation and discounted ownership postcodes must match." not_joint_purchase: "Buyer’s last accommodation and discounted ownership postcodes must match."
uprn: uprn:
postcode_must_match_previous: postcode_must_match_previous:
joint_purchase: "Buyers’ last accommodation and discounted ownership postcodes must match." joint_purchase: "Buyers’ last accommodation and discounted ownership postcodes must match."
not_joint_purchase: "Buyer’s last accommodation and discounted ownership postcodes must match." not_joint_purchase: "Buyer’s last accommodation and discounted ownership postcodes must match."
invalid: "UPRN must be 12 digits or less." invalid: "UPRN must be 12 digits or less."

1
config/locales/validations/sales/setup.en.yml

@ -17,6 +17,7 @@ en:
"Enter a date when the owning organisation was active. %{owning_organisation} became active on %{available_from}." "Enter a date when the owning organisation was active. %{owning_organisation} became active on %{available_from}."
owning_organisation: owning_organisation:
data_sharing_agreement_not_signed: "The organisation must accept the Data Sharing Agreement before it can be selected as the owning organisation."
inactive: inactive:
merged_organisation: merged_organisation:
"The owning organisation must be active on the sale completion date. %{owning_organisation} became inactive on %{merge_date} and was replaced by %{absorbing_organisation}." "The owning organisation must be active on the sale completion date. %{owning_organisation} became inactive on %{merge_date} and was replaced by %{absorbing_organisation}."

19
config/locales/validations/shared.en.yml

@ -0,0 +1,19 @@
en:
validations:
shared:
other_field_missing: "If %{main_field_label} is other then %{other_field_label} must be provided."
other_field_not_required: "%{other_field_label} must not be provided if %{main_field_label} was not other."
numeric:
within_range: "%{field} must be between %{min} and %{max}."
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_hundredth: "%{field} must be given to the nearest hundredth."
normal_format: "Enter a number."
format: "%{field} must be a number."
postcode: "Enter a postcode in the correct format, for example AA1 1AA."
date:
invalid_date: "Enter a date in the correct format, for example 31 1 2024."

4
lib/tasks/generate_lettings_documentation.rake

@ -60,13 +60,13 @@ namespace :generate_lettings_documentation do
min = [question.prefix, question.min].join("") if question.min min = [question.prefix, question.min].join("") if question.min
max = [question.prefix, question.max].join("") if question.max max = [question.prefix, question.max].join("") if question.max
error_message = I18n.t("validations.numeric.above_min", field:, min:) error_message = I18n.t("validations.shared.numeric.above_min", field:, min:)
validation_name = "minimum" validation_name = "minimum"
validation_description = "Field value is lower than the minimum value" validation_description = "Field value is lower than the minimum value"
if min && max if min && max
validation_name = "range" validation_name = "range"
error_message = I18n.t("validations.numeric.within_range", field:, min:, max:) error_message = I18n.t("validations.shared.numeric.within_range", field:, min:, max:)
validation_description = "Field value is lower than the minimum value or higher than the maximum value" validation_description = "Field value is lower than the minimum value or higher than the maximum value"
end end

4
lib/tasks/generate_sales_documentation.rake

@ -59,13 +59,13 @@ namespace :generate_sales_documentation do
min = [question.prefix, question.min].join("") if question.min min = [question.prefix, question.min].join("") if question.min
max = [question.prefix, question.max].join("") if question.max max = [question.prefix, question.max].join("") if question.max
error_message = I18n.t("validations.numeric.above_min", field:, min:) error_message = I18n.t("validations.shared.numeric.above_min", field:, min:)
validation_name = "minimum" validation_name = "minimum"
validation_description = "Field value is lower than the minimum value" validation_description = "Field value is lower than the minimum value"
if min && max if min && max
validation_name = "range" validation_name = "range"
error_message = I18n.t("validations.numeric.within_range", field:, min:, max:) error_message = I18n.t("validations.shared.numeric.within_range", field:, min:, max:)
validation_description = "Field value is lower than the minimum value or higher than the maximum value" validation_description = "Field value is lower than the minimum value or higher than the maximum value"
end end

8
spec/models/form/sales/pages/la_nominations_spec.rb

@ -7,8 +7,8 @@ RSpec.describe Form::Sales::Pages::LaNominations, type: :model do
let(:page_id) { nil } let(:page_id) { nil }
let(:page_definition) { nil } let(:page_definition) { nil }
let(:start_year_after_2024) { false } let(:start_year_2024_or_later) { false }
let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2024_or_later?: start_year_after_2024) } let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2024_or_later?: start_year_2024_or_later) }
let(:subsection) { instance_double(Form::Subsection, form:) } let(:subsection) { instance_double(Form::Subsection, form:) }
before do before do
@ -32,7 +32,7 @@ RSpec.describe Form::Sales::Pages::LaNominations, type: :model do
end end
context "with 23/24 log" do context "with 23/24 log" do
let(:start_year_after_2024) { false } let(:start_year_2024_or_later) { false }
it "has correct routed to" do it "has correct routed to" do
log.staircase = 1 log.staircase = 1
@ -41,7 +41,7 @@ RSpec.describe Form::Sales::Pages::LaNominations, type: :model do
end end
context "with 24/25 log" do context "with 24/25 log" do
let(:start_year_after_2024) { true } let(:start_year_2024_or_later) { true }
it "has correct routed to when staircase is yes" do it "has correct routed to when staircase is yes" do
log.staircase = 1 log.staircase = 1

6
spec/models/form/sales/pages/last_accommodation_la_spec.rb

@ -5,8 +5,8 @@ RSpec.describe Form::Sales::Pages::LastAccommodationLa, type: :model do
let(:page_id) { nil } let(:page_id) { nil }
let(:page_definition) { nil } let(:page_definition) { nil }
let(:start_year_after_2024) { false } let(:start_year_2024_or_later) { false }
let(:form) { instance_double(Form, depends_on_met: true, start_date: Time.zone.local(2023, 4, 1), start_year_2024_or_later?: start_year_after_2024) } let(:form) { instance_double(Form, depends_on_met: true, start_date: Time.zone.local(2023, 4, 1), start_year_2024_or_later?: start_year_2024_or_later) }
let(:subsection) { instance_double(Form::Subsection, form:, depends_on: nil, enabled?: true) } let(:subsection) { instance_double(Form::Subsection, form:, depends_on: nil, enabled?: true) }
let(:log) { build(:sales_log, :completed) } let(:log) { build(:sales_log, :completed) }
@ -38,7 +38,7 @@ RSpec.describe Form::Sales::Pages::LastAccommodationLa, type: :model do
end end
context "with 2024 form" do context "with 2024 form" do
let(:start_year_after_2024) { true } let(:start_year_2024_or_later) { true }
it "is routed to for 2024 non discounted sale logs" do it "is routed to for 2024 non discounted sale logs" do
log.update!(ownershipsch: 1) log.update!(ownershipsch: 1)

6
spec/models/form/sales/pages/last_accommodation_spec.rb

@ -7,8 +7,8 @@ RSpec.describe Form::Sales::Pages::LastAccommodation, type: :model do
let(:page_id) { nil } let(:page_id) { nil }
let(:page_definition) { nil } let(:page_definition) { nil }
let(:start_year_after_2024) { false } let(:start_year_2024_or_later) { false }
let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2024_or_later?: start_year_after_2024) } let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2024_or_later?: start_year_2024_or_later) }
let(:subsection) { instance_double(Form::Subsection, form:, depends_on: nil) } let(:subsection) { instance_double(Form::Subsection, form:, depends_on: nil) }
it "has correct subsection" do it "has correct subsection" do
@ -37,7 +37,7 @@ RSpec.describe Form::Sales::Pages::LastAccommodation, type: :model do
end end
context "with 2024 form" do context "with 2024 form" do
let(:start_year_after_2024) { true } let(:start_year_2024_or_later) { true }
it "is routed to for 2024 non discounted sale logs" do it "is routed to for 2024 non discounted sale logs" do
log.update!(ownershipsch: 1) log.update!(ownershipsch: 1)

2
spec/models/validations/date_validations_spec.rb

@ -12,7 +12,7 @@ RSpec.describe Validations::DateValidations do
it "must be a valid date" do it "must be a valid date" do
record.startdate = Time.zone.local(0, 7, 1) record.startdate = Time.zone.local(0, 7, 1)
date_validator.validate_startdate(record) date_validator.validate_startdate(record)
expect(record.errors["startdate"]).to include(match I18n.t("validations.date.invalid_date")) expect(record.errors["startdate"]).to include(match I18n.t("validations.shared.date.invalid_date"))
end end
it "does not raise an error when valid" do it "does not raise an error when valid" do

14
spec/models/validations/household_validations_spec.rb

@ -27,13 +27,13 @@ RSpec.describe Validations::HouseholdValidations do
end end
describe "reason for leaving last settled home validations" do describe "reason for leaving last settled home validations" do
let(:field) { "validations.other_field_not_required" } let(:field) { "validations.shared.other_field_not_required" }
let(:main_field_label) { "reason" } let(:main_field_label) { "reason" }
let(:other_field_label) { "reasonother" } let(:other_field_label) { "reasonother" }
let(:expected_error) { I18n.t(field, main_field_label:, other_field_label:) } let(:expected_error) { I18n.t(field, main_field_label:, other_field_label:) }
context "when reason is other" do context "when reason is other" do
let(:field) { "validations.other_field_missing" } let(:field) { "validations.shared.other_field_missing" }
it "validates that a reason is provided" do it "validates that a reason is provided" do
record.reason = 20 record.reason = 20
@ -251,14 +251,14 @@ RSpec.describe Validations::HouseholdValidations do
record.hhmemb = 0 record.hhmemb = 0
household_validator.validate_numeric_min_max(record) household_validator.validate_numeric_min_max(record)
expect(record.errors["hhmemb"]) expect(record.errors["hhmemb"])
.to include(match I18n.t("validations.numeric.within_range", field: "Number of household members", min: 1, max: 8)) .to include(match I18n.t("validations.shared.numeric.within_range", field: "Number of household members", min: 1, max: 8))
end end
it "validates that the number of household members cannot be more than 8" do it "validates that the number of household members cannot be more than 8" do
record.hhmemb = 9 record.hhmemb = 9
household_validator.validate_numeric_min_max(record) household_validator.validate_numeric_min_max(record)
expect(record.errors["hhmemb"]) expect(record.errors["hhmemb"])
.to include(match I18n.t("validations.numeric.within_range", field: "Number of household members", min: 1, max: 8)) .to include(match I18n.t("validations.shared.numeric.within_range", field: "Number of household members", min: 1, max: 8))
end end
it "expects that the number of other household members is between the min and max" do it "expects that the number of other household members is between the min and max" do
@ -276,11 +276,11 @@ RSpec.describe Validations::HouseholdValidations do
record.relat3 = "P" record.relat3 = "P"
household_validator.validate_partner_count(record) household_validator.validate_partner_count(record)
expect(record.errors["relat2"]) expect(record.errors["relat2"])
.to include(match I18n.t("validations.household.relat.one_partner")) .to include(match I18n.t("validations.lettings.household.relat.one_partner"))
expect(record.errors["relat3"]) expect(record.errors["relat3"])
.to include(match I18n.t("validations.household.relat.one_partner")) .to include(match I18n.t("validations.lettings.household.relat.one_partner"))
expect(record.errors["relat4"]) expect(record.errors["relat4"])
.not_to include(match I18n.t("validations.household.relat.one_partner")) .not_to include(match I18n.t("validations.lettings.household.relat.one_partner"))
end end
it "expects that a tenant can have a partner" do it "expects that a tenant can have a partner" do

42
spec/models/validations/setup_validations_spec.rb

@ -436,9 +436,9 @@ RSpec.describe Validations::SetupValidations do
record.scheme = scheme record.scheme = scheme
setup_validator.validate_scheme(record) setup_validator.validate_scheme(record)
expect(record.errors["startdate"]) expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.scheme.deactivated.startdate", name: scheme.service_name, date: "4 June 2022")) .to include(match I18n.t("validations.lettings.setup.startdate.scheme.deactivated.startdate", name: scheme.service_name, date: "4 June 2022"))
expect(record.errors["scheme_id"]) expect(record.errors["scheme_id"])
.to include(match I18n.t("validations.setup.startdate.scheme.deactivated.scheme_id", name: scheme.service_name, date: "4 June 2022")) .to include(match I18n.t("validations.lettings.setup.startdate.scheme.deactivated.scheme_id", name: scheme.service_name, date: "4 June 2022"))
end end
it "produces no error when tenancy start date is during an active scheme period" do it "produces no error when tenancy start date is during an active scheme period" do
@ -465,9 +465,9 @@ RSpec.describe Validations::SetupValidations do
record.scheme = scheme record.scheme = scheme
setup_validator.validate_scheme(record) setup_validator.validate_scheme(record)
expect(record.errors["startdate"]) expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon.startdate", name: scheme.service_name, date: "4 August 2022")) .to include(match I18n.t("validations.lettings.setup.startdate.scheme.reactivating_soon.startdate", name: scheme.service_name, date: "4 August 2022"))
expect(record.errors["scheme_id"]) expect(record.errors["scheme_id"])
.to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon.scheme_id", name: scheme.service_name, date: "4 August 2022")) .to include(match I18n.t("validations.lettings.setup.startdate.scheme.reactivating_soon.scheme_id", name: scheme.service_name, date: "4 August 2022"))
end end
it "produces no error when tenancy start date is during an active scheme period" do it "produces no error when tenancy start date is during an active scheme period" do
@ -498,9 +498,9 @@ RSpec.describe Validations::SetupValidations do
record.scheme = scheme record.scheme = scheme
setup_validator.validate_scheme(record) setup_validator.validate_scheme(record)
expect(record.errors["startdate"]) expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon.startdate", name: scheme.service_name, date: "4 September 2022")) .to include(match I18n.t("validations.lettings.setup.startdate.scheme.reactivating_soon.startdate", name: scheme.service_name, date: "4 September 2022"))
expect(record.errors["scheme_id"]) expect(record.errors["scheme_id"])
.to include(match I18n.t("validations.setup.startdate.scheme.reactivating_soon.scheme_id", name: scheme.service_name, date: "4 September 2022")) .to include(match I18n.t("validations.lettings.setup.startdate.scheme.reactivating_soon.scheme_id", name: scheme.service_name, date: "4 September 2022"))
end end
it "produces no error when tenancy start date is during an active scheme period" do it "produces no error when tenancy start date is during an active scheme period" do
@ -526,8 +526,8 @@ RSpec.describe Validations::SetupValidations do
record.startdate = Time.zone.local(2022, 7, 5) record.startdate = Time.zone.local(2022, 7, 5)
record.scheme = scheme record.scheme = scheme
setup_validator.validate_scheme(record) setup_validator.validate_scheme(record)
expect(record.errors["startdate"]).to include(match I18n.t("validations.setup.startdate.scheme.locations_inactive.startdate", name: scheme.service_name)) expect(record.errors["startdate"]).to include(match I18n.t("validations.lettings.setup.startdate.scheme.locations_inactive.startdate", name: scheme.service_name))
expect(record.errors["scheme_id"]).to include(match I18n.t("validations.setup.startdate.scheme.locations_inactive.startdate", name: scheme.service_name)) expect(record.errors["scheme_id"]).to include(match I18n.t("validations.lettings.setup.startdate.scheme.locations_inactive.startdate", name: scheme.service_name))
end end
it "produces no error when scheme has active locations on the tenancy start date" do it "produces no error when scheme has active locations on the tenancy start date" do
@ -553,8 +553,8 @@ RSpec.describe Validations::SetupValidations do
record.scheme = scheme record.scheme = scheme
record.location = location record.location = location
setup_validator.validate_scheme(record) setup_validator.validate_scheme(record)
expect(record.errors["startdate"]).to include(match I18n.t("validations.setup.startdate.scheme.locations_inactive.startdate", name: scheme.service_name)) expect(record.errors["startdate"]).to include(match I18n.t("validations.lettings.setup.startdate.scheme.locations_inactive.startdate", name: scheme.service_name))
expect(record.errors["startdate"]).not_to include(match I18n.t("validations.setup.startdate.location.deactivated.startdate", postcode: location.postcode)) expect(record.errors["startdate"]).not_to include(match I18n.t("validations.lettings.setup.startdate.location.deactivated.startdate", postcode: location.postcode))
end end
it "produces no error when scheme has active locations on the tenancy start date" do it "produces no error when scheme has active locations on the tenancy start date" do
@ -593,9 +593,9 @@ RSpec.describe Validations::SetupValidations do
record.location = location record.location = location
setup_validator.validate_location(record) setup_validator.validate_location(record)
expect(record.errors["startdate"]) expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.location.deactivated.startdate", postcode: location.postcode, date: "4 June 2022")) .to include(match I18n.t("validations.lettings.setup.startdate.location.deactivated.startdate", postcode: location.postcode, date: "4 June 2022"))
expect(record.errors["location_id"]) expect(record.errors["location_id"])
.to include(match I18n.t("validations.setup.startdate.location.deactivated.location_id", postcode: location.postcode, date: "4 June 2022")) .to include(match I18n.t("validations.lettings.setup.startdate.location.deactivated.location_id", postcode: location.postcode, date: "4 June 2022"))
end end
it "produces no error when tenancy start date is during an active location period" do it "produces no error when tenancy start date is during an active location period" do
@ -622,9 +622,9 @@ RSpec.describe Validations::SetupValidations do
record.location = location record.location = location
setup_validator.validate_location(record) setup_validator.validate_location(record)
expect(record.errors["startdate"]) expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.location.reactivating_soon.startdate", postcode: location.postcode, date: "4 August 2022")) .to include(match I18n.t("validations.lettings.setup.startdate.location.reactivating_soon.startdate", postcode: location.postcode, date: "4 August 2022"))
expect(record.errors["location_id"]) expect(record.errors["location_id"])
.to include(match I18n.t("validations.setup.startdate.location.reactivating_soon.location_id", postcode: location.postcode, date: "4 August 2022")) .to include(match I18n.t("validations.lettings.setup.startdate.location.reactivating_soon.location_id", postcode: location.postcode, date: "4 August 2022"))
end end
it "produces no error when tenancy start date is during an active location period" do it "produces no error when tenancy start date is during an active location period" do
@ -655,9 +655,9 @@ RSpec.describe Validations::SetupValidations do
record.location = location record.location = location
setup_validator.validate_location(record) setup_validator.validate_location(record)
expect(record.errors["startdate"]) expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.location.reactivating_soon.startdate", postcode: location.postcode, date: "4 September 2022")) .to include(match I18n.t("validations.lettings.setup.startdate.location.reactivating_soon.startdate", postcode: location.postcode, date: "4 September 2022"))
expect(record.errors["location_id"]) expect(record.errors["location_id"])
.to include(match I18n.t("validations.setup.startdate.location.reactivating_soon.location_id", postcode: location.postcode, date: "4 September 2022")) .to include(match I18n.t("validations.lettings.setup.startdate.location.reactivating_soon.location_id", postcode: location.postcode, date: "4 September 2022"))
end end
it "produces no error when tenancy start date is during an active location period" do it "produces no error when tenancy start date is during an active location period" do
@ -686,9 +686,9 @@ RSpec.describe Validations::SetupValidations do
record.location = location record.location = location
setup_validator.validate_location(record) setup_validator.validate_location(record)
expect(record.errors["startdate"]) expect(record.errors["startdate"])
.to include(match I18n.t("validations.setup.startdate.location.activating_soon.startdate", postcode: location.postcode, date: "15 September 2022")) .to include(match I18n.t("validations.lettings.setup.startdate.location.activating_soon.startdate", postcode: location.postcode, date: "15 September 2022"))
expect(record.errors["location_id"]) expect(record.errors["location_id"])
.to include(match I18n.t("validations.setup.startdate.location.activating_soon.location_id", postcode: location.postcode, date: "15 September 2022")) .to include(match I18n.t("validations.lettings.setup.startdate.location.activating_soon.location_id", postcode: location.postcode, date: "15 September 2022"))
end end
end end
@ -726,7 +726,7 @@ RSpec.describe Validations::SetupValidations do
record.startdate = Time.zone.local(2022, 7, 5) record.startdate = Time.zone.local(2022, 7, 5)
record.location = location record.location = location
setup_validator.validate_location(record) setup_validator.validate_location(record)
expect(record.errors["startdate"]).to include(match I18n.t("validations.setup.startdate.location.deactivated.startdate", postcode: location.postcode)) expect(record.errors["startdate"]).to include(match I18n.t("validations.lettings.setup.startdate.location.deactivated.startdate", postcode: location.postcode))
end end
it "produces no error when the chosen location is active on the tenancy start date" do it "produces no error when the chosen location is active on the tenancy start date" do
@ -900,7 +900,7 @@ RSpec.describe Validations::SetupValidations do
it "produces an error" do it "produces an error" do
record.scheme = scheme record.scheme = scheme
setup_validator.validate_scheme_has_confirmed_locations_validation(record) setup_validator.validate_scheme(record)
expect(record.errors["scheme_id"]) expect(record.errors["scheme_id"])
.to include(match I18n.t("validations.lettings.setup.scheme.no_completed_locations")) .to include(match I18n.t("validations.lettings.setup.scheme.no_completed_locations"))
end end
@ -914,7 +914,7 @@ RSpec.describe Validations::SetupValidations do
it "does not produce an error" do it "does not produce an error" do
record.scheme = scheme record.scheme = scheme
setup_validator.validate_scheme_has_confirmed_locations_validation(record) setup_validator.validate_scheme(record)
expect(record.errors["scheme_id"]) expect(record.errors["scheme_id"])
.to be_empty .to be_empty
end end

34
spec/models/validations/shared_validations_spec.rb

@ -18,42 +18,42 @@ RSpec.describe Validations::SharedValidations do
lettings_log.age1 = "random" lettings_log.age1 = "random"
shared_validator.validate_numeric_min_max(lettings_log) shared_validator.validate_numeric_min_max(lettings_log)
expect(lettings_log.errors["age1"]) expect(lettings_log.errors["age1"])
.to include(match I18n.t("validations.numeric.within_range", field: "Lead tenant’s age", min: 16, max: 120)) .to include(match I18n.t("validations.shared.numeric.within_range", field: "Lead tenant’s age", min: 16, max: 120))
end end
it "validates that other household member ages are a number" do it "validates that other household member ages are a number" do
lettings_log.age2 = "random" lettings_log.age2 = "random"
shared_validator.validate_numeric_min_max(lettings_log) shared_validator.validate_numeric_min_max(lettings_log)
expect(lettings_log.errors["age2"]) expect(lettings_log.errors["age2"])
.to include(match I18n.t("validations.numeric.within_range", field: "Person 2’s age", min: 1, max: 120)) .to include(match I18n.t("validations.shared.numeric.within_range", field: "Person 2’s age", min: 1, max: 120))
end end
it "validates that person 1's age is greater than 16" do it "validates that person 1's age is greater than 16" do
lettings_log.age1 = 15 lettings_log.age1 = 15
shared_validator.validate_numeric_min_max(lettings_log) shared_validator.validate_numeric_min_max(lettings_log)
expect(lettings_log.errors["age1"]) expect(lettings_log.errors["age1"])
.to include(match I18n.t("validations.numeric.within_range", field: "Lead tenant’s age", min: 16, max: 120)) .to include(match I18n.t("validations.shared.numeric.within_range", field: "Lead tenant’s age", min: 16, max: 120))
end end
it "validates that other household member ages are greater than 1" do it "validates that other household member ages are greater than 1" do
lettings_log.age2 = 0 lettings_log.age2 = 0
shared_validator.validate_numeric_min_max(lettings_log) shared_validator.validate_numeric_min_max(lettings_log)
expect(lettings_log.errors["age2"]) expect(lettings_log.errors["age2"])
.to include(match I18n.t("validations.numeric.within_range", field: "Person 2’s age", min: 1, max: 120)) .to include(match I18n.t("validations.shared.numeric.within_range", field: "Person 2’s age", min: 1, max: 120))
end end
it "validates that person 1's age is less than 121" do it "validates that person 1's age is less than 121" do
lettings_log.age1 = 121 lettings_log.age1 = 121
shared_validator.validate_numeric_min_max(lettings_log) shared_validator.validate_numeric_min_max(lettings_log)
expect(lettings_log.errors["age1"]) expect(lettings_log.errors["age1"])
.to include(match I18n.t("validations.numeric.within_range", field: "Lead tenant’s age", min: 16, max: 120)) .to include(match I18n.t("validations.shared.numeric.within_range", field: "Lead tenant’s age", min: 16, max: 120))
end end
it "validates that other household member ages are greater than 121" do it "validates that other household member ages are greater than 121" do
lettings_log.age2 = 123 lettings_log.age2 = 123
shared_validator.validate_numeric_min_max(lettings_log) shared_validator.validate_numeric_min_max(lettings_log)
expect(lettings_log.errors["age2"]) expect(lettings_log.errors["age2"])
.to include(match I18n.t("validations.numeric.within_range", field: "Person 2’s age", min: 1, max: 120)) .to include(match I18n.t("validations.shared.numeric.within_range", field: "Person 2’s age", min: 1, max: 120))
end end
it "validates that person 1's age is between 16 and 120" do it "validates that person 1's age is between 16 and 120" do
@ -91,7 +91,7 @@ RSpec.describe Validations::SharedValidations do
sales_log.savings = -10 sales_log.savings = -10
sales_log.jointpur = 1 sales_log.jointpur = 1
shared_validator.validate_numeric_min_max(sales_log) shared_validator.validate_numeric_min_max(sales_log)
expect(sales_log.errors["savings"]).to include(match I18n.t("validations.numeric.above_min", field: "Buyers’ total savings before any deposit paid", min: "£0")) expect(sales_log.errors["savings"]).to include(match I18n.t("validations.shared.numeric.above_min", field: "Buyers’ total savings before any deposit paid", min: "£0"))
end end
context "when validating percent" do context "when validating percent" do
@ -101,7 +101,7 @@ RSpec.describe Validations::SharedValidations do
sales_log.stairbought = 150 sales_log.stairbought = 150
shared_validator.validate_numeric_min_max(sales_log) shared_validator.validate_numeric_min_max(sales_log)
expect(sales_log.errors["stairbought"]) expect(sales_log.errors["stairbought"])
.to include(match I18n.t("validations.numeric.within_range", field: "Percentage bought in this staircasing transaction", min: "0%", max: "100%")) .to include(match I18n.t("validations.shared.numeric.within_range", field: "Percentage bought in this staircasing transaction", min: "0%", max: "100%"))
end end
end end
@ -110,7 +110,7 @@ RSpec.describe Validations::SharedValidations do
sales_log.income1 = -5 sales_log.income1 = -5
shared_validator.validate_numeric_min_max(sales_log) shared_validator.validate_numeric_min_max(sales_log)
expect(sales_log.errors["income1"]) expect(sales_log.errors["income1"])
.to include(match I18n.t("validations.numeric.within_range", field: "Buyer 1’s gross annual income", min: "£0", max: "£999,999")) .to include(match I18n.t("validations.shared.numeric.within_range", field: "Buyer 1’s gross annual income", min: "£0", max: "£999,999"))
end end
end end
end end
@ -120,13 +120,13 @@ RSpec.describe Validations::SharedValidations do
it "adds an error if input is a decimal" do it "adds an error if input is a decimal" do
sales_log.income1 = 30_000.5 sales_log.income1 = 30_000.5
shared_validator.validate_numeric_step(sales_log) shared_validator.validate_numeric_step(sales_log)
expect(sales_log.errors[:income1]).to include I18n.t("validations.numeric.whole_number", field: "Buyer 1’s gross annual income") expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.whole_number", field: "Buyer 1’s gross annual income")
end end
it "adds an error if the user attempts to input a number in exponent format" do it "adds an error if the user attempts to input a number in exponent format" do
sales_log.income1 = "3e5" sales_log.income1 = "3e5"
shared_validator.validate_numeric_step(sales_log) shared_validator.validate_numeric_step(sales_log)
expect(sales_log.errors[:income1]).to include I18n.t("validations.numeric.whole_number", field: "Buyer 1’s gross annual income") expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.whole_number", field: "Buyer 1’s gross annual income")
end end
it "does not add an error if input is an integer" do it "does not add an error if input is an integer" do
@ -141,14 +141,14 @@ RSpec.describe Validations::SharedValidations do
sales_log.savings = 30_005 sales_log.savings = 30_005
sales_log.jointpur = 1 sales_log.jointpur = 1
shared_validator.validate_numeric_step(sales_log) shared_validator.validate_numeric_step(sales_log)
expect(sales_log.errors[:savings]).to include I18n.t("validations.numeric.nearest_ten", field: "Buyers’ total savings before any deposit paid") expect(sales_log.errors[:savings]).to include I18n.t("validations.shared.numeric.nearest_ten", field: "Buyers’ total savings before any deposit paid")
end end
it "adds an error if the user attempts to input a number in exponent format" do it "adds an error if the user attempts to input a number in exponent format" do
sales_log.savings = "3e5" sales_log.savings = "3e5"
sales_log.jointpur = 1 sales_log.jointpur = 1
shared_validator.validate_numeric_step(sales_log) shared_validator.validate_numeric_step(sales_log)
expect(sales_log.errors[:savings]).to include I18n.t("validations.numeric.nearest_ten", field: "Buyers’ total savings before any deposit paid") expect(sales_log.errors[:savings]).to include I18n.t("validations.shared.numeric.nearest_ten", field: "Buyers’ total savings before any deposit paid")
end end
it "does not add an error if input is a multiple of ten" do it "does not add an error if input is a multiple of ten" do
@ -162,7 +162,7 @@ RSpec.describe Validations::SharedValidations do
it "adds an error if input has more than 2 decimal places" do it "adds an error if input has more than 2 decimal places" do
sales_log.mscharge = 30.7418 sales_log.mscharge = 30.7418
shared_validator.validate_numeric_step(sales_log) shared_validator.validate_numeric_step(sales_log)
expect(sales_log.errors[:mscharge]).to include I18n.t("validations.numeric.nearest_hundredth", field: "Monthly leasehold charges") expect(sales_log.errors[:mscharge]).to include I18n.t("validations.shared.numeric.nearest_hundredth", field: "Monthly leasehold charges")
end end
it "does not add an error if the user attempts to input a number in exponent format" do it "does not add an error if the user attempts to input a number in exponent format" do
@ -220,13 +220,13 @@ RSpec.describe Validations::SharedValidations do
it "does not allow letters" do it "does not allow letters" do
sales_log.income1 = "abc" sales_log.income1 = "abc"
shared_validator.validate_numeric_input(sales_log) shared_validator.validate_numeric_input(sales_log)
expect(sales_log.errors[:income1]).to include I18n.t("validations.numeric.format", field: "Buyer 1’s gross annual income") expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.format", field: "Buyer 1’s gross annual income")
end end
it "does not allow special characters" do it "does not allow special characters" do
sales_log.income1 = "3%5" sales_log.income1 = "3%5"
shared_validator.validate_numeric_input(sales_log) shared_validator.validate_numeric_input(sales_log)
expect(sales_log.errors[:income1]).to include I18n.t("validations.numeric.format", field: "Buyer 1’s gross annual income") expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.format", field: "Buyer 1’s gross annual income")
end end
it "allows a digit" do it "allows a digit" do
@ -244,7 +244,7 @@ RSpec.describe Validations::SharedValidations do
it "does not allow decimal point in a wrong format" do it "does not allow decimal point in a wrong format" do
sales_log.income1 = "300.09.78" sales_log.income1 = "300.09.78"
shared_validator.validate_numeric_input(sales_log) shared_validator.validate_numeric_input(sales_log)
expect(sales_log.errors[:income1]).to include I18n.t("validations.numeric.format", field: "Buyer 1’s gross annual income") expect(sales_log.errors[:income1]).to include I18n.t("validations.shared.numeric.format", field: "Buyer 1’s gross annual income")
end end
end end
end end

4
spec/models/validations/tenancy_validations_spec.rb

@ -276,7 +276,7 @@ RSpec.describe Validations::TenancyValidations do
describe "tenancy type validations" do describe "tenancy type validations" do
let(:record) { FactoryBot.build(:lettings_log, :setup_completed) } let(:record) { FactoryBot.build(:lettings_log, :setup_completed) }
let(:field) { "validations.other_field_missing" } let(:field) { "validations.shared.other_field_missing" }
let(:main_field_label) { "tenancy type" } let(:main_field_label) { "tenancy type" }
let(:other_field) { "tenancyother" } let(:other_field) { "tenancyother" }
let(:other_field_label) { "other tenancy type" } let(:other_field_label) { "other tenancy type" }
@ -299,7 +299,7 @@ RSpec.describe Validations::TenancyValidations do
end end
context "when tenancy type is not other" do context "when tenancy type is not other" do
let(:field) { "validations.other_field_not_required" } let(:field) { "validations.shared.other_field_not_required" }
it "validates that other tenancy type is not provided" do it "validates that other tenancy type is not provided" do
record.tenancy = 2 record.tenancy = 2

2
spec/requests/lettings_logs_controller_spec.rb

@ -82,7 +82,7 @@ RSpec.describe LettingsLogsController, type: :request do
it "validates lettings log parameters" do it "validates lettings log parameters" do
json_response = JSON.parse(response.body) json_response = JSON.parse(response.body)
expect(response).to have_http_status(:unprocessable_entity) expect(response).to have_http_status(:unprocessable_entity)
expect(json_response["errors"]).to match_array([["offered", [I18n.t("validations.numeric.within_range", field: "Times previously offered since becoming available", min: 0, max: 20)]], ["age1", [I18n.t("validations.numeric.within_range", field: "Lead tenant’s age", min: 16, max: 120)]]]) expect(json_response["errors"]).to match_array([["offered", [I18n.t("validations.shared.numeric.within_range", field: "Times previously offered since becoming available", min: 0, max: 20)]], ["age1", [I18n.t("validations.shared.numeric.within_range", field: "Lead tenant’s age", min: 16, max: 120)]]])
end end
end end

Loading…
Cancel
Save