Browse Source

CLDC-3694 Extract lettings BU validations

pull/2719/head^2
kosiakkatrina 6 months ago committed by GitHub
parent
commit
1e968e50a6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 10
      app/services/bulk_upload/lettings/validator.rb
  2. 138
      app/services/bulk_upload/lettings/year2023/row_parser.rb
  3. 144
      app/services/bulk_upload/lettings/year2024/row_parser.rb
  4. 27
      app/services/bulk_upload/processor.rb
  5. 27
      config/locales/en.yml
  6. 56
      config/locales/validations/lettings/2023/bulk_upload.en.yml
  7. 56
      config/locales/validations/lettings/2024/bulk_upload.en.yml
  8. 126
      spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb
  9. 142
      spec/services/bulk_upload/lettings/year2024/row_parser_spec.rb

10
app/services/bulk_upload/lettings/validator.rb

@ -158,7 +158,7 @@ private
def validate_file_not_empty def validate_file_not_empty
if File.size(path).zero? || csv_parser.body_rows.flatten.compact.empty? if File.size(path).zero? || csv_parser.body_rows.flatten.compact.empty?
errors.add(:base, :blank_file) errors.add(:base, I18n.t("validations.lettings.#{@bulk_upload.year}.bulk_upload.blank_file"))
halt_validations! halt_validations!
end end
@ -168,7 +168,7 @@ private
return if halt_validations? return if halt_validations?
unless csv_parser.correct_field_count? unless csv_parser.correct_field_count?
errors.add(:base, :wrong_field_numbers_count) errors.add(:base, I18n.t("validations.lettings.#{@bulk_upload.year}.bulk_upload.wrong_template.wrong_field_numbers_count"))
halt_validations! halt_validations!
end end
end end
@ -177,7 +177,7 @@ private
return if halt_validations? return if halt_validations?
if csv_parser.too_many_columns? if csv_parser.too_many_columns?
errors.add(:base, :over_max_column_count) errors.add(:base, I18n.t("validations.lettings.#{@bulk_upload.year}.bulk_upload.wrong_template.over_max_column_count"))
halt_validations! halt_validations!
end end
end end
@ -185,14 +185,14 @@ private
def validate_correct_template def validate_correct_template
return if halt_validations? return if halt_validations?
errors.add(:base, :wrong_template) if csv_parser.wrong_template_for_year? errors.add(:base, I18n.t("validations.lettings.#{@bulk_upload.year}.bulk_upload.wrong_template.wrong_template")) if csv_parser.wrong_template_for_year?
end end
def validate_missing_required_headers def validate_missing_required_headers
return if halt_validations? return if halt_validations?
if csv_parser.missing_required_headers? if csv_parser.missing_required_headers?
errors.add :base, I18n.t("activemodel.errors.models.bulk_upload/lettings/validator.attributes.base.no_headers", guidance_link: bulk_upload_lettings_log_url(id: "guidance", form: { year: bulk_upload.year }, host: ENV["APP_HOST"], anchor: "using-the-bulk-upload-template")) errors.add :base, I18n.t("validations.lettings.#{@bulk_upload.year}.bulk_upload.wrong_template.no_headers", guidance_link: bulk_upload_lettings_log_url(id: "guidance", form: { year: bulk_upload.year }, host: ENV["APP_HOST"], anchor: "using-the-bulk-upload-template"))
halt_validations! halt_validations!
end end
end end

138
app/services/bulk_upload/lettings/year2023/row_parser.rb

