Browse Source

CLDC-3669 Extract bulk upload validations (#2719)

pull/2748/head^2
kosiakkatrina 3 months ago committed by GitHub
parent
commit
dd9bc7b191
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 6
      app/services/bulk_upload/processor.rb
  2. 10
      app/services/bulk_upload/sales/validator.rb
  3. 77
      app/services/bulk_upload/sales/year2023/row_parser.rb
  4. 90
      app/services/bulk_upload/sales/year2024/row_parser.rb
  5. 8
      config/locales/en.yml
  6. 29
      config/locales/validations/sales/2023/bulk_upload.en.yml
  7. 44
      config/locales/validations/sales/2024/bulk_upload.en.yml
  8. 6
      spec/services/bulk_upload/sales/validator_spec.rb
  9. 20
      spec/services/bulk_upload/sales/year2023/row_parser_spec.rb
  10. 92
      spec/services/bulk_upload/sales/year2024/row_parser_spec.rb

6
app/services/bulk_upload/processor.rb

@ -6,7 +6,8 @@ class BulkUpload::Processor
[ [
I18n.t("validations.lettings.#{current_collection_start_year}.bulk_upload.blank_file"), I18n.t("validations.lettings.#{current_collection_start_year}.bulk_upload.blank_file"),
I18n.t("validations.lettings.#{previous_collection_start_year}.bulk_upload.blank_file"), 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"), I18n.t("validations.sales.#{current_collection_start_year}.bulk_upload.blank_file"),
I18n.t("validations.sales.#{previous_collection_start_year}.bulk_upload.blank_file"),
].freeze ].freeze
end end
@ -14,7 +15,8 @@ class BulkUpload::Processor
[ [
*I18n.t("validations.lettings.#{current_collection_start_year}.bulk_upload.wrong_template", default: {}).values, *I18n.t("validations.lettings.#{current_collection_start_year}.bulk_upload.wrong_template", default: {}).values,
*I18n.t("validations.lettings.#{previous_collection_start_year}.bulk_upload.wrong_template", default: {}).values, *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, *I18n.t("validations.sales.#{current_collection_start_year}.bulk_upload.wrong_template", default: {}).values,
*I18n.t("validations.sales.#{previous_collection_start_year}.bulk_upload.wrong_template", default: {}).values,
].freeze ].freeze
end end

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

@ -153,7 +153,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.sales.#{@bulk_upload.year}.bulk_upload.blank_file"))
halt_validations! halt_validations!
end end
@ -164,20 +164,20 @@ private
column_count = rows.map(&:size).max column_count = rows.map(&:size).max
errors.add(:base, :over_max_column_count) if column_count > csv_parser.class::MAX_COLUMNS errors.add(:base, I18n.t("validations.sales.#{@bulk_upload.year}.bulk_upload.wrong_template.over_max_column_count")) if column_count > csv_parser.class::MAX_COLUMNS
end end
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.sales.#{@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/sales/validator.attributes.base.no_headers", guidance_link: bulk_upload_sales_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.sales.#{@bulk_upload.year}.bulk_upload.wrong_template.no_headers", guidance_link: bulk_upload_sales_log_url(id: "guidance", form: { year: bulk_upload.year }, host: ENV["APP_HOST"], anchor: "using-the-bulk-upload-template"))
end end
end end
@ -185,7 +185,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.sales.#{@bulk_upload.year}.bulk_upload.wrong_template.wrong_field_numbers_count"))
halt_validations! halt_validations!
end end
end end

77
app/services/bulk_upload/sales/year2023/row_parser.rb

@ -155,6 +155,8 @@ class BulkUpload::Sales::Year2023::RowParser
field_135: "What are the total monthly leasehold charges for the property?", field_135: "What are the total monthly leasehold charges for the property?",
}.freeze }.freeze
ERROR_BASE_KEY = "validations.sales.2023.bulk_upload".freeze
attribute :bulk_upload attribute :bulk_upload
attribute :block_log_creation, :boolean, default: -> { false } attribute :block_log_creation, :boolean, default: -> { false }
@ -311,32 +313,32 @@ class BulkUpload::Sales::Year2023::RowParser
validates :field_3, validates :field_3,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "sale completion date (day)."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "sale completion date (day)."),
category: :setup, category: :setup,
}, },
on: :after_log on: :after_log
validates :field_4, validates :field_4,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "sale completion date (month)."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "sale completion date (month)."),
category: :setup, category: :setup,
}, on: :after_log }, on: :after_log
validates :field_5, validates :field_5,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "sale completion date (year)."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "sale completion 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.saledate.year_not_two_or_four_digits"), message: I18n.t("#{ERROR_BASE_KEY}.saledate.year_not_two_or_four_digits"),
category: :setup, category: :setup,
if: proc { field_5.present? }, if: proc { field_5.present? },
}, on: :after_log }, on: :after_log
validates :field_7, validates :field_7,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "purchase made under ownership scheme."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "purchase made under ownership scheme."),
category: :setup, category: :setup,
}, },
on: :after_log on: :after_log
@ -352,7 +354,7 @@ class BulkUpload::Sales::Year2023::RowParser
validates :field_8, validates :field_8,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "type of shared ownership sale."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "type of shared ownership sale."),
category: :setup, category: :setup,
if: :shared_ownership?, if: :shared_ownership?,
}, },
@ -369,7 +371,7 @@ class BulkUpload::Sales::Year2023::RowParser
validates :field_9, validates :field_9,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "type of discounted ownership sale."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "type of discounted ownership sale."),
category: :setup, category: :setup,
if: :discounted_ownership?, if: :discounted_ownership?,
}, },
@ -386,7 +388,7 @@ class BulkUpload::Sales::Year2023::RowParser
validates :field_10, validates :field_10,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "type of outright sale."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "type of outright sale."),
category: :setup, category: :setup,
if: :outright_sale?, if: :outright_sale?,
}, },
@ -394,7 +396,7 @@ class BulkUpload::Sales::Year2023::RowParser
validates :field_11, validates :field_11,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "type of outright sale."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "type of outright sale."),
category: :setup, category: :setup,
if: proc { field_10 == 12 }, if: proc { field_10 == 12 },
}, },
@ -411,7 +413,7 @@ class BulkUpload::Sales::Year2023::RowParser
validates :field_12, validates :field_12,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "company buyer."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "company buyer."),
category: :setup, category: :setup,
if: :outright_sale?, if: :outright_sale?,
}, },
@ -428,7 +430,7 @@ class BulkUpload::Sales::Year2023::RowParser
validates :field_13, validates :field_13,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "buyers living in property."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "buyers living in property."),
category: :setup, category: :setup,
if: :outright_sale?, if: :outright_sale?,
}, },
@ -436,7 +438,7 @@ class BulkUpload::Sales::Year2023::RowParser
validates :field_14, validates :field_14,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "joint purchase."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "joint purchase."),
category: :setup, category: :setup,
if: :joint_purchase_asked?, if: :joint_purchase_asked?,
}, },
@ -444,7 +446,7 @@ class BulkUpload::Sales::Year2023::RowParser
validates :field_15, validates :field_15,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "more than 2 joint buyers."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "more than 2 joint buyers."),
category: :setup, category: :setup,
if: :joint_purchase?, if: :joint_purchase?,
}, },
@ -560,7 +562,7 @@ class BulkUpload::Sales::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
@ -568,7 +570,7 @@ private
def validate_data_protection_answered def validate_data_protection_answered
unless field_29 == 1 unless field_29 == 1
errors.add(:field_29, I18n.t("validations.not_answered", question: "Data Protection question."), category: :setup) errors.add(:field_29, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "Data Protection question."), category: :setup)
end end
end end
@ -600,18 +602,19 @@ 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_19.blank? && (field_20.blank? || field_22.blank?) if field_19.blank? && (field_20.blank? || field_22.blank?)
errors.add(:field_19, I18n.t("validations.not_answered", question: "UPRN."), category: :not_answered) # I18n.t("#{ERROR_BASE_KEY}.not_answered", question: question.error_display_label)
errors.add(:field_19, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "UPRN."), category: :not_answered)
end end
end end
def validate_address_fields def validate_address_fields
if field_19.blank? || log.errors.attribute_names.include?(:uprn) if field_19.blank? || log.errors.attribute_names.include?(:uprn)
if field_20.blank? if field_20.blank?
errors.add(:field_20, I18n.t("validations.not_answered", question: "address line 1."), category: :not_answered) errors.add(:field_20, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "address line 1."), category: :not_answered)
end end
if field_22.blank? if field_22.blank?
errors.add(:field_22, I18n.t("validations.not_answered", question: "town or city."), category: :not_answered) errors.add(:field_22, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "town or city."), category: :not_answered)
end end
end end
end end
@ -1162,7 +1165,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_answered"), category: :setup)
end end
end end
end end
@ -1172,7 +1175,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
@ -1182,7 +1185,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
@ -1192,7 +1195,7 @@ 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
@ -1201,7 +1204,7 @@ private
return if field_2.blank? return if field_2.blank?
unless assigned_to unless assigned_to
errors.add(:field_2, "User with the specified email could not be found.") errors.add(:field_2, I18n.t("#{ERROR_BASE_KEY}.assigned_to.not_found"))
end end
end end
@ -1211,7 +1214,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_2, "User must be related to owning organisation or managing organisation.", category: :setup) errors.add(:field_2, I18n.t("#{ERROR_BASE_KEY}.assigned_to.organisation_not_related"), category: :setup)
end end
def managing_organisation def managing_organisation
@ -1225,7 +1228,7 @@ private
block_log_creation! block_log_creation!
if errors[:field_2].blank? if errors[:field_2].blank?
errors.add(:field_2, "This user belongs to an organisation that does not have a relationship with the owning organisation.", category: :setup) errors.add(:field_2, I18n.t("#{ERROR_BASE_KEY}.assigned_to.managing_organisation_not_related"), category: :setup)
end end
end end
end end
@ -1246,13 +1249,13 @@ private
if setup_question?(question) if setup_question?(question)
fields.each do |field| fields.each do |field|
unless errors.any? { |e| fields.include?(e.attribute) } unless errors.any? { |e| fields.include?(e.attribute) }
errors.add(field, I18n.t("validations.not_answered", question: question.error_display_label), category: :setup) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: question.error_display_label), category: :setup)
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) }
errors.add(field, I18n.t("validations.not_answered", question: question.error_display_label), category: :not_answered) errors.add(field, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: question.error_display_label), category: :not_answered)
end end
end end
end end
@ -1272,15 +1275,15 @@ private
if setup_question?(question) if setup_question?(question)
fields.each do |field| fields.each do |field|
if errors[field].none? next unless errors[field].none?
block_log_creation!
errors.add(field, I18n.t("validations.invalid_option", question: format_ending(QUESTIONS[field])), category: :setup) block_log_creation!
end errors.add(field, I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: format_ending(QUESTIONS[field])), category: :setup)
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) }
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
@ -1292,15 +1295,15 @@ private
return if errors.key?(:field_3) || errors.key?(:field_4) || errors.key?(:field_5) return if errors.key?(:field_3) || errors.key?(:field_4) || errors.key?(:field_5)
unless bulk_upload.form.valid_start_date_for_form?(saledate) unless bulk_upload.form.valid_start_date_for_form?(saledate)
errors.add(:field_3, 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_3, I18n.t("#{ERROR_BASE_KEY}.saledate.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_4, 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_4, I18n.t("#{ERROR_BASE_KEY}.saledate.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_5, 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_5, I18n.t("#{ERROR_BASE_KEY}.saledate.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_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 org errors.add(:field_1, error_message) # Owning org
errors.add(:field_3, error_message) # Sale completion date errors.add(:field_3, error_message) # Sale completion date
@ -1335,7 +1338,7 @@ private
def validate_buyer1_economic_status def validate_buyer1_economic_status
if field_35 == 9 if field_35 == 9
errors.add(:field_35, "Buyer 1 cannot be a child under 16.") errors.add(:field_35, I18n.t("#{ERROR_BASE_KEY}.ecstat1.child_under_16"))
end end
end end
end end

90
app/services/bulk_upload/sales/year2024/row_parser.rb

@ -151,6 +151,8 @@ class BulkUpload::Sales::Year2024::RowParser
field_131: "What are the total monthly leasehold charges for the property?", field_131: "What are the total monthly leasehold charges for the property?",
}.freeze }.freeze
ERROR_BASE_KEY = "validations.sales.2024.bulk_upload".freeze
attribute :bulk_upload attribute :bulk_upload
attribute :block_log_creation, :boolean, default: -> { false } attribute :block_log_creation, :boolean, default: -> { false }
@ -303,32 +305,32 @@ class BulkUpload::Sales::Year2024::RowParser
validates :field_4, validates :field_4,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "sale completion date (day)."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "sale completion date (day)."),
category: :setup, category: :setup,
}, },
on: :after_log on: :after_log
validates :field_5, validates :field_5,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "sale completion date (month)."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "sale completion date (month)."),
category: :setup, category: :setup,
}, on: :after_log }, on: :after_log
validates :field_6, validates :field_6,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "sale completion date (year)."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "sale completion 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.saledate.year_not_two_or_four_digits"), message: I18n.t("#{ERROR_BASE_KEY}.saledate.year_not_two_or_four_digits"),
category: :setup, category: :setup,
if: proc { field_6.present? }, if: proc { field_6.present? },
}, on: :after_log }, on: :after_log
validates :field_8, validates :field_8,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "purchase made under ownership scheme."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "purchase made under ownership scheme."),
category: :setup, category: :setup,
}, },
on: :after_log on: :after_log
@ -344,7 +346,7 @@ class BulkUpload::Sales::Year2024::RowParser
validates :field_9, validates :field_9,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "type of shared ownership sale."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "type of shared ownership sale."),
category: :setup, category: :setup,
if: :shared_ownership?, if: :shared_ownership?,
}, },
@ -361,7 +363,7 @@ class BulkUpload::Sales::Year2024::RowParser
validates :field_10, validates :field_10,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "type of discounted ownership sale."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "type of discounted ownership sale."),
category: :setup, category: :setup,
if: :discounted_ownership?, if: :discounted_ownership?,
}, },
@ -369,7 +371,7 @@ class BulkUpload::Sales::Year2024::RowParser
validates :field_116, validates :field_116,
numericality: { numericality: {
message: I18n.t("validations.numeric.within_range", field: "Percentage discount", min: "0%", max: "70%"), message: I18n.t("#{ERROR_BASE_KEY}.numeric.within_range", field: "Percentage discount", min: "0%", max: "70%"),
greater_than_or_equal_to: 0, greater_than_or_equal_to: 0,
less_than_or_equal_to: 70, less_than_or_equal_to: 70,
if: :discounted_ownership?, if: :discounted_ownership?,
@ -387,7 +389,7 @@ class BulkUpload::Sales::Year2024::RowParser
validates :field_11, validates :field_11,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "type of outright sale."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "type of outright sale."),
category: :setup, category: :setup,
if: :outright_sale?, if: :outright_sale?,
}, },
@ -395,7 +397,7 @@ class BulkUpload::Sales::Year2024::RowParser
validates :field_12, validates :field_12,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "type of outright sale."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "type of outright sale."),
category: :setup, category: :setup,
if: proc { field_11 == 12 }, if: proc { field_11 == 12 },
}, },
@ -412,7 +414,7 @@ class BulkUpload::Sales::Year2024::RowParser
validates :field_13, validates :field_13,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "company buyer."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "company buyer."),
category: :setup, category: :setup,
if: :outright_sale?, if: :outright_sale?,
}, },
@ -429,7 +431,7 @@ class BulkUpload::Sales::Year2024::RowParser
validates :field_14, validates :field_14,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "buyers living in property."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "buyers living in property."),
category: :setup, category: :setup,
if: :outright_sale?, if: :outright_sale?,
}, },
@ -437,7 +439,7 @@ class BulkUpload::Sales::Year2024::RowParser
validates :field_15, validates :field_15,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "joint purchase."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "joint purchase."),
category: :setup, category: :setup,
if: :joint_purchase_asked?, if: :joint_purchase_asked?,
}, },
@ -445,7 +447,7 @@ class BulkUpload::Sales::Year2024::RowParser
validates :field_16, validates :field_16,
presence: { presence: {
message: I18n.t("validations.not_answered", question: "more than 2 joint buyers."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "more than 2 joint buyers."),
category: :setup, category: :setup,
if: :joint_purchase?, if: :joint_purchase?,
}, },
@ -569,7 +571,7 @@ class BulkUpload::Sales::Year2024::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
@ -603,14 +605,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_22.blank? && !key_address_fields_provided? if field_22.blank? && !key_address_fields_provided?
errors.add(:field_22, I18n.t("validations.not_answered", question: "UPRN.")) errors.add(:field_22, 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_22.blank? && key_address_fields_provided? if log.uprn.nil? && field_22.blank? && key_address_fields_provided?
%i[field_23 field_24 field_25 field_26 field_27 field_28].each do |field| %i[field_23 field_24 field_25 field_26 field_27 field_28].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
@ -622,19 +624,19 @@ private
def validate_address_fields def validate_address_fields
if field_22.blank? || log.errors.attribute_names.include?(:uprn) if field_22.blank? || log.errors.attribute_names.include?(:uprn)
if field_23.blank? if field_23.blank?
errors.add(:field_23, I18n.t("validations.not_answered", question: "address line 1.")) errors.add(:field_23, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "address line 1."))
end end
if field_25.blank? if field_25.blank?
errors.add(:field_25, I18n.t("validations.not_answered", question: "town or city.")) errors.add(:field_25, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "town or city."))
end end
if field_27.blank? if field_27.blank?
errors.add(:field_27, I18n.t("validations.not_answered", question: "part 1 of postcode.")) errors.add(:field_27, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "part 1 of postcode."))
end end
if field_28.blank? if field_28.blank?
errors.add(:field_28, I18n.t("validations.not_answered", question: "part 2 of postcode.")) errors.add(:field_28, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "part 2 of postcode."))
end end
end end
end end
@ -1281,7 +1283,7 @@ private
block_log_creation! block_log_creation!
if errors[:field_1].blank? if errors[:field_1].blank?
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
end end
@ -1291,7 +1293,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
@ -1301,7 +1303,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
@ -1315,9 +1317,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", 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
@ -1325,13 +1327,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 sales 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 sales log should be assigned to?"))
end end
end end
@ -1341,7 +1343,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.", category: :setup) errors.add(:field_3, I18n.t("#{ERROR_BASE_KEY}.assigned_to.organisation_not_related"), category: :setup)
end end
def managing_organisation def managing_organisation
@ -1361,7 +1363,7 @@ private
block_log_creation! block_log_creation!
if errors[:field_2].blank? if errors[:field_2].blank?
errors.add(:field_2, "This organisation does not have a relationship with the owning organisation.", category: :setup) errors.add(:field_2, I18n.t("#{ERROR_BASE_KEY}.assigned_to.managing_organisation_not_related"), category: :setup)
end end
end end
end end
@ -1410,13 +1412,13 @@ private
fields.each do |field| fields.each do |field|
if errors[field].none? if errors[field].none?
block_log_creation! block_log_creation!
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)
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) }
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
@ -1428,15 +1430,15 @@ private
return if errors.key?(:field_4) || errors.key?(:field_5) || errors.key?(:field_6) return if errors.key?(:field_4) || errors.key?(:field_5) || errors.key?(:field_6)
unless bulk_upload.form.valid_start_date_for_form?(saledate) unless bulk_upload.form.valid_start_date_for_form?(saledate)
errors.add(:field_4, 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_4, I18n.t("#{ERROR_BASE_KEY}.saledate.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_5, 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_5, I18n.t("#{ERROR_BASE_KEY}.saledate.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_6, 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_6, I18n.t("#{ERROR_BASE_KEY}.saledate.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_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 org errors.add(:field_1, error_message) # Owning org
errors.add(:field_4, error_message) # Sale completion date errors.add(:field_4, error_message) # Sale completion date
@ -1472,10 +1474,10 @@ private
def validate_buyer1_economic_status def validate_buyer1_economic_status
if field_35 == 9 if field_35 == 9
if field_31.present? && field_31.to_i >= 16 if field_31.present? && field_31.to_i >= 16
errors.add(:field_35, I18n.t("validations.sales.household.ecstat.buyer_cannot_be_over_16_and_child", buyer_index: "1")) errors.add(:field_35, I18n.t("#{ERROR_BASE_KEY}.ecstat1.buyer_cannot_be_over_16_and_child"))
errors.add(:field_31, I18n.t("validations.sales.household.ecstat.buyer_cannot_be_over_16_and_child", buyer_index: "1")) errors.add(:field_31, I18n.t("#{ERROR_BASE_KEY}.age1.buyer_cannot_be_over_16_and_child"))
else else
errors.add(:field_35, I18n.t("validations.sales.household.ecstat1.buyer_cannot_be_child")) errors.add(:field_35, I18n.t("#{ERROR_BASE_KEY}.ecstat1.buyer_cannot_be_child"))
end end
end end
end end
@ -1485,23 +1487,23 @@ private
if field_42 == 9 if field_42 == 9
if field_38.present? && field_38.to_i >= 16 if field_38.present? && field_38.to_i >= 16
errors.add(:field_42, I18n.t("validations.sales.household.ecstat.buyer_cannot_be_over_16_and_child", buyer_index: "2")) errors.add(:field_42, I18n.t("#{ERROR_BASE_KEY}.ecstat2.buyer_cannot_be_over_16_and_child"))
errors.add(:field_38, I18n.t("validations.sales.household.ecstat.buyer_cannot_be_over_16_and_child", buyer_index: "2")) errors.add(:field_38, I18n.t("#{ERROR_BASE_KEY}.age2.buyer_cannot_be_over_16_and_child"))
else else
errors.add(:field_42, I18n.t("validations.sales.household.ecstat2.buyer_cannot_be_child")) errors.add(:field_42, I18n.t("#{ERROR_BASE_KEY}.ecstat2.buyer_cannot_be_child"))
end end
end end
end end
def validate_nationality def validate_nationality
if field_34.present? && !valid_nationality_options.include?(field_34.to_s) if field_34.present? && !valid_nationality_options.include?(field_34.to_s)
errors.add(:field_34, I18n.t("validations.household.nationality")) errors.add(:field_34, I18n.t("#{ERROR_BASE_KEY}.nationality.invalid"))
end end
end end
def validate_buyer_2_nationality def validate_buyer_2_nationality
if field_41.present? && !valid_nationality_options.include?(field_41.to_s) if field_41.present? && !valid_nationality_options.include?(field_41.to_s)
errors.add(:field_41, I18n.t("validations.household.nationality")) errors.add(:field_41, I18n.t("#{ERROR_BASE_KEY}.nationality.invalid"))
end end
end end

8
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/sales/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 sale 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})."
forms/bulk_upload_lettings/year: forms/bulk_upload_lettings/year:
attributes: attributes:
year: year:

