Browse Source

fix typos, field numbers, staircasing tests

pull/2945/head
Carolyn 2 months ago
parent
commit
4bd1b04eda
  1. 8
      app/services/bulk_upload/sales/year2025/csv_parser.rb
  2. 678
      app/services/bulk_upload/sales/year2025/row_parser.rb
  3. 14
      spec/services/bulk_upload/sales/year2025/csv_parser_spec.rb
  4. 340
      spec/services/bulk_upload/sales/year2025/row_parser_spec.rb

8
app/services/bulk_upload/sales/year2025/csv_parser.rb

@ -114,11 +114,11 @@ private
def first_record_start_date def first_record_start_date
if with_headers? 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 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_5.to_i, row_parsers.first.field_4.to_i) Date.new(year, row_parsers.first.field_2.to_i, row_parsers.first.field_1.to_i)
else else
year = rows.first[5].to_s.strip.length.between?(1, 2) ? rows.first[5].to_i + 2000 : rows.first[5].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[4].to_i, rows.first[3].to_i) Date.new(year, rows.first[1].to_i, rows.first[0].to_i)
end end
end end
end end

678
app/services/bulk_upload/sales/year2025/row_parser.rb

@ -5,12 +5,12 @@ class BulkUpload::Sales::Year2025::RowParser
include FormattingHelper include FormattingHelper
QUESTIONS = { QUESTIONS = {
field_1: "Which organisation owned this property before the sale?", field_1: "What is the day of the sale completion date? - DD",
field_2: "Which organisation is reporting this sale?", field_2: "What is the month of the sale completion date? - MM",
field_3: "Username", field_3: "What is the year of the sale completion date? - YY",
field_4: "What is the day of the sale completion date? - DD", field_4: "Which organisation owned this property before the sale?",
field_5: "What is the month of the sale completion date? - MM", field_5: "Which organisation is reporting this sale?",
field_6: "What is the year of the sale completion date? - YY", field_6: "Username",
field_7: "What is the purchaser code?", field_7: "What is the purchaser code?",
field_8: "What is the sale type?", field_8: "What is the sale type?",
field_9: "What is the type of shared ownership sale?", field_9: "What is the type of shared ownership sale?",
@ -144,12 +144,12 @@ class BulkUpload::Sales::Year2025::RowParser
attribute :field_blank attribute :field_blank
attribute :field_1, :string attribute :field_1, :integer
attribute :field_2, :string attribute :field_2, :integer
attribute :field_3, :string attribute :field_3, :integer
attribute :field_4, :integer attribute :field_4, :string
attribute :field_5, :integer attribute :field_5, :string
attribute :field_6, :integer attribute :field_6, :string
attribute :field_7, :string attribute :field_7, :string
attribute :field_8, :integer attribute :field_8, :integer
attribute :field_9, :integer attribute :field_9, :integer
@ -196,7 +196,7 @@ class BulkUpload::Sales::Year2025::RowParser
attribute :field_47, :string attribute :field_47, :string
attribute :field_48, :string attribute :field_48, :string
attribute :field_49, :integer attribute :field_49, :integer
attribute :field_49, :integer attribute :field_50, :integer
attribute :field_51, :string attribute :field_51, :string
attribute :field_52, :string attribute :field_52, :string
attribute :field_53, :integer attribute :field_53, :integer
@ -244,6 +244,8 @@ class BulkUpload::Sales::Year2025::RowParser
attribute :field_91, :integer attribute :field_91, :integer
attribute :field_92, :integer attribute :field_92, :integer
attribute :field_93, :decimal attribute :field_93, :decimal
attribute :field_94, :decimal
attribute :field_95, :decimal
attribute :field_96, :integer attribute :field_96, :integer
attribute :field_97, :integer attribute :field_97, :integer
@ -273,20 +275,20 @@ class BulkUpload::Sales::Year2025::RowParser
attribute :field_120, :integer attribute :field_120, :integer
attribute :field_121, :integer attribute :field_121, :integer
validates :field_4, validates :field_1,
presence: { presence: {
message: I18n.t("#{ERROR_BASE_KEY}.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_2,
presence: { presence: {
message: I18n.t("#{ERROR_BASE_KEY}.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_3,
presence: { presence: {
message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "sale completion date (year)."), message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "sale completion date (year)."),
category: :setup, category: :setup,
@ -295,7 +297,7 @@ class BulkUpload::Sales::Year2025::RowParser
with: /\A(\d{2}|\d{4})\z/, with: /\A(\d{2}|\d{4})\z/,
message: I18n.t("#{ERROR_BASE_KEY}.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_3.present? },
}, on: :after_log }, on: :after_log
validates :field_8, validates :field_8,
@ -390,565 +392,6 @@ class BulkUpload::Sales::Year2025::RowParser
}, },
on: :after_log 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_buyer1_economic_status, on: :before_log
validate :validate_address_option_found, on: :after_log validate :validate_address_option_found, on: :after_log
validate :validate_buyer2_economic_status, on: :before_log validate :validate_buyer2_economic_status, on: :before_log
@ -1052,10 +495,10 @@ class BulkUpload::Sales::Year2025::RowParser
def spreadsheet_duplicate_hash def spreadsheet_duplicate_hash
attributes.slice( attributes.slice(
"field_1", # owning org "field_4", # owning org
"field_4", # saledate "field_1", # saledate
"field_5", # saledate "field_2", # saledate
"field_6", # saledate "field_3", # saledate
"field_7", # purchaser_code "field_7", # purchaser_code
"field_24", # postcode "field_24", # postcode
"field_25", # postcode "field_25", # postcode
@ -1202,13 +645,13 @@ private
end end
def rtb_like_sale_type? def rtb_like_sale_type?
[9, 14, 27, 29].includes(field_11) [9, 14, 27, 29].include?(field_11)
end end
def field_mapping_for_errors def field_mapping_for_errors
{ {
purchid: %i[field_7], purchid: %i[field_7],
saledate: %i[field_4 field_5 field_6], saledate: %i[field_1 field_2 field_3],
noint: %i[field_14], noint: %i[field_14],
age1_known: %i[field_28], age1_known: %i[field_28],
age1: %i[field_28], age1: %i[field_28],
@ -1292,15 +735,13 @@ private
mscharge: mscharge_fields, mscharge: mscharge_fields,
grant: %i[field_114], grant: %i[field_114],
discount: %i[field_115], discount: %i[field_115],
owning_organisation_id: %i[field_1], owning_organisation_id: %i[field_4],
managing_organisation_id: [:field_2], managing_organisation_id: [:field_5],
assigned_to: %i[field_3], assigned_to: %i[field_6],
hhregres: %i[field_65], hhregres: %i[field_65],
hhregresstill: %i[field_66], hhregresstill: %i[field_66],
armedforcesspouse: %i[field_67], armedforcesspouse: %i[field_67],
mortgagelenderother: mortgagelenderother_fields,
hb: %i[field_74], hb: %i[field_74],
mortlen: mortlen_fields, mortlen: mortlen_fields,
proplen: proplen_fields, proplen: proplen_fields,
@ -1484,9 +925,6 @@ private
attributes["hhregresstill"] = field_66 attributes["hhregresstill"] = field_66
attributes["armedforcesspouse"] = field_67 attributes["armedforcesspouse"] = field_67
attributes["mortgagelender"] = mortgagelender
attributes["mortgagelenderother"] = mortgagelenderother
attributes["hb"] = field_74 attributes["hb"] = field_74
attributes["mortlen"] = mortlen attributes["mortlen"] = mortlen
@ -1552,8 +990,8 @@ private
end end
def saledate def saledate
year = field_6.to_s.strip.length.between?(1, 2) ? field_6 + 2000 : field_6 year = field_3.to_s.strip.length.between?(1, 2) ? field_3 + 2000 : field_3
Date.new(year, field_5, field_4) if field_6.present? && field_5.present? && field_4.present? Date.new(year, field_2, field_1) if field_3.present? && field_2.present? && field_1.present?
rescue Date::Error rescue Date::Error
Date.new Date.new
end end
@ -1777,11 +1215,11 @@ private
end end
def owning_organisation 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 end
def assigned_to def assigned_to
@assigned_to ||= User.where("lower(email) = ?", field_3&.downcase).first @assigned_to ||= User.where("lower(email) = ?", field_6&.downcase).first
end end
def previous_la_known def previous_la_known
@ -1825,11 +1263,11 @@ private
end end
def validate_owning_org_data_given def validate_owning_org_data_given
if field_1.blank? if field_4.blank?
block_log_creation! block_log_creation!
if errors[:field_1].blank? if errors[:field_4].blank?
errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "owning organisation."), category: :setup) errors.add(:field_4, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "owning organisation."), category: :setup)
end end
end end
end end
@ -1838,8 +1276,8 @@ private
if owning_organisation.nil? if owning_organisation.nil?
block_log_creation! block_log_creation!
if field_1.present? && errors[:field_1].blank? if field_4.present? && errors[:field_4].blank?
errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_found"), category: :setup) errors.add(:field_4, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_found"), category: :setup)
end end
end end
end end
@ -1848,8 +1286,8 @@ private
if owning_organisation && !owning_organisation.holds_own_stock? if owning_organisation && !owning_organisation.holds_own_stock?
block_log_creation! block_log_creation!
if errors[:field_1].blank? if errors[:field_4].blank?
errors.add(:field_1, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_stock_owner"), category: :setup) errors.add(:field_4, I18n.t("#{ERROR_BASE_KEY}.owning_organisation.not_stock_owner"), category: :setup)
end end
end end
end end
@ -1860,26 +1298,26 @@ private
block_log_creation! block_log_creation!
return if errors[:field_1].present? return if errors[:field_4].present?
if bulk_upload.user.support? 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 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
end end
def validate_assigned_to_exists def validate_assigned_to_exists
return if field_3.blank? return if field_6.blank?
unless assigned_to 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
end end
def validate_assigned_to_when_support def validate_assigned_to_when_support
if field_3.blank? && bulk_upload.user.support? if field_6.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?")) 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
end end
@ -1889,11 +1327,11 @@ 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, 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 end
def managing_organisation def managing_organisation
Organisation.find_by_id_on_multiple_fields(field_2) Organisation.find_by_id_on_multiple_fields(field_5)
end end
def nationality_group(nationality_value) def nationality_group(nationality_value)
@ -1908,8 +1346,8 @@ private
if owning_organisation && managing_organisation && !owning_organisation.can_be_managed_by?(organisation: managing_organisation) if owning_organisation && managing_organisation && !owning_organisation.can_be_managed_by?(organisation: managing_organisation)
block_log_creation! block_log_creation!
if errors[:field_2].blank? if errors[:field_5].blank?
errors.add(:field_2, I18n.t("#{ERROR_BASE_KEY}.assigned_to.managing_organisation_not_related"), category: :setup) errors.add(:field_5, I18n.t("#{ERROR_BASE_KEY}.assigned_to.managing_organisation_not_related"), category: :setup)
end end
end end
end end
@ -1973,12 +1411,12 @@ private
def validate_relevant_collection_window def validate_relevant_collection_window
return if saledate.blank? || bulk_upload.form.blank? 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) 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_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_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_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_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_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
end end
@ -1986,10 +1424,10 @@ private
if log_already_exists? if log_already_exists?
error_message = I18n.t("#{ERROR_BASE_KEY}.duplicate") error_message = I18n.t("#{ERROR_BASE_KEY}.duplicate")
errors.add(:field_1, error_message) # Owning org errors.add(:field_4, error_message) # Owning org
errors.add(:field_4, error_message) # Sale completion date errors.add(:field_1, error_message) # Sale completion date
errors.add(:field_5, error_message) # Sale completion date errors.add(:field_2, error_message) # Sale completion date
errors.add(:field_6, error_message) # Sale completion date errors.add(:field_3, error_message) # Sale completion date
errors.add(:field_24, error_message) # Postcode errors.add(:field_24, error_message) # Postcode
errors.add(:field_25, error_message) # Postcode errors.add(:field_25, error_message) # Postcode
errors.add(:field_28, error_message) # Buyer 1 age errors.add(:field_28, error_message) # Buyer 1 age

14
spec/services/bulk_upload/sales/year2025/csv_parser_spec.rb

@ -27,7 +27,7 @@ RSpec.describe BulkUpload::Sales::Year2025::CsvParser do
end end
it "parses csv correctly" do 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
it "counts the number of valid field numbers correctly" do it "counts the number of valid field numbers correctly" do
@ -59,7 +59,7 @@ RSpec.describe BulkUpload::Sales::Year2025::CsvParser do
end end
it "parses csv correctly" do 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
it "counts the number of valid field numbers correctly" do it "counts the number of valid field numbers correctly" do
@ -92,7 +92,7 @@ RSpec.describe BulkUpload::Sales::Year2025::CsvParser do
end end
it "parses csv correctly" do 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 end
@ -112,7 +112,7 @@ RSpec.describe BulkUpload::Sales::Year2025::CsvParser do
end end
it "parses csv correctly" do 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 end
@ -129,7 +129,7 @@ RSpec.describe BulkUpload::Sales::Year2025::CsvParser do
end end
it "parses csv correctly" do 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 end
@ -146,7 +146,7 @@ RSpec.describe BulkUpload::Sales::Year2025::CsvParser do
end end
it "parses csv correctly" do 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 end
@ -185,7 +185,7 @@ RSpec.describe BulkUpload::Sales::Year2025::CsvParser do
end end
it "parses csv correctly" do 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 end
end end

340
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 let(:setup_section_params) do
{ {
bulk_upload:, bulk_upload:,
field_1: owning_org.old_visible_id, # organisation field_1: now.day.to_s, # sale day
field_2: managing_org.old_visible_id, # organisation field_2: now.month.to_s, # sale month
field_3: user.email, # user field_3: now.strftime("%g"), # sale year
field_4: now.day.to_s, # sale day field_4: owning_org.old_visible_id, # organisation
field_5: now.month.to_s, # sale month field_5: managing_org.old_visible_id, # organisation
field_6: now.strftime("%g"), # sale year field_6: user.email, # user
field_7: "test id", # purchase id field_7: "test id", # purchase id
field_8: "1", # owhershipsch field_8: "1", # owhershipsch
field_9: "2", # shared ownership sale type field_9: "2", # shared ownership sale type
@ -32,12 +32,11 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
let(:valid_attributes) do let(:valid_attributes) do
{ {
bulk_upload:, bulk_upload:,
field_1: owning_org.old_visible_id, field_1: "12",
field_2: managing_org.old_visible_id, field_2: "5",
field_3: "25",
field_4: "12", field_4: owning_org.old_visible_id,
field_5: "5", field_5: managing_org.old_visible_id,
field_6: "24",
field_7: "test id", field_7: "test id",
field_8: "1", field_8: "1",
field_9: "2", field_9: "2",
@ -93,26 +92,33 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
field_83: "1", field_83: "1",
field_84: "1", field_84: "1",
field_85: "1", field_85: "1",
field_86: "250000", field_107: "250000",
field_87: "25", field_108: "25",
field_88: "1", field_109: "1",
field_89: "5000", field_89: "5000",
field_90: "20", field_90: "20",
field_91: "30",
field_92: "3",
field_93: "2022",
field_96: "10", field_96: "10",
field_97: "40", field_97: "40",
field_98: "1", field_98: "1",
field_99: "2",
field_94: "200", 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 end
around do |example| around do |example|
create(:organisation_relationship, parent_organisation: owning_org, child_organisation: managing_org) 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) Singleton.__init__(FormHandler)
example.run example.run
end end
@ -127,7 +133,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
context "when any field is populated" do context "when any field is populated" do
before do before do
parser.field_1 = "1" parser.field_4 = "1"
end end
it "returns false" do it "returns false" do
@ -308,7 +314,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end end
context "when an invalid value error has been added" do 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 it "does not add an additional error" do
parser.valid? 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 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
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 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
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 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
end end
@ -380,7 +386,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
bulk_upload:, bulk_upload:,
field_7: "test id", field_7: "test id",
field_8: "2", field_8: "2",
field_10: nil, field_11: nil,
} }
end end
@ -389,7 +395,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
errors = parser.errors.select { |e| e.options[:category] == :setup }.map(&:attribute).sort 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
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 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
end end
describe "#field_1" do # owning org describe "#field_4" do # owning org
context "when no data given" do 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 it "is not permitted as setup error" do
parser.valid? 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 end
it "blocks log creation" do it "blocks log creation" do
@ -428,11 +434,11 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end end
context "when cannot find owning org" do 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 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([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 end
it "blocks log creation" do it "blocks log creation" do
@ -444,11 +450,11 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
context "when not affiliated with owning org" do context "when not affiliated with owning org" do
let(:unaffiliated_org) { create(:organisation, :with_old_visible_id) } 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 it "is not permitted as setup error" do
parser.valid? 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 end
it "blocks log creation" do 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) { 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(: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 before do
create(:organisation_relationship, parent_organisation: merged_org_stock_owner, child_organisation: merged_org) 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 it "is permitted" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_1)).not_to be_present expect(parser.errors.where(:field_4)).not_to be_present
end end
end end
context "when user's org has absorbed owning organisation" do context "when user's org has absorbed owning organisation" do
let(:merged_org) { create(:organisation, :with_old_visible_id, holds_own_stock: true) } 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 before do
merged_org.update!(absorbing_organisation: user.organisation, merge_date: Time.zone.today) 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 = described_class.new(attributes)
parser.valid? parser.valid?
expect(parser.errors.where(:field_1)).not_to be_present expect(parser.errors.where(:field_4)).not_to be_present
expect(parser.errors.where(:field_3)).not_to be_present expect(parser.errors.where(:field_6)).not_to be_present
end end
end end
context "when user's org has absorbed owning organisation before the startdate" do 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(: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 before do
merged_org.update!(absorbing_organisation: user.organisation, merge_date: Time.zone.today - 3.years) 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 = described_class.new(attributes)
parser.valid? 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(/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_1]).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_2]).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_3]).to include(/Enter a date when the owning organisation was active/)
end end
end end
context "when user is an unaffiliated non-support user and bulk upload organisation is affiliated with the owning organisation" do 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(:affiliated_org) { create(:organisation, :with_old_visible_id) }
let(:unaffiliated_user) { create(:user, organisation: create(:organisation)) } 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 } let(:organisation_id) { unaffiliated_user.organisation_id }
before do before do
@ -531,18 +537,18 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
bulk_upload.update!(organisation_id:, user: unaffiliated_user) bulk_upload.update!(organisation_id:, user: unaffiliated_user)
end 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 = 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(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
end end
context "when user is an unaffiliated support user and bulk upload organisation is affiliated with the owning organisation" do 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(:affiliated_org) { create(:organisation, :with_old_visible_id) }
let(:unaffiliated_support_user) { create(:user, :support, organisation: create(:organisation)) } 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 } let(:organisation_id) { affiliated_org.id }
before do before do
@ -550,21 +556,21 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
bulk_upload.update!(organisation_id:, user: unaffiliated_support_user) bulk_upload.update!(organisation_id:, user: unaffiliated_support_user)
end 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 = described_class.new(attributes)
parser.valid? 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 end
end end
describe "#field_3" do # username for assigned_to describe "#field_6" do # username for assigned_to
context "when blank" do 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 it "is permitted" do
parser.valid? parser.valid?
expect(parser.errors[:field_3]).to be_blank expect(parser.errors[:field_6]).to be_blank
end end
it "sets assigned to to bulk upload user" do 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 context "when blank and bulk upload user is support" do
let(:bulk_upload) { create(:bulk_upload, :sales, user: create(:user, :support), year: 2025) } 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 it "is not permitted" do
parser.valid? parser.valid?
expect(parser.errors[:field_3]).to be_present expect(parser.errors[:field_6]).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 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 end
it "blocks log creation" do it "blocks log creation" do
@ -596,22 +602,22 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end end
context "when user could not be found" do 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 it "is not permitted" do
parser.valid? parser.valid?
expect(parser.errors[:field_3]).to be_present expect(parser.errors[:field_6]).to be_present
end end
end end
context "when an unaffiliated user" do context "when an unaffiliated user" do
let(:other_user) { create(:user) } 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 it "is not permitted as a setup error" do
parser.valid? 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 end
it "blocks log creation" do 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 context "when a user part of owning org" do
let(:other_user) { create(:user, organisation: owning_org) } 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 it "is permitted" do
parser.valid? parser.valid?
expect(parser.errors[:field_3]).to be_blank expect(parser.errors[:field_6]).to be_blank
end end
it "sets assigned to to the user" do 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 context "when email matches other than casing" do
let(:other_user) { create(:user, organisation: owning_org) } 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 it "is permitted" do
parser.valid? parser.valid?
expect(parser.errors[:field_3]).to be_blank expect(parser.errors[:field_6]).to be_blank
end end
end 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 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 it "returns them as setup errors" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_4, category: :setup)).to be_present expect(parser.errors.where(:field_1, category: :setup)).to be_present
expect(parser.errors.where(:field_5, category: :setup)).to be_present expect(parser.errors.where(:field_2, category: :setup)).to be_present
expect(parser.errors.where(:field_6, category: :setup)).to be_present expect(parser.errors.where(:field_3, category: :setup)).to be_present
end end
end end
context "when one of these fields is blank" do 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 it "returns an error only on blank field as setup error" do
parser.valid? parser.valid?
expect(parser.errors[:field_4]).to be_blank expect(parser.errors[:field_1]).to be_blank
expect(parser.errors[:field_5]).to be_blank expect(parser.errors[:field_2]).to be_blank
expect(parser.errors.where(:field_6, category: :setup)).to be_present expect(parser.errors.where(:field_3, category: :setup)).to be_present
end end
end end
context "when field 6 is 4 digits instead of 2" do context "when field 3 is 4 digits instead of 2" do
let(:attributes) { setup_section_params.merge({ bulk_upload:, field_6: "2025" }) } let(:attributes) { setup_section_params.merge({ bulk_upload:, field_3: "2025" }) }
it "correctly sets the date" do it "correctly sets the date" do
parser.valid? 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)) expect(parser.log.saledate).to eq(Time.zone.local(2025, 5, 1))
end end
end end
context "when field 5 is not 2 or 4 digits" do context "when field 2 is not 2 or 4 digits" do
let(:attributes) { setup_section_params.merge({ bulk_upload:, field_6: "202" }) } let(:attributes) { setup_section_params.merge({ bulk_upload:, field_3: "202" }) }
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(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
end end
context "when invalid date given" do 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 it "does not raise an error" do
expect { parser.valid? }.not_to raise_error expect { parser.valid? }.not_to raise_error
@ -710,15 +716,15 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end end
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) } let(:bulk_upload) { create(:bulk_upload, :sales, user:, year: 2025) }
it "does not return errors" do it "does not return errors" do
parser.valid? parser.valid?
expect(parser.errors[:field_4]).not_to be_present expect(parser.errors[:field_1]).not_to be_present
expect(parser.errors[:field_5]).not_to be_present expect(parser.errors[:field_2]).not_to be_present
expect(parser.errors[:field_6]).not_to be_present expect(parser.errors[:field_3]).not_to be_present
end end
end end
@ -729,15 +735,15 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end end
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) } let(:bulk_upload) { create(:bulk_upload, :sales, user:, year: 2023) }
it "returns setup errors" do it "returns setup errors" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_4, category: :setup)).to be_present expect(parser.errors.where(:field_1, category: :setup)).to be_present
expect(parser.errors.where(:field_5, category: :setup)).to be_present expect(parser.errors.where(:field_2, category: :setup)).to be_present
expect(parser.errors.where(:field_6, category: :setup)).to be_present expect(parser.errors.where(:field_3, category: :setup)).to be_present
end end
end end
end end
@ -760,10 +766,10 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
error_message = I18n.t("validations.sales.2025.bulk_upload.duplicate") error_message = I18n.t("validations.sales.2025.bulk_upload.duplicate")
[ [
:field_1, # Owning org :field_4, # Owning org
:field_4, # Sale completion date :field_1, # Sale completion date
:field_5, # Sale completion date :field_2, # Sale completion date
:field_6, # Sale completion date :field_3, # Sale completion date
:field_24, # Postcode :field_24, # Postcode
:field_25, # Postcode :field_25, # Postcode
:field_28, # Buyer 1 age :field_28, # Buyer 1 age
@ -790,10 +796,10 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
parser.valid? parser.valid?
[ [
:field_1, # Owning org :field_4, # Owning org
:field_4, # Sale completion date :field_1, # Sale completion date
:field_5, # Sale completion date :field_2, # Sale completion date
:field_6, # Sale completion date :field_3, # Sale completion date
:field_24, # Postcode :field_24, # Postcode
:field_25, # Postcode :field_25, # Postcode
:field_28, # Buyer 1 age :field_28, # Buyer 1 age
@ -828,42 +834,42 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end end
end end
describe "#field_10" do # type for discounted sale describe "#field_11" do # type for discounted sale
context "when an invalid option" do 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 it "returns setup error" do
parser.valid? 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 end
end end
describe "#field_116" do # percentage discount describe "#field_115" do # percentage discount
context "when percentage discount over 70" do 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 it "returns correct error" do
parser.valid? 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 end
context "when percentage discount not over 70" do 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 it "does not return error" do
parser.valid? parser.valid?
expect(parser.errors.where(:field_116)).not_to be_present expect(parser.errors.where(:field_115)).not_to be_present
end end
end end
context "when percentage less than 0" do 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 it "returns correct error" do
parser.valid? 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 end
end end
@ -1199,7 +1205,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
describe "#field_33" do # will buyer1 live in property? describe "#field_33" do # will buyer1 live in property?
context "when not a possible value" do 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 it "is not valid" do
parser.valid? parser.valid?
@ -1208,13 +1214,13 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end end
end end
describe "#field_88" do # shared ownership mortgageused describe "#field_109" do # staircasing mortgageused
context "when invalid value" do 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 it "returns correct errors" do
parser.valid? 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.blank_invalid_non_setup_fields!
parser.log.save! parser.log.save!
@ -1223,11 +1229,11 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end end
context "when value is 3 and stairowned is not 100" do 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 it "returns correct errors" do
parser.valid? 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.blank_invalid_non_setup_fields!
parser.log.save! parser.log.save!
@ -1236,58 +1242,57 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end end
context "when value is 3 and stairowned is not answered" do 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 it "does not add errors" do
parser.valid? parser.valid?
expect(parser.errors[:field_88]).to be_empty expect(parser.errors[:field_109]).to be_empty
expect(parser.errors[:field_88]).to be_empty
end end
end end
context "when it is not a staircasing transaction" do context "when value is 3 and stairowned is 100" do
context "when value is 3 and stairowned is not answered" do let(:attributes) { setup_section_params.merge(field_109: "3", field_10: "1", field_96: "50", field_97: "100", field_120: nil) }
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?"))
parser.log.blank_invalid_non_setup_fields! it "does not add errors and sets mortgage used to 3" do
parser.log.save! parser.valid?
expect(parser.log.mortgageused).to be_nil expect(parser.log.mortgageused).to eq(3)
end 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
end
context "when value is 3 and stairowned is 100" do describe "#field_88" do # shared ownership mortgageused
let(:attributes) { setup_section_params.merge(field_88: "3", field_10: "2", field_96: "50", field_97: "100", field_120: nil) } context "when invalid value" do
let(:attributes) { setup_section_params.merge(field_10: "2", field_88: "4") }
it "returns correct errors" do it "returns correct errors" do
parser.valid? 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?")) 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.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
end
end end
end end
context "when value is 3 and stairowned is 100" do 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: "100", field_120: nil) } 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? parser.valid?
expect(parser.log.mortgageused).to eq(3) expect(parser.errors[:field_88]).to include(I18n.t("validations.invalid_option", question: "was a mortgage used for the purchase of this property?"))
expect(parser.log.stairowned).to eq(100)
expect(parser.log.deposit).to be_nil parser.log.blank_invalid_non_setup_fields!
expect(parser.errors[:field_88]).to be_empty parser.log.save!
expect(parser.errors[:field_120]).to be_empty expect(parser.log.mortgageused).to be_nil
end end
end end
context "with non staircasing mortgage error" do 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 it "does not add a BU error on type (because it's a setup field and would block log creation)" do
parser.valid? parser.valid?
@ -1297,7 +1302,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
it "includes errors on other related fields" do it "includes errors on other related fields" do
parser.valid? 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.</br></br>The full purchase price (£30,000.00) multiplied by the percentage equity stake purchased (28.0%) is £8,400.00.</br></br>These two amounts should be the same.") expect(parser.errors[:field_89]).to include("The mortgage (£10,000.00) and cash deposit (£5,000.00) added together is £15,000.00.</br></br>The full purchase price (£30,000.00) multiplied by the percentage equity stake purchased (28.0%) is £8,400.00.</br></br>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.</br></br>The full purchase price (£30,000.00) multiplied by the percentage equity stake purchased (28.0%) is £8,400.00.</br></br>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.</br></br>The full purchase price (£30,000.00) multiplied by the percentage equity stake purchased (28.0%) is £8,400.00.</br></br>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.</br></br>The full purchase price (£30,000.00) multiplied by the percentage equity stake purchased (28.0%) is £8,400.00.</br></br>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.</br></br>The full purchase price (£30,000.00) multiplied by the percentage equity stake purchased (28.0%) is £8,400.00.</br></br>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.</br></br>The full purchase price (£30,000.00) multiplied by the percentage equity stake purchased (28.0%) is £8,400.00.</br></br>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.</br></br>The full purchase price (£30,000.00) multiplied by the percentage equity stake purchased (28.0%) is £8,400.00.</br></br>These two amounts should be the same.")
end end
@ -1305,23 +1310,22 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
it "does not add errors to other ownership type fields" do it "does not add errors to other ownership type fields" do
parser.valid? parser.valid?
expect(parser.errors[:field_117]).to be_empty expect(parser.errors[:field_117]).to be_empty
expect(parser.errors[:field_126]).to be_empty expect(parser.errors[:field_120]).to be_empty
expect(parser.errors[:field_118]).to be_empty expect(parser.errors[:field_113]).to be_empty
expect(parser.errors[:field_127]).to be_empty expect(parser.errors[:field_107]).to be_empty
expect(parser.errors[:field_123]).to be_empty expect(parser.errors[:field_108]).to be_empty
expect(parser.errors[:field_130]).to be_empty expect(parser.errors[:field_116]).to be_empty
expect(parser.errors[:field_114]).to be_empty expect(parser.errors[:field_109]).to be_empty
expect(parser.errors[:field_125]).to be_empty
end end
end end
end end
describe "#field_117" do describe "#field_116" do
let(:attributes) { valid_attributes.merge({ field_8: "2", field_10: "9", field_117: "3" }) } 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 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(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.blank_invalid_non_setup_fields!
parser.log.save! parser.log.save!
@ -1329,7 +1333,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end end
context "when validate_discounted_ownership_value is triggered" do 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 it "only adds errors to the discounted ownership field" do
parser.valid? parser.valid?
@ -1342,7 +1346,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
describe "soft validations" do describe "soft validations" do
context "when soft validation is triggered" 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 it "adds an error to the relevant fields" do
parser.valid? parser.valid?
@ -1756,7 +1760,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end end
describe "with living before purchase years for discounted ownership more than 0" do 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 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) expect(parser.log.proplen_asked).to be(0)
@ -1774,7 +1778,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end end
describe "with living before purchase 0 years for discounted ownership set to 0" do 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 it "is sets living before purchase asked to no" do
expect(parser.log.proplen_asked).to be(1) expect(parser.log.proplen_asked).to be(1)
@ -1793,7 +1797,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end end
context "when mscharge is given, but is set to 0 for discounted ownership" do 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 it "does not override variables correctly" do
log = parser.log log = parser.log
@ -1825,13 +1829,13 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end end
context "when blank" do 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 it "is not permitted as setup error" 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(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 end
it "blocks log creation" do it "blocks log creation" do
@ -1841,13 +1845,13 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end end
context "when cannot find managing org" do 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 it "is not permitted as setup error" 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(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 end
it "blocks log creation" do it "blocks log creation" do
@ -1859,13 +1863,13 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
context "when not affiliated with managing org" do context "when not affiliated with managing org" do
let(:unaffiliated_org) { create(:organisation, :with_old_visible_id) } 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 it "is not permitted as setup error" 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(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 end
it "blocks log creation" do it "blocks log creation" do
@ -1887,7 +1891,7 @@ RSpec.describe BulkUpload::Sales::Year2025::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(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 end
it "blocks log creation" do it "blocks log creation" do

Loading…
Cancel
Save