@ -141,6 +141,8 @@ class BulkUpload::Lettings::Year2023::RowParser
field_134: "What do you expect the outstanding amount to be?", field_134: "What do you expect the outstanding amount to be?",
}.freeze }.freeze
ERROR_BASE_KEY = "validations.lettings.2023.bulk_upload".freeze
attribute :bulk_upload attribute :bulk_upload
attribute :block_log_creation, :boolean, default: -> { false } attribute :block_log_creation, :boolean, default: -> { false }
@ -285,12 +287,12 @@ class BulkUpload::Lettings::Year2023::RowParser
validates :field_5, validates :field_5,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "letting type."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "letting type."),
category: :setup, category: :setup,
}, },
inclusion: { inclusion: {
in: (1..12).to_a, in: (1..12).to_a,
message: I18n.t("validations.invalid_option", question: "letting type."), message: I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: "letting type."),
unless: -> { field_5.blank? }, unless: -> { field_5.blank? },
category: :setup, category: :setup,
}, },
@ -298,33 +300,33 @@ class BulkUpload::Lettings::Year2023::RowParser
validates :field_6, validates :field_6,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "property renewal."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "property renewal."),
category: :setup, category: :setup,
}, },
on: :after_log on: :after_log
validates :field_7, validates :field_7,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "tenancy start date (day)."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "tenancy start date (day)."),
category: :setup, category: :setup,
}, },
on: :after_log on: :after_log
validates :field_8, validates :field_8,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "tenancy start date (month)."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "tenancy start date (month)."),
category: :setup, category: :setup,
}, },
on: :after_log on: :after_log
validates :field_9, validates :field_9,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "tenancy start date (year)."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "tenancy start date (year)."),
category: :setup, category: :setup,
}, },
format: { format: {
with: /\A(\d{2}|\d{4})\z/, with: /\A(\d{2}|\d{4})\z/,
message: I18n.t("validations.setup.startdate.year_not_two_or_four_digits"), message: I18n.t("#{ERROR_BASE_KEY}.startdate.year_not_two_or_four_digits"),
category: :setup, category: :setup,
unless: -> { field_9.blank? }, unless: -> { field_9.blank? },
}, },
@ -333,55 +335,55 @@ class BulkUpload::Lettings::Year2023::RowParser
validates :field_16, validates :field_16,
presence: { presence: {
if: proc { supported_housing? }, if: proc { supported_housing? },
message: I18n.t("validations.not_answered", question: "scheme code."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "scheme code."),
category: :setup, category: :setup,
}, },
on: :after_log on: :after_log
validates :field_116, validates :field_116,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "was the letting made under the Choice-Based Lettings (CBL)?"), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "was the letting made under the Choice-Based Lettings (CBL)?"),
category: :not_answered, category: :not_answered,
}, },
inclusion: { inclusion: {
in: [1, 2], in: [1, 2],
message: I18n.t("validations.invalid_option", question: "was the letting made under the Choice-Based Lettings (CBL)?"), message: I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: "was the letting made under the Choice-Based Lettings (CBL)?"),
if: -> { field_116.present? }, if: -> { field_116.present? },
}, },
on: :after_log on: :after_log
validates :field_117, validates :field_117,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "was the letting made under the Common Allocation Policy (CAP)?"), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "was the letting made under the Common Allocation Policy (CAP)?"),
category: :not_answered, category: :not_answered,
}, },
inclusion: { inclusion: {
in: [1, 2], in: [1, 2],
message: I18n.t("validations.invalid_option", question: "was the letting made under the Common Allocation Policy (CAP)?"), message: I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: "was the letting made under the Common Allocation Policy (CAP)?"),
if: -> { field_117.present? }, if: -> { field_117.present? },
}, },
on: :after_log on: :after_log
validates :field_118, validates :field_118,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "was the letting made under the Common Housing Register (CHR)?"), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "was the letting made under the Common Housing Register (CHR)?"),
category: :not_answered, category: :not_answered,
}, },
inclusion: { inclusion: {
in: [1, 2], in: [1, 2],
message: I18n.t("validations.invalid_option", question: "was the letting made under the Common Housing Register (CHR)?"), message: I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: "was the letting made under the Common Housing Register (CHR)?"),
if: -> { field_118.present? }, if: -> { field_118.present? },
}, },
on: :after_log on: :after_log
validates :field_46, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 1 must be a number or the letter R" }, on: :after_log validates :field_46, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 1) }, on: :after_log
validates :field_52, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 2 must be a number or the letter R" }, on: :after_log, if: proc { details_known?(2).zero? } validates :field_52, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 2) }, on: :after_log, if: proc { details_known?(2).zero? }
validates :field_56, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 3 must be a number or the letter R" }, on: :after_log, if: proc { details_known?(3).zero? } validates :field_56, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 3) }, on: :after_log, if: proc { details_known?(3).zero? }
validates :field_60, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 4 must be a number or the letter R" }, on: :after_log, if: proc { details_known?(4).zero? } validates :field_60, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 4) }, on: :after_log, if: proc { details_known?(4).zero? }
validates :field_64, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 5 must be a number or the letter R" }, on: :after_log, if: proc { details_known?(5).zero? } validates :field_64, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 5) }, on: :after_log, if: proc { details_known?(5).zero? }
validates :field_68, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 6 must be a number or the letter R" }, on: :after_log, if: proc { details_known?(6).zero? } validates :field_68, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 6) }, on: :after_log, if: proc { details_known?(6).zero? }
validates :field_72, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 7 must be a number or the letter R" }, on: :after_log, if: proc { details_known?(7).zero? } validates :field_72, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 7) }, on: :after_log, if: proc { details_known?(7).zero? }
validates :field_76, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 8 must be a number or the letter R" }, on: :after_log, if: proc { details_known?(8).zero? } validates :field_76, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 8) }, on: :after_log, if: proc { details_known?(8).zero? }
validate :validate_needs_type_present, on: :after_log validate :validate_needs_type_present, on: :after_log
validate :validate_data_types, on: :after_log validate :validate_data_types, on: :after_log
@ -521,7 +523,7 @@ class BulkUpload::Lettings::Year2023::RowParser
def add_duplicate_found_in_spreadsheet_errors def add_duplicate_found_in_spreadsheet_errors
spreadsheet_duplicate_hash.each_key do |field| spreadsheet_duplicate_hash.each_key do |field|
errors.add(field, :spreadsheet_dupe, category: :setup) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.spreadsheet_dupe"), category: :setup)
end end
end end
@ -529,7 +531,7 @@ private
def validate_declaration_acceptance def validate_declaration_acceptance
unless field_45 == 1 unless field_45 == 1
errors.add(:field_45, I18n.t("validations.declaration.missing.pre_2024"), category: :setup) errors.add(:field_45, I18n.t("#{ERROR_BASE_KEY}.declaration.missing"), category: :setup)
end end
end end
@ -544,9 +546,9 @@ private
fields.each do |field| fields.each do |field|
if setup_question?(question) if setup_question?(question)
errors.add(field, I18n.t("validations.invalid_option", question: format_ending(QUESTIONS[field])), category: :setup) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: format_ending(QUESTIONS[field])), category: :setup)
else else
errors.add(field, I18n.t("validations.invalid_option", question: format_ending(QUESTIONS[field]))) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: format_ending(QUESTIONS[field])))
end end
end end
end end
@ -556,7 +558,7 @@ private
return if field_3.blank? return if field_3.blank?
unless assigned_to unless assigned_to
errors.add(:field_3, "User with the specified email could not be found.") errors.add(:field_3, I18n.t("#{ERROR_BASE_KEY}.assigned_to.not_found"))
end end
end end
@ -566,7 +568,7 @@ private
return if assigned_to.organisation == owning_organisation&.absorbing_organisation || assigned_to.organisation == managing_organisation&.absorbing_organisation return if assigned_to.organisation == owning_organisation&.absorbing_organisation || assigned_to.organisation == managing_organisation&.absorbing_organisation
block_log_creation! block_log_creation!
errors.add(:field_3, "User must be related to owning organisation or managing organisation.") errors.add(:field_3, I18n.t("#{ERROR_BASE_KEY}.assigned_to.organisation_not_related"))
end end
def assigned_to def assigned_to
@ -575,7 +577,7 @@ private
def validate_uprn_exists_if_any_key_address_fields_are_blank def validate_uprn_exists_if_any_key_address_fields_are_blank
if field_18.blank? && (field_19.blank? || field_21.blank?) if field_18.blank? && (field_19.blank? || field_21.blank?)
errors.add(:field_18, I18n.t("validations.not_answered", question: "UPRN."), category: :not_answered) errors.add(:field_18, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "UPRN."), category: :not_answered)
end end
end end
@ -614,21 +616,21 @@ private
def validate_needs_type_present def validate_needs_type_present
if field_4.blank? if field_4.blank?
errors.add(:field_4, I18n.t("validations.not_answered", question: "needs type."), category: :setup) errors.add(:field_4, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "needs type."), category: :setup)
end end
end end
def validate_no_and_dont_know_disabled_needs_conjunction def validate_no_and_dont_know_disabled_needs_conjunction
if field_87 == 1 && field_88 == 1 if field_87 == 1 && field_88 == 1
errors.add(:field_87, I18n.t("validations.household.housingneeds.no_and_dont_know_disabled_needs_conjunction")) errors.add(:field_87, I18n.t("#{ERROR_BASE_KEY}.housingneeds.no_and_dont_know_disabled_needs_conjunction"))
errors.add(:field_88, I18n.t("validations.household.housingneeds.no_and_dont_know_disabled_needs_conjunction")) errors.add(:field_88, I18n.t("#{ERROR_BASE_KEY}.housingneeds.no_and_dont_know_disabled_needs_conjunction"))
end end
end end
def validate_dont_know_disabled_needs_conjunction def validate_dont_know_disabled_needs_conjunction
if field_88 == 1 && [field_83, field_84, field_85, field_86].count(1).positive? if field_88 == 1 && [field_83, field_84, field_85, field_86].count(1).positive?
%i[field_88 field_83 field_84 field_85 field_86].each do |field| %i[field_88 field_83 field_84 field_85 field_86].each do |field|
errors.add(field, I18n.t("validations.household.housingneeds.dont_know_disabled_needs_conjunction")) if send(field) == 1 errors.add(field, I18n.t("#{ERROR_BASE_KEY}.housingneeds.dont_know_disabled_needs_conjunction")) if send(field) == 1
end end
end end
end end
@ -636,7 +638,7 @@ private
def validate_no_disabled_needs_conjunction def validate_no_disabled_needs_conjunction
if field_87 == 1 && [field_83, field_84, field_85, field_86].count(1).positive? if field_87 == 1 && [field_83, field_84, field_85, field_86].count(1).positive?
%i[field_87 field_83 field_84 field_85 field_86].each do |field| %i[field_87 field_83 field_84 field_85 field_86].each do |field|
errors.add(field, I18n.t("validations.household.housingneeds.no_disabled_needs_conjunction")) if send(field) == 1 errors.add(field, I18n.t("#{ERROR_BASE_KEY}.housingneeds.no_disabled_needs_conjunction")) if send(field) == 1
end end
end end
end end
@ -644,17 +646,17 @@ private
def validate_only_one_housing_needs_type def validate_only_one_housing_needs_type
if [field_83, field_84, field_85].count(1) > 1 if [field_83, field_84, field_85].count(1) > 1
%i[field_83 field_84 field_85].each do |field| %i[field_83 field_84 field_85].each do |field|
errors.add(field, I18n.t("validations.household.housingneeds_type.only_one_option_permitted")) if send(field) == 1 errors.add(field, I18n.t("#{ERROR_BASE_KEY}.housingneeds_type.only_one_option_permitted")) if send(field) == 1
end end
end end
end end
def validate_no_housing_needs_questions_answered def validate_no_housing_needs_questions_answered
if [field_83, field_84, field_85, field_86, field_87, field_88].all?(&:blank?) if [field_83, field_84, field_85, field_86, field_87, field_88].all?(&:blank?)
errors.add(:field_87, I18n.t("validations.not_answered", question: "anybody with disabled access needs."), category: :not_answered) errors.add(:field_87, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "anybody with disabled access needs."), category: :not_answered)
errors.add(:field_86, I18n.t("validations.not_answered", question: "other access needs."), category: :not_answered) errors.add(:field_86, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "other access needs."), category: :not_answered)
%i[field_83 field_84 field_85].each do |field| %i[field_83 field_84 field_85].each do |field|
errors.add(field, I18n.t("validations.not_answered", question: "disabled access needs type."), category: :not_answered) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "disabled access needs type."), category: :not_answered)
end end
end end
end end
@ -663,7 +665,7 @@ private
reason_fields = %i[field_111 field_112 field_113 field_114 field_115] reason_fields = %i[field_111 field_112 field_113 field_114 field_115]
if field_110 == 1 && reason_fields.all? { |field| attributes[field.to_s].blank? } if field_110 == 1 && reason_fields.all? { |field| attributes[field.to_s].blank? }
reason_fields.each do |field| reason_fields.each do |field|
errors.add(field, I18n.t("validations.not_answered", question: "reason for reasonable preference."), category: :not_answered) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "reason for reasonable preference."), category: :not_answered)
end end
end end
end end
@ -673,12 +675,12 @@ private
if household_no_illness? if household_no_illness?
illness_option_fields.each do |field| illness_option_fields.each do |field|
if attributes[field.to_s] == 1 if attributes[field.to_s] == 1
errors.add(field, I18n.t("validations.household.condition_effects.no_choices")) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.condition_effects.no_choices"))
end end
end end
elsif illness_option_fields.all? { |field| attributes[field.to_s].blank? } elsif illness_option_fields.all? { |field| attributes[field.to_s].blank? }
illness_option_fields.each do |field| illness_option_fields.each do |field|
errors.add(field, I18n.t("validations.not_answered", question: "how is person affected by condition or illness."), category: :not_answered) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "how is person affected by condition or illness."), category: :not_answered)
end end
end end
end end
@ -690,20 +692,20 @@ private
def validate_lettings_type_matches_bulk_upload def validate_lettings_type_matches_bulk_upload
if [1, 3, 5, 7, 9, 11].include?(field_5) && !general_needs? if [1, 3, 5, 7, 9, 11].include?(field_5) && !general_needs?
block_log_creation! block_log_creation!
errors.add(:field_4, I18n.t("validations.setup.needstype.lettype_not_supported_housing"), category: :setup) errors.add(:field_4, I18n.t("#{ERROR_BASE_KEY}.needstype.lettype_not_supported_housing"), category: :setup)
errors.add(:field_5, I18n.t("validations.setup.lettype.needstype_supported_housing"), category: :setup) errors.add(:field_5, I18n.t("#{ERROR_BASE_KEY}.lettype.needstype_supported_housing"), category: :setup)
end end
if [2, 4, 6, 8, 10, 12].include?(field_5) && !supported_housing? if [2, 4, 6, 8, 10, 12].include?(field_5) && !supported_housing?
block_log_creation! block_log_creation!
errors.add(:field_4, I18n.t("validations.setup.needstype.lettype_not_general_needs"), category: :setup) errors.add(:field_4, I18n.t("#{ERROR_BASE_KEY}.needstype.lettype_not_general_needs"), category: :setup)
errors.add(:field_5, I18n.t("validations.setup.lettype.needstype_general_needs"), category: :setup) errors.add(:field_5, I18n.t("#{ERROR_BASE_KEY}.lettype.needstype_general_needs"), category: :setup)
end end
end end
def validate_leaving_reason_for_renewal def validate_leaving_reason_for_renewal
if field_6 == 1 && ![40, 42].include?(field_102) if field_6 == 1 && ![40, 42].include?(field_102)
errors.add(:field_102, I18n.t("validations.household.reason.renewal_reason_needed")) errors.add(:field_102, I18n.t("#{ERROR_BASE_KEY}.reason.renewal_reason_needed"))
end end
end end
@ -717,13 +719,13 @@ private
def validate_cannot_be_la_referral_if_general_needs_and_la def validate_cannot_be_la_referral_if_general_needs_and_la
if field_119 == 4 && general_needs? && owning_organisation && owning_organisation.la? if field_119 == 4 && general_needs? && owning_organisation && owning_organisation.la?
errors.add :field_119, I18n.t("validations.household.referral.la_general_needs.prp_referred_by_la") errors.add :field_119, I18n.t("#{ERROR_BASE_KEY}.referral.general_needs_prp_referred_by_la")
end end
end end
def validate_la_with_local_housing_referral def validate_la_with_local_housing_referral
if field_119 == 3 && owning_organisation && owning_organisation.la? if field_119 == 3 && owning_organisation && owning_organisation.la?
errors.add(:field_119, I18n.t("validations.household.referral.nominated_by_local_ha_but_la")) errors.add(:field_119, I18n.t("#{ERROR_BASE_KEY}.referral.nominated_by_local_ha_but_la"))
end end
end end
@ -731,15 +733,15 @@ private
return if startdate.blank? || bulk_upload.form.blank? return if startdate.blank? || bulk_upload.form.blank?
unless bulk_upload.form.valid_start_date_for_form?(startdate) unless bulk_upload.form.valid_start_date_for_form?(startdate)
errors.add(:field_7, I18n.t("validations.date.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup) errors.add(:field_7, I18n.t("#{ERROR_BASE_KEY}.startdate.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup)
errors.add(:field_8, I18n.t("validations.date.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup) errors.add(:field_8, I18n.t("#{ERROR_BASE_KEY}.startdate.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup)
errors.add(:field_9, I18n.t("validations.date.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup) errors.add(:field_9, I18n.t("#{ERROR_BASE_KEY}.startdate.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup)
end end
end end
def validate_data_types def validate_data_types
unless attribute_set["field_5"].value_before_type_cast&.match?(/^\d+\.?0*$/) unless attribute_set["field_5"].value_before_type_cast&.match?(/^\d+\.?0*$/)
errors.add(:field_5, I18n.t("validations.invalid_number", question: "letting type.")) errors.add(:field_5, I18n.t("#{ERROR_BASE_KEY}.invalid_number", question: "letting type."))
end end
end end
@ -756,14 +758,14 @@ private
fields.each do |field| fields.each do |field|
if errors.select { |e| fields.include?(e.attribute) }.none? if errors.select { |e| fields.include?(e.attribute) }.none?
question_text = question.error_display_label.presence || "this question." question_text = question.error_display_label.presence || "this question."
errors.add(field, I18n.t("validations.not_answered", question: format_ending(question_text)), category: :setup) if field.present? errors.add(field, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: format_ending(question_text)), category: :setup) if field.present?
end end
end end
else else
fields.each do |field| fields.each do |field|
unless errors.any? { |e| fields.include?(e.attribute) } unless errors.any? { |e| fields.include?(e.attribute) }
question_text = question.error_display_label.presence || "this question." question_text = question.error_display_label.presence || "this question."
errors.add(field, I18n.t("validations.not_answered", question: format_ending(question_text)), category: :not_answered) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: format_ending(question_text)), category: :not_answered)
end end
end end
end end
@ -773,28 +775,28 @@ private
def validate_related_location_exists def validate_related_location_exists
if scheme && location_id.present? && location.nil? && location_field.present? if scheme && location_id.present? && location.nil? && location_field.present?
block_log_creation! block_log_creation!
errors.add(location_field, "#{location_or_scheme.capitalize} code must relate to a #{location_or_scheme} that is owned by the owning organisation or managing organisation.", category: :setup) errors.add(location_field, I18n.t("#{ERROR_BASE_KEY}.scheme.must_relate_to_org", capitalised_location_or_scheme: location_or_scheme.capitalize, location_or_scheme:), category: :setup)
end end
end end
def validate_location_data_given def validate_location_data_given
if supported_housing? && location_id.blank? && location_field.present? if supported_housing? && location_id.blank? && location_field.present?
block_log_creation! block_log_creation!
errors.add(location_field, I18n.t("validations.not_answered", question: "#{location_or_scheme} code."), category: :setup) errors.add(location_field, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "#{location_or_scheme} code."), category: :setup)
end end
end end
def validate_related_scheme_exists def validate_related_scheme_exists
if scheme_id.present? && scheme_field.present? && owning_organisation.present? && managing_organisation.present? && scheme.nil? if scheme_id.present? && scheme_field.present? && owning_organisation.present? && managing_organisation.present? && scheme.nil?
block_log_creation! block_log_creation!
errors.add(scheme_field, "This #{scheme_or_management_group} code does not belong to the owning organisation or managing organisation.", category: :setup) errors.add(scheme_field, I18n.t("#{ERROR_BASE_KEY}.scheme.does_not_belong_to_org", scheme_or_management_group:), category: :setup)
end end
end end
def validate_scheme_data_given def validate_scheme_data_given
if supported_housing? && scheme_field.present? && scheme_id.blank? if supported_housing? && scheme_field.present? && scheme_id.blank?
block_log_creation! block_log_creation!
errors.add(scheme_field, I18n.t("validations.not_answered", question: "#{scheme_or_management_group} code."), category: :setup) errors.add(scheme_field, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "#{scheme_or_management_group} code."), category: :setup)
end end
end end
@ -803,7 +805,7 @@ private
block_log_creation! block_log_creation!
if errors[:field_2].blank? if errors[:field_2].blank?
errors.add(:field_2, "This managing organisation does not have a relationship with the owning organisation.", category: :setup) errors.add(:field_2, I18n.t("#{ERROR_BASE_KEY}.managing_organisation.no_relationship"), category: :setup)
end end
end end
end end
@ -813,7 +815,7 @@ private
block_log_creation! block_log_creation!
if errors[:field_2].blank? if errors[:field_2].blank?
errors.add(:field_2, "The managing organisation code is incorrect.", category: :setup) errors.add(:field_2, I18n.t("#{ERROR_BASE_KEY}.managing_organisation.not_found"), category: :setup)
end end
end end
end end
@ -821,7 +823,7 @@ private
def validate_managing_org_data_given def validate_managing_org_data_given
if field_2.blank? if field_2.blank?
block_log_creation! block_log_creation!
errors.add(:field_2, "The managing organisation code is incorrect.", category: :setup) errors.add(:field_2, I18n.t("#{ERROR_BASE_KEY}.managing_organisation.not_answered"), category: :setup)
end end
end end
@ -830,7 +832,7 @@ private
block_log_creation! block_log_creation!
if errors[:field_1].blank? if errors[:field_1].blank?
errors.add(:field_1, "The owning organisation code provided is for an organisation that does not own stock.", category: :setup) errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_stock_owner"), category: :setup)
end end
end end
end end
@ -840,7 +842,7 @@ private
block_log_creation! block_log_creation!
if errors[:field_1].blank? if errors[:field_1].blank?
errors.add(:field_1, "The owning organisation code is incorrect.", category: :setup) errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_found"), category: :setup)
end end
end end
end end
@ -848,7 +850,7 @@ private
def validate_owning_org_data_given def validate_owning_org_data_given
if field_1.blank? if field_1.blank?
block_log_creation! block_log_creation!
errors.add(:field_1, I18n.t("validations.not_answered", question: "owning organisation."), category: :setup) errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "owning organisation."), category: :setup)
end end
end end
@ -857,20 +859,20 @@ private
block_log_creation! block_log_creation!
if errors[:field_1].blank? if errors[:field_1].blank?
errors.add(:field_1, "You do not have permission to add logs for this owning organisation.", category: :setup) errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_permitted"), category: :setup)
end end
end end
end end
def validate_correct_intermediate_rent_type def validate_correct_intermediate_rent_type
if field_11.blank? || ![1, 2, 3].include?(field_11.to_i) if field_11.blank? || ![1, 2, 3].include?(field_11.to_i)
errors.add(:field_11, I18n.t("validations.not_answered", question: "intermediate rent type."), category: :setup) errors.add(:field_11, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "intermediate rent type."), category: :setup)
end end
end end
def validate_correct_affordable_rent_type def validate_correct_affordable_rent_type
if field_10.blank? || ![1, 2, 3].include?(field_10.to_i) if field_10.blank? || ![1, 2, 3].include?(field_10.to_i)
errors.add(:field_10, I18n.t("validations.not_answered", question: "is this a London Affordable Rent letting."), category: :setup) errors.add(:field_10, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "is this a London Affordable Rent letting."), category: :setup)
end end
end end
@ -880,7 +882,7 @@ private
def validate_if_log_already_exists def validate_if_log_already_exists
if log_already_exists? if log_already_exists?
error_message = "This is a duplicate log." error_message = I18n.t("#{ERROR_BASE_KEY}.duplicate")
errors.add(:field_1, error_message) # owning_organisation errors.add(:field_1, error_message) # owning_organisation
errors.add(:field_7, error_message) # startdate errors.add(:field_7, error_message) # startdate

144
app/services/bulk_upload/lettings/year2024/row_parser.rb