29
config/locales/validations/sales/2023/bulk_upload.en.yml

@ -0,0 +1,29 @@
en:
validations:
sales:
2023:
bulk_upload:
not_answered: "You must answer %{question}"
invalid_option: "Enter a valid value 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 sale 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_answered: "The owning organisation code is incorrect."
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."
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."
managing_organisation_not_related: "This user belongs to an organisation that does not have a relationship with the owning organisation."
saledate:
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: "Sale completion year must be 2 or 4 digits."
ecstat1:
child_under_16: "Buyer 1 cannot be a child under 16."

44
config/locales/validations/sales/2024/bulk_upload.en.yml

@ -0,0 +1,44 @@
en:
validations:
sales:
2024:
bulk_upload:
not_answered: "You must answer %{question}"
invalid_option: "Enter a valid value 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:
over_max_column_count: "Too many columns, 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."
wrong_template: "Incorrect sale dates, please ensure you have used the correct template."
numeric:
within_range: "%{field} must be between %{min} and %{max}."
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:
support: "This owning organisation is not affiliated with %(name)."
not_support: "You do not have permission to add logs for this owning organisation."
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."
managing_organisation_not_related: "This organisation does not have a relationship with the owning organisation."
saledate:
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: "Sale completion year must be 2 or 4 digits."
ecstat1:
buyer_cannot_be_over_16_and_child: "Buyer 1's age cannot be 16 or over if their working situation is child under 16."
buyer_cannot_be_child: "Buyer 1 cannot have a working situation of child under 16."
age1:
buyer_cannot_be_over_16_and_child: "Buyer 1's age cannot be 16 or over if their working situation is child under 16."
ecstat2:
buyer_cannot_be_over_16_and_child: "Buyer 2's age cannot be 16 or over if their working situation is child under 16."
buyer_cannot_be_child: "Buyer 2 cannot have a working situation of child under 16."
age2:
buyer_cannot_be_over_16_and_child: "Buyer 2's age cannot be 16 or over if their working situation is child under 16."
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."

