From 4bd1b04eda4c1fdde430b2fe43f1f82c09567605 Mon Sep 17 00:00:00 2001 From: Carolyn Date: Thu, 20 Feb 2025 11:25:31 +0000 Subject: [PATCH] fix typos, field numbers, staircasing tests --- .../bulk_upload/sales/year2025/csv_parser.rb | 8 +- .../bulk_upload/sales/year2025/row_parser.rb | 678 ++---------------- .../sales/year2025/csv_parser_spec.rb | 14 +- .../sales/year2025/row_parser_spec.rb | 340 ++++----- 4 files changed, 241 insertions(+), 799 deletions(-) diff --git a/app/services/bulk_upload/sales/year2025/csv_parser.rb b/app/services/bulk_upload/sales/year2025/csv_parser.rb index 49113e1f4..ec052dbfb 100644 --- a/app/services/bulk_upload/sales/year2025/csv_parser.rb +++ b/app/services/bulk_upload/sales/year2025/csv_parser.rb @@ -114,11 +114,11 @@ private def first_record_start_date if with_headers? - year = row_parsers.first.field_6.to_s.strip.length.between?(1, 2) ? row_parsers.first.field_6.to_i + 2000 : row_parsers.first.field_6.to_i - Date.new(year, row_parsers.first.field_5.to_i, row_parsers.first.field_4.to_i) + year = row_parsers.first.field_3.to_s.strip.length.between?(1, 2) ? row_parsers.first.field_3.to_i + 2000 : row_parsers.first.field_3.to_i + Date.new(year, row_parsers.first.field_2.to_i, row_parsers.first.field_1.to_i) else - year = rows.first[5].to_s.strip.length.between?(1, 2) ? rows.first[5].to_i + 2000 : rows.first[5].to_i - Date.new(year, rows.first[4].to_i, rows.first[3].to_i) + year = rows.first[2].to_s.strip.length.between?(1, 2) ? rows.first[2].to_i + 2000 : rows.first[2].to_i + Date.new(year, rows.first[1].to_i, rows.first[0].to_i) end end end diff --git a/app/services/bulk_upload/sales/year2025/row_parser.rb b/app/services/bulk_upload/sales/year2025/row_parser.rb index 35ab2189a..5768dfefa 100644 --- a/app/services/bulk_upload/sales/year2025/row_parser.rb +++ b/app/services/bulk_upload/sales/year2025/row_parser.rb @@ -5,12 +5,12 @@ class BulkUpload::Sales::Year2025::RowParser include FormattingHelper QUESTIONS = { - field_1: "Which organisation owned this property before the sale?", - field_2: "Which organisation is reporting this sale?", - field_3: "Username", - field_4: "What is the day of the sale completion date? - DD", - field_5: "What is the month of the sale completion date? - MM", - field_6: "What is the year of the sale completion date? - YY", + field_1: "What is the day of the sale completion date? - DD", + field_2: "What is the month of the sale completion date? - MM", + field_3: "What is the year of the sale completion date? - YY", + field_4: "Which organisation owned this property before the sale?", + field_5: "Which organisation is reporting this sale?", + field_6: "Username", field_7: "What is the purchaser code?", field_8: "What is the sale type?", field_9: "What is the type of shared ownership sale?", @@ -144,12 +144,12 @@ class BulkUpload::Sales::Year2025::RowParser attribute :field_blank - attribute :field_1, :string - attribute :field_2, :string - attribute :field_3, :string - attribute :field_4, :integer - attribute :field_5, :integer - attribute :field_6, :integer + attribute :field_1, :integer + attribute :field_2, :integer + attribute :field_3, :integer + attribute :field_4, :string + attribute :field_5, :string + attribute :field_6, :string attribute :field_7, :string attribute :field_8, :integer attribute :field_9, :integer @@ -196,7 +196,7 @@ class BulkUpload::Sales::Year2025::RowParser attribute :field_47, :string attribute :field_48, :string attribute :field_49, :integer - attribute :field_49, :integer + attribute :field_50, :integer attribute :field_51, :string attribute :field_52, :string attribute :field_53, :integer @@ -244,6 +244,8 @@ class BulkUpload::Sales::Year2025::RowParser attribute :field_91, :integer attribute :field_92, :integer attribute :field_93, :decimal + attribute :field_94, :decimal + attribute :field_95, :decimal attribute :field_96, :integer attribute :field_97, :integer @@ -273,20 +275,20 @@ class BulkUpload::Sales::Year2025::RowParser attribute :field_120, :integer attribute :field_121, :integer - validates :field_4, + validates :field_1, presence: { message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "sale completion date (day)."), category: :setup, }, on: :after_log - validates :field_5, + validates :field_2, presence: { message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "sale completion date (month)."), category: :setup, }, on: :after_log - validates :field_6, + validates :field_3, presence: { message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "sale completion date (year)."), category: :setup, @@ -295,7 +297,7 @@ class BulkUpload::Sales::Year2025::RowParser with: /\A(\d{2}|\d{4})\z/, message: I18n.t("#{ERROR_BASE_KEY}.saledate.year_not_two_or_four_digits"), category: :setup, - if: proc { field_6.present? }, + if: proc { field_3.present? }, }, on: :after_log validates :field_8, @@ -390,565 +392,6 @@ class BulkUpload::Sales::Year2025::RowParser }, on: :after_log - validates :field_18, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "type of building."), - category: :setup, - if: :shared_or_discounted_but_not_staircasing?, - }, - on: :after_log - - validates :field_27, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "meets wheelchair standards."), - category: :setup, - if: :shared_or_discounted_but_not_staircasing?, - }, - on: :after_log - - validates :field_30, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "buyer 1 ethnicity."), - category: :setup, - if: :shared_or_discounted_but_not_staircasing?, - }, - on: :after_log - - validates :field_31, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "buyer 1 nationality."), - category: :setup, - if: :shared_or_discounted_but_not_staircasing?, - }, - on: :after_log - - validates :field_32, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "buyer 1 working situation."), - category: :setup, - if: :shared_or_discounted_but_not_staircasing?, - }, - on: :after_log - - validates :field_33, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "whether buyer 1 will live in the property."), - category: :setup, - if: :shared_or_discounted_but_not_staircasing?, - }, - on: :after_log - - validates :field_37, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "buyer 2 ethnic background."), - category: :setup, - if: :shared_or_discounted_but_not_staircasing?, - }, - on: :after_log - - validates :field_38, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "buyer 2 nationality."), - category: :setup, - if: :shared_or_discounted_but_not_staircasing?, - }, - on: :after_log - - validates :field_39, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "buyer 2 working situation."), - category: :setup, - if: :shared_or_discounted_but_not_staircasing?, - }, - on: :after_log - - validates :field_40, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "whether buyer 2 will live in the property."), - category: :setup, - if: :shared_or_discounted_but_not_staircasing?, - }, - on: :after_log - - validates :field_41, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "number of other people living in the property."), - category: :setup, - unless: :staircasing?, - }, - on: :after_log - - validates :field_58, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "buyer 1's previous tenure."), - category: :setup, - unless: :staircasing?, - }, - on: :after_log - - validates :field_59, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "buyer 1's last settled accommodation."), - category: :setup, - unless: :discounted_ownership || :staircasing?, - }, - on: :after_log - - validates :field_63, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "whether buyer 2 was living with buyer 1."), - category: :setup, - if: :shared_or_discounted_but_not_staircasing?, - }, - on: :after_log - - validates :field_64, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "buyer 2's previous tenure."), - category: :setup, - if: :shared_or_discounted_but_not_staircasing? && :two_buyers_share_address?, - }, - on: :after_log - - validates :field_65, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "whether a buyer has served in the armed forces."), - category: :setup, - unless: :staircasing?, - }, - on: :after_log - - validates :field_66, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "whether a buyer is currently in the armed forces."), - category: :setup, - unless: :staircasing?, - }, - on: :after_log - - validates :field_67, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "whether a buyer's spouse recently died in service."), - category: :setup, - unless: :staircasing?, - }, - on: :after_log - - validates :field_68, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "whether any buyer has a disability."), - category: :setup, - unless: :staircasing?, - }, - on: :after_log - - validates :field_69, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "whether any buyer uses a wheelchair."), - category: :setup, - unless: :staircasing?, - }, - on: :after_log - - validates :field_70, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "buyer 1's annual income."), - category: :setup, - unless: :staircasing?, - }, - on: :after_log - - validates :field_72, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "buyer 2's annual income."), - category: :setup, - if: :joint_purchase, - unless: :staircasing?, - }, - on: :after_log - - validates :field_74, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "whether buyers were receiving housing benefits."), - category: :setup, - unless: :staircasing?, - }, - on: :after_log - - validates :field_75, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "the buyers' total savings."), - category: :setup, - unless: :staircasing?, - }, - on: :after_log - - validates :field_76, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "whether the buyers have previously owned a property."), - category: :setup, - unless: :staircasing?, - }, - on: :after_log - - validates :field_78, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "whether this is a resale."), - category: :setup, - if: :shared_or_discounted_but_not_staircasing?, - }, - on: :after_log - - validates :field_79, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "how long the buyer lived there prior to purchase."), - category: :setup, - if: :shared_ownership_initial_purchase? && :not_resale?, - }, - on: :after_log - - validates :field_80, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "day of practical completion or handover."), - category: :setup, - if: :shared_ownership_initial_purchase? && :not_resale?, - }, - on: :after_log - - validates :field_81, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "month of practical completion or handover."), - category: :setup, - if: :shared_ownership_initial_purchase? && :not_resale?, - }, - on: :after_log - - validates :field_82, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "year of practical completion or handover."), - category: :setup, - if: :shared_ownership_initial_purchase? && :not_resale?, - }, - on: :after_log - - validates :field_83, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "number of bedrooms in previous property."), - category: :setup, - if: :shared_ownership_initial_purchase? && :buyer_1_previous_tenure_not_1_or_2?, - }, - on: :after_log - - validates :field_84, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "previous property type."), - category: :setup, - if: :shared_ownership_initial_purchase? && :buyer_1_previous_tenure_not_1_or_2?, - }, - on: :after_log - - validates :field_85, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "buyer's previous tenure."), - category: :setup, - if: :shared_ownership_initial_purchase? && :buyer_1_previous_tenure_not_1_or_2?, - }, - on: :after_log - - validates :field_86, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "full purchase price."), - category: :setup, - if: :shared_ownership_initial_purchase?, - }, - on: :after_log - - validates :field_87, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "initial percentage share purchased."), - category: :setup, - if: :shared_ownership_initial_purchase?, - }, - on: :after_log - - validates :field_88, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "whether a mortgage was used."), - category: :setup, - if: :shared_ownership_initial_purchase?, - }, - on: :after_log - - validates :field_88, - inclusion: { - in: [1, 2], - if: proc { field_88.present? }, - category: :setup, - question: QUESTIONS[:field_88].downcase, - }, - on: :before_log - - validates :field_89, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "mortgage amount."), - category: :setup, - if: :shared_ownership_initial_purchase? && :mortgage_used?, - }, - on: :after_log - - validates :field_90, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "mortgage length."), - category: :setup, - if: :shared_ownership_initial_purchase? && :mortgage_used?, - }, - on: :after_log - - validates :field_91, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "deposit amount."), - category: :setup, - if: :shared_ownership_initial_purchase?, - }, - on: :after_log - - validates :field_92, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "deposit amount."), - category: :setup, - if: :shared_ownership_initial_purchase?, - unless: :social_homebuy?, - }, - on: :after_log - - validates :field_93, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "basic monthly rent."), - category: :setup, - if: :shared_ownership_initial_purchase?, - }, - on: :after_log - - validates :field_94, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "monthly service charges."), - category: :setup, - if: :shared_ownership_initial_purchase?, - }, - on: :after_log - - validates :field_95, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "monthly estate management fees."), - category: :setup, - if: :shared_ownership_initial_purchase?, - }, - on: :after_log - - validates :field_96, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "percentage of property bought this transaction."), - category: :setup, - if: :staircasing?, - }, - on: :after_log - - validates :field_97, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "total percentage of property buyers now own."), - category: :setup, - if: :staircasing?, - }, - on: :after_log - - validates :field_98, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "whether transaction is part of a back to back staircasing transaction."), - category: :setup, - if: :staircasing? && :buyers_own_all?, - }, - on: :after_log - - validates :field_99, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "whether it is the first time the buyer has engaged in staircasing."), - category: :setup, - if: :staircasing?, - }, - on: :after_log - - validates :field_99, - inclusion: { - in: [1, 2], - if: proc { field_99.present? }, - category: :setup, - question: QUESTIONS[:field_99].downcase, - }, - on: :before_log - - validates :field_100, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "day of the initial purchase of a share."), - category: :setup, - if: :staircasing?, - }, - on: :after_log - - validates :field_101, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "month of the initial purchase of a share."), - category: :setup, - if: :staircasing?, - }, - on: :after_log - - validates :field_102, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "year of the initial purchase of a share."), - category: :setup, - if: :staircasing?, - }, - on: :after_log - - validates :field_103, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "number of times buyer has engaged in staircasing."), - category: :setup, - if: :staircasing? && :buyer_staircased_before?, - }, - on: :after_log - - validates :field_103, - inclusion: { - in: [2, 3, 4, 5, 6, 7, 8, 9, 10], - if: proc { field_103.present? }, - category: :setup, - question: QUESTIONS[:field_103].downcase, - }, - on: :before_log - - validates :field_104, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "day of last staircasing transaction."), - category: :setup, - if: :staircasing? && :buyer_staircased_before?, - }, - on: :after_log - - validates :field_105, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "month of last staircasing transaction."), - category: :setup, - if: :staircasing? && :buyer_staircased_before?, - }, - on: :after_log - - validates :field_106, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "year of last staircasing transaction."), - category: :setup, - if: :staircasing? && :buyer_staircased_before?, - }, - on: :after_log - - validates :field_107, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "full purchase price."), - category: :setup, - if: :staircasing?, - }, - on: :after_log - - validates :field_108, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "percentage share purchased initially."), - category: :setup, - if: :staircasing?, - }, - on: :after_log - - validates :field_109, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "whether a mortgage was used."), - category: :setup, - if: :staircasing?, - }, - on: :after_log - - validates :field_110, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "basic monthly rent before staircasing."), - category: :setup, - if: :staircasing?, - }, - on: :after_log - - validates :field_111, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "basic monthly rent after staircasing."), - category: :setup, - if: :staircasing?, - unless: :buyers_own_all?, - }, - on: :after_log - - validates :field_112, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "how long buyers lived in property before purchasing."), - category: :setup, - if: :discounted_ownership?, - }, - on: :after_log - - validates :field_113, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "full purchase price."), - category: :setup, - if: :discounted_ownership?, - }, - on: :after_log - - validates :field_114, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "amount of loan or subsidy."), - category: :setup, - if: :discounted_ownership?, - unless: :rtb_like_sale_type?, - }, - on: :after_log - - validates :field_115, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "percentage discount."), - category: :setup, - if: :discounted_ownership? && :rtb_like_sale_type?, - }, - on: :after_log - - validates :field_117, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "mortgage amount."), - category: :setup, - if: :discounted_ownership? && :mortgage_used?, - }, - on: :after_log - - validates :field_118, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "mortgage duration."), - category: :setup, - if: :discounted_ownership? && :mortgage_used?, - }, - on: :after_log - - validates :field_119, - presence: { - message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "whether any extra borrowing is included."), - category: :setup, - if: :discounted_ownership? && :mortgage_used?, - }, - on: :after_log - validate :validate_buyer1_economic_status, on: :before_log validate :validate_address_option_found, on: :after_log validate :validate_buyer2_economic_status, on: :before_log @@ -1052,10 +495,10 @@ class BulkUpload::Sales::Year2025::RowParser def spreadsheet_duplicate_hash attributes.slice( - "field_1", # owning org - "field_4", # saledate - "field_5", # saledate - "field_6", # saledate + "field_4", # owning org + "field_1", # saledate + "field_2", # saledate + "field_3", # saledate "field_7", # purchaser_code "field_24", # postcode "field_25", # postcode @@ -1202,13 +645,13 @@ private end def rtb_like_sale_type? - [9, 14, 27, 29].includes(field_11) + [9, 14, 27, 29].include?(field_11) end def field_mapping_for_errors { purchid: %i[field_7], - saledate: %i[field_4 field_5 field_6], + saledate: %i[field_1 field_2 field_3], noint: %i[field_14], age1_known: %i[field_28], age1: %i[field_28], @@ -1292,15 +735,13 @@ private mscharge: mscharge_fields, grant: %i[field_114], discount: %i[field_115], - owning_organisation_id: %i[field_1], - managing_organisation_id: [:field_2], - assigned_to: %i[field_3], + owning_organisation_id: %i[field_4], + managing_organisation_id: [:field_5], + assigned_to: %i[field_6], hhregres: %i[field_65], hhregresstill: %i[field_66], armedforcesspouse: %i[field_67], - mortgagelenderother: mortgagelenderother_fields, - hb: %i[field_74], mortlen: mortlen_fields, proplen: proplen_fields, @@ -1484,9 +925,6 @@ private attributes["hhregresstill"] = field_66 attributes["armedforcesspouse"] = field_67 - attributes["mortgagelender"] = mortgagelender - attributes["mortgagelenderother"] = mortgagelenderother - attributes["hb"] = field_74 attributes["mortlen"] = mortlen @@ -1552,8 +990,8 @@ private end def saledate - year = field_6.to_s.strip.length.between?(1, 2) ? field_6 + 2000 : field_6 - Date.new(year, field_5, field_4) if field_6.present? && field_5.present? && field_4.present? + year = field_3.to_s.strip.length.between?(1, 2) ? field_3 + 2000 : field_3 + Date.new(year, field_2, field_1) if field_3.present? && field_2.present? && field_1.present? rescue Date::Error Date.new end @@ -1777,11 +1215,11 @@ private end def owning_organisation - @owning_organisation ||= Organisation.find_by_id_on_multiple_fields(field_1) + @owning_organisation ||= Organisation.find_by_id_on_multiple_fields(field_4) end def assigned_to - @assigned_to ||= User.where("lower(email) = ?", field_3&.downcase).first + @assigned_to ||= User.where("lower(email) = ?", field_6&.downcase).first end def previous_la_known @@ -1825,11 +1263,11 @@ private end def validate_owning_org_data_given - if field_1.blank? + if field_4.blank? block_log_creation! - if errors[:field_1].blank? - errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "owning organisation."), category: :setup) + if errors[:field_4].blank? + errors.add(:field_4, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "owning organisation."), category: :setup) end end end @@ -1838,8 +1276,8 @@ private if owning_organisation.nil? block_log_creation! - if field_1.present? && errors[:field_1].blank? - errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_found"), category: :setup) + if field_4.present? && errors[:field_4].blank? + errors.add(:field_4, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_found"), category: :setup) end end end @@ -1848,8 +1286,8 @@ private if owning_organisation && !owning_organisation.holds_own_stock? block_log_creation! - if errors[:field_1].blank? - errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_stock_owner"), category: :setup) + if errors[:field_4].blank? + errors.add(:field_4, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_stock_owner"), category: :setup) end end end @@ -1860,26 +1298,26 @@ private block_log_creation! - return if errors[:field_1].present? + return if errors[:field_4].present? if bulk_upload.user.support? - errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_permitted.support", name: bulk_upload_organisation.name), category: :setup) + errors.add(:field_4, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_permitted.support", name: bulk_upload_organisation.name), category: :setup) else - errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_permitted.not_support"), category: :setup) + errors.add(:field_4, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_permitted.not_support"), category: :setup) end end def validate_assigned_to_exists - return if field_3.blank? + return if field_6.blank? unless assigned_to - errors.add(:field_3, I18n.t("#{ERROR_BASE_KEY}.assigned_to.not_found")) + errors.add(:field_6, I18n.t("#{ERROR_BASE_KEY}.assigned_to.not_found")) end end def validate_assigned_to_when_support - if field_3.blank? && bulk_upload.user.support? - 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?")) + if field_6.blank? && bulk_upload.user.support? + errors.add(:field_6, 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 @@ -1889,11 +1327,11 @@ private return if assigned_to.organisation == owning_organisation&.absorbing_organisation || assigned_to.organisation == managing_organisation&.absorbing_organisation block_log_creation! - errors.add(:field_3, I18n.t("#{ERROR_BASE_KEY}.assigned_to.organisation_not_related"), category: :setup) + errors.add(:field_6, I18n.t("#{ERROR_BASE_KEY}.assigned_to.organisation_not_related"), category: :setup) end def managing_organisation - Organisation.find_by_id_on_multiple_fields(field_2) + Organisation.find_by_id_on_multiple_fields(field_5) end def nationality_group(nationality_value) @@ -1908,8 +1346,8 @@ private if owning_organisation && managing_organisation && !owning_organisation.can_be_managed_by?(organisation: managing_organisation) block_log_creation! - if errors[:field_2].blank? - errors.add(:field_2, I18n.t("#{ERROR_BASE_KEY}.assigned_to.managing_organisation_not_related"), category: :setup) + if errors[:field_5].blank? + errors.add(:field_5, I18n.t("#{ERROR_BASE_KEY}.assigned_to.managing_organisation_not_related"), category: :setup) end end end @@ -1973,12 +1411,12 @@ private def validate_relevant_collection_window return if saledate.blank? || bulk_upload.form.blank? - return if errors.key?(:field_4) || errors.key?(:field_5) || errors.key?(:field_6) + return if errors.key?(:field_1) || errors.key?(:field_2) || errors.key?(:field_3) unless bulk_upload.form.valid_start_date_for_form?(saledate) - 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("#{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("#{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_1, 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_2, 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_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) end end @@ -1986,10 +1424,10 @@ private if log_already_exists? error_message = I18n.t("#{ERROR_BASE_KEY}.duplicate") - errors.add(:field_1, error_message) # Owning org - errors.add(:field_4, error_message) # Sale completion date - errors.add(:field_5, error_message) # Sale completion date - errors.add(:field_6, error_message) # Sale completion date + errors.add(:field_4, error_message) # Owning org + errors.add(:field_1, error_message) # Sale completion date + errors.add(:field_2, error_message) # Sale completion date + errors.add(:field_3, error_message) # Sale completion date errors.add(:field_24, error_message) # Postcode errors.add(:field_25, error_message) # Postcode errors.add(:field_28, error_message) # Buyer 1 age diff --git a/spec/services/bulk_upload/sales/year2025/csv_parser_spec.rb b/spec/services/bulk_upload/sales/year2025/csv_parser_spec.rb index d0f27cbbf..7031b0dbe 100644 --- a/spec/services/bulk_upload/sales/year2025/csv_parser_spec.rb +++ b/spec/services/bulk_upload/sales/year2025/csv_parser_spec.rb @@ -27,7 +27,7 @@ RSpec.describe BulkUpload::Sales::Year2025::CsvParser do end it "parses csv correctly" do - expect(service.row_parsers[0].field_22).to eql(log.uprn) + expect(service.row_parsers[0].field_19).to eql(log.uprn) end it "counts the number of valid field numbers correctly" do @@ -59,7 +59,7 @@ RSpec.describe BulkUpload::Sales::Year2025::CsvParser do end it "parses csv correctly" do - expect(service.row_parsers[0].field_22).to eql(log.uprn) + expect(service.row_parsers[0].field_19).to eql(log.uprn) end it "counts the number of valid field numbers correctly" do @@ -92,7 +92,7 @@ RSpec.describe BulkUpload::Sales::Year2025::CsvParser do end it "parses csv correctly" do - expect(service.row_parsers[0].field_22).to eql(log.uprn) + expect(service.row_parsers[0].field_19).to eql(log.uprn) end end @@ -112,7 +112,7 @@ RSpec.describe BulkUpload::Sales::Year2025::CsvParser do end it "parses csv correctly" do - expect(service.row_parsers[0].field_22).to eql(log.uprn) + expect(service.row_parsers[0].field_19).to eql(log.uprn) end end @@ -129,7 +129,7 @@ RSpec.describe BulkUpload::Sales::Year2025::CsvParser do end it "parses csv correctly" do - expect(service.row_parsers[0].field_22).to eql(log.uprn) + expect(service.row_parsers[0].field_19).to eql(log.uprn) end end @@ -146,7 +146,7 @@ RSpec.describe BulkUpload::Sales::Year2025::CsvParser do end it "parses csv correctly" do - expect(service.row_parsers[0].field_22).to eql(log.uprn) + expect(service.row_parsers[0].field_19).to eql(log.uprn) end end @@ -185,7 +185,7 @@ RSpec.describe BulkUpload::Sales::Year2025::CsvParser do end it "parses csv correctly" do - expect(service.row_parsers[0].field_22).to eql(log.uprn) + expect(service.row_parsers[0].field_19).to eql(log.uprn) end end end diff --git a/spec/services/bulk_upload/sales/year2025/row_parser_spec.rb b/spec/services/bulk_upload/sales/year2025/row_parser_spec.rb index 532b24e8f..0e0874bfe 100644 --- a/spec/services/bulk_upload/sales/year2025/row_parser_spec.rb +++ b/spec/services/bulk_upload/sales/year2025/row_parser_spec.rb @@ -14,12 +14,12 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do let(:setup_section_params) do { bulk_upload:, - field_1: owning_org.old_visible_id, # organisation - field_2: managing_org.old_visible_id, # organisation - field_3: user.email, # user - field_4: now.day.to_s, # sale day - field_5: now.month.to_s, # sale month - field_6: now.strftime("%g"), # sale year + field_1: now.day.to_s, # sale day + field_2: now.month.to_s, # sale month + field_3: now.strftime("%g"), # sale year + field_4: owning_org.old_visible_id, # organisation + field_5: managing_org.old_visible_id, # organisation + field_6: user.email, # user field_7: "test id", # purchase id field_8: "1", # owhershipsch field_9: "2", # shared ownership sale type @@ -32,12 +32,11 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do let(:valid_attributes) do { bulk_upload:, - field_1: owning_org.old_visible_id, - field_2: managing_org.old_visible_id, - - field_4: "12", - field_5: "5", - field_6: "24", + field_1: "12", + field_2: "5", + field_3: "25", + field_4: owning_org.old_visible_id, + field_5: managing_org.old_visible_id, field_7: "test id", field_8: "1", field_9: "2", @@ -93,26 +92,33 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do field_83: "1", field_84: "1", field_85: "1", - field_86: "250000", - field_87: "25", - field_88: "1", + field_107: "250000", + field_108: "25", + field_109: "1", field_89: "5000", field_90: "20", - field_91: "30", - field_92: "3", - field_93: "2022", field_96: "10", field_97: "40", field_98: "1", + field_99: "2", field_94: "200", - field_120: "20000", + field_91: "20000", + field_111: "800", + field_100: "05", + field_101: "04", + field_102: "2020", + field_103: "4", + field_104: "06", + field_105: "07", + field_106: "2023", + field_110: "900", } end around do |example| create(:organisation_relationship, parent_organisation: owning_org, child_organisation: managing_org) - Timecop.freeze(Time.zone.local(2025, 2, 22)) do + Timecop.freeze(Time.zone.local(2026, 2, 22)) do Singleton.__init__(FormHandler) example.run end @@ -127,7 +133,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do context "when any field is populated" do before do - parser.field_1 = "1" + parser.field_4 = "1" end it "returns false" do @@ -308,7 +314,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do end context "when an invalid value error has been added" do - let(:attributes) { setup_section_params.merge({ field_32: "100" }) } + let(:attributes) { setup_section_params.merge({ field_10: "2", field_32: "100" }) } it "does not add an additional error" do parser.valid? @@ -332,7 +338,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do errors = parser.errors.select { |e| e.options[:category] == :setup }.map(&:attribute).sort - expect(errors).to eql(%i[field_1 field_14 field_15 field_2 field_4 field_5 field_6 field_8]) + expect(errors).to eql(%i[field_1 field_14 field_15 field_2 field_3 field_4 field_5 field_8]) end end @@ -350,7 +356,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do errors = parser.errors.select { |e| e.options[:category] == :setup }.map(&:attribute).sort - expect(errors).to eql(%i[field_1 field_12 field_14 field_15 field_2 field_4 field_5 field_6 field_9]) + expect(errors).to eql(%i[field_1 field_10 field_12 field_14 field_15 field_2 field_3 field_4 field_5 field_9]) end end @@ -370,7 +376,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do errors = parser.errors.select { |e| e.options[:category] == :setup }.map(&:attribute).sort - expect(errors).to eql(%i[field_1 field_13 field_14 field_15 field_2 field_4 field_5 field_6]) + expect(errors).to eql(%i[field_1 field_10 field_13 field_14 field_15 field_2 field_3 field_4 field_5]) end end @@ -380,7 +386,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do bulk_upload:, field_7: "test id", field_8: "2", - field_10: nil, + field_11: nil, } end @@ -389,7 +395,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do errors = parser.errors.select { |e| e.options[:category] == :setup }.map(&:attribute).sort - expect(errors).to eql(%i[field_1 field_10 field_12 field_14 field_15 field_2 field_4 field_5 field_6]) + expect(errors).to eql(%i[field_1 field_11 field_12 field_14 field_15 field_2 field_3 field_4 field_5]) end end @@ -408,17 +414,17 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do errors = parser.errors.select { |e| e.options[:category] == :setup }.map(&:attribute).sort - expect(errors).to eql(%i[field_1 field_14 field_15 field_2 field_4 field_5 field_6 field_8]) + expect(errors).to eql(%i[field_1 field_14 field_15 field_2 field_3 field_4 field_5 field_8]) end end - describe "#field_1" do # owning org + describe "#field_4" do # owning org context "when no data given" do - let(:attributes) { setup_section_params.merge(field_1: nil) } + let(:attributes) { setup_section_params.merge(field_4: nil) } it "is not permitted as setup error" do parser.valid? - expect(parser.errors.where(:field_1, category: :setup).map(&:message)).to eql([I18n.t("validations.sales.2025.bulk_upload.not_answered", question: "owning organisation.")]) + expect(parser.errors.where(:field_4, category: :setup).map(&:message)).to eql([I18n.t("validations.sales.2025.bulk_upload.not_answered", question: "owning organisation.")]) end it "blocks log creation" do @@ -428,11 +434,11 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do end context "when cannot find owning org" do - let(:attributes) { { bulk_upload:, field_1: "donotexist" } } + let(:attributes) { { bulk_upload:, field_4: "donotexist" } } it "is not permitted as a setup error" do parser.valid? - expect(parser.errors.where(:field_1, category: :setup).map(&:message)).to eql([I18n.t("validations.sales.2025.bulk_upload.owning_organisation.not_found")]) + expect(parser.errors.where(:field_4, category: :setup).map(&:message)).to eql([I18n.t("validations.sales.2025.bulk_upload.owning_organisation.not_found")]) end it "blocks log creation" do @@ -444,11 +450,11 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do context "when not affiliated with owning org" do let(:unaffiliated_org) { create(:organisation, :with_old_visible_id) } - let(:attributes) { { bulk_upload:, field_1: unaffiliated_org.old_visible_id } } + let(:attributes) { { bulk_upload:, field_4: unaffiliated_org.old_visible_id } } it "is not permitted as setup error" do parser.valid? - expect(parser.errors.where(:field_1, category: :setup).map(&:message)).to eql([I18n.t("validations.sales.2025.bulk_upload.owning_organisation.not_permitted.not_support")]) + expect(parser.errors.where(:field_4, category: :setup).map(&:message)).to eql([I18n.t("validations.sales.2025.bulk_upload.owning_organisation.not_permitted.not_support")]) end it "blocks log creation" do @@ -461,7 +467,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do let(:merged_org) { create(:organisation, :with_old_visible_id, holds_own_stock: true) } let(:merged_org_stock_owner) { create(:organisation, :with_old_visible_id, holds_own_stock: true) } - let(:attributes) { { bulk_upload:, field_1: merged_org_stock_owner.old_visible_id } } + let(:attributes) { { bulk_upload:, field_4: merged_org_stock_owner.old_visible_id } } before do create(:organisation_relationship, parent_organisation: merged_org_stock_owner, child_organisation: merged_org) @@ -472,14 +478,14 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do it "is permitted" do parser.valid? - expect(parser.errors.where(:field_1)).not_to be_present + expect(parser.errors.where(:field_4)).not_to be_present end end context "when user's org has absorbed owning organisation" do let(:merged_org) { create(:organisation, :with_old_visible_id, holds_own_stock: true) } - let(:attributes) { { bulk_upload:, field_1: merged_org.old_visible_id, field_3: user.email } } + let(:attributes) { { bulk_upload:, field_4: merged_org.old_visible_id, field_6: user.email } } before do merged_org.update!(absorbing_organisation: user.organisation, merge_date: Time.zone.today) @@ -492,15 +498,15 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do parser = described_class.new(attributes) parser.valid? - expect(parser.errors.where(:field_1)).not_to be_present - expect(parser.errors.where(:field_3)).not_to be_present + expect(parser.errors.where(:field_4)).not_to be_present + expect(parser.errors.where(:field_6)).not_to be_present end end context "when user's org has absorbed owning organisation before the startdate" do let(:merged_org) { create(:organisation, :with_old_visible_id, holds_own_stock: true) } - let(:attributes) { setup_section_params.merge({ field_1: merged_org.old_visible_id, field_3: user.email }) } + let(:attributes) { setup_section_params.merge({ field_4: merged_org.old_visible_id, field_6: user.email }) } before do merged_org.update!(absorbing_organisation: user.organisation, merge_date: Time.zone.today - 3.years) @@ -513,17 +519,17 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do parser = described_class.new(attributes) parser.valid? - expect(parser.errors[:field_1]).to include(/The owning organisation must be active on the sale completion date/) - expect(parser.errors[:field_4]).to include(/Enter a date when the owning organisation was active/) - expect(parser.errors[:field_5]).to include(/Enter a date when the owning organisation was active/) - expect(parser.errors[:field_6]).to include(/Enter a date when the owning organisation was active/) + expect(parser.errors[:field_4]).to include(/The owning organisation must be active on the sale completion date/) + expect(parser.errors[:field_1]).to include(/Enter a date when the owning organisation was active/) + expect(parser.errors[:field_2]).to include(/Enter a date when the owning organisation was active/) + expect(parser.errors[:field_3]).to include(/Enter a date when the owning organisation was active/) end end context "when user is an unaffiliated non-support user and bulk upload organisation is affiliated with the owning organisation" do let(:affiliated_org) { create(:organisation, :with_old_visible_id) } let(:unaffiliated_user) { create(:user, organisation: create(:organisation)) } - let(:attributes) { { bulk_upload:, field_1: affiliated_org.old_visible_id } } + let(:attributes) { { bulk_upload:, field_4: affiliated_org.old_visible_id } } let(:organisation_id) { unaffiliated_user.organisation_id } before do @@ -531,18 +537,18 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do bulk_upload.update!(organisation_id:, user: unaffiliated_user) end - it "blocks log creation and adds an error to field_1" do + it "blocks log creation and adds an error to field_4" do parser = described_class.new(attributes) parser.valid? expect(parser).to be_block_log_creation - expect(parser.errors[:field_1]).to include(I18n.t("validations.sales.2025.bulk_upload.owning_organisation.not_permitted.not_support")) + expect(parser.errors[:field_4]).to include(I18n.t("validations.sales.2025.bulk_upload.owning_organisation.not_permitted.not_support")) end end context "when user is an unaffiliated support user and bulk upload organisation is affiliated with the owning organisation" do let(:affiliated_org) { create(:organisation, :with_old_visible_id) } let(:unaffiliated_support_user) { create(:user, :support, organisation: create(:organisation)) } - let(:attributes) { { bulk_upload:, field_1: affiliated_org.old_visible_id } } + let(:attributes) { { bulk_upload:, field_4: affiliated_org.old_visible_id } } let(:organisation_id) { affiliated_org.id } before do @@ -550,21 +556,21 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do bulk_upload.update!(organisation_id:, user: unaffiliated_support_user) end - 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_4" do parser = described_class.new(attributes) parser.valid? - expect(parser.errors[:field_1]).not_to include(I18n.t("validations.sales.2025.bulk_upload.owning_organisation.not_permitted.not_support")) + expect(parser.errors[:field_4]).not_to include(I18n.t("validations.sales.2025.bulk_upload.owning_organisation.not_permitted.not_support")) end end end - describe "#field_3" do # username for assigned_to + describe "#field_6" do # username for assigned_to context "when blank" do - let(:attributes) { setup_section_params.merge(bulk_upload:, field_3: nil) } + let(:attributes) { setup_section_params.merge(bulk_upload:, field_6: nil) } it "is permitted" do parser.valid? - expect(parser.errors[:field_3]).to be_blank + expect(parser.errors[:field_6]).to be_blank end it "sets assigned to to bulk upload user" do @@ -581,12 +587,12 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do context "when blank and bulk upload user is support" do let(:bulk_upload) { create(:bulk_upload, :sales, user: create(:user, :support), year: 2025) } - let(:attributes) { setup_section_params.merge(bulk_upload:, field_3: nil) } + let(:attributes) { setup_section_params.merge(bulk_upload:, field_6: nil) } it "is not permitted" do parser.valid? - expect(parser.errors[:field_3]).to be_present - expect(parser.errors[:field_3]).to include(I18n.t("validations.sales.2025.bulk_upload.not_answered", question: "what is the CORE username of the account this sales log should be assigned to?")) + expect(parser.errors[:field_6]).to be_present + expect(parser.errors[:field_6]).to include(I18n.t("validations.sales.2025.bulk_upload.not_answered", question: "what is the CORE username of the account this sales log should be assigned to?")) end it "blocks log creation" do @@ -596,22 +602,22 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do end context "when user could not be found" do - let(:attributes) { { bulk_upload:, field_3: "idonotexist@example.com" } } + let(:attributes) { { bulk_upload:, field_6: "idonotexist@example.com" } } it "is not permitted" do parser.valid? - expect(parser.errors[:field_3]).to be_present + expect(parser.errors[:field_6]).to be_present end end context "when an unaffiliated user" do let(:other_user) { create(:user) } - let(:attributes) { { bulk_upload:, field_1: owning_org.old_visible_id, field_3: other_user.email } } + let(:attributes) { { bulk_upload:, field_4: owning_org.old_visible_id, field_6: other_user.email } } it "is not permitted as a setup error" do parser.valid? - expect(parser.errors.where(:field_3, category: :setup)).to be_present + expect(parser.errors.where(:field_6, category: :setup)).to be_present end it "blocks log creation" do @@ -623,11 +629,11 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do context "when a user part of owning org" do let(:other_user) { create(:user, organisation: owning_org) } - let(:attributes) { { bulk_upload:, field_1: owning_org.old_visible_id, field_3: other_user.email } } + let(:attributes) { { bulk_upload:, field_4: owning_org.old_visible_id, field_6: other_user.email } } it "is permitted" do parser.valid? - expect(parser.errors[:field_3]).to be_blank + expect(parser.errors[:field_6]).to be_blank end it "sets assigned to to the user" do @@ -644,59 +650,59 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do context "when email matches other than casing" do let(:other_user) { create(:user, organisation: owning_org) } - let(:attributes) { { bulk_upload:, field_1: owning_org.old_visible_id, field_3: other_user.email.upcase! } } + let(:attributes) { { bulk_upload:, field_4: owning_org.old_visible_id, field_6: other_user.email.upcase! } } it "is permitted" do parser.valid? - expect(parser.errors[:field_3]).to be_blank + expect(parser.errors[:field_6]).to be_blank end end end - describe "fields 3, 4, 5 => saledate" do + describe "fields 1, 2, 3 => saledate" do context "when all of these fields are blank" do - let(:attributes) { setup_section_params.merge({ field_4: nil, field_5: nil, field_6: nil }) } + let(:attributes) { setup_section_params.merge({ field_1: nil, field_2: nil, field_3: nil }) } it "returns them as setup errors" do parser.valid? - expect(parser.errors.where(:field_4, category: :setup)).to be_present - expect(parser.errors.where(:field_5, category: :setup)).to be_present - expect(parser.errors.where(:field_6, category: :setup)).to be_present + expect(parser.errors.where(:field_1, category: :setup)).to be_present + expect(parser.errors.where(:field_2, category: :setup)).to be_present + expect(parser.errors.where(:field_3, category: :setup)).to be_present end end context "when one of these fields is blank" do - let(:attributes) { setup_section_params.merge({ field_4: "1", field_5: "1", field_6: nil }) } + let(:attributes) { setup_section_params.merge({ field_1: "1", field_2: "1", field_3: nil }) } it "returns an error only on blank field as setup error" do parser.valid? - expect(parser.errors[:field_4]).to be_blank - expect(parser.errors[:field_5]).to be_blank - expect(parser.errors.where(:field_6, category: :setup)).to be_present + expect(parser.errors[:field_1]).to be_blank + expect(parser.errors[:field_2]).to be_blank + expect(parser.errors.where(:field_3, category: :setup)).to be_present end end - context "when field 6 is 4 digits instead of 2" do - let(:attributes) { setup_section_params.merge({ bulk_upload:, field_6: "2025" }) } + context "when field 3 is 4 digits instead of 2" do + let(:attributes) { setup_section_params.merge({ bulk_upload:, field_3: "2025" }) } it "correctly sets the date" do parser.valid? - expect(parser.errors.where(:field_6, category: :setup)).to be_empty + expect(parser.errors.where(:field_3, category: :setup)).to be_empty expect(parser.log.saledate).to eq(Time.zone.local(2025, 5, 1)) end end - context "when field 5 is not 2 or 4 digits" do - let(:attributes) { setup_section_params.merge({ bulk_upload:, field_6: "202" }) } + context "when field 2 is not 2 or 4 digits" do + let(:attributes) { setup_section_params.merge({ bulk_upload:, field_3: "202" }) } it "returns a setup error" do parser.valid? - expect(parser.errors.where(:field_6, category: :setup).map(&:message)).to include(I18n.t("validations.sales.2025.bulk_upload.saledate.year_not_two_or_four_digits")) + expect(parser.errors.where(:field_3, category: :setup).map(&:message)).to include(I18n.t("validations.sales.2025.bulk_upload.saledate.year_not_two_or_four_digits")) end end context "when invalid date given" do - let(:attributes) { setup_section_params.merge({ field_4: "a", field_5: "12", field_6: "2023" }) } + let(:attributes) { setup_section_params.merge({ field_1: "a", field_2: "12", field_3: "2023" }) } it "does not raise an error" do expect { parser.valid? }.not_to raise_error @@ -710,15 +716,15 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do end end - let(:attributes) { setup_section_params.merge({ field_4: "1", field_5: "10", field_6: "24" }) } + let(:attributes) { setup_section_params.merge({ field_1: "1", field_2: "10", field_3: "25" }) } let(:bulk_upload) { create(:bulk_upload, :sales, user:, year: 2025) } it "does not return errors" do parser.valid? - expect(parser.errors[:field_4]).not_to be_present - expect(parser.errors[:field_5]).not_to be_present - expect(parser.errors[:field_6]).not_to be_present + expect(parser.errors[:field_1]).not_to be_present + expect(parser.errors[:field_2]).not_to be_present + expect(parser.errors[:field_3]).not_to be_present end end @@ -729,15 +735,15 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do end end - let(:attributes) { setup_section_params.merge({ field_4: "1", field_5: "1", field_6: "22" }) } + let(:attributes) { setup_section_params.merge({ field_1: "1", field_2: "1", field_3: "22" }) } let(:bulk_upload) { create(:bulk_upload, :sales, user:, year: 2023) } it "returns setup errors" do parser.valid? - expect(parser.errors.where(:field_4, category: :setup)).to be_present - expect(parser.errors.where(:field_5, category: :setup)).to be_present - expect(parser.errors.where(:field_6, category: :setup)).to be_present + expect(parser.errors.where(:field_1, category: :setup)).to be_present + expect(parser.errors.where(:field_2, category: :setup)).to be_present + expect(parser.errors.where(:field_3, category: :setup)).to be_present end end end @@ -760,10 +766,10 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do error_message = I18n.t("validations.sales.2025.bulk_upload.duplicate") [ - :field_1, # Owning org - :field_4, # Sale completion date - :field_5, # Sale completion date - :field_6, # Sale completion date + :field_4, # Owning org + :field_1, # Sale completion date + :field_2, # Sale completion date + :field_3, # Sale completion date :field_24, # Postcode :field_25, # Postcode :field_28, # Buyer 1 age @@ -790,10 +796,10 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do parser.valid? [ - :field_1, # Owning org - :field_4, # Sale completion date - :field_5, # Sale completion date - :field_6, # Sale completion date + :field_4, # Owning org + :field_1, # Sale completion date + :field_2, # Sale completion date + :field_3, # Sale completion date :field_24, # Postcode :field_25, # Postcode :field_28, # Buyer 1 age @@ -828,42 +834,42 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do end end - describe "#field_10" do # type for discounted sale + describe "#field_11" do # type for discounted sale context "when an invalid option" do - let(:attributes) { setup_section_params.merge({ field_10: "100" }) } + let(:attributes) { setup_section_params.merge({ field_11: "100" }) } it "returns setup error" do parser.valid? - expect(parser.errors.where(:field_10, category: :setup)).to be_present + expect(parser.errors.where(:field_11, category: :setup)).to be_present end end end - describe "#field_116" do # percentage discount + describe "#field_115" do # percentage discount context "when percentage discount over 70" do - let(:attributes) { valid_attributes.merge({ field_8: "2", field_116: "71" }) } + let(:attributes) { valid_attributes.merge({ field_8: "2", field_10: "2", field_11: "9", field_115: "71" }) } it "returns correct error" do parser.valid? - expect(parser.errors.where(:field_116).map(&:message)).to include(I18n.t("validations.sales.2025.bulk_upload.numeric.within_range", field: "Percentage discount", min: "0%", max: "70%")) + expect(parser.errors.where(:field_115).map(&:message)).to include(I18n.t("validations.sales.2025.bulk_upload.numeric.within_range", field: "Percentage discount", min: "0%", max: "70%")) end end context "when percentage discount not over 70" do - let(:attributes) { valid_attributes.merge({ field_8: "2", field_116: "70" }) } + let(:attributes) { valid_attributes.merge({ field_8: "2", field_10: "2", field_115: "70" }) } it "does not return error" do parser.valid? - expect(parser.errors.where(:field_116)).not_to be_present + expect(parser.errors.where(:field_115)).not_to be_present end end context "when percentage less than 0" do - let(:attributes) { valid_attributes.merge({ field_8: "2", field_116: "-1" }) } + let(:attributes) { valid_attributes.merge({ field_8: "2", field_10: "2", field_115: "-1" }) } it "returns correct error" do parser.valid? - expect(parser.errors.where(:field_116).map(&:message)).to include(I18n.t("validations.sales.2025.bulk_upload.numeric.within_range", field: "Percentage discount", min: "0%", max: "70%")) + expect(parser.errors.where(:field_115).map(&:message)).to include(I18n.t("validations.sales.2025.bulk_upload.numeric.within_range", field: "Percentage discount", min: "0%", max: "70%")) end end end @@ -1199,7 +1205,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do describe "#field_33" do # will buyer1 live in property? context "when not a possible value" do - let(:attributes) { valid_attributes.merge({ field_33: "3" }) } + let(:attributes) { valid_attributes.merge({ field_10: "2", field_33: "3" }) } it "is not valid" do parser.valid? @@ -1208,13 +1214,13 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do end end - describe "#field_88" do # shared ownership mortgageused + describe "#field_109" do # staircasing mortgageused context "when invalid value" do - let(:attributes) { setup_section_params.merge(field_88: "4") } + let(:attributes) { setup_section_params.merge(field_109: "4") } it "returns correct errors" do parser.valid? - expect(parser.errors[:field_88]).to include(I18n.t("validations.sales.2025.bulk_upload.invalid_option", question: "was a mortgage used for the purchase of this property? - Shared ownership.")) + expect(parser.errors[:field_109]).to include(I18n.t("validations.sales.2025.bulk_upload.invalid_option", question: "was a mortgage used for this staircasing transaction?")) parser.log.blank_invalid_non_setup_fields! parser.log.save! @@ -1223,11 +1229,11 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do end context "when value is 3 and stairowned is not 100" do - let(:attributes) { setup_section_params.merge(field_88: "3", field_10: "1", field_96: "50", field_97: "99", field_120: nil) } + let(:attributes) { setup_section_params.merge(field_109: "3", field_10: "1", field_96: "50", field_97: "99", field_120: nil) } it "returns correct errors" do parser.valid? - expect(parser.errors[:field_88]).to include("The percentage owned has to be 100% if the mortgage used is 'Don’t know'") + expect(parser.errors[:field_109]).to include("The percentage owned has to be 100% if the mortgage used is 'Don’t know'") parser.log.blank_invalid_non_setup_fields! parser.log.save! @@ -1236,58 +1242,57 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do end context "when value is 3 and stairowned is not answered" do - let(:attributes) { setup_section_params.merge(field_88: "3", field_10: "1", field_96: "50", field_97: nil, field_120: nil) } + let(:attributes) { setup_section_params.merge(field_109: "3", field_10: "1", field_96: "50", field_97: nil, field_120: nil) } it "does not add errors" do parser.valid? - expect(parser.errors[:field_88]).to be_empty - expect(parser.errors[:field_88]).to be_empty + expect(parser.errors[:field_109]).to be_empty end end - context "when it is not a staircasing transaction" do - context "when value is 3 and stairowned is not answered" do - let(:attributes) { setup_section_params.merge(field_88: "3", field_10: "2", field_96: "50", field_97: nil, field_120: nil) } - - it "returns correct errors" do - parser.valid? - expect(parser.errors[:field_88]).to include(I18n.t("validations.invalid_option", question: "was a mortgage used for the purchase of this property?")) + context "when value is 3 and stairowned is 100" do + let(:attributes) { setup_section_params.merge(field_109: "3", field_10: "1", field_96: "50", field_97: "100", field_120: nil) } - parser.log.blank_invalid_non_setup_fields! - parser.log.save! - expect(parser.log.mortgageused).to be_nil - end + it "does not add errors and sets mortgage used to 3" do + parser.valid? + expect(parser.log.mortgageused).to eq(3) + expect(parser.log.stairowned).to eq(100) + expect(parser.log.deposit).to be_nil + expect(parser.errors[:field_109]).to be_empty + expect(parser.errors[:field_120]).to be_empty end + end + end - context "when value is 3 and stairowned is 100" do - let(:attributes) { setup_section_params.merge(field_88: "3", field_10: "2", field_96: "50", field_97: "100", field_120: nil) } + describe "#field_88" do # shared ownership mortgageused + context "when invalid value" do + let(:attributes) { setup_section_params.merge(field_10: "2", field_88: "4") } - it "returns correct errors" do - parser.valid? - expect(parser.errors[:field_88]).to include(I18n.t("validations.invalid_option", question: "was a mortgage used for the purchase of this property?")) + it "returns correct errors" do + parser.valid? + expect(parser.errors[:field_88]).to include(I18n.t("validations.sales.2025.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.save! - expect(parser.log.mortgageused).to be_nil - end + parser.log.blank_invalid_non_setup_fields! + parser.log.save! + expect(parser.log.mortgageused).to be_nil end end - context "when value is 3 and stairowned is 100" do - let(:attributes) { setup_section_params.merge(field_88: "3", field_10: "1", field_96: "50", field_97: "100", field_120: nil) } + context "when value is 3 and stairowned is not answered" do + let(:attributes) { setup_section_params.merge(field_88: "3", field_10: "2", field_96: "50", field_97: nil, field_120: nil) } - it "does not add errors and sets mortgage used to 3" do + it "returns correct errors" do parser.valid? - expect(parser.log.mortgageused).to eq(3) - expect(parser.log.stairowned).to eq(100) - expect(parser.log.deposit).to be_nil - expect(parser.errors[:field_88]).to be_empty - expect(parser.errors[:field_120]).to be_empty + expect(parser.errors[:field_88]).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.save! + expect(parser.log.mortgageused).to be_nil end end context "with non staircasing mortgage error" do - let(:attributes) { setup_section_params.merge(field_9: "30", field_88: "1", field_89: "10000", field_120: "5000", field_86: "30000", field_87: "28", field_10: "2") } + let(:attributes) { setup_section_params.merge(field_9: "30", field_88: "1", field_89: "10000", field_91: "5000", field_86: "30000", field_87: "28", field_10: "2") } it "does not add a BU error on type (because it's a setup field and would block log creation)" do parser.valid? @@ -1297,7 +1302,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do it "includes errors on other related fields" do parser.valid? expect(parser.errors[:field_89]).to include("The mortgage (£10,000.00) and cash deposit (£5,000.00) added together is £15,000.00.

The full purchase price (£30,000.00) multiplied by the percentage equity stake purchased (28.0%) is £8,400.00.

These two amounts should be the same.") - expect(parser.errors[:field_120]).to include("The mortgage (£10,000.00) and cash deposit (£5,000.00) added together is £15,000.00.

The full purchase price (£30,000.00) multiplied by the percentage equity stake purchased (28.0%) is £8,400.00.

These two amounts should be the same.") + expect(parser.errors[:field_91]).to include("The mortgage (£10,000.00) and cash deposit (£5,000.00) added together is £15,000.00.

The full purchase price (£30,000.00) multiplied by the percentage equity stake purchased (28.0%) is £8,400.00.

These two amounts should be the same.") expect(parser.errors[:field_86]).to include("The mortgage (£10,000.00) and cash deposit (£5,000.00) added together is £15,000.00.

The full purchase price (£30,000.00) multiplied by the percentage equity stake purchased (28.0%) is £8,400.00.

These two amounts should be the same.") expect(parser.errors[:field_87]).to include("The mortgage (£10,000.00) and cash deposit (£5,000.00) added together is £15,000.00.

The full purchase price (£30,000.00) multiplied by the percentage equity stake purchased (28.0%) is £8,400.00.

These two amounts should be the same.") end @@ -1305,23 +1310,22 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do it "does not add errors to other ownership type fields" do parser.valid? expect(parser.errors[:field_117]).to be_empty - expect(parser.errors[:field_126]).to be_empty - expect(parser.errors[:field_118]).to be_empty - expect(parser.errors[:field_127]).to be_empty - expect(parser.errors[:field_123]).to be_empty - expect(parser.errors[:field_130]).to be_empty - expect(parser.errors[:field_114]).to be_empty - expect(parser.errors[:field_125]).to be_empty + expect(parser.errors[:field_120]).to be_empty + expect(parser.errors[:field_113]).to be_empty + expect(parser.errors[:field_107]).to be_empty + expect(parser.errors[:field_108]).to be_empty + expect(parser.errors[:field_116]).to be_empty + expect(parser.errors[:field_109]).to be_empty end end end - describe "#field_117" do - let(:attributes) { valid_attributes.merge({ field_8: "2", field_10: "9", field_117: "3" }) } + describe "#field_116" do + let(:attributes) { valid_attributes.merge({ field_8: "2", field_11: "9", field_116: "3" }) } it "does not allow 3 (don't know) as an option for discounted ownership" do parser.valid? - expect(parser.errors[:field_117]).to include(I18n.t("validations.invalid_option", question: "was a mortgage used for the purchase of this property?")) + expect(parser.errors[:field_116]).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.save! @@ -1329,7 +1333,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do end context "when validate_discounted_ownership_value is triggered" do - let(:attributes) { setup_section_params.merge(field_114: 100, field_123: 100, field_8: 2, field_10: 9, field_117: 2, field_116: 10) } + let(:attributes) { setup_section_params.merge(field_113: 100, field_120: 100, field_8: 2, field_10: 2, field_11: 9, field_116: 2, field_115: 10) } it "only adds errors to the discounted ownership field" do parser.valid? @@ -1342,7 +1346,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do describe "soft validations" do context "when soft validation is triggered" do - let(:attributes) { valid_attributes.merge({ field_28: 22, field_32: 5 }) } + let(:attributes) { valid_attributes.merge({ field_10: 2, field_28: 22, field_32: 5 }) } it "adds an error to the relevant fields" do parser.valid? @@ -1756,7 +1760,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do end describe "with living before purchase years for discounted ownership more than 0" do - let(:attributes) { setup_section_params.merge({ field_8: "2", field_113: "1" }) } + let(:attributes) { setup_section_params.merge({ field_8: "2", field_112: "1" }) } it "is sets living before purchase asked to yes and sets the correct living before purchase years" do expect(parser.log.proplen_asked).to be(0) @@ -1774,7 +1778,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do end describe "with living before purchase 0 years for discounted ownership set to 0" do - let(:attributes) { setup_section_params.merge({ field_8: "2", field_113: "0" }) } + let(:attributes) { setup_section_params.merge({ field_8: "2", field_112: "0" }) } it "is sets living before purchase asked to no" do expect(parser.log.proplen_asked).to be(1) @@ -1793,7 +1797,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do end context "when mscharge is given, but is set to 0 for discounted ownership" do - let(:attributes) { valid_attributes.merge(field_8: "2", field_124: "0") } + let(:attributes) { valid_attributes.merge(field_8: "2", field_121: "0") } it "does not override variables correctly" do log = parser.log @@ -1825,13 +1829,13 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do end context "when blank" do - let(:attributes) { { bulk_upload:, field_2: "", field_6: "not blank" } } + let(:attributes) { { bulk_upload:, field_5: "", field_3: "not blank" } } it "is not permitted as setup error" do parser.valid? setup_errors = parser.errors.select { |e| e.options[:category] == :setup } - expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql(I18n.t("validations.not_answered", question: "reported by.")) + expect(setup_errors.find { |e| e.attribute == :field_5 }.message).to eql(I18n.t("validations.not_answered", question: "reported by.")) end it "blocks log creation" do @@ -1841,13 +1845,13 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do end context "when cannot find managing org" do - let(:attributes) { { bulk_upload:, field_2: "donotexist" } } + let(:attributes) { { bulk_upload:, field_5: "donotexist" } } it "is not permitted as setup error" do parser.valid? setup_errors = parser.errors.select { |e| e.options[:category] == :setup } - expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql(I18n.t("validations.not_answered", question: "reported by.")) + expect(setup_errors.find { |e| e.attribute == :field_5 }.message).to eql(I18n.t("validations.not_answered", question: "reported by.")) end it "blocks log creation" do @@ -1859,13 +1863,13 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do context "when not affiliated with managing org" do let(:unaffiliated_org) { create(:organisation, :with_old_visible_id) } - let(:attributes) { { bulk_upload:, field_1: owning_org.old_visible_id, field_2: unaffiliated_org.old_visible_id } } + let(:attributes) { { bulk_upload:, field_4: owning_org.old_visible_id, field_5: unaffiliated_org.old_visible_id } } it "is not permitted as setup error" do parser.valid? setup_errors = parser.errors.select { |e| e.options[:category] == :setup } - expect(setup_errors.find { |e| e.attribute == :field_2 }.message).to eql(I18n.t("validations.sales.2025.bulk_upload.assigned_to.managing_organisation_not_related")) + expect(setup_errors.find { |e| e.attribute == :field_5 }.message).to eql(I18n.t("validations.sales.2025.bulk_upload.assigned_to.managing_organisation_not_related")) end it "blocks log creation" do @@ -1887,7 +1891,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do parser.valid? setup_errors = parser.errors.select { |e| e.options[:category] == :setup } - expect(setup_errors.find { |e| e.attribute == :field_1 }.message).to eql(I18n.t("validations.sales.2025.bulk_upload.owning_organisation.not_stock_owner")) + expect(setup_errors.find { |e| e.attribute == :field_4 }.message).to eql(I18n.t("validations.sales.2025.bulk_upload.owning_organisation.not_stock_owner")) end it "blocks log creation" do