@ -146,6 +146,8 @@ class BulkUpload::Lettings::Year2024::RowParser
6 => 5, 6 => 5,
}.freeze }.freeze
ERROR_BASE_KEY = "validations.lettings.2024.bulk_upload".freeze
attribute :bulk_upload attribute :bulk_upload
attribute :block_log_creation, :boolean, default: -> { false } attribute :block_log_creation, :boolean, default: -> { false }
@ -286,12 +288,12 @@ class BulkUpload::Lettings::Year2024::RowParser
validates :field_11, validates :field_11,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "rent type."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "rent type."),
category: :setup, category: :setup,
}, },
inclusion: { inclusion: {
in: (1..6).to_a, in: (1..6).to_a,
message: I18n.t("validations.invalid_option", question: "rent type."), message: I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: "rent type."),
unless: -> { field_11.blank? }, unless: -> { field_11.blank? },
category: :setup, category: :setup,
}, },
@ -299,33 +301,33 @@ class BulkUpload::Lettings::Year2024::RowParser
validates :field_7, validates :field_7,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "property renewal."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "property renewal."),
category: :setup, category: :setup,
}, },
on: :after_log on: :after_log
validates :field_8, validates :field_8,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "tenancy start date (day)."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "tenancy start date (day)."),
category: :setup, category: :setup,
}, },
on: :after_log on: :after_log
validates :field_9, validates :field_9,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "tenancy start date (month)."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "tenancy start date (month)."),
category: :setup, category: :setup,
}, },
on: :after_log on: :after_log
validates :field_10, validates :field_10,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "tenancy start date (year)."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "tenancy start date (year)."),
category: :setup, category: :setup,
}, },
format: { format: {
with: /\A(\d{2}|\d{4})\z/, with: /\A(\d{2}|\d{4})\z/,
message: I18n.t("validations.setup.startdate.year_not_two_or_four_digits"), message: I18n.t("#{ERROR_BASE_KEY}.startdate.year_not_two_or_four_digits"),
category: :setup, category: :setup,
unless: -> { field_10.blank? }, unless: -> { field_10.blank? },
}, },
@ -334,7 +336,7 @@ class BulkUpload::Lettings::Year2024::RowParser
validates :field_5, validates :field_5,
presence: { presence: {
if: proc { supported_housing? }, if: proc { supported_housing? },
message: I18n.t("validations.not_answered", question: "scheme code."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "scheme code."),
category: :setup, category: :setup,
}, },
on: :after_log on: :after_log
@ -342,67 +344,67 @@ class BulkUpload::Lettings::Year2024::RowParser
validates :field_6, validates :field_6,
presence: { presence: {
if: proc { supported_housing? }, if: proc { supported_housing? },
message: I18n.t("validations.not_answered", question: "location code."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "location code."),
category: :setup, category: :setup,
}, },
on: :after_log on: :after_log
validates :field_112, validates :field_112,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "was the letting made under the Choice-Based Lettings (CBL)?"), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "was the letting made under the Choice-Based Lettings (CBL)?"),
category: :not_answered, category: :not_answered,
}, },
inclusion: { inclusion: {
in: [1, 2], in: [1, 2],
message: I18n.t("validations.invalid_option", question: "was the letting made under the Choice-Based Lettings (CBL)?"), message: I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: "was the letting made under the Choice-Based Lettings (CBL)?"),
if: -> { field_112.present? }, if: -> { field_112.present? },
}, },
on: :after_log on: :after_log
validates :field_113, validates :field_113,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "was the letting made under the Common Allocation Policy (CAP)?"), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "was the letting made under the Common Allocation Policy (CAP)?"),
category: :not_answered, category: :not_answered,
}, },
inclusion: { inclusion: {
in: [1, 2], in: [1, 2],
message: I18n.t("validations.invalid_option", question: "was the letting made under the Common Allocation Policy (CAP)?"), message: I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: "was the letting made under the Common Allocation Policy (CAP)?"),
if: -> { field_113.present? }, if: -> { field_113.present? },
}, },
on: :after_log on: :after_log
validates :field_114, validates :field_114,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "was the letting made under the Common Housing Register (CHR)?"), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "was the letting made under the Common Housing Register (CHR)?"),
category: :not_answered, category: :not_answered,
}, },
inclusion: { inclusion: {
in: [1, 2], in: [1, 2],
message: I18n.t("validations.invalid_option", question: "was the letting made under the Common Housing Register (CHR)?"), message: I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: "was the letting made under the Common Housing Register (CHR)?"),
if: -> { field_114.present? }, if: -> { field_114.present? },
}, },
on: :after_log on: :after_log
validates :field_115, validates :field_115,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "was the letting made under the Accessible Register?"), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "was the letting made under the Accessible Register?"),
category: :not_answered, category: :not_answered,
}, },
inclusion: { inclusion: {
in: [1, 2], in: [1, 2],
message: I18n.t("validations.invalid_option", question: "was the letting made under the Accessible Register?"), message: I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: "was the letting made under the Accessible Register?"),
if: -> { field_115.present? }, if: -> { field_115.present? },
}, },
on: :after_log on: :after_log
validates :field_42, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 1 must be a number or the letter R" }, on: :after_log validates :field_42, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 1) }, on: :after_log
validates :field_48, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 2 must be a number or the letter R" }, on: :after_log, if: proc { details_known?(2).zero? } validates :field_48, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 2) }, on: :after_log, if: proc { details_known?(2).zero? }
validates :field_52, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 3 must be a number or the letter R" }, on: :after_log, if: proc { details_known?(3).zero? } validates :field_52, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 3) }, on: :after_log, if: proc { details_known?(3).zero? }
validates :field_56, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 4 must be a number or the letter R" }, on: :after_log, if: proc { details_known?(4).zero? } validates :field_56, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 4) }, on: :after_log, if: proc { details_known?(4).zero? }
validates :field_60, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 5 must be a number or the letter R" }, on: :after_log, if: proc { details_known?(5).zero? } validates :field_60, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 5) }, on: :after_log, if: proc { details_known?(5).zero? }
validates :field_64, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 6 must be a number or the letter R" }, on: :after_log, if: proc { details_known?(6).zero? } validates :field_64, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 6) }, on: :after_log, if: proc { details_known?(6).zero? }
validates :field_68, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 7 must be a number or the letter R" }, on: :after_log, if: proc { details_known?(7).zero? } validates :field_68, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 7) }, on: :after_log, if: proc { details_known?(7).zero? }
validates :field_72, format: { with: /\A\d{1,3}\z|\AR\z/, message: "Age of person 8 must be a number or the letter R" }, on: :after_log, if: proc { details_known?(8).zero? } validates :field_72, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 8) }, on: :after_log, if: proc { details_known?(8).zero? }
validate :validate_needs_type_present, on: :after_log validate :validate_needs_type_present, on: :after_log
validate :validate_data_types, on: :after_log validate :validate_data_types, on: :after_log
@ -547,10 +549,10 @@ class BulkUpload::Lettings::Year2024::RowParser
spreadsheet_duplicate_hash.each_key do |field| spreadsheet_duplicate_hash.each_key do |field|
if field == "tcharge" if field == "tcharge"
%w[field_125 field_126 field_127 field_128].each do |sub_field| %w[field_125 field_126 field_127 field_128].each do |sub_field|
errors.add(sub_field, :spreadsheet_dupe, category: :setup) errors.add(sub_field, I18n.t("#{ERROR_BASE_KEY}.spreadsheet_dupe"), category: :setup)
end end
else else
errors.add(field, :spreadsheet_dupe, category: :setup) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.spreadsheet_dupe"), category: :setup)
end end
end end
end end
@ -568,9 +570,9 @@ private
fields.each do |field| fields.each do |field|
if setup_question?(question) if setup_question?(question)
errors.add(field, I18n.t("validations.invalid_option", question: format_ending(QUESTIONS[field])), category: :setup) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: format_ending(QUESTIONS[field])), category: :setup)
else else
errors.add(field, I18n.t("validations.invalid_option", question: format_ending(QUESTIONS[field]))) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: format_ending(QUESTIONS[field])))
end end
end end
end end
@ -580,13 +582,13 @@ private
return if field_3.blank? return if field_3.blank?
unless assigned_to unless assigned_to
errors.add(:field_3, "User with the specified email could not be found.") errors.add(:field_3, I18n.t("#{ERROR_BASE_KEY}.assigned_to.not_found"))
end end
end end
def validate_assigned_to_when_support def validate_assigned_to_when_support
if field_3.blank? && bulk_upload.user.support? if field_3.blank? && bulk_upload.user.support?
errors.add(:field_3, category: :setup, message: I18n.t("validations.not_answered", question: "what is the CORE username of the account this letting log should be assigned to?")) errors.add(:field_3, category: :setup, message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "what is the CORE username of the account this letting log should be assigned to?"))
end end
end end
@ -596,7 +598,7 @@ private
return if assigned_to.organisation == owning_organisation&.absorbing_organisation || assigned_to.organisation == managing_organisation&.absorbing_organisation return if assigned_to.organisation == owning_organisation&.absorbing_organisation || assigned_to.organisation == managing_organisation&.absorbing_organisation
block_log_creation! block_log_creation!
errors.add(:field_3, "User must be related to owning organisation or managing organisation.") errors.add(:field_3, I18n.t("#{ERROR_BASE_KEY}.assigned_to.organisation_not_related"))
end end
def assigned_to def assigned_to
@ -605,14 +607,14 @@ private
def validate_uprn_exists_if_any_key_address_fields_are_blank def validate_uprn_exists_if_any_key_address_fields_are_blank
if field_16.blank? && !key_address_fields_provided? if field_16.blank? && !key_address_fields_provided?
errors.add(:field_16, I18n.t("validations.not_answered", question: "UPRN.")) errors.add(:field_16, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "UPRN."))
end end
end end
def validate_address_option_found def validate_address_option_found
if log.uprn.nil? && field_16.blank? && key_address_fields_provided? if log.uprn.nil? && field_16.blank? && key_address_fields_provided?
%i[field_17 field_18 field_19 field_20 field_21 field_22].each do |field| %i[field_17 field_18 field_19 field_20 field_21 field_22].each do |field|
errors.add(field, I18n.t("validations.no_address_found")) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.address.not_found"))
end end
end end
end end
@ -624,19 +626,19 @@ private
def validate_address_fields def validate_address_fields
if field_16.blank? || log.errors.attribute_names.include?(:uprn) if field_16.blank? || log.errors.attribute_names.include?(:uprn)
if field_17.blank? if field_17.blank?
errors.add(:field_17, I18n.t("validations.not_answered", question: "address line 1.")) errors.add(:field_17, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "address line 1."))
end end
if field_19.blank? if field_19.blank?
errors.add(:field_19, I18n.t("validations.not_answered", question: "town or city.")) errors.add(:field_19, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "town or city."))
end end
if field_21.blank? if field_21.blank?
errors.add(:field_21, I18n.t("validations.not_answered", question: "part 1 of postcode.")) errors.add(:field_21, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "part 1 of postcode."))
end end
if field_22.blank? if field_22.blank?
errors.add(:field_22, I18n.t("validations.not_answered", question: "part 2 of postcode.")) errors.add(:field_22, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "part 2 of postcode."))
end end
end end
end end
@ -661,7 +663,7 @@ private
def validate_nationality def validate_nationality
if field_45.present? && !valid_nationality_options.include?(field_45.to_s) if field_45.present? && !valid_nationality_options.include?(field_45.to_s)
errors.add(:field_45, I18n.t("validations.household.nationality")) errors.add(:field_45, I18n.t("#{ERROR_BASE_KEY}.nationality.invalid"))
end end
end end
@ -682,21 +684,21 @@ private
def validate_needs_type_present def validate_needs_type_present
if field_4.blank? if field_4.blank?
errors.add(:field_4, I18n.t("validations.not_answered", question: "needs type."), category: :setup) errors.add(:field_4, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "needs type."), category: :setup)
end end
end end
def validate_no_and_dont_know_disabled_needs_conjunction def validate_no_and_dont_know_disabled_needs_conjunction
if field_83 == 1 && field_84 == 1 if field_83 == 1 && field_84 == 1
errors.add(:field_83, I18n.t("validations.household.housingneeds.no_and_dont_know_disabled_needs_conjunction")) errors.add(:field_83, I18n.t("#{ERROR_BASE_KEY}.housingneeds.no_and_dont_know_disabled_needs_conjunction"))
errors.add(:field_84, I18n.t("validations.household.housingneeds.no_and_dont_know_disabled_needs_conjunction")) errors.add(:field_84, I18n.t("#{ERROR_BASE_KEY}.housingneeds.no_and_dont_know_disabled_needs_conjunction"))
end end
end end
def validate_dont_know_disabled_needs_conjunction def validate_dont_know_disabled_needs_conjunction
if field_84 == 1 && [field_79, field_80, field_81, field_82].count(1).positive? if field_84 == 1 && [field_79, field_80, field_81, field_82].count(1).positive?
%i[field_84 field_79 field_80 field_81 field_82].each do |field| %i[field_84 field_79 field_80 field_81 field_82].each do |field|
errors.add(field, I18n.t("validations.household.housingneeds.dont_know_disabled_needs_conjunction")) if send(field) == 1 errors.add(field, I18n.t("#{ERROR_BASE_KEY}.housingneeds.dont_know_disabled_needs_conjunction")) if send(field) == 1
end end
end end
end end
@ -704,7 +706,7 @@ private
def validate_no_disabled_needs_conjunction def validate_no_disabled_needs_conjunction
if field_83 == 1 && [field_79, field_80, field_81, field_82].count(1).positive? if field_83 == 1 && [field_79, field_80, field_81, field_82].count(1).positive?
%i[field_83 field_79 field_80 field_81 field_82].each do |field| %i[field_83 field_79 field_80 field_81 field_82].each do |field|
errors.add(field, I18n.t("validations.household.housingneeds.no_disabled_needs_conjunction")) if send(field) == 1 errors.add(field, I18n.t("#{ERROR_BASE_KEY}.housingneeds.no_disabled_needs_conjunction")) if send(field) == 1
end end
end end
end end
@ -712,17 +714,17 @@ private
def validate_only_one_housing_needs_type def validate_only_one_housing_needs_type
if [field_79, field_80, field_81].count(1) > 1 if [field_79, field_80, field_81].count(1) > 1
%i[field_79 field_80 field_81].each do |field| %i[field_79 field_80 field_81].each do |field|
errors.add(field, I18n.t("validations.household.housingneeds_type.only_one_option_permitted")) if send(field) == 1 errors.add(field, I18n.t("#{ERROR_BASE_KEY}.housingneeds_type.only_one_option_permitted")) if send(field) == 1
end end
end end
end end
def validate_no_housing_needs_questions_answered def validate_no_housing_needs_questions_answered
if [field_79, field_80, field_81, field_82, field_83, field_84].all?(&:blank?) if [field_79, field_80, field_81, field_82, field_83, field_84].all?(&:blank?)
errors.add(:field_83, I18n.t("validations.not_answered", question: "anybody with disabled access needs.")) errors.add(:field_83, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "anybody with disabled access needs."))
errors.add(:field_82, I18n.t("validations.not_answered", question: "other access needs.")) errors.add(:field_82, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "other access needs."))
%i[field_79 field_80 field_81].each do |field| %i[field_79 field_80 field_81].each do |field|
errors.add(field, I18n.t("validations.not_answered", question: "disabled access needs type.")) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "disabled access needs type."))
end end
end end
end end
@ -731,7 +733,7 @@ private
reason_fields = %i[field_107 field_108 field_109 field_110 field_111] reason_fields = %i[field_107 field_108 field_109 field_110 field_111]
if field_106 == 1 && reason_fields.all? { |field| attributes[field.to_s].blank? } if field_106 == 1 && reason_fields.all? { |field| attributes[field.to_s].blank? }
reason_fields.each do |field| reason_fields.each do |field|
errors.add(field, I18n.t("validations.not_answered", question: "reason for reasonable preference.")) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "reason for reasonable preference."))
end end
end end
end end
@ -741,12 +743,12 @@ private
if household_no_illness? if household_no_illness?
illness_option_fields.each do |field| illness_option_fields.each do |field|
if attributes[field.to_s] == 1 if attributes[field.to_s] == 1
errors.add(field, I18n.t("validations.household.condition_effects.no_choices")) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.condition_effects.no_choices"))
end end
end end
elsif illness_option_fields.all? { |field| attributes[field.to_s].blank? } elsif illness_option_fields.all? { |field| attributes[field.to_s].blank? }
illness_option_fields.each do |field| illness_option_fields.each do |field|
errors.add(field, I18n.t("validations.not_answered", question: "how is person affected by condition or illness.")) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "how is person affected by condition or illness."))
end end
end end
end end
@ -757,7 +759,7 @@ private
def validate_leaving_reason_for_renewal def validate_leaving_reason_for_renewal
if field_7 == 1 && ![50, 51, 52, 53].include?(field_98) if field_7 == 1 && ![50, 51, 52, 53].include?(field_98)
errors.add(:field_98, I18n.t("validations.household.reason.renewal_reason_needed_2024")) errors.add(:field_98, I18n.t("#{ERROR_BASE_KEY}.reason.renewal_reason_needed"))
end end
end end
@ -771,13 +773,13 @@ private
def validate_cannot_be_la_referral_if_general_needs_and_la def validate_cannot_be_la_referral_if_general_needs_and_la
if field_116 == 4 && general_needs? && owning_organisation && owning_organisation.la? if field_116 == 4 && general_needs? && owning_organisation && owning_organisation.la?
errors.add :field_116, I18n.t("validations.household.referral.la_general_needs.prp_referred_by_la") errors.add :field_116, I18n.t("#{ERROR_BASE_KEY}.referral.general_needs_prp_referred_by_la")
end end
end end
def validate_la_with_local_housing_referral def validate_la_with_local_housing_referral
if field_116 == 3 && owning_organisation && owning_organisation.la? if field_116 == 3 && owning_organisation && owning_organisation.la?
errors.add(:field_116, I18n.t("validations.household.referral.nominated_by_local_ha_but_la")) errors.add(:field_116, I18n.t("#{ERROR_BASE_KEY}.referral.nominated_by_local_ha_but_la"))
end end
end end
@ -785,15 +787,15 @@ private
return if startdate.blank? || bulk_upload.form.blank? return if startdate.blank? || bulk_upload.form.blank?
unless bulk_upload.form.valid_start_date_for_form?(startdate) unless bulk_upload.form.valid_start_date_for_form?(startdate)
errors.add(:field_8, I18n.t("validations.date.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup) errors.add(:field_8, I18n.t("#{ERROR_BASE_KEY}.startdate.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup)
errors.add(:field_9, I18n.t("validations.date.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup) errors.add(:field_9, I18n.t("#{ERROR_BASE_KEY}.startdate.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup)
errors.add(:field_10, I18n.t("validations.date.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup) errors.add(:field_10, I18n.t("#{ERROR_BASE_KEY}.startdate.outside_collection_window", year_combo: bulk_upload.year_combo, start_year: bulk_upload.year, end_year: bulk_upload.end_year), category: :setup)
end end
end end
def validate_data_types def validate_data_types
unless attribute_set["field_11"].value_before_type_cast&.match?(/^\d+\.?0*$/) unless attribute_set["field_11"].value_before_type_cast&.match?(/^\d+\.?0*$/)
errors.add(:field_11, I18n.t("validations.invalid_number", question: "rent type.")) errors.add(:field_11, I18n.t("#{ERROR_BASE_KEY}.invalid_number", question: "rent type."))
end end
end end
@ -825,14 +827,14 @@ private
def validate_related_location_exists def validate_related_location_exists
if scheme && field_6.present? && location.nil? && :field_6.present? if scheme && field_6.present? && location.nil? && :field_6.present?
block_log_creation! block_log_creation!
errors.add(:field_6, "Location code must relate to a location that is owned by the owning organisation or managing organisation.", category: :setup) errors.add(:field_6, I18n.t("#{ERROR_BASE_KEY}.location.must_relate_to_org"), category: :setup)
end end
end end
def validate_related_scheme_exists def validate_related_scheme_exists
if field_5.present? && :field_5.present? && owning_organisation.present? && managing_organisation.present? && scheme.nil? if field_5.present? && :field_5.present? && owning_organisation.present? && managing_organisation.present? && scheme.nil?
block_log_creation! block_log_creation!
errors.add(:field_5, "This scheme code does not belong to the owning organisation or managing organisation.", category: :setup) errors.add(:field_5, I18n.t("#{ERROR_BASE_KEY}.scheme.must_relate_to_org"), category: :setup)
end end
end end
@ -841,7 +843,7 @@ private
block_log_creation! block_log_creation!
if errors[:field_2].blank? if errors[:field_2].blank?
errors.add(:field_2, "This managing organisation does not have a relationship with the owning organisation.", category: :setup) errors.add(:field_2, I18n.t("#{ERROR_BASE_KEY}.managing_organisation.no_relationship"), category: :setup)
end end
end end
end end
@ -851,7 +853,7 @@ private
block_log_creation! block_log_creation!
if field_2.present? && errors[:field_2].blank? if field_2.present? && errors[:field_2].blank?
errors.add(:field_2, "The managing organisation code is incorrect.", category: :setup) errors.add(:field_2, I18n.t("#{ERROR_BASE_KEY}.managing_organisation.not_found"), category: :setup)
end end
end end
end end
@ -859,7 +861,7 @@ private
def validate_managing_org_data_given def validate_managing_org_data_given
if field_2.blank? if field_2.blank?
block_log_creation! block_log_creation!
errors.add(:field_2, I18n.t("validations.not_answered", question: "managing organisation."), category: :setup) errors.add(:field_2, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "managing organisation."), category: :setup)
end end
end end
@ -868,7 +870,7 @@ private
block_log_creation! block_log_creation!
if errors[:field_1].blank? if errors[:field_1].blank?
errors.add(:field_1, "The owning organisation code provided is for an organisation that does not own stock.", category: :setup) errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_stock_owner"), category: :setup)
end end
end end
end end
@ -878,7 +880,7 @@ private
block_log_creation! block_log_creation!
if field_1.present? && errors[:field_1].blank? if field_1.present? && errors[:field_1].blank?
errors.add(:field_1, "The owning organisation code is incorrect.", category: :setup) errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_found"), category: :setup)
end end
end end
end end
@ -886,7 +888,7 @@ private
def validate_owning_org_data_given def validate_owning_org_data_given
if field_1.blank? if field_1.blank?
block_log_creation! block_log_creation!
errors.add(:field_1, I18n.t("validations.not_answered", question: "owning organisation."), category: :setup) errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "owning organisation."), category: :setup)
end end
end end
@ -899,9 +901,9 @@ private
return if errors[:field_1].present? return if errors[:field_1].present?
if bulk_upload.user.support? if bulk_upload.user.support?
errors.add(:field_1, "This owning organisation is not affiliated with #{bulk_upload_organisation.name}.", category: :setup) errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_permitted.support", org_name: bulk_upload_organisation.name), category: :setup)
else else
errors.add(:field_1, "You do not have permission to add logs for this owning organisation.", category: :setup) errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_permitted.not_support"), category: :setup)
end end
end end
@ -916,12 +918,12 @@ private
}.partition { |field, _| public_send(field).blank? }.map(&:to_h) }.partition { |field, _| public_send(field).blank? }.map(&:to_h)
blank_charge_fields.each do |field, charge| blank_charge_fields.each do |field, charge|
errors.add(field, I18n.t("validations.financial.charges.missing_charges", sentence_fragment: charge)) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.charges.missing_charges", sentence_fragment: charge))
end end
other_charge_fields.each do |field, _charge| other_charge_fields.each do |field, _charge|
blank_charge_fields.each do |_blank_field, blank_charge| blank_charge_fields.each do |_blank_field, blank_charge|
errors.add(field, I18n.t("validations.financial.charges.missing_charges", sentence_fragment: blank_charge)) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.charges.missing_charges", sentence_fragment: blank_charge))
end end
end end
end end
@ -936,7 +938,7 @@ private
def validate_if_log_already_exists def validate_if_log_already_exists
if log_already_exists? if log_already_exists?
error_message = "This is a duplicate log." error_message = I18n.t("#{ERROR_BASE_KEY}.duplicate")
errors.add(:field_1, error_message) # owning_organisation errors.add(:field_1, error_message) # owning_organisation
errors.add(:field_8, error_message) # startdate errors.add(:field_8, error_message) # startdate

27
app/services/bulk_upload/processor.rb

@ -1,15 +1,22 @@
class BulkUpload::Processor class BulkUpload::Processor
include CollectionTimeHelper
attr_reader :bulk_upload attr_reader :bulk_upload
BLANK_TEMPLATE_ERRORS = [ def blank_template_errors
I18n.t("activemodel.errors.models.bulk_upload/lettings/validator.attributes.base.blank_file"), [
I18n.t("activemodel.errors.models.bulk_upload/sales/validator.attributes.base.blank_file"), I18n.t("validations.lettings.#{current_collection_start_year}.bulk_upload.blank_file"),
].freeze I18n.t("validations.lettings.#{previous_collection_start_year}.bulk_upload.blank_file"),
I18n.t("activemodel.errors.models.bulk_upload/sales/validator.attributes.base.blank_file"),
].freeze
end
WRONG_TEMPLATE_ERRORS = [ def wrong_template_errors
*I18n.t("activemodel.errors.models.bulk_upload/lettings/validator.attributes.base", default: {}).values, [
*I18n.t("activemodel.errors.models.bulk_upload/sales/validator.attributes.base", default: {}).values, *I18n.t("validations.lettings.#{current_collection_start_year}.bulk_upload.wrong_template", default: {}).values,
].freeze *I18n.t("validations.lettings.#{previous_collection_start_year}.bulk_upload.wrong_template", default: {}).values,
*I18n.t("activemodel.errors.models.bulk_upload/sales/validator.attributes.base", default: {}).values,
].freeze
end
def initialize(bulk_upload:) def initialize(bulk_upload:)
@bulk_upload = bulk_upload @bulk_upload = bulk_upload
@ -157,9 +164,9 @@ private
end end
def handle_invalid_validator def handle_invalid_validator
if BLANK_TEMPLATE_ERRORS.any? { |error| validator.errors.full_messages.include?(error) } if blank_template_errors.any? { |error| validator.errors.full_messages.include?(error) }
@bulk_upload.update!(failure_reason: "blank_template") @bulk_upload.update!(failure_reason: "blank_template")
elsif WRONG_TEMPLATE_ERRORS.any? { |error| validator.errors.full_messages.include?(error) } elsif wrong_template_errors.any? { |error| validator.errors.full_messages.include?(error) }
@bulk_upload.update!(failure_reason: "wrong_template") @bulk_upload.update!(failure_reason: "wrong_template")
end end

27
config/locales/en.yml

@ -61,14 +61,6 @@ en:
<<: *bulk_upload__row_parser__base <<: *bulk_upload__row_parser__base
bulk_upload/sales/year2023/row_parser: bulk_upload/sales/year2023/row_parser:
<<: *bulk_upload__row_parser__base <<: *bulk_upload__row_parser__base
bulk_upload/lettings/validator:
attributes:
base:
blank_file: "Template is blank - The template must be filled in for us to create the logs and check if data is correct."
wrong_field_numbers_count: "Incorrect number of fields, please ensure you have used the correct template."
over_max_column_count: "Too many columns, please ensure you have used the correct template."
wrong_template: "Incorrect start dates, please ensure you have used the correct template."
no_headers: "Your file does not contain the required header rows. Add or check the header rows and upload your file again. [Read more about using the template headers](%{guidance_link})."
bulk_upload/sales/validator: bulk_upload/sales/validator:
attributes: attributes:
base: base:
@ -290,7 +282,6 @@ en:
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."
year_not_two_or_four_digits: "Tenancy start year must be 2 or 4 digits."
location: location:
deactivated: deactivated:
startdate: "The location %{postcode} is inactive on this date. Enter another date or choose another location." startdate: "The location %{postcode} is inactive on this date. Enter another date or choose another location."
@ -313,15 +304,6 @@ en:
scheme_id: "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."
lettype:
general_needs_mismatch: "Lettings type must be a general needs type because you selected general needs when uploading the file."
supported_housing_mismatch: "Lettings type must be a supported housing type because you selected supported housing when uploading the file."
needstype_general_needs: "This needs type is general needs, but the letting type is supported housing. Change either the needs type or the letting type."
needstype_supported_housing: "This needs type is supported housing, but the letting type is general needs. Change either the needs type or the letting type."
needstype:
lettype_not_general_needs: "This letting type is supported housing, but the needs type is general needs. Change either the needs type or the letting type."
lettype_not_supported_housing: "This letting type is general needs, but the needs type is supported housing. Change either the needs type or the letting type."
property: property:
uprn: uprn:
invalid: "UPRN must be 12 digits or less." invalid: "UPRN must be 12 digits or less."
@ -486,13 +468,8 @@ en:
child_over_19: "Answer cannot be child as you told us person %{person_num} is over 19." child_over_19: "Answer cannot be child as you told us person %{person_num} is over 19."
housingneeds_a: housingneeds_a:
one_or_two_choices: "You can only select one option or ‘other disabled access needs’ plus ‘wheelchair-accessible housing’, ‘wheelchair access to essential rooms’ or ‘level access housing’." one_or_two_choices: "You can only select one option or ‘other disabled access needs’ plus ‘wheelchair-accessible housing’, ‘wheelchair access to essential rooms’ or ‘level access housing’."
housingneeds_type:
only_one_option_permitted: "Only one disabled access need: fully wheelchair-accessible housing, wheelchair access to essential rooms or level access housing, can be selected."
housingneeds: housingneeds:
invalid: "If somebody in the household has disabled access needs, they must have the access needs listed, or other access needs." invalid: "If somebody in the household has disabled access needs, they must have the access needs listed, or other access needs."
no_disabled_needs_conjunction: "No disabled access needs can’t be selected if you have selected fully wheelchair-accessible housing, wheelchair access to essential rooms, level access housing or other disabled access needs."
dont_know_disabled_needs_conjunction: "Don’t know disabled access needs can’t be selected if you have selected fully wheelchair-accessible housing, wheelchair access to essential rooms, level access housing or other disabled access needs."
no_and_dont_know_disabled_needs_conjunction: "No disabled access needs and don’t know disabled access needs cannot be selected together."
prevten: prevten:
non_temp_accommodation: "Answer cannot be non-temporary accommodation as this is a re-let to a tenant who occupied the same property as temporary accommodation." non_temp_accommodation: "Answer cannot be non-temporary accommodation as this is a re-let to a tenant who occupied the same property as temporary accommodation."
over_25_foster_care: "Answer cannot be a children’s home or foster care as the lead tenant is 26 or older." over_25_foster_care: "Answer cannot be a children’s home or foster care as the lead tenant is 26 or older."
@ -507,10 +484,8 @@ en:
other_homeless: "Answer cannot be internal transfer as the tenant was considered homeless by their landlord." other_homeless: "Answer cannot be internal transfer as the tenant was considered homeless by their landlord."
prevten_invalid: "Answer cannot be internal transfer as the household situation immediately before this letting was %{prevten}." prevten_invalid: "Answer cannot be internal transfer as the household situation immediately before this letting was %{prevten}."
reason_permanently_decanted: "Answer must be internal transfer as the tenant was permanently decanted from another property owned by this landlord." reason_permanently_decanted: "Answer must be internal transfer as the tenant was permanently decanted from another property owned by this landlord."
nominated_by_local_ha_but_la: "The source of the referral cannot be Nominated by local housing authority as your organisation is a local authority."
la_general_needs: la_general_needs:
internal_transfer: "Answer cannot be internal transfer as it’s the same landlord on the tenancy agreement and the household had either a fixed-term or lifetime local authority general needs tenancy immediately before this letting." internal_transfer: "Answer cannot be internal transfer as it’s the same landlord on the tenancy agreement and the household had either a fixed-term or lifetime local authority general needs tenancy immediately before this letting."
prp_referred_by_la: "The source of the referral cannot be referred by local authority housing department for a general needs log."
homeless: homeless:
assessed: assessed:
internal_transfer: "Answer cannot be 'assessed as homeless' as this tenancy is an internal transfer." internal_transfer: "Answer cannot be 'assessed as homeless' as this tenancy is an internal transfer."
@ -531,8 +506,6 @@ en:
retired_female: "Answer cannot be ‘female’ as tenant is under 60 and retired." retired_female: "Answer cannot be ‘female’ as tenant is under 60 and retired."
reason: reason:
not_internal_transfer: "Answer cannot be ‘permanently decanted from another property owned by this landlord’ as you told us the source of referral for this tenancy was not an internal transfer." not_internal_transfer: "Answer cannot be ‘permanently decanted from another property owned by this landlord’ as you told us the source of referral for this tenancy was not an internal transfer."
renewal_reason_needed: 'The reason for leaving must be "End of assured shorthold tenancy - no fault" or "End of fixed term tenancy - no fault" if the letting is a renewal.'
renewal_reason_needed_2024: 'The reason for leaving must be "End of social or private sector tenancy - no fault", "End of social or private sector tenancy - evicted due to anti-social behaviour (ASB)", "End of social or private sector tenancy - evicted due to rent arrears" or "End of social or private sector tenancy - evicted for any other reason".'
other_not_settled: "Please give the reason for the tenant leaving their last settled home. This is where they were living before they became homeless, were living in temporary accommodation or sleeping rough." other_not_settled: "Please give the reason for the tenant leaving their last settled home. This is where they were living before they became homeless, were living in temporary accommodation or sleeping rough."
condition_effects: condition_effects:
no_choices: "You cannot answer this question as you told us nobody in the household has a physical or mental health condition (or other illness) expected to last 12 months or more." no_choices: "You cannot answer this question as you told us nobody in the household has a physical or mental health condition (or other illness) expected to last 12 months or more."

56
config/locales/validations/lettings/2023/bulk_upload.en.yml

@ -0,0 +1,56 @@
en:
validations:
lettings:
2023:
bulk_upload:
not_answered: "You must answer %{question}"
invalid_option: "Enter a valid value for %{question}"
invalid_number: "Enter a number for %{question}"
spreadsheet_dupe: "This is a duplicate of a log in your file."
duplicate: "This is a duplicate log."
blank_file: "Template is blank - The template must be filled in for us to create the logs and check if data is correct."
wrong_template:
wrong_template: "Incorrect start dates, please ensure you have used the correct template."
no_headers: "Your file does not contain the required header rows. Add or check the header rows and upload your file again. [Read more about using the template headers](%{guidance_link})."
wrong_field_numbers_count: "Incorrect number of fields, please ensure you have used the correct template."
over_max_column_count: "Too many columns, please ensure you have used the correct template."
owning_organisation:
not_found: "The owning organisation code is incorrect."
not_stock_owner: "The owning organisation code provided is for an organisation that does not own stock."
not_permitted: "You do not have permission to add logs for this owning organisation."
managing_organisation:
no_relationship: "This managing organisation does not have a relationship with the owning organisation."
not_found: "The managing organisation code is incorrect."
not_answered: "The managing organisation code is incorrect."
assigned_to:
not_found: "User with the specified email could not be found."
organisation_not_related: "User must be related to owning organisation or managing organisation."
startdate:
outside_collection_window: "Enter a date within the %{year_combo} collection year, which is between 1st April %{start_year} and 31st March %{end_year}."
year_not_two_or_four_digits: "Tenancy start year must be 2 or 4 digits."
housingneeds:
no_and_dont_know_disabled_needs_conjunction: "No disabled access needs and don’t know disabled access needs cannot be selected together."
dont_know_disabled_needs_conjunction: "Don’t know disabled access needs can’t be selected if you have selected fully wheelchair-accessible housing, wheelchair access to essential rooms, level access housing or other disabled access needs."
no_disabled_needs_conjunction: "No disabled access needs can’t be selected if you have selected fully wheelchair-accessible housing, wheelchair access to essential rooms, level access housing or other disabled access needs."
housingneeds_type:
only_one_option_permitted: "Only one disabled access need: fully wheelchair-accessible housing, wheelchair access to essential rooms or level access housing, can be selected."
condition_effects:
no_choices: "You cannot answer this question as you told us nobody in the household has a physical or mental health condition (or other illness) expected to last 12 months or more."
lettype:
needstype_general_needs: "This needs type is general needs, but the letting type is supported housing. Change either the needs type or the letting type."
needstype_supported_housing: "This needs type is supported housing, but the letting type is general needs. Change either the needs type or the letting type."
needstype:
lettype_not_general_needs: "This letting type is supported housing, but the needs type is general needs. Change either the needs type or the letting type."
lettype_not_supported_housing: "This letting type is general needs, but the needs type is supported housing. Change either the needs type or the letting type."
reason:
renewal_reason_needed: "The reason for leaving must be \"End of assured shorthold tenancy - no fault\" or \"End of fixed term tenancy - no fault\" if the letting is a renewal."
referral:
general_needs_prp_referred_by_la: "The source of the referral cannot be referred by local authority housing department for a general needs log."
nominated_by_local_ha_but_la: "The source of the referral cannot be Nominated by local housing authority as your organisation is a local authority."
scheme:
must_relate_to_org: "%{capitalised_location_or_scheme} code must relate to a %{location_or_scheme} that is owned by the owning organisation or managing organisation."
does_not_belong_to_org: "This %{scheme_or_management_group} code does not belong to the owning organisation or managing organisation."
declaration:
missing: "You must show the MHCLG privacy notice to the tenant before you can submit this log."
age:
invalid: "Age of person %{person_num} must be a number or the letter R"

56
config/locales/validations/lettings/2024/bulk_upload.en.yml

@ -0,0 +1,56 @@
en:
validations:
lettings:
2024:
bulk_upload:
not_answered: "You must answer %{question}"
invalid_option: "Enter a valid value for %{question}"
invalid_number: "Enter a number for %{question}"
spreadsheet_dupe: "This is a duplicate of a log in your file."
duplicate: "This is a duplicate log."
blank_file: "Template is blank - The template must be filled in for us to create the logs and check if data is correct."
wrong_template:
wrong_template: "Incorrect start dates, please ensure you have used the correct template."
no_headers: "Your file does not contain the required header rows. Add or check the header rows and upload your file again. [Read more about using the template headers](%{guidance_link})."
wrong_field_numbers_count: "Incorrect number of fields, please ensure you have used the correct template."
over_max_column_count: "Too many columns, please ensure you have used the correct template."
owning_organisation:
not_found: "The owning organisation code is incorrect."
not_stock_owner: "The owning organisation code provided is for an organisation that does not own stock."
not_permitted:
not_support: "You do not have permission to add logs for this owning organisation."
support: "This owning organisation is not affiliated with %{org_name}."
managing_organisation:
no_relationship: "This managing organisation does not have a relationship with the owning organisation."
not_found: "The managing organisation code is incorrect."
assigned_to:
not_found: "User with the specified email could not be found."
organisation_not_related: "User must be related to owning organisation or managing organisation."
startdate:
outside_collection_window: "Enter a date within the %{year_combo} collection year, which is between 1st April %{start_year} and 31st March %{end_year}."
year_not_two_or_four_digits: "Tenancy start year must be 2 or 4 digits."
housingneeds:
no_and_dont_know_disabled_needs_conjunction: "No disabled access needs and don’t know disabled access needs cannot be selected together."
dont_know_disabled_needs_conjunction: "Don’t know disabled access needs can’t be selected if you have selected fully wheelchair-accessible housing, wheelchair access to essential rooms, level access housing or other disabled access needs."
no_disabled_needs_conjunction: "No disabled access needs can’t be selected if you have selected fully wheelchair-accessible housing, wheelchair access to essential rooms, level access housing or other disabled access needs."
housingneeds_type:
only_one_option_permitted: "Only one disabled access need: fully wheelchair-accessible housing, wheelchair access to essential rooms or level access housing, can be selected."
condition_effects:
no_choices: "You cannot answer this question as you told us nobody in the household has a physical or mental health condition (or other illness) expected to last 12 months or more."
reason:
renewal_reason_needed: "The reason for leaving must be \"End of social or private sector tenancy - no fault\", \"End of social or private sector tenancy - evicted due to anti-social behaviour (ASB)\", \"End of social or private sector tenancy - evicted due to rent arrears\" or \"End of social or private sector tenancy - evicted for any other reason\"."
referral:
general_needs_prp_referred_by_la: "The source of the referral cannot be referred by local authority housing department for a general needs log."
nominated_by_local_ha_but_la: "The source of the referral cannot be Nominated by local housing authority as your organisation is a local authority."
scheme:
must_relate_to_org: "This scheme code does not belong to the owning organisation or managing organisation."
location:
must_relate_to_org: "Location code must relate to a location that is owned by the owning organisation or managing organisation."
age:
invalid: "Age of person %{person_num} must be a number or the letter R"
address:
not_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."
nationality:
invalid: "Select a valid nationality."
charges:
missing_charges: "Please enter the %{sentence_fragment}. If there is no %{sentence_fragment}, please enter '0'."

126
spec/services/bulk_upload/lettings/year2023/row_parser_spec.rb

@ -263,7 +263,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "adds an error to all (and only) the fields used to determine duplicates" do it "adds an error to all (and only) the fields used to determine duplicates" do
parser.valid? parser.valid?
error_message = "This is a duplicate log." error_message = I18n.t("validations.lettings.2023.bulk_upload.duplicate")
[ [
:field_1, # owning_organisation :field_1, # owning_organisation
@ -300,7 +300,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "adds an error to all the fields used to determine duplicates" do it "adds an error to all the fields used to determine duplicates" do
parser.valid? parser.valid?
error_message = "This is a duplicate log." error_message = I18n.t("validations.lettings.2023.bulk_upload.duplicate")
[ [
:field_1, # owning_organisation :field_1, # owning_organisation
@ -338,7 +338,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "adds an error to all the fields used to determine duplicates" do it "adds an error to all the fields used to determine duplicates" do
parser.valid? parser.valid?
error_message = "This is a duplicate log." error_message = I18n.t("validations.lettings.2023.bulk_upload.duplicate")
[ [
:field_1, # owning_organisation :field_1, # owning_organisation
@ -385,7 +385,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "adds an error to all the fields used to determine duplicates" do it "adds an error to all the fields used to determine duplicates" do
parser.valid? parser.valid?
error_message = "This is a duplicate log." error_message = I18n.t("validations.lettings.2023.bulk_upload.duplicate")
[ [
:field_1, # owning_organisation :field_1, # owning_organisation
@ -444,7 +444,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "does not add an error to all the fields used to determine duplicates" do it "does not add an error to all the fields used to determine duplicates" do
parser_too.valid? parser_too.valid?
error_message = "This is a duplicate log." error_message = I18n.t("validations.lettings.2023.bulk_upload.duplicate")
[ [
:field_1, # owning_organisation :field_1, # owning_organisation
@ -479,7 +479,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "adds an error to all the fields used to determine duplicates" do it "adds an error to all the fields used to determine duplicates" do
parser.valid? parser.valid?
error_message = "This is a duplicate log." error_message = I18n.t("validations.lettings.2023.bulk_upload.duplicate")
[ [
:field_1, # owning_organisation :field_1, # owning_organisation
@ -526,7 +526,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "adds an error to all the fields used to determine duplicates" do it "adds an error to all the fields used to determine duplicates" do
parser.valid? parser.valid?
error_message = "This is a duplicate log." error_message = I18n.t("validations.lettings.2023.bulk_upload.duplicate")
[ [
:field_1, # owning_organisation :field_1, # owning_organisation
@ -585,7 +585,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "does not add an error to all the fields used to determine duplicates" do it "does not add an error to all the fields used to determine duplicates" do
parser_too.valid? parser_too.valid?
error_message = "This is a duplicate log." error_message = I18n.t("validations.lettings.2023.bulk_upload.duplicate")
[ [
:field_1, # owning_organisation :field_1, # owning_organisation
@ -686,7 +686,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "cannot be nulled" do it "cannot be nulled" do
parser.valid? parser.valid?
expect(parser.errors[:field_45]).to eq(["You must show the MHCLG privacy notice to the tenant before you can submit this log."]) expect(parser.errors[:field_45]).to eq([I18n.t("validations.lettings.2023.bulk_upload.declaration.missing")])
end end
end end
end end
@ -697,8 +697,8 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "fetches the question's check_answer_label if it exists" do it "fetches the question's check_answer_label if it exists" do
parser.valid? parser.valid?
expect(parser.errors[:field_19]).to eql(["You must answer address line 1."]) expect(parser.errors[:field_19]).to eql([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "address line 1.")])
expect(parser.errors[:field_21]).to eql(["You must answer town or city."]) expect(parser.errors[:field_21]).to eql([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "town or city.")])
end end
end end
end end
@ -846,7 +846,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
expect(parser.errors[:field_5]).to be_present expect(parser.errors[:field_5]).to be_present
expect(parser.errors[:field_11]).to eq(["You must answer intermediate rent type."]) expect(parser.errors[:field_11]).to eq([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "intermediate rent type.")])
end end
end end
@ -857,7 +857,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
expect(parser.errors[:field_5]).to be_present expect(parser.errors[:field_5]).to be_present
expect(parser.errors[:field_11]).to eq(["You must answer intermediate rent type."]) expect(parser.errors[:field_11]).to eq([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "intermediate rent type.")])
end end
end end
@ -868,7 +868,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
expect(parser.errors[:field_5]).to be_present expect(parser.errors[:field_5]).to be_present
expect(parser.errors[:field_10]).to eq(["You must answer is this a London Affordable Rent letting."]) expect(parser.errors[:field_10]).to eq([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "is this a London Affordable Rent letting.")])
end end
end end
@ -879,7 +879,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
expect(parser.errors[:field_5]).to be_present expect(parser.errors[:field_5]).to be_present
expect(parser.errors[:field_10]).to eq(["You must answer is this a London Affordable Rent letting."]) expect(parser.errors[:field_10]).to eq([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "is this a London Affordable Rent letting.")])
end end
end end
@ -888,7 +888,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "adds error on field_12" do it "adds error on field_12" do
parser.valid? parser.valid?
expect(parser.errors[:field_12]).to eq(["You must answer product name."]) expect(parser.errors[:field_12]).to eq([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "product name.")])
end end
end end
@ -910,8 +910,8 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "is not permitted" do it "is not permitted" do
parser.valid? parser.valid?
expect(parser.errors[:field_4]).to include("This letting type is supported housing, but the needs type is general needs. Change either the needs type or the letting type.") expect(parser.errors[:field_4]).to include(I18n.t("validations.lettings.2023.bulk_upload.needstype.lettype_not_general_needs"))
expect(parser.errors[:field_5]).to include("This needs type is general needs, but the letting type is supported housing. Change either the needs type or the letting type.") expect(parser.errors[:field_5]).to include(I18n.t("validations.lettings.2023.bulk_upload.lettype.needstype_general_needs"))
end end
end end
end end
@ -925,8 +925,8 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "is not permitted" do it "is not permitted" do
parser.valid? parser.valid?
expect(parser.errors[:field_4]).to include("This letting type is general needs, but the needs type is supported housing. Change either the needs type or the letting type.") expect(parser.errors[:field_4]).to include(I18n.t("validations.lettings.2023.bulk_upload.needstype.lettype_not_supported_housing"))
expect(parser.errors[:field_5]).to include("This needs type is supported housing, but the letting type is general needs. Change either the needs type or the letting type.") expect(parser.errors[:field_5]).to include(I18n.t("validations.lettings.2023.bulk_upload.lettype.needstype_supported_housing"))
end end
end end
@ -951,7 +951,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
expect(parser.errors[:field_15]).to be_blank expect(parser.errors[:field_15]).to be_blank
expect(parser.errors[:field_16]).to eq(["You must answer scheme code."]) expect(parser.errors[:field_16]).to eq([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "scheme code.")])
expect(parser.errors[:field_17]).to be_blank expect(parser.errors[:field_17]).to be_blank
end end
end end
@ -979,7 +979,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
expect(parser.errors[:field_15]).to be_blank expect(parser.errors[:field_15]).to be_blank
expect(parser.errors.where(:field_16, category: :setup).map(&:message)).to eq(["This scheme code does not belong to the owning organisation or managing organisation."]) expect(parser.errors.where(:field_16, category: :setup).map(&:message)).to eq([I18n.t("validations.lettings.2023.bulk_upload.scheme.does_not_belong_to_org", scheme_or_management_group: "scheme")])
expect(parser.errors[:field_17]).to be_blank expect(parser.errors[:field_17]).to be_blank
end end
end end
@ -992,7 +992,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
expect(parser.errors[:field_15]).to be_blank expect(parser.errors[:field_15]).to be_blank
expect(parser.errors[:field_16]).to be_blank expect(parser.errors[:field_16]).to be_blank
expect(parser.errors.where(:field_17, category: :setup).map(&:message)).to eq(["You must answer location code."]) expect(parser.errors.where(:field_17, category: :setup).map(&:message)).to eq([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "location code.")])
expect(parser.errors[:field_17].count).to eq(1) expect(parser.errors[:field_17].count).to eq(1)
end end
end end
@ -1005,7 +1005,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
expect(parser.errors[:field_16]).to be_blank expect(parser.errors[:field_16]).to be_blank
expect(parser.errors[:field_17]).to be_blank expect(parser.errors[:field_17]).to be_blank
expect(parser.errors.where(:field_15, category: :setup).map(&:message)).to eq(["You must answer management group code."]) expect(parser.errors.where(:field_15, category: :setup).map(&:message)).to eq([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "management group code.")])
expect(parser.errors[:field_15].count).to eq(1) expect(parser.errors[:field_15].count).to eq(1)
end end
end end
@ -1018,7 +1018,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
expect(parser.errors[:field_15]).to be_blank expect(parser.errors[:field_15]).to be_blank
expect(parser.errors[:field_16]).to be_blank expect(parser.errors[:field_16]).to be_blank
expect(parser.errors.where(:field_17, category: :setup).map(&:message)).to eq(["Location code must relate to a location that is owned by the owning organisation or managing organisation."]) expect(parser.errors.where(:field_17, category: :setup).map(&:message)).to eq([I18n.t("validations.lettings.2023.bulk_upload.scheme.must_relate_to_org", capitalised_location_or_scheme: "Location", location_or_scheme: "location")])
end end
end end
@ -1054,7 +1054,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
expect(parser.errors[:field_15]).to be_blank expect(parser.errors[:field_15]).to be_blank
expect(parser.errors[:field_16]).to be_blank expect(parser.errors[:field_16]).to be_blank
expect(parser.errors.where(:field_17, category: :setup).map(&:message)).to eq(["Location code must relate to a location that is owned by the owning organisation or managing organisation."]) expect(parser.errors.where(:field_17, category: :setup).map(&:message)).to eq([I18n.t("validations.lettings.2023.bulk_upload.scheme.must_relate_to_org", capitalised_location_or_scheme: "Location", location_or_scheme: "location")])
end end
end end
@ -1067,7 +1067,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
expect(parser.errors[:field_15]).to be_blank expect(parser.errors[:field_15]).to be_blank
expect(parser.errors.where(:field_16, category: :setup).map(&:message)).to eq(["This scheme code does not belong to the owning organisation or managing organisation."]) expect(parser.errors.where(:field_16, category: :setup).map(&:message)).to eq([I18n.t("validations.lettings.2023.bulk_upload.scheme.does_not_belong_to_org", scheme_or_management_group: "scheme")])
expect(parser.errors[:field_17]).to be_blank expect(parser.errors[:field_17]).to be_blank
end end
end end
@ -1093,7 +1093,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
expect(parser.errors[:field_15]).to be_blank expect(parser.errors[:field_15]).to be_blank
expect(parser.errors[:field_16]).to include("You must answer scheme name.") expect(parser.errors[:field_16]).to include(I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "scheme name."))
expect(parser.errors[:field_17]).to be_blank expect(parser.errors[:field_17]).to be_blank
end end
end end
@ -1122,7 +1122,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "returns a setup error" do it "returns a setup error" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_15, category: :setup).map(&:message)).to eq(["This management group code does not belong to the owning organisation or managing organisation."]) expect(parser.errors.where(:field_15, category: :setup).map(&:message)).to eq([I18n.t("validations.lettings.2023.bulk_upload.scheme.does_not_belong_to_org", scheme_or_management_group: "management group")])
expect(parser.errors[:field_16]).to be_blank expect(parser.errors[:field_16]).to be_blank
expect(parser.errors[:field_17]).to be_blank expect(parser.errors[:field_17]).to be_blank
end end
@ -1135,7 +1135,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
expect(parser.errors[:field_15]).to be_blank expect(parser.errors[:field_15]).to be_blank
expect(parser.errors.where(:field_16, category: :setup).map(&:message)).to eq(["You must answer scheme code."]) expect(parser.errors.where(:field_16, category: :setup).map(&:message)).to eq([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "scheme code.")])
expect(parser.errors[:field_17]).to be_blank expect(parser.errors[:field_17]).to be_blank
end end
end end
@ -1147,7 +1147,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
expect(parser.errors[:field_15]).to be_blank expect(parser.errors[:field_15]).to be_blank
expect(parser.errors.where(:field_16, category: :setup).map(&:message)).to eq(["Scheme code must relate to a scheme that is owned by the owning organisation or managing organisation."]) expect(parser.errors.where(:field_16, category: :setup).map(&:message)).to eq([I18n.t("validations.lettings.2023.bulk_upload.scheme.must_relate_to_org", capitalised_location_or_scheme: "Scheme", location_or_scheme: "scheme")])
expect(parser.errors[:field_17]).to be_blank expect(parser.errors[:field_17]).to be_blank
end end
end end
@ -1173,7 +1173,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
expect(parser.errors[:field_15]).to be_blank expect(parser.errors[:field_15]).to be_blank
expect(parser.errors.where(:field_16, category: :setup).map(&:message)).to eq(["Scheme code must relate to a scheme that is owned by the owning organisation or managing organisation."]) expect(parser.errors.where(:field_16, category: :setup).map(&:message)).to eq([I18n.t("validations.lettings.2023.bulk_upload.scheme.must_relate_to_org", capitalised_location_or_scheme: "Scheme", location_or_scheme: "scheme")])
expect(parser.errors[:field_17]).to be_blank expect(parser.errors[:field_17]).to be_blank
end end
end end
@ -1186,7 +1186,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "returns a setup error" do it "returns a setup error" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_15, category: :setup).map(&:message)).to eq(["This management group code does not belong to the owning organisation or managing organisation."]) expect(parser.errors.where(:field_15, category: :setup).map(&:message)).to eq([I18n.t("validations.lettings.2023.bulk_upload.scheme.does_not_belong_to_org", scheme_or_management_group: "management group")])
expect(parser.errors[:field_16]).to be_blank expect(parser.errors[:field_16]).to be_blank
expect(parser.errors[:field_17]).to be_blank expect(parser.errors[:field_17]).to be_blank
end end
@ -1212,7 +1212,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "clears the scheme answer" do it "clears the scheme answer" do
parser.valid? parser.valid?
expect(parser.errors[:field_15]).to include("You must answer scheme name.") expect(parser.errors[:field_15]).to include(I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "scheme name."))
expect(parser.errors[:field_16]).to be_blank expect(parser.errors[:field_16]).to be_blank
expect(parser.errors[:field_17]).to be_blank expect(parser.errors[:field_17]).to be_blank
end end
@ -1255,7 +1255,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "returns an error" do it "returns an error" do
parser.valid? parser.valid?
expect(parser.errors[:field_102]).to include("Enter a valid value for what is the tenant’s main reason for the household leaving their last settled home?") expect(parser.errors[:field_102]).to include(I18n.t("validations.lettings.2023.bulk_upload.invalid_option", question: "what is the tenant’s main reason for the household leaving their last settled home?"))
end end
end end
end end
@ -1490,7 +1490,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "returns an error" do it "returns an error" do
parser.valid? parser.valid?
expect(parser.errors[:field_9]).to include("Tenancy start year must be 2 or 4 digits.") expect(parser.errors[:field_9]).to include(I18n.t("validations.lettings.2023.bulk_upload.startdate.year_not_two_or_four_digits"))
end end
end end
@ -1537,7 +1537,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "is not permitted as setup error" do it "is not permitted as setup error" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_1, category: :setup).map(&:message)).to eql(["You must answer owning organisation."]) expect(parser.errors.where(:field_1, category: :setup).map(&:message)).to eql([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "owning organisation.")])
end end
it "blocks log creation" do it "blocks log creation" do
@ -1553,7 +1553,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
setup_errors = parser.errors.select { |e| e.options[:category] == :setup } setup_errors = parser.errors.select { |e| e.options[:category] == :setup }
expect(setup_errors.find { |e| e.attribute == :field_1 }.message).to eql("The owning organisation code is incorrect.") expect(setup_errors.find { |e| e.attribute == :field_1 }.message).to eql(I18n.t("validations.lettings.2023.bulk_upload.owning_organisation.not_found"))
end end
it "blocks log creation" do it "blocks log creation" do
@ -1571,7 +1571,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
setup_errors = parser.errors.select { |e| e.options[:category] == :setup } setup_errors = parser.errors.select { |e| e.options[:category] == :setup }
expect(setup_errors.find { |e| e.attribute == :field_1 }.message).to eql("The owning organisation code provided is for an organisation that does not own stock.") expect(setup_errors.find { |e| e.attribute == :field_1 }.message).to eql(I18n.t("validations.lettings.2023.bulk_upload.owning_organisation.not_stock_owner"))
end end
it "blocks log creation" do it "blocks log creation" do
@ -1589,7 +1589,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
setup_errors = parser.errors.select { |e| e.options[:category] == :setup } setup_errors = parser.errors.select { |e| e.options[:category] == :setup }
expect(setup_errors.find { |e| e.attribute == :field_1 }.message).to eql("You do not have permission to add logs for this owning organisation.") expect(setup_errors.find { |e| e.attribute == :field_1 }.message).to eql(I18n.t("validations.lettings.2023.bulk_upload.owning_organisation.not_permitted"))
end end
it "blocks log creation" do it "blocks log creation" do
@ -1652,7 +1652,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
setup_errors = parser.errors.select { |e| e.options[:category] == :setup } setup_errors = parser.errors.select { |e| e.options[:category] == :setup }
expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql("The managing organisation code is incorrect.") expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql(I18n.t("validations.lettings.2023.bulk_upload.managing_organisation.not_answered"))
end end
it "blocks log creation" do it "blocks log creation" do
@ -1668,7 +1668,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
setup_errors = parser.errors.select { |e| e.options[:category] == :setup } setup_errors = parser.errors.select { |e| e.options[:category] == :setup }
expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql("The managing organisation code is incorrect.") expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql(I18n.t("validations.lettings.2023.bulk_upload.managing_organisation.not_found"))
end end
it "blocks log creation" do it "blocks log creation" do
@ -1686,7 +1686,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
parser.valid? parser.valid?
setup_errors = parser.errors.select { |e| e.options[:category] == :setup } setup_errors = parser.errors.select { |e| e.options[:category] == :setup }
expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql("This managing organisation does not have a relationship with the owning organisation.") expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql(I18n.t("validations.lettings.2023.bulk_upload.managing_organisation.no_relationship"))
end end
it "blocks log creation" do it "blocks log creation" do
@ -1702,7 +1702,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "is reported as a setup error" do it "is reported as a setup error" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_4, category: :setup).map(&:message)).to eql(["You must answer needs type."]) expect(parser.errors.where(:field_4, category: :setup).map(&:message)).to eql([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "needs type.")])
end end
end end
end end
@ -1713,7 +1713,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "has setup errors on the field" do it "has setup errors on the field" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_6, category: :setup).map(&:message)).to eql(["You must answer property renewal."]) expect(parser.errors.where(:field_6, category: :setup).map(&:message)).to eql([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "property renewal.")])
end end
end end
@ -1722,7 +1722,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "adds a setup error" do it "adds a setup error" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_6, category: :setup).map(&:message)).to include("Enter a valid value for is this letting a renewal?") expect(parser.errors.where(:field_6, category: :setup).map(&:message)).to include(I18n.t("validations.lettings.2023.bulk_upload.invalid_option", question: "is this letting a renewal?"))
end end
end end
end end
@ -1743,9 +1743,9 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "adds appropriate errors" do it "adds appropriate errors" do
parser.valid? parser.valid?
expect(parser.errors[:field_18]).to eql(["You must answer UPRN."]) expect(parser.errors[:field_18]).to eql([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "UPRN.")])
expect(parser.errors[:field_19]).to eql(["You must answer address line 1."]) expect(parser.errors[:field_19]).to eql([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "address line 1.")])
expect(parser.errors[:field_21]).to eql(["You must answer town or city."]) expect(parser.errors[:field_21]).to eql([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "town or city.")])
end end
end end
@ -1821,7 +1821,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "populates with correct error message" do it "populates with correct error message" do
parser.valid? parser.valid?
expect(parser.errors[:field_30]).to eql(["You must answer type of building."]) expect(parser.errors[:field_30]).to eql([I18n.t("validations.lettings.2023.bulk_upload.not_answered", question: "type of building.")])
end end
end end
end end
@ -2170,7 +2170,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "adds an error" do it "adds an error" do
parser.valid? parser.valid?
expect(parser.errors[:field_116]).to include("Enter a valid value for was the letting made under the Choice-Based Lettings (CBL)?") expect(parser.errors[:field_116]).to include(I18n.t("validations.lettings.2023.bulk_upload.invalid_option", question: "was the letting made under the Choice-Based Lettings (CBL)?"))
end end
end end
end end
@ -2197,7 +2197,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "adds an error" do it "adds an error" do
parser.valid? parser.valid?
expect(parser.errors[:field_118]).to include("Enter a valid value for was the letting made under the Common Housing Register (CHR)?") expect(parser.errors[:field_118]).to include(I18n.t("validations.lettings.2023.bulk_upload.invalid_option", question: "was the letting made under the Common Housing Register (CHR)?"))
end end
end end
end end
@ -2224,7 +2224,7 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "adds an error" do it "adds an error" do
parser.valid? parser.valid?
expect(parser.errors[:field_117]).to include("Enter a valid value for was the letting made under the Common Allocation Policy (CAP)?") expect(parser.errors[:field_117]).to include(I18n.t("validations.lettings.2023.bulk_upload.invalid_option", question: "was the letting made under the Common Allocation Policy (CAP)?"))
end end
end end
end end
@ -2736,8 +2736,8 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "sets error on housingneeds a and b" do it "sets error on housingneeds a and b" do
parser.valid? parser.valid?
expect(parser.errors[:field_83]).to include("Only one disabled access need: fully wheelchair-accessible housing, wheelchair access to essential rooms or level access housing, can be selected.") expect(parser.errors[:field_83]).to include(I18n.t("validations.lettings.2023.bulk_upload.housingneeds_type.only_one_option_permitted"))
expect(parser.errors[:field_84]).to include("Only one disabled access need: fully wheelchair-accessible housing, wheelchair access to essential rooms or level access housing, can be selected.") expect(parser.errors[:field_84]).to include(I18n.t("validations.lettings.2023.bulk_upload.housingneeds_type.only_one_option_permitted"))
expect(parser.errors[:field_85]).to be_blank expect(parser.errors[:field_85]).to be_blank
end end
end end
@ -2747,8 +2747,8 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "sets error on housingneeds a and c" do it "sets error on housingneeds a and c" do
parser.valid? parser.valid?
expect(parser.errors[:field_83]).to include("Only one disabled access need: fully wheelchair-accessible housing, wheelchair access to essential rooms or level access housing, can be selected.") expect(parser.errors[:field_83]).to include(I18n.t("validations.lettings.2023.bulk_upload.housingneeds_type.only_one_option_permitted"))
expect(parser.errors[:field_85]).to include("Only one disabled access need: fully wheelchair-accessible housing, wheelchair access to essential rooms or level access housing, can be selected.") expect(parser.errors[:field_85]).to include(I18n.t("validations.lettings.2023.bulk_upload.housingneeds_type.only_one_option_permitted"))
expect(parser.errors[:field_84]).to be_blank expect(parser.errors[:field_84]).to be_blank
end end
end end
@ -2758,8 +2758,8 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "sets error on housingneeds b and c" do it "sets error on housingneeds b and c" do
parser.valid? parser.valid?
expect(parser.errors[:field_84]).to include("Only one disabled access need: fully wheelchair-accessible housing, wheelchair access to essential rooms or level access housing, can be selected.") expect(parser.errors[:field_84]).to include(I18n.t("validations.lettings.2023.bulk_upload.housingneeds_type.only_one_option_permitted"))
expect(parser.errors[:field_85]).to include("Only one disabled access need: fully wheelchair-accessible housing, wheelchair access to essential rooms or level access housing, can be selected.") expect(parser.errors[:field_85]).to include(I18n.t("validations.lettings.2023.bulk_upload.housingneeds_type.only_one_option_permitted"))
expect(parser.errors[:field_83]).to be_blank expect(parser.errors[:field_83]).to be_blank
end end
end end
@ -2769,8 +2769,8 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "sets error on housingneeds a and g" do it "sets error on housingneeds a and g" do
parser.valid? parser.valid?
expect(parser.errors[:field_87]).to include("No disabled access needs can’t be selected if you have selected fully wheelchair-accessible housing, wheelchair access to essential rooms, level access housing or other disabled access needs.") expect(parser.errors[:field_87]).to include(I18n.t("validations.lettings.2023.bulk_upload.housingneeds.no_disabled_needs_conjunction"))
expect(parser.errors[:field_83]).to include("No disabled access needs can’t be selected if you have selected fully wheelchair-accessible housing, wheelchair access to essential rooms, level access housing or other disabled access needs.") expect(parser.errors[:field_83]).to include(I18n.t("validations.lettings.2023.bulk_upload.housingneeds.no_disabled_needs_conjunction"))
expect(parser.errors[:field_84]).to be_blank expect(parser.errors[:field_84]).to be_blank
expect(parser.errors[:field_85]).to be_blank expect(parser.errors[:field_85]).to be_blank
end end
@ -2793,8 +2793,8 @@ RSpec.describe BulkUpload::Lettings::Year2023::RowParser do
it "sets error on housingneeds a and h" do it "sets error on housingneeds a and h" do
parser.valid? parser.valid?
expect(parser.errors[:field_88]).to include("Don’t know disabled access needs can’t be selected if you have selected fully wheelchair-accessible housing, wheelchair access to essential rooms, level access housing or other disabled access needs.") expect(parser.errors[:field_88]).to include(I18n.t("validations.lettings.2023.bulk_upload.housingneeds.dont_know_disabled_needs_conjunction"))
expect(parser.errors[:field_83]).to include("Don’t know disabled access needs can’t be selected if you have selected fully wheelchair-accessible housing, wheelchair access to essential rooms, level access housing or other disabled access needs.") expect(parser.errors[:field_83]).to include(I18n.t("validations.lettings.2023.bulk_upload.housingneeds.dont_know_disabled_needs_conjunction"))
expect(parser.errors[:field_84]).to be_blank expect(parser.errors[:field_84]).to be_blank
expect(parser.errors[:field_85]).to be_blank expect(parser.errors[:field_85]).to be_blank
end end