6
spec/services/bulk_upload/sales/validator_spec.rb

@ -15,7 +15,7 @@ RSpec.describe BulkUpload::Sales::Validator do
context "when file is empty" do context "when file is empty" do
it "is not valid" do it "is not valid" do
expect(validator).not_to be_valid expect(validator).not_to be_valid
expect(validator.errors["base"]).to eql(["Template is blank - The template must be filled in for us to create the logs and check if data is correct."]) expect(validator.errors["base"]).to eql([I18n.t("validations.sales.2024.bulk_upload.blank_file")])
end end
end end
@ -27,7 +27,7 @@ RSpec.describe BulkUpload::Sales::Validator do
it "is not valid" do it "is not valid" do
expect(validator).not_to be_valid expect(validator).not_to be_valid
expect(validator.errors["base"]).to eql(["Template is blank - The template must be filled in for us to create the logs and check if data is correct."]) expect(validator.errors["base"]).to eql([I18n.t("validations.sales.2024.bulk_upload.blank_file")])
end end
end end
@ -54,7 +54,7 @@ RSpec.describe BulkUpload::Sales::Validator do
it "is not valid" do it "is not valid" do
expect(validator).not_to be_valid expect(validator).not_to be_valid
expect(validator.errors["base"]).to eql(["Incorrect sale dates, please ensure you have used the correct template."]) expect(validator.errors["base"]).to eql([I18n.t("validations.sales.2024.bulk_upload.wrong_template.wrong_template")])
end end
end end