142
spec/services/bulk_upload/lettings/year2024/row_parser_spec.rb

@ -283,7 +283,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds an error to all (and only) the fields used to determine duplicates" do it "adds an error to all (and only) the fields used to determine duplicates" do
parser.valid? parser.valid?
error_message = "This is a duplicate log." error_message = I18n.t("validations.lettings.2024.bulk_upload.duplicate")
[ [
:field_1, # owning_organisation :field_1, # owning_organisation
@ -339,7 +339,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds an error to all the fields used to determine duplicates" do it "adds an error to all the fields used to determine duplicates" do
parser.valid? parser.valid?
error_message = "This is a duplicate log." error_message = I18n.t("validations.lettings.2024.bulk_upload.duplicate")
[ [
:field_1, # owning_organisation :field_1, # owning_organisation
@ -381,7 +381,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds an error to all the fields used to determine duplicates" do it "adds an error to all the fields used to determine duplicates" do
parser.valid? parser.valid?
error_message = "This is a duplicate log." error_message = I18n.t("validations.lettings.2024.bulk_upload.duplicate")
[ [
:field_1, # owning_organisation :field_1, # owning_organisation
@ -432,7 +432,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds an error to all the fields used to determine duplicates" do it "adds an error to all the fields used to determine duplicates" do
parser.valid? parser.valid?
error_message = "This is a duplicate log." error_message = I18n.t("validations.lettings.2024.bulk_upload.duplicate")
[ [
:field_1, # owning_organisation :field_1, # owning_organisation
@ -492,7 +492,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "does not add an error to all the fields used to determine duplicates" do it "does not add an error to all the fields used to determine duplicates" do
parser_too.valid? parser_too.valid?
error_message = "This is a duplicate log." error_message = I18n.t("validations.lettings.2024.bulk_upload.duplicate")
[ [
:field_1, # owning_organisation :field_1, # owning_organisation
@ -527,7 +527,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds an error to all the fields used to determine duplicates" do it "adds an error to all the fields used to determine duplicates" do
parser.valid? parser.valid?
error_message = "This is a duplicate log." error_message = I18n.t("validations.lettings.2024.bulk_upload.duplicate")
[ [
:field_1, # owning_organisation :field_1, # owning_organisation
@ -574,7 +574,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds an error to all the fields used to determine duplicates" do it "adds an error to all the fields used to determine duplicates" do
parser.valid? parser.valid?
error_message = "This is a duplicate log." error_message = I18n.t("validations.lettings.2024.bulk_upload.duplicate")
[ [
:field_1, # owning_organisation :field_1, # owning_organisation
@ -634,7 +634,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "does not add an error to all the fields used to determine duplicates" do it "does not add an error to all the fields used to determine duplicates" do
parser_too.valid? parser_too.valid?
error_message = "This is a duplicate log." error_message = I18n.t("validations.lettings.2024.bulk_upload.duplicate")
[ [
:field_1, # owning_organisation :field_1, # owning_organisation
@ -770,7 +770,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "fetches the question's check_answer_label if it exists" do it "fetches the question's check_answer_label if it exists" do
parser.valid? parser.valid?
expect(parser.errors[:field_43]).to eql(["You must answer lead tenant’s gender identity."]) expect(parser.errors[:field_43]).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "lead tenant’s gender identity.")])
end end
end end
@ -779,7 +779,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "only has one error added to the field" do it "only has one error added to the field" do
parser.valid? parser.valid?
expect(parser.errors[:field_112]).to eql(["You must answer was the letting made under the Choice-Based Lettings (CBL)?"]) expect(parser.errors[:field_112]).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "was the letting made under the Choice-Based Lettings (CBL)?")])
end end
end end
@ -789,7 +789,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "does not add an additional error" do it "does not add an additional error" do
parser.valid? parser.valid?
expect(parser.errors[:field_116].length).to eq(1) expect(parser.errors[:field_116].length).to eq(1)
expect(parser.errors[:field_116]).to include(match "Enter a valid value for") expect(parser.errors[:field_116]).to include(match I18n.t("validations.lettings.2024.bulk_upload.invalid_option", question: ""))
end end
end end
end end
@ -833,7 +833,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "is not permitted" do it "is not permitted" do
parser.valid? parser.valid?
expect(parser.errors[:field_3]).to be_present expect(parser.errors[:field_3]).to be_present
expect(parser.errors[:field_3]).to include("You must answer what is the CORE username of the account this letting log should be assigned to?") expect(parser.errors[:field_3]).to include(I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "what is the CORE username of the account this letting log should be assigned to?"))
end end
it "blocks log creation" do it "blocks log creation" do
@ -915,8 +915,8 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "cannot be nulled" do it "cannot be nulled" do
parser.valid? parser.valid?
expect(parser.errors[:field_5]).to eq(["You must answer scheme code."]) expect(parser.errors[:field_5]).to eq([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "scheme code.")])
expect(parser.errors[:field_6]).to eq(["You must answer location code."]) expect(parser.errors[:field_6]).to eq([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "location code.")])
end end
end end
@ -942,7 +942,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
let(:attributes) { { bulk_upload:, field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id, field_4: "2", field_11: "2", field_5: "S123", field_6: location.id } } let(:attributes) { { bulk_upload:, field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id, field_4: "2", field_11: "2", field_5: "S123", field_6: location.id } }
it "returns a setup error" do it "returns a setup error" do
expect(parser.errors.where(:field_5, category: :setup).map(&:message)).to eq(["This scheme code does not belong to the owning organisation or managing organisation."]) expect(parser.errors.where(:field_5, category: :setup).map(&:message)).to eq([I18n.t("validations.lettings.2024.bulk_upload.scheme.must_relate_to_org")])
expect(parser.errors[:field_6]).to be_blank expect(parser.errors[:field_6]).to be_blank
end end
end end
@ -952,7 +952,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "returns a setup error" do it "returns a setup error" do
expect(parser.errors[:field_5]).to be_blank expect(parser.errors[:field_5]).to be_blank
expect(parser.errors.where(:field_6, category: :setup).map(&:message)).to eq(["You must answer location code."]) expect(parser.errors.where(:field_6, category: :setup).map(&:message)).to eq([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "location code.")])
expect(parser.errors[:field_6].count).to eq(1) expect(parser.errors[:field_6].count).to eq(1)
end end
end end
@ -962,7 +962,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "returns a setup error" do it "returns a setup error" do
expect(parser.errors[:field_5]).to be_blank expect(parser.errors[:field_5]).to be_blank
expect(parser.errors.where(:field_6, category: :setup).map(&:message)).to eq(["Location code must relate to a location that is owned by the owning organisation or managing organisation."]) expect(parser.errors.where(:field_6, category: :setup).map(&:message)).to eq([I18n.t("validations.lettings.2024.bulk_upload.location.must_relate_to_org")])
end end
end end
@ -991,7 +991,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "returns a setup error" do it "returns a setup error" do
expect(parser.errors[:field_5]).to be_blank expect(parser.errors[:field_5]).to be_blank
expect(parser.errors.where(:field_6, category: :setup).map(&:message)).to eq(["Location code must relate to a location that is owned by the owning organisation or managing organisation."]) expect(parser.errors.where(:field_6, category: :setup).map(&:message)).to eq([I18n.t("validations.lettings.2024.bulk_upload.location.must_relate_to_org")])
end end
end end
@ -1001,7 +1001,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
let(:attributes) { { bulk_upload:, field_4: "2", field_11: "2", field_5: "S#{other_scheme.id}", field_6: other_location.id, field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id } } let(:attributes) { { bulk_upload:, field_4: "2", field_11: "2", field_5: "S#{other_scheme.id}", field_6: other_location.id, field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id } }
it "returns a setup error" do it "returns a setup error" do
expect(parser.errors.where(:field_5, category: :setup).map(&:message)).to eq(["This scheme code does not belong to the owning organisation or managing organisation."]) expect(parser.errors.where(:field_5, category: :setup).map(&:message)).to eq([I18n.t("validations.lettings.2024.bulk_upload.scheme.must_relate_to_org")])
expect(parser.errors[:field_6]).to be_blank expect(parser.errors[:field_6]).to be_blank
end end
end end
@ -1081,7 +1081,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "is not permitted" do it "is not permitted" do
parser.valid? parser.valid?
expect(parser.errors[:field_98]).to include('The reason for leaving must be "End of social or private sector tenancy - no fault", "End of social or private sector tenancy - evicted due to anti-social behaviour (ASB)", "End of social or private sector tenancy - evicted due to rent arrears" or "End of social or private sector tenancy - evicted for any other reason".') expect(parser.errors[:field_98]).to include(I18n.t("validations.lettings.2024.bulk_upload.reason.renewal_reason_needed"))
end end
end end
end end
@ -1091,7 +1091,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "returns an error" do it "returns an error" do
parser.valid? parser.valid?
expect(parser.errors[:field_98]).to include("Enter a valid value for what is the tenant’s main reason for the household leaving their last settled home?") expect(parser.errors[:field_98]).to include(I18n.t("validations.lettings.2024.bulk_upload.invalid_option", question: "what is the tenant’s main reason for the household leaving their last settled home?"))
end end
end end
end end
@ -1317,7 +1317,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "returns an error" do it "returns an error" do
parser.valid? parser.valid?
expect(parser.errors[:field_10]).to include("Tenancy start year must be 2 or 4 digits.") expect(parser.errors[:field_10]).to include(I18n.t("validations.lettings.2024.bulk_upload.startdate.year_not_two_or_four_digits"))
end end
end end
@ -1368,7 +1368,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "is not permitted as setup error" do it "is not permitted as setup error" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_1, category: :setup).map(&:message)).to eql(["You must answer owning organisation."]) expect(parser.errors.where(:field_1, category: :setup).map(&:message)).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "owning organisation.")])
end end
it "blocks log creation" do it "blocks log creation" do
@ -1385,7 +1385,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
setup_errors = parser.errors.select { |e| e.options[:category] == :setup } setup_errors = parser.errors.select { |e| e.options[:category] == :setup }
expect(setup_errors.find { |e| e.attribute == :field_1 }.message).to eql("The owning organisation code is incorrect.") expect(setup_errors.find { |e| e.attribute == :field_1 }.message).to eql(I18n.t("validations.lettings.2024.bulk_upload.owning_organisation.not_found"))
end end
it "blocks log creation" do it "blocks log creation" do
@ -1404,7 +1404,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
setup_errors = parser.errors.select { |e| e.options[:category] == :setup } setup_errors = parser.errors.select { |e| e.options[:category] == :setup }
expect(setup_errors.find { |e| e.attribute == :field_1 }.message).to eql("The owning organisation code provided is for an organisation that does not own stock.") expect(setup_errors.find { |e| e.attribute == :field_1 }.message).to eql(I18n.t("validations.lettings.2024.bulk_upload.owning_organisation.not_stock_owner"))
end end
it "blocks log creation" do it "blocks log creation" do
@ -1423,7 +1423,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
setup_errors = parser.errors.select { |e| e.options[:category] == :setup } setup_errors = parser.errors.select { |e| e.options[:category] == :setup }
expect(setup_errors.find { |e| e.attribute == :field_1 }.message).to eql("You do not have permission to add logs for this owning organisation.") expect(setup_errors.find { |e| e.attribute == :field_1 }.message).to eql(I18n.t("validations.lettings.2024.bulk_upload.owning_organisation.not_permitted.not_support"))
end end
it "blocks log creation" do it "blocks log creation" do
@ -1492,7 +1492,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
parser = described_class.new(attributes) parser = described_class.new(attributes)
parser.valid? parser.valid?
expect(parser).to be_block_log_creation expect(parser).to be_block_log_creation
expect(parser.errors[:field_1]).to include("You do not have permission to add logs for this owning organisation.") expect(parser.errors[:field_1]).to include(I18n.t("validations.lettings.2024.bulk_upload.owning_organisation.not_permitted.not_support"))
end end
end end
@ -1510,7 +1510,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "does not block log creation and does not add an error to field_1" do it "does not block log creation and does not add an error to field_1" do
parser = described_class.new(attributes) parser = described_class.new(attributes)
parser.valid? parser.valid?
expect(parser.errors[:field_1]).not_to include("You do not have permission to add logs for this owning organisation.") expect(parser.errors[:field_1]).not_to include(I18n.t("validations.lettings.2024.bulk_upload.owning_organisation.not_permitted"))
end end
end end
end end
@ -1524,7 +1524,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
setup_errors = parser.errors.select { |e| e.options[:category] == :setup } setup_errors = parser.errors.select { |e| e.options[:category] == :setup }
expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql("You must answer managing organisation.") expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql(I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "managing organisation."))
end end
it "blocks log creation" do it "blocks log creation" do
@ -1541,7 +1541,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
setup_errors = parser.errors.select { |e| e.options[:category] == :setup } setup_errors = parser.errors.select { |e| e.options[:category] == :setup }
expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql("The managing organisation code is incorrect.") expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql(I18n.t("validations.lettings.2024.bulk_upload.managing_organisation.not_found"))
end end
it "blocks log creation" do it "blocks log creation" do
@ -1560,7 +1560,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
setup_errors = parser.errors.select { |e| e.options[:category] == :setup } setup_errors = parser.errors.select { |e| e.options[:category] == :setup }
expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql("This managing organisation does not have a relationship with the owning organisation.") expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql(I18n.t("validations.lettings.2024.bulk_upload.managing_organisation.no_relationship"))
end end
it "blocks log creation" do it "blocks log creation" do
@ -1576,7 +1576,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "is reported as a setup error" do it "is reported as a setup error" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_4, category: :setup).map(&:message)).to eql(["You must answer needs type."]) expect(parser.errors.where(:field_4, category: :setup).map(&:message)).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "needs type.")])
end end
end end
end end
@ -1587,7 +1587,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "has setup errors on the field" do it "has setup errors on the field" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_7, category: :setup).map(&:message)).to eql(["You must answer property renewal."]) expect(parser.errors.where(:field_7, category: :setup).map(&:message)).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "property renewal.")])
end end
end end
@ -1596,7 +1596,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds a setup error" do it "adds a setup error" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_7, category: :setup).map(&:message)).to include("Enter a valid value for is this letting a renewal?") expect(parser.errors.where(:field_7, category: :setup).map(&:message)).to include(I18n.t("validations.lettings.2024.bulk_upload.invalid_option", question: "is this letting a renewal?"))
end end
end end
end end
@ -1627,10 +1627,10 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds errors to missing key address fields" do it "adds errors to missing key address fields" do
parser.valid? parser.valid?
expect(parser.errors[:field_17]).to eql(["You must answer address line 1."]) expect(parser.errors[:field_17]).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "address line 1.")])
expect(parser.errors[:field_19]).to eql(["You must answer town or city."]) expect(parser.errors[:field_19]).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "town or city.")])
expect(parser.errors[:field_21]).to eql(["You must answer part 1 of postcode."]) expect(parser.errors[:field_21]).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "part 1 of postcode.")])
expect(parser.errors[:field_22]).to eql(["You must answer part 2 of postcode."]) expect(parser.errors[:field_22]).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "part 2 of postcode.")])
end end
end end
@ -1658,11 +1658,11 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds appropriate errors to UPRN and key address fields" do it "adds appropriate errors to UPRN and key address fields" do
parser.valid? parser.valid?
expect(parser.errors[:field_16]).to eql(["You must answer UPRN."]) expect(parser.errors[:field_16]).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "UPRN.")])
expect(parser.errors[:field_17]).to eql(["You must answer address line 1."]) expect(parser.errors[:field_17]).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "address line 1.")])
expect(parser.errors[:field_19]).to eql(["You must answer town or city."]) expect(parser.errors[:field_19]).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "town or city.")])
expect(parser.errors[:field_21]).to eql(["You must answer part 1 of postcode."]) expect(parser.errors[:field_21]).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "part 1 of postcode.")])
expect(parser.errors[:field_22]).to eql(["You must answer part 2 of postcode."]) expect(parser.errors[:field_22]).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "part 2 of postcode.")])
end end
end end
@ -1671,8 +1671,8 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds errors to UPRN and the missing key address field" do it "adds errors to UPRN and the missing key address field" do
parser.valid? parser.valid?
expect(parser.errors[:field_16]).to eql(["You must answer UPRN."]) expect(parser.errors[:field_16]).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "UPRN.")])
expect(parser.errors[:field_17]).to eql(["You must answer address line 1."]) expect(parser.errors[:field_17]).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "address line 1.")])
expect(parser.errors[:field_19]).to be_empty expect(parser.errors[:field_19]).to be_empty
expect(parser.errors[:field_21]).to be_empty expect(parser.errors[:field_21]).to be_empty
expect(parser.errors[:field_22]).to be_empty expect(parser.errors[:field_22]).to be_empty
@ -1706,7 +1706,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
parser.valid? parser.valid?
expect(parser.errors[:field_16]).to be_empty expect(parser.errors[:field_16]).to be_empty
%i[field_17 field_18 field_19 field_20 field_21 field_22].each do |field| %i[field_17 field_18 field_19 field_20 field_21 field_22].each do |field|
expect(parser.errors[field]).to eql(["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."]) expect(parser.errors[field]).to eql([I18n.t("validations.lettings.2024.bulk_upload.address.not_found")])
end end
end end
end end
@ -1721,7 +1721,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
parser.valid? parser.valid?
expect(parser.errors[:field_16]).to be_empty expect(parser.errors[:field_16]).to be_empty
%i[field_17 field_18 field_19 field_20 field_21 field_22].each do |field| %i[field_17 field_18 field_19 field_20 field_21 field_22].each do |field|
expect(parser.errors[field]).to eql(["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."]) expect(parser.errors[field]).to eql([I18n.t("validations.lettings.2024.bulk_upload.address.not_found")])
end end
end end
end end
@ -1765,7 +1765,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "populates with correct error message" do it "populates with correct error message" do
parser.valid? parser.valid?
expect(parser.errors[:field_27]).to eql(["You must answer type of building."]) expect(parser.errors[:field_27]).to eql([I18n.t("validations.lettings.2024.bulk_upload.not_answered", question: "type of building.")])
end end
end end
end end
@ -1864,7 +1864,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds an error to field_45" do it "adds an error to field_45" do
parser.valid? parser.valid?
expect(parser.errors["field_45"]).to include("Select a valid nationality.") expect(parser.errors["field_45"]).to include(I18n.t("validations.lettings.2024.bulk_upload.nationality.invalid"))
end end
end end
end end
@ -2185,7 +2185,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds an error" do it "adds an error" do
parser.valid? parser.valid?
expect(parser.errors[:field_112]).to include("Enter a valid value for was the letting made under the Choice-Based Lettings (CBL)?") expect(parser.errors[:field_112]).to include(I18n.t("validations.lettings.2024.bulk_upload.invalid_option", question: "was the letting made under the Choice-Based Lettings (CBL)?"))
end end
end end
end end
@ -2212,7 +2212,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds an error" do it "adds an error" do
parser.valid? parser.valid?
expect(parser.errors[:field_114]).to include("Enter a valid value for was the letting made under the Common Housing Register (CHR)?") expect(parser.errors[:field_114]).to include(I18n.t("validations.lettings.2024.bulk_upload.invalid_option", question: "was the letting made under the Common Housing Register (CHR)?"))
end end
end end
end end
@ -2239,7 +2239,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds an error" do it "adds an error" do
parser.valid? parser.valid?
expect(parser.errors[:field_113]).to include("Enter a valid value for was the letting made under the Common Allocation Policy (CAP)?") expect(parser.errors[:field_113]).to include(I18n.t("validations.lettings.2024.bulk_upload.invalid_option", question: "was the letting made under the Common Allocation Policy (CAP)?"))
end end
end end
end end
@ -2266,7 +2266,7 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds an error" do it "adds an error" do
parser.valid? parser.valid?
expect(parser.errors[:field_115]).to include("Enter a valid value for was the letting made under the Accessible Register?") expect(parser.errors[:field_115]).to include(I18n.t("validations.lettings.2024.bulk_upload.invalid_option", question: "was the letting made under the Accessible Register?"))
end end
end end
end end
@ -2603,10 +2603,10 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds an error to all missing charges" do it "adds an error to all missing charges" do
parser.valid? parser.valid?
expect(parser.errors[:field_125]).to eql(["Please enter the basic rent. If there is no basic rent, please enter '0'."]) expect(parser.errors[:field_125]).to eql([I18n.t("validations.lettings.2024.bulk_upload.charges.missing_charges", sentence_fragment: "basic rent")])
expect(parser.errors[:field_126]).to eql(["Please enter the service charge. If there is no service charge, please enter '0'."]) expect(parser.errors[:field_126]).to eql([I18n.t("validations.lettings.2024.bulk_upload.charges.missing_charges", sentence_fragment: "service charge")])
expect(parser.errors[:field_127]).to eql(["Please enter the personal service charge. If there is no personal service charge, please enter '0'."]) expect(parser.errors[:field_127]).to eql([I18n.t("validations.lettings.2024.bulk_upload.charges.missing_charges", sentence_fragment: "personal service charge")])
expect(parser.errors[:field_128]).to eql(["Please enter the basic rent. If there is no basic rent, please enter '0'.", "Please enter the service charge. If there is no service charge, please enter '0'.", "Please enter the personal service charge. If there is no personal service charge, please enter '0'."]) expect(parser.errors[:field_128]).to eql([I18n.t("validations.lettings.2024.bulk_upload.charges.missing_charges", sentence_fragment: "basic rent"), I18n.t("validations.lettings.2024.bulk_upload.charges.missing_charges", sentence_fragment: "service charge"), I18n.t("validations.lettings.2024.bulk_upload.charges.missing_charges", sentence_fragment: "personal service charge")])
end end
end end
end end
@ -2627,10 +2627,10 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "adds an error to all charges" do it "adds an error to all charges" do
parser.valid? parser.valid?
expect(parser.errors[:field_125]).to eql(["Please enter the support charge. If there is no support charge, please enter '0'."]) expect(parser.errors[:field_125]).to eql([I18n.t("validations.lettings.2024.bulk_upload.charges.missing_charges", sentence_fragment: "support charge")])
expect(parser.errors[:field_126]).to eql(["Please enter the support charge. If there is no support charge, please enter '0'."]) expect(parser.errors[:field_126]).to eql([I18n.t("validations.lettings.2024.bulk_upload.charges.missing_charges", sentence_fragment: "support charge")])
expect(parser.errors[:field_127]).to eql(["Please enter the support charge. If there is no support charge, please enter '0'."]) expect(parser.errors[:field_127]).to eql([I18n.t("validations.lettings.2024.bulk_upload.charges.missing_charges", sentence_fragment: "support charge")])
expect(parser.errors[:field_128]).to eql(["Please enter the support charge. If there is no support charge, please enter '0'."]) expect(parser.errors[:field_128]).to eql([I18n.t("validations.lettings.2024.bulk_upload.charges.missing_charges", sentence_fragment: "support charge")])
end end
end end
end end
@ -2857,8 +2857,8 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "sets error on housingneeds a and b" do it "sets error on housingneeds a and b" do
parser.valid? parser.valid?
expect(parser.errors[:field_79]).to include("Only one disabled access need: fully wheelchair-accessible housing, wheelchair access to essential rooms or level access housing, can be selected.") expect(parser.errors[:field_79]).to include(I18n.t("validations.lettings.2024.bulk_upload.housingneeds_type.only_one_option_permitted"))
expect(parser.errors[:field_80]).to include("Only one disabled access need: fully wheelchair-accessible housing, wheelchair access to essential rooms or level access housing, can be selected.") expect(parser.errors[:field_80]).to include(I18n.t("validations.lettings.2024.bulk_upload.housingneeds_type.only_one_option_permitted"))
expect(parser.errors[:field_81]).to be_blank expect(parser.errors[:field_81]).to be_blank
end end
end end
@ -2868,8 +2868,8 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "sets error on housingneeds a and c" do it "sets error on housingneeds a and c" do
parser.valid? parser.valid?
expect(parser.errors[:field_79]).to include("Only one disabled access need: fully wheelchair-accessible housing, wheelchair access to essential rooms or level access housing, can be selected.") expect(parser.errors[:field_79]).to include(I18n.t("validations.lettings.2024.bulk_upload.housingneeds_type.only_one_option_permitted"))
expect(parser.errors[:field_81]).to include("Only one disabled access need: fully wheelchair-accessible housing, wheelchair access to essential rooms or level access housing, can be selected.") expect(parser.errors[:field_81]).to include(I18n.t("validations.lettings.2024.bulk_upload.housingneeds_type.only_one_option_permitted"))
expect(parser.errors[:field_80]).to be_blank expect(parser.errors[:field_80]).to be_blank
end end
end end
@ -2879,8 +2879,8 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "sets error on housingneeds b and c" do it "sets error on housingneeds b and c" do
parser.valid? parser.valid?
expect(parser.errors[:field_80]).to include("Only one disabled access need: fully wheelchair-accessible housing, wheelchair access to essential rooms or level access housing, can be selected.") expect(parser.errors[:field_80]).to include(I18n.t("validations.lettings.2024.bulk_upload.housingneeds_type.only_one_option_permitted"))
expect(parser.errors[:field_81]).to include("Only one disabled access need: fully wheelchair-accessible housing, wheelchair access to essential rooms or level access housing, can be selected.") expect(parser.errors[:field_81]).to include(I18n.t("validations.lettings.2024.bulk_upload.housingneeds_type.only_one_option_permitted"))
expect(parser.errors[:field_79]).to be_blank expect(parser.errors[:field_79]).to be_blank
end end
end end
@ -2890,8 +2890,8 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "sets error on housingneeds a and g" do it "sets error on housingneeds a and g" do
parser.valid? parser.valid?
expect(parser.errors[:field_83]).to include("No disabled access needs can’t be selected if you have selected fully wheelchair-accessible housing, wheelchair access to essential rooms, level access housing or other disabled access needs.") expect(parser.errors[:field_83]).to include(I18n.t("validations.lettings.2024.bulk_upload.housingneeds.no_disabled_needs_conjunction"))
expect(parser.errors[:field_79]).to include("No disabled access needs can’t be selected if you have selected fully wheelchair-accessible housing, wheelchair access to essential rooms, level access housing or other disabled access needs.") expect(parser.errors[:field_79]).to include(I18n.t("validations.lettings.2024.bulk_upload.housingneeds.no_disabled_needs_conjunction"))
expect(parser.errors[:field_80]).to be_blank expect(parser.errors[:field_80]).to be_blank
expect(parser.errors[:field_81]).to be_blank expect(parser.errors[:field_81]).to be_blank
end end
@ -2914,8 +2914,8 @@ RSpec.describe BulkUpload::Lettings::Year2024::RowParser do
it "sets error on housingneeds a and h" do it "sets error on housingneeds a and h" do
parser.valid? parser.valid?
expect(parser.errors[:field_84]).to include("Don’t know disabled access needs can’t be selected if you have selected fully wheelchair-accessible housing, wheelchair access to essential rooms, level access housing or other disabled access needs.") expect(parser.errors[:field_84]).to include(I18n.t("validations.lettings.2024.bulk_upload.housingneeds.dont_know_disabled_needs_conjunction"))
expect(parser.errors[:field_79]).to include("Don’t know disabled access needs can’t be selected if you have selected fully wheelchair-accessible housing, wheelchair access to essential rooms, level access housing or other disabled access needs.") expect(parser.errors[:field_79]).to include(I18n.t("validations.lettings.2024.bulk_upload.housingneeds.dont_know_disabled_needs_conjunction"))
expect(parser.errors[:field_80]).to be_blank expect(parser.errors[:field_80]).to be_blank
expect(parser.errors[:field_81]).to be_blank expect(parser.errors[:field_81]).to be_blank
end end

Loading…
Cancel
Save