20
spec/services/bulk_upload/sales/year2023/row_parser_spec.rb

@ -406,7 +406,7 @@ RSpec.describe BulkUpload::Sales::Year2023::RowParser do
let(:attributes) { setup_section_params.merge(field_1: nil) } let(:attributes) { setup_section_params.merge(field_1: nil) }
it "is not permitted as setup error" do it "is not permitted as setup error" do
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.sales.2023.bulk_upload.not_answered", question: "owning organisation.")])
end end
it "blocks log creation" do it "blocks log creation" do
@ -418,7 +418,7 @@ RSpec.describe BulkUpload::Sales::Year2023::RowParser do
let(:attributes) { { bulk_upload:, field_1: "donotexist" } } let(:attributes) { { bulk_upload:, field_1: "donotexist" } }
it "is not permitted as a setup error" do it "is not permitted as a setup error" do
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.sales.2023.bulk_upload.not_answered", question: "owning organisation.")])
end end
it "blocks log creation" do it "blocks log creation" do
@ -432,7 +432,7 @@ RSpec.describe BulkUpload::Sales::Year2023::RowParser do
let(:attributes) { { bulk_upload:, field_1: unaffiliated_org.old_visible_id } } let(:attributes) { { bulk_upload:, field_1: unaffiliated_org.old_visible_id } }
it "is not permitted as setup error" do it "is not permitted as setup error" do
expect(parser.errors.where(:field_1, category: :setup).map(&:message)).to eql(["You do not have permission to add logs for this owning organisation."]) expect(parser.errors.where(:field_1, category: :setup).map(&:message)).to eql([I18n.t("validations.sales.2023.bulk_upload.owning_organisation.not_permitted")])
end end
it "blocks log creation" do it "blocks log creation" do
@ -608,7 +608,7 @@ RSpec.describe BulkUpload::Sales::Year2023::RowParser do
it "returns a setup error" do it "returns a setup error" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_5, category: :setup).map(&:message)).to include("Sale completion year must be 2 or 4 digits.") expect(parser.errors.where(:field_5, category: :setup).map(&:message)).to include(I18n.t("validations.sales.2023.bulk_upload.saledate.year_not_two_or_four_digits"))
end end
end end
@ -672,7 +672,7 @@ RSpec.describe BulkUpload::Sales::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.sales.2023.bulk_upload.duplicate")
[ [
:field_1, # Owning org :field_1, # Owning org
@ -932,7 +932,7 @@ RSpec.describe BulkUpload::Sales::Year2023::RowParser do
it "does not set ##{age}" do it "does not set ##{age}" do
parser.valid? parser.valid?
expect(parser.errors[field.to_sym]).to include(/You must answer/) expect(parser.errors[field.to_sym]).to include(/#{I18n.t("validations.sales.2023.bulk_upload.not_answered", question: "")}/)
end end
end end
end end
@ -980,7 +980,7 @@ RSpec.describe BulkUpload::Sales::Year2023::RowParser do
let(:attributes) { valid_attributes.merge({ field_35: "9" }) } let(:attributes) { valid_attributes.merge({ field_35: "9" }) }
it "a custom validation is applied" do it "a custom validation is applied" do
validation_message = "Buyer 1 cannot be a child under 16." validation_message = I18n.t("validations.sales.2023.bulk_upload.ecstat1.child_under_16")
expect(parser.errors[:field_35]).to include validation_message expect(parser.errors[:field_35]).to include validation_message
end end
end end
@ -1052,7 +1052,7 @@ RSpec.describe BulkUpload::Sales::Year2023::RowParser do
let(:attributes) { setup_section_params.merge(field_105: "4") } let(:attributes) { setup_section_params.merge(field_105: "4") }
it "returns correct errors" do it "returns correct errors" do
expect(parser.errors[:field_105]).to include("Enter a valid value for was a mortgage used for the purchase of this property? - Shared ownership.") expect(parser.errors[:field_105]).to include(I18n.t("validations.sales.2023.bulk_upload.invalid_option", question: "was a mortgage used for the purchase of this property? - Shared ownership."))
parser.log.blank_invalid_non_setup_fields! parser.log.blank_invalid_non_setup_fields!
parser.log.save! parser.log.save!
expect(parser.log.mortgageused).to be_nil expect(parser.log.mortgageused).to be_nil
@ -1420,7 +1420,7 @@ RSpec.describe BulkUpload::Sales::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 user belongs to an organisation that does not have a relationship with the owning organisation.") expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql(I18n.t("validations.sales.2023.bulk_upload.assigned_to.managing_organisation_not_related"))
end end
it "blocks log creation" do it "blocks log creation" do
@ -1442,7 +1442,7 @@ RSpec.describe BulkUpload::Sales::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.sales.2023.bulk_upload.owning_organisation.not_stock_owner"))
end end
it "blocks log creation" do it "blocks log creation" do

92
spec/services/bulk_upload/sales/year2024/row_parser_spec.rb

@ -301,7 +301,7 @@ RSpec.describe BulkUpload::Sales::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_32]).to eql(["You must answer buyer 1’s gender identity."]) expect(parser.errors[:field_32]).to eql([I18n.t("validations.not_answered", question: "buyer 1’s gender identity.")])
end end
end end
@ -310,7 +310,7 @@ RSpec.describe BulkUpload::Sales::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_23]).to eql(["You must answer address line 1."]) expect(parser.errors[:field_23]).to eql([I18n.t("validations.sales.2024.bulk_upload.not_answered", question: "address line 1.")])
end end
end end
@ -320,7 +320,7 @@ RSpec.describe BulkUpload::Sales::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_35].length).to eq(1) expect(parser.errors[:field_35].length).to eq(1)
expect(parser.errors[:field_35]).to include(match "Enter a valid value for") expect(parser.errors[:field_35]).to include(match I18n.t("validations.sales.2024.bulk_upload.invalid_option", question: ""))
end end
end end
end end
@ -463,7 +463,7 @@ RSpec.describe BulkUpload::Sales::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.sales.2024.bulk_upload.not_answered", question: "owning organisation.")])
end end
it "blocks log creation" do it "blocks log creation" do
@ -477,7 +477,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
it "is not permitted as a setup error" do it "is not permitted as a setup error" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_1, category: :setup).map(&:message)).to eql(["The owning organisation code is incorrect."]) expect(parser.errors.where(:field_1, category: :setup).map(&:message)).to eql([I18n.t("validations.sales.2024.bulk_upload.owning_organisation.not_found")])
end end
it "blocks log creation" do it "blocks log creation" do
@ -493,7 +493,7 @@ RSpec.describe BulkUpload::Sales::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 do not have permission to add logs for this owning organisation."]) expect(parser.errors.where(:field_1, category: :setup).map(&:message)).to eql([I18n.t("validations.sales.2024.bulk_upload.owning_organisation.not_permitted.not_support")])
end end
it "blocks log creation" do it "blocks log creation" do
@ -580,7 +580,7 @@ RSpec.describe BulkUpload::Sales::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.sales.2024.bulk_upload.owning_organisation.not_permitted.not_support"))
end end
end end
@ -598,7 +598,7 @@ RSpec.describe BulkUpload::Sales::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.sales.2024.bulk_upload.owning_organisation.not_permitted.not_support"))
end end
end end
end end
@ -631,7 +631,7 @@ RSpec.describe BulkUpload::Sales::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 sales log should be assigned to?") expect(parser.errors[:field_3]).to include(I18n.t("validations.sales.2024.bulk_upload.not_answered", question: "what is the CORE username of the account this sales log should be assigned to?"))
end end
it "blocks log creation" do it "blocks log creation" do
@ -736,7 +736,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
it "returns a setup error" do it "returns a setup error" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_6, category: :setup).map(&:message)).to include("Sale completion year must be 2 or 4 digits.") expect(parser.errors.where(:field_6, category: :setup).map(&:message)).to include(I18n.t("validations.sales.2024.bulk_upload.saledate.year_not_two_or_four_digits"))
end end
end end
@ -802,7 +802,7 @@ RSpec.describe BulkUpload::Sales::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.sales.2024.bulk_upload.duplicate")
[ [
:field_1, # Owning org :field_1, # Owning org
@ -891,7 +891,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
it "returns correct error" do it "returns correct error" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_116).map(&:message)).to include("Percentage discount must be between 0% and 70%.") expect(parser.errors.where(:field_116).map(&:message)).to include(I18n.t("validations.sales.2024.bulk_upload.numeric.within_range", field: "Percentage discount", min: "0%", max: "70%"))
end end
end end
@ -909,7 +909,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
it "returns correct error" do it "returns correct error" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_116).map(&:message)).to include("Percentage discount must be between 0% and 70%.") expect(parser.errors.where(:field_116).map(&:message)).to include(I18n.t("validations.sales.2024.bulk_upload.numeric.within_range", field: "Percentage discount", min: "0%", max: "70%"))
end end
end end
end end
@ -942,7 +942,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
it "returns setup error" do it "returns setup error" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_13).map(&:message)).to include("Enter a valid value for is the buyer a company?") expect(parser.errors.where(:field_13).map(&:message)).to include(I18n.t("validations.invalid_option", question: "is the buyer a company?"))
expect(parser.errors.where(:field_13, category: :setup)).to be_present expect(parser.errors.where(:field_13, category: :setup)).to be_present
end end
end end
@ -954,7 +954,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
it "returns setup error" do it "returns setup error" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_14).map(&:message)).to eql(["Enter a valid value for will the buyers live in the property?"]) expect(parser.errors.where(:field_14).map(&:message)).to eql([I18n.t("validations.invalid_option", question: "will the buyers live in the property?")])
expect(parser.errors.where(:field_14, category: :setup)).to be_present expect(parser.errors.where(:field_14, category: :setup)).to be_present
end end
end end
@ -1011,10 +1011,10 @@ RSpec.describe BulkUpload::Sales::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_23]).to eql(["You must answer address line 1."]) expect(parser.errors[:field_23]).to eql([I18n.t("validations.sales.2024.bulk_upload.not_answered", question: "address line 1.")])
expect(parser.errors[:field_25]).to eql(["You must answer town or city."]) expect(parser.errors[:field_25]).to eql([I18n.t("validations.sales.2024.bulk_upload.not_answered", question: "town or city.")])
expect(parser.errors[:field_27]).to eql(["You must answer part 1 of postcode."]) expect(parser.errors[:field_27]).to eql([I18n.t("validations.sales.2024.bulk_upload.not_answered", question: "part 1 of postcode.")])
expect(parser.errors[:field_28]).to eql(["You must answer part 2 of postcode."]) expect(parser.errors[:field_28]).to eql([I18n.t("validations.sales.2024.bulk_upload.not_answered", question: "part 2 of postcode.")])
end end
end end
@ -1042,11 +1042,11 @@ RSpec.describe BulkUpload::Sales::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_22]).to eql(["You must answer UPRN."]) expect(parser.errors[:field_22]).to eql([I18n.t("validations.sales.2024.bulk_upload.not_answered", question: "UPRN.")])
expect(parser.errors[:field_23]).to eql(["You must answer address line 1."]) expect(parser.errors[:field_23]).to eql([I18n.t("validations.sales.2024.bulk_upload.not_answered", question: "address line 1.")])
expect(parser.errors[:field_25]).to eql(["You must answer town or city."]) expect(parser.errors[:field_25]).to eql([I18n.t("validations.sales.2024.bulk_upload.not_answered", question: "town or city.")])
expect(parser.errors[:field_27]).to eql(["You must answer part 1 of postcode."]) expect(parser.errors[:field_27]).to eql([I18n.t("validations.sales.2024.bulk_upload.not_answered", question: "part 1 of postcode.")])
expect(parser.errors[:field_28]).to eql(["You must answer part 2 of postcode."]) expect(parser.errors[:field_28]).to eql([I18n.t("validations.sales.2024.bulk_upload.not_answered", question: "part 2 of postcode.")])
end end
end end
@ -1055,8 +1055,8 @@ RSpec.describe BulkUpload::Sales::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_22]).to eql(["You must answer UPRN."]) expect(parser.errors[:field_22]).to eql([I18n.t("validations.sales.2024.bulk_upload.not_answered", question: "UPRN.")])
expect(parser.errors[:field_23]).to eql(["You must answer address line 1."]) expect(parser.errors[:field_23]).to eql([I18n.t("validations.sales.2024.bulk_upload.not_answered", question: "address line 1.")])
expect(parser.errors[:field_25]).to be_empty expect(parser.errors[:field_25]).to be_empty
expect(parser.errors[:field_27]).to be_empty expect(parser.errors[:field_27]).to be_empty
expect(parser.errors[:field_28]).to be_empty expect(parser.errors[:field_28]).to be_empty
@ -1090,7 +1090,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
parser.valid? parser.valid?
expect(parser.errors[:field_22]).to be_empty expect(parser.errors[:field_22]).to be_empty
%i[field_23 field_24 field_25 field_26 field_27 field_28].each do |field| %i[field_23 field_24 field_25 field_26 field_27 field_28].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.sales.2024.bulk_upload.address.not_found")])
end end
end end
end end
@ -1105,7 +1105,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
parser.valid? parser.valid?
expect(parser.errors[:field_22]).to be_empty expect(parser.errors[:field_22]).to be_empty
%i[field_23 field_24 field_25 field_26 field_27 field_28].each do |field| %i[field_23 field_24 field_25 field_26 field_27 field_28].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.sales.2024.bulk_upload.address.not_found")])
end end
end end
end end
@ -1218,8 +1218,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
it "a custom validation is applied" do it "a custom validation is applied" do
parser.valid? parser.valid?
validation_message = "Buyer 2 cannot have a working situation of child under 16." expect(parser.errors[:field_42]).to include I18n.t("validations.sales.2024.bulk_upload.ecstat2.buyer_cannot_be_child")
expect(parser.errors[:field_42]).to include validation_message
end end
end end
@ -1240,9 +1239,8 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
it "a custom validation is applied" do it "a custom validation is applied" do
parser.valid? parser.valid?
validation_message = "Buyer 2's age cannot be 16 or over if their working situation is child under 16." expect(parser.errors[:field_42]).to include I18n.t("validations.sales.2024.bulk_upload.ecstat2.buyer_cannot_be_over_16_and_child")
expect(parser.errors[:field_42]).to include validation_message expect(parser.errors[:field_38]).to include I18n.t("validations.sales.2024.bulk_upload.age2.buyer_cannot_be_over_16_and_child")
expect(parser.errors[:field_38]).to include validation_message
end end
end end
@ -1264,8 +1262,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
it "a custom validation is applied" do it "a custom validation is applied" do
parser.valid? parser.valid?
validation_message = "Buyer 1 cannot have a working situation of child under 16." expect(parser.errors[:field_35]).to include I18n.t("validations.sales.2024.bulk_upload.ecstat1.buyer_cannot_be_child")
expect(parser.errors[:field_35]).to include validation_message
end end
end end
@ -1286,9 +1283,8 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
it "a custom validation is applied" do it "a custom validation is applied" do
parser.valid? parser.valid?
validation_message = "Buyer 1's age cannot be 16 or over if their working situation is child under 16." expect(parser.errors[:field_35]).to include I18n.t("validations.sales.2024.bulk_upload.ecstat1.buyer_cannot_be_over_16_and_child")
expect(parser.errors[:field_35]).to include validation_message expect(parser.errors[:field_31]).to include I18n.t("validations.sales.2024.bulk_upload.age1.buyer_cannot_be_over_16_and_child")
expect(parser.errors[:field_31]).to include validation_message
end end
end end
end end
@ -1333,7 +1329,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
it "returns correct errors" do it "returns correct errors" do
parser.valid? parser.valid?
expect(parser.errors[:field_103]).to include("Enter a valid value for was a mortgage used for the purchase of this property? - Shared ownership.") expect(parser.errors[:field_103]).to include(I18n.t("validations.sales.2024.bulk_upload.invalid_option", question: "was a mortgage used for the purchase of this property? - Shared ownership."))
parser.log.blank_invalid_non_setup_fields! parser.log.blank_invalid_non_setup_fields!
parser.log.save! parser.log.save!
@ -1370,7 +1366,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
it "returns correct errors" do it "returns correct errors" do
parser.valid? parser.valid?
expect(parser.errors[:field_103]).to include("Enter a valid value for was a mortgage used for the purchase of this property?") expect(parser.errors[:field_103]).to include(I18n.t("validations.invalid_option", question: "was a mortgage used for the purchase of this property?"))
parser.log.blank_invalid_non_setup_fields! parser.log.blank_invalid_non_setup_fields!
parser.log.save! parser.log.save!
@ -1383,7 +1379,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
it "returns correct errors" do it "returns correct errors" do
parser.valid? parser.valid?
expect(parser.errors[:field_103]).to include("Enter a valid value for was a mortgage used for the purchase of this property?") expect(parser.errors[:field_103]).to include(I18n.t("validations.invalid_option", question: "was a mortgage used for the purchase of this property?"))
parser.log.blank_invalid_non_setup_fields! parser.log.blank_invalid_non_setup_fields!
parser.log.save! parser.log.save!
@ -1440,7 +1436,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
it "does not allow 3 (don't know) as an option for discounted ownership" do it "does not allow 3 (don't know) as an option for discounted ownership" do
parser.valid? parser.valid?
expect(parser.errors[:field_117]).to include("Enter a valid value for was a mortgage used for the purchase of this property?") expect(parser.errors[:field_117]).to include(I18n.t("validations.invalid_option", question: "was a mortgage used for the purchase of this property?"))
parser.log.blank_invalid_non_setup_fields! parser.log.blank_invalid_non_setup_fields!
parser.log.save! parser.log.save!
@ -1696,7 +1692,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
parser.valid? parser.valid?
expect(parser.log.nationality_all).to be(nil) expect(parser.log.nationality_all).to be(nil)
expect(parser.log.nationality_all_group).to be(nil) expect(parser.log.nationality_all_group).to be(nil)
expect(parser.errors["field_34"]).to include("Select a valid nationality.") expect(parser.errors["field_34"]).to include(I18n.t("validations.sales.2024.bulk_upload.nationality.invalid"))
end end
end end
end end
@ -1781,7 +1777,7 @@ RSpec.describe BulkUpload::Sales::Year2024::RowParser do
parser.valid? parser.valid?
expect(parser.log.nationality_all_buyer2).to be(nil) expect(parser.log.nationality_all_buyer2).to be(nil)
expect(parser.log.nationality_all_buyer2_group).to be(nil) expect(parser.log.nationality_all_buyer2_group).to be(nil)
expect(parser.errors["field_41"]).to include("Select a valid nationality.") expect(parser.errors["field_41"]).to include(I18n.t("validations.sales.2024.bulk_upload.nationality.invalid"))
end end
end end
end end
@ -1983,7 +1979,7 @@ RSpec.describe BulkUpload::Sales::Year2024::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("You must answer reported by.") expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql(I18n.t("validations.not_answered", question: "reported by."))
end end
it "blocks log creation" do it "blocks log creation" do
@ -1999,7 +1995,7 @@ RSpec.describe BulkUpload::Sales::Year2024::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("You must answer reported by.") expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql(I18n.t("validations.not_answered", question: "reported by."))
end end
it "blocks log creation" do it "blocks log creation" do
@ -2017,7 +2013,7 @@ RSpec.describe BulkUpload::Sales::Year2024::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 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.sales.2024.bulk_upload.assigned_to.managing_organisation_not_related"))
end end
it "blocks log creation" do it "blocks log creation" do
@ -2039,7 +2035,7 @@ RSpec.describe BulkUpload::Sales::Year2024::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.sales.2024.bulk_upload.owning_organisation.not_stock_owner"))
end end
it "blocks log creation" do it "blocks log creation" do

Loading…
Cancel
Save