From e42a263eeb6f0f14565c2bdb464967f991a09a76 Mon Sep 17 00:00:00 2001 From: samyou-softwire Date: Fri, 20 Feb 2026 11:41:21 +0000 Subject: [PATCH] CLDC-4203: Remove builtype from BU --- .../bulk_upload/lettings_log_to_csv.rb | 1 - .../lettings/year2026/csv_parser.rb | 2 +- .../lettings/year2026/row_parser.rb | 1025 ++++++++--------- .../lettings/year2026/csv_parser_spec.rb | 8 +- .../lettings/year2026/row_parser_spec.rb | 927 ++++++++------- 5 files changed, 979 insertions(+), 984 deletions(-) diff --git a/app/helpers/bulk_upload/lettings_log_to_csv.rb b/app/helpers/bulk_upload/lettings_log_to_csv.rb index bd29b962b..bc851d654 100644 --- a/app/helpers/bulk_upload/lettings_log_to_csv.rb +++ b/app/helpers/bulk_upload/lettings_log_to_csv.rb @@ -126,7 +126,6 @@ class BulkUpload::LettingsLogToCsv ((log.postcode_full || "").split(" ") || [""]).last, log.la, log.unittype_gn, - log.builtype, log.wchair, log.beds, log.voiddate&.day, # 30 diff --git a/app/services/bulk_upload/lettings/year2026/csv_parser.rb b/app/services/bulk_upload/lettings/year2026/csv_parser.rb index 643990c8b..d2f1ab7b1 100644 --- a/app/services/bulk_upload/lettings/year2026/csv_parser.rb +++ b/app/services/bulk_upload/lettings/year2026/csv_parser.rb @@ -4,7 +4,7 @@ class BulkUpload::Lettings::Year2026::CsvParser include CollectionTimeHelper # TODO: CLDC-4162: Update when 2026 format is known - FIELDS = 148 + FIELDS = 147 FORM_YEAR = 2026 attr_reader :path diff --git a/app/services/bulk_upload/lettings/year2026/row_parser.rb b/app/services/bulk_upload/lettings/year2026/row_parser.rb index f411c081d..3c43d2112 100644 --- a/app/services/bulk_upload/lettings/year2026/row_parser.rb +++ b/app/services/bulk_upload/lettings/year2026/row_parser.rb @@ -31,130 +31,129 @@ class BulkUpload::Lettings::Year2026::RowParser field_24: "Part 2 of the property’s postcode", field_25: "What is the property’s local authority?", field_26: "What type of unit is the property?", - field_27: "Which type of building is the property?", - field_28: "Is the property built or adapted to wheelchair-user standards?", - field_29: "How many bedrooms does the property have?", + field_27: "Is the property built or adapted to wheelchair-user standards?", + field_28: "How many bedrooms does the property have?", + field_29: "What is the void date?", field_30: "What is the void date?", field_31: "What is the void date?", - field_32: "What is the void date?", + field_32: "What date were any major repairs completed on?", field_33: "What date were any major repairs completed on?", field_34: "What date were any major repairs completed on?", - field_35: "What date were any major repairs completed on?", - field_36: "Is this letting sheltered accommodation?", - field_37: "Is this a joint tenancy?", - field_38: "Is this a starter tenancy?", - field_39: "What is the type of tenancy?", - field_40: "If 'Other', what is the type of tenancy?", - field_41: "What is the length of the fixed-term tenancy to the nearest year?", - field_42: "What is the lead tenant’s age?", - field_43: "Lead tenant's sex, as registered at birth", - field_44: "Which of these best describes the lead tenant’s ethnic background?", - field_45: "What is the lead tenant’s nationality?", - field_46: "Which of these best describes the lead tenant’s working situation?", - field_47: "Is person 2 the partner of the lead tenant?", - field_48: "What is person 2’s age?", - field_49: "Person 2's sex, as registered at birth", - field_50: "Which of these best describes person 2’s working situation?", - field_51: "Is person 3 the partner of the lead tenant?", - field_52: "What is person 3’s age?", - field_53: "Person 3's sex, as registered at birth", - field_54: "Which of these best describes person 3’s working situation?", - field_55: "Is person 4 the partner of the lead tenant?", - field_56: "What is person 4’s age?", - field_57: "Person 4's sex, as registered at birth", - field_58: "Which of these best describes person 4’s working situation?", - field_59: "Is person 5 the partner of the lead tenant?", - field_60: "What is person 5’s age?", - field_61: "Person 5's sex, as registered at birth", - field_62: "Which of these best describes person 5’s working situation?", - field_63: "Is person 6 the partner of the lead tenant?", - field_64: "What is person 6’s age?", - field_65: "Person 6's sex, as registered at birth", - field_66: "Which of these best describes person 6’s working situation?", - field_67: "Is person 7 the partner of the lead tenant?", - field_68: "What is person 7’s age?", - field_69: "Person 7's sex, as registered at birth", - field_70: "Which of these best describes person 7’s working situation?", - field_71: "Is person 8 the partner of the lead tenant?", - field_72: "What is person 8’s age?", - field_73: "Person 8's sex, as registered at birth", - field_74: "Which of these best describes person 8’s working situation?", - field_75: "Does anybody in the household have links to the UK armed forces?", - field_76: "Is this person still serving in the UK armed forces?", - field_77: "Was this person seriously injured or ill as a result of serving in the UK armed forces?", - field_78: "Is anybody in the household pregnant?", + field_35: "Is this letting sheltered accommodation?", + field_36: "Is this a joint tenancy?", + field_37: "Is this a starter tenancy?", + field_38: "What is the type of tenancy?", + field_39: "If 'Other', what is the type of tenancy?", + field_40: "What is the length of the fixed-term tenancy to the nearest year?", + field_41: "What is the lead tenant’s age?", + field_42: "Lead tenant's sex, as registered at birth", + field_43: "Which of these best describes the lead tenant’s ethnic background?", + field_44: "What is the lead tenant’s nationality?", + field_45: "Which of these best describes the lead tenant’s working situation?", + field_46: "Is person 2 the partner of the lead tenant?", + field_47: "What is person 2’s age?", + field_48: "Person 2's sex, as registered at birth", + field_49: "Which of these best describes person 2’s working situation?", + field_50: "Is person 3 the partner of the lead tenant?", + field_51: "What is person 3’s age?", + field_52: "Person 3's sex, as registered at birth", + field_53: "Which of these best describes person 3’s working situation?", + field_54: "Is person 4 the partner of the lead tenant?", + field_55: "What is person 4’s age?", + field_56: "Person 4's sex, as registered at birth", + field_57: "Which of these best describes person 4’s working situation?", + field_58: "Is person 5 the partner of the lead tenant?", + field_59: "What is person 5’s age?", + field_60: "Person 5's sex, as registered at birth", + field_61: "Which of these best describes person 5’s working situation?", + field_62: "Is person 6 the partner of the lead tenant?", + field_63: "What is person 6’s age?", + field_64: "Person 6's sex, as registered at birth", + field_65: "Which of these best describes person 6’s working situation?", + field_66: "Is person 7 the partner of the lead tenant?", + field_67: "What is person 7’s age?", + field_68: "Person 7's sex, as registered at birth", + field_69: "Which of these best describes person 7’s working situation?", + field_70: "Is person 8 the partner of the lead tenant?", + field_71: "What is person 8’s age?", + field_72: "Person 8's sex, as registered at birth", + field_73: "Which of these best describes person 8’s working situation?", + field_74: "Does anybody in the household have links to the UK armed forces?", + field_75: "Is this person still serving in the UK armed forces?", + field_76: "Was this person seriously injured or ill as a result of serving in the UK armed forces?", + field_77: "Is anybody in the household pregnant?", + field_78: "Does anybody in the household have any disabled access needs?", field_79: "Does anybody in the household have any disabled access needs?", field_80: "Does anybody in the household have any disabled access needs?", field_81: "Does anybody in the household have any disabled access needs?", field_82: "Does anybody in the household have any disabled access needs?", field_83: "Does anybody in the household have any disabled access needs?", - field_84: "Does anybody in the household have any disabled access needs?", - field_85: "Does anybody in the household have a physical or mental health condition (or other illness) expected to last 12 months or more?", - field_86: "Does this person’s condition affect their dexterity?", - field_87: "Does this person’s condition affect their learning or understanding or concentrating?", - field_88: "Does this person’s condition affect their hearing?", - field_89: "Does this person’s condition affect their memory?", - field_90: "Does this person’s condition affect their mental health?", - field_91: "Does this person’s condition affect their mobility?", - field_92: "Does this person’s condition affect them socially or behaviourally?", - field_93: "Does this person’s condition affect their stamina or breathing or fatigue?", - field_94: "Does this person’s condition affect their vision?", - field_95: "Does this person’s condition affect them in another way?", - field_96: "How long has the household continuously lived in the local authority area of the new letting?", - field_97: "How long has the household been on the local authority waiting list for the new letting?", - field_98: "What is the tenant’s main reason for the household leaving their last settled home?", - field_99: "If 'Other', what was the main reason for leaving their last settled home?", - field_100: "Where was the household immediately before this letting?", - field_101: "Did the household experience homelessness immediately before this letting?", - field_102: "Do you know the postcode of the household’s last settled home?", + field_84: "Does anybody in the household have a physical or mental health condition (or other illness) expected to last 12 months or more?", + field_85: "Does this person’s condition affect their dexterity?", + field_86: "Does this person’s condition affect their learning or understanding or concentrating?", + field_87: "Does this person’s condition affect their hearing?", + field_88: "Does this person’s condition affect their memory?", + field_89: "Does this person’s condition affect their mental health?", + field_90: "Does this person’s condition affect their mobility?", + field_91: "Does this person’s condition affect them socially or behaviourally?", + field_92: "Does this person’s condition affect their stamina or breathing or fatigue?", + field_93: "Does this person’s condition affect their vision?", + field_94: "Does this person’s condition affect them in another way?", + field_95: "How long has the household continuously lived in the local authority area of the new letting?", + field_96: "How long has the household been on the local authority waiting list for the new letting?", + field_97: "What is the tenant’s main reason for the household leaving their last settled home?", + field_98: "If 'Other', what was the main reason for leaving their last settled home?", + field_99: "Where was the household immediately before this letting?", + field_100: "Did the household experience homelessness immediately before this letting?", + field_101: "Do you know the postcode of the household’s last settled home?", + field_102: "What is the postcode of the household’s last settled home?", field_103: "What is the postcode of the household’s last settled home?", - field_104: "What is the postcode of the household’s last settled home?", - field_105: "What is the local authority of the household’s last settled home?", - field_106: "Was the household given 'reasonable preference' by the local authority?", - field_107: "Reasonable preference reason - They were homeless or about to lose their home (within 56 days)", - field_108: "Reasonable preference reason - They were living in insanitary, overcrowded or unsatisfactory housing", - field_109: "Reasonable preference reason - They needed to move on medical and welfare reasons (including disability)", - field_110: "Reasonable preference reason - They needed to move to avoid hardship to themselves or others", - field_111: "Reasonable preference reason - Don’t know", - field_112: "Was the letting made under the Choice-Based Lettings (CBL)?", - field_113: "Was the letting made under the Common Allocation Policy (CAP)?", - field_114: "Was the letting made under the Common Housing Register (CHR)?", - field_115: "Was the letting made under the Accessible Register?", - field_116: "What was the source of referral for this letting? - LA properties", - field_117: "Do you know the household’s combined total income after tax?", - field_118: "How often does the household receive income?", - field_119: "How much income does the household have in total?", - field_120: "Is the tenant likely to be receiving any of these housing-related benefits?", - field_121: "How much of the household’s income is from Universal Credit, state pensions or benefits?", - field_122: "Does the household pay rent or other charges for the accommodation?", - field_123: "How often does the household pay rent and other charges?", - field_124: "What is the basic rent?", - field_125: "What is the service charge?", - field_126: "What is the personal service charge?", - field_127: "What is the support charge?", - field_128: "After the household has received any housing-related benefits, will they still need to pay for rent and charges?", - field_129: "What do you expect the outstanding amount to be?", - - field_130: "Is the gender the lead tenant identifies with the same as their sex registered at birth?", - field_131: "If 'No', enter the lead tenant's gender identity", - field_132: "Is the gender person 2 identifies with the same as their sex registered at birth?", - field_133: "If 'No', enter person 2's gender identity", - field_134: "Is the gender person 3 identifies with the same as their sex registered at birth?", - field_135: "If 'No', enter person 3's gender identity", - field_136: "Is the gender person 4 identifies with the same as their sex registered at birth?", - field_137: "If 'No', enter person 4's gender identity", - field_138: "Is the gender person 5 identifies with the same as their sex registered at birth?", - field_139: "If 'No', enter person 5's gender identity", - field_140: "Is the gender person 6 identifies with the same as their sex registered at birth?", - field_141: "If 'No', enter person 6's gender identity", - field_142: "Is the gender person 7 identifies with the same as their sex registered at birth?", - field_143: "If 'No', enter person 7's gender identity", - field_144: "Is the gender person 8 identifies with the same as their sex registered at birth?", - field_145: "If 'No', enter person 8's gender identity", - - field_146: "What was the source of referral for this letting? - PRP properties part 1", - field_147: "What was the source of referral for this letting? - PRP properties part 2", - field_148: "What was the source of referral for this letting? - PRP properties part 3", + field_104: "What is the local authority of the household’s last settled home?", + field_105: "Was the household given 'reasonable preference' by the local authority?", + field_106: "Reasonable preference reason - They were homeless or about to lose their home (within 56 days)", + field_107: "Reasonable preference reason - They were living in insanitary, overcrowded or unsatisfactory housing", + field_108: "Reasonable preference reason - They needed to move on medical and welfare reasons (including disability)", + field_109: "Reasonable preference reason - They needed to move to avoid hardship to themselves or others", + field_110: "Reasonable preference reason - Don’t know", + field_111: "Was the letting made under the Choice-Based Lettings (CBL)?", + field_112: "Was the letting made under the Common Allocation Policy (CAP)?", + field_113: "Was the letting made under the Common Housing Register (CHR)?", + field_114: "Was the letting made under the Accessible Register?", + field_115: "What was the source of referral for this letting? - LA properties", + field_116: "Do you know the household’s combined total income after tax?", + field_117: "How often does the household receive income?", + field_118: "How much income does the household have in total?", + field_119: "Is the tenant likely to be receiving any of these housing-related benefits?", + field_120: "How much of the household’s income is from Universal Credit, state pensions or benefits?", + field_121: "Does the household pay rent or other charges for the accommodation?", + field_122: "How often does the household pay rent and other charges?", + field_123: "What is the basic rent?", + field_124: "What is the service charge?", + field_125: "What is the personal service charge?", + field_126: "What is the support charge?", + field_127: "After the household has received any housing-related benefits, will they still need to pay for rent and charges?", + field_128: "What do you expect the outstanding amount to be?", + + field_129: "Is the gender the lead tenant identifies with the same as their sex registered at birth?", + field_130: "If 'No', enter the lead tenant's gender identity", + field_131: "Is the gender person 2 identifies with the same as their sex registered at birth?", + field_132: "If 'No', enter person 2's gender identity", + field_133: "Is the gender person 3 identifies with the same as their sex registered at birth?", + field_134: "If 'No', enter person 3's gender identity", + field_135: "Is the gender person 4 identifies with the same as their sex registered at birth?", + field_136: "If 'No', enter person 4's gender identity", + field_137: "Is the gender person 5 identifies with the same as their sex registered at birth?", + field_138: "If 'No', enter person 5's gender identity", + field_139: "Is the gender person 6 identifies with the same as their sex registered at birth?", + field_140: "If 'No', enter person 6's gender identity", + field_141: "Is the gender person 7 identifies with the same as their sex registered at birth?", + field_142: "If 'No', enter person 7's gender identity", + field_143: "Is the gender person 8 identifies with the same as their sex registered at birth?", + field_144: "If 'No', enter person 8's gender identity", + + field_145: "What was the source of referral for this letting? - PRP properties part 1", + field_146: "What was the source of referral for this letting? - PRP properties part 2", + field_147: "What was the source of referral for this letting? - PRP properties part 3", }.freeze RENT_TYPE_BU_MAPPING = { @@ -200,6 +199,7 @@ class BulkUpload::Lettings::Year2026::RowParser attribute :field_16, :integer attribute :field_26, :integer attribute :field_27, :integer + attribute :field_27, :integer attribute :field_28, :integer attribute :field_29, :integer attribute :field_30, :integer @@ -207,46 +207,46 @@ class BulkUpload::Lettings::Year2026::RowParser attribute :field_32, :integer attribute :field_33, :integer attribute :field_34, :integer - attribute :field_35, :integer + attribute :field_36, :integer attribute :field_37, :integer attribute :field_38, :integer - attribute :field_39, :integer - attribute :field_40, :string - attribute :field_41, :integer - attribute :field_36, :integer + attribute :field_39, :string + attribute :field_40, :integer + attribute :field_35, :integer attribute :field_15, :integer + attribute :field_41, :string attribute :field_42, :string - attribute :field_43, :string + attribute :field_43, :integer attribute :field_44, :integer attribute :field_45, :integer attribute :field_46, :integer - attribute :field_47, :integer + attribute :field_47, :string attribute :field_48, :string - attribute :field_49, :string + attribute :field_49, :integer attribute :field_50, :integer - attribute :field_51, :integer + attribute :field_51, :string attribute :field_52, :string - attribute :field_53, :string + attribute :field_53, :integer attribute :field_54, :integer - attribute :field_55, :integer + attribute :field_55, :string attribute :field_56, :string - attribute :field_57, :string + attribute :field_57, :integer attribute :field_58, :integer - attribute :field_59, :integer + attribute :field_59, :string attribute :field_60, :string - attribute :field_61, :string + attribute :field_61, :integer attribute :field_62, :integer - attribute :field_63, :integer + attribute :field_63, :string attribute :field_64, :string - attribute :field_65, :string + attribute :field_65, :integer attribute :field_66, :integer - attribute :field_67, :integer + attribute :field_67, :string attribute :field_68, :string - attribute :field_69, :string + attribute :field_69, :integer attribute :field_70, :integer - attribute :field_71, :integer + attribute :field_71, :string attribute :field_72, :string - attribute :field_73, :string + attribute :field_73, :integer attribute :field_74, :integer attribute :field_75, :integer attribute :field_76, :integer @@ -271,14 +271,14 @@ class BulkUpload::Lettings::Year2026::RowParser attribute :field_95, :integer attribute :field_96, :integer attribute :field_97, :integer - attribute :field_98, :integer - attribute :field_99, :string + attribute :field_98, :string + attribute :field_99, :integer attribute :field_100, :integer attribute :field_101, :integer - attribute :field_102, :integer + attribute :field_102, :string attribute :field_103, :string attribute :field_104, :string - attribute :field_105, :string + attribute :field_105, :integer attribute :field_106, :integer attribute :field_107, :integer attribute :field_108, :integer @@ -291,19 +291,19 @@ class BulkUpload::Lettings::Year2026::RowParser attribute :field_115, :integer attribute :field_116, :integer attribute :field_117, :integer - attribute :field_118, :integer - attribute :field_119, :decimal + attribute :field_118, :decimal + attribute :field_119, :integer attribute :field_120, :integer attribute :field_121, :integer attribute :field_122, :integer - attribute :field_123, :integer + attribute :field_123, :decimal attribute :field_124, :decimal attribute :field_125, :decimal attribute :field_126, :decimal - attribute :field_127, :decimal - attribute :field_128, :integer - attribute :field_129, :decimal + attribute :field_127, :integer + attribute :field_128, :decimal + attribute :field_129, :string attribute :field_130, :string attribute :field_131, :string attribute :field_132, :string @@ -311,19 +311,18 @@ class BulkUpload::Lettings::Year2026::RowParser attribute :field_134, :string attribute :field_135, :string attribute :field_136, :string - attribute :field_137, :string - attribute :field_138, :integer - attribute :field_139, :string - attribute :field_140, :integer - attribute :field_141, :string - attribute :field_142, :integer - attribute :field_143, :string - attribute :field_144, :integer - attribute :field_145, :string - + attribute :field_137, :integer + attribute :field_138, :string + attribute :field_139, :integer + attribute :field_140, :string + attribute :field_141, :integer + attribute :field_142, :string + attribute :field_143, :integer + attribute :field_144, :string + + attribute :field_145, :integer attribute :field_146, :integer attribute :field_147, :integer - attribute :field_148, :integer validate :validate_valid_radio_option, on: :before_log @@ -390,7 +389,7 @@ class BulkUpload::Lettings::Year2026::RowParser }, on: :after_log - validates :field_112, + validates :field_111, presence: { message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "was the letting made under the Choice-Based Lettings (CBL)?"), category: :not_answered, @@ -398,11 +397,11 @@ class BulkUpload::Lettings::Year2026::RowParser inclusion: { in: [1, 2], message: I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: "was the letting made under the Choice-Based Lettings (CBL)?"), - if: -> { field_112.present? }, + if: -> { field_111.present? }, }, on: :after_log - validates :field_113, + validates :field_112, presence: { message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "was the letting made under the Common Allocation Policy (CAP)?"), category: :not_answered, @@ -410,11 +409,11 @@ class BulkUpload::Lettings::Year2026::RowParser inclusion: { in: [1, 2], message: I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: "was the letting made under the Common Allocation Policy (CAP)?"), - if: -> { field_113.present? }, + if: -> { field_112.present? }, }, on: :after_log - validates :field_114, + validates :field_113, presence: { message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "was the letting made under the Common Housing Register (CHR)?"), category: :not_answered, @@ -422,11 +421,11 @@ class BulkUpload::Lettings::Year2026::RowParser inclusion: { in: [1, 2], message: I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: "was the letting made under the Common Housing Register (CHR)?"), - if: -> { field_114.present? }, + if: -> { field_113.present? }, }, on: :after_log - validates :field_115, + validates :field_114, presence: { message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "was the letting made under the Accessible Register?"), category: :not_answered, @@ -434,18 +433,18 @@ class BulkUpload::Lettings::Year2026::RowParser inclusion: { in: [1, 2], message: I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: "was the letting made under the Accessible Register?"), - if: -> { field_115.present? }, + if: -> { field_114.present? }, }, on: :after_log - validates :field_42, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 1) }, on: :after_log - validates :field_48, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 2) }, on: :after_log, if: proc { details_known?(2).zero? } - validates :field_52, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 3) }, on: :after_log, if: proc { details_known?(3).zero? } - validates :field_56, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 4) }, on: :after_log, if: proc { details_known?(4).zero? } - validates :field_60, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 5) }, on: :after_log, if: proc { details_known?(5).zero? } - validates :field_64, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 6) }, on: :after_log, if: proc { details_known?(6).zero? } - validates :field_68, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 7) }, on: :after_log, if: proc { details_known?(7).zero? } - validates :field_72, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 8) }, on: :after_log, if: proc { details_known?(8).zero? } + validates :field_41, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 1) }, on: :after_log + validates :field_47, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 2) }, on: :after_log, if: proc { details_known?(2).zero? } + validates :field_51, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 3) }, on: :after_log, if: proc { details_known?(3).zero? } + validates :field_55, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 4) }, on: :after_log, if: proc { details_known?(4).zero? } + validates :field_59, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 5) }, on: :after_log, if: proc { details_known?(5).zero? } + validates :field_63, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 6) }, on: :after_log, if: proc { details_known?(6).zero? } + validates :field_67, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 7) }, on: :after_log, if: proc { details_known?(7).zero? } + validates :field_71, format: { with: /\A\d{1,3}\z|\AR\z/, message: I18n.t("#{ERROR_BASE_KEY}.age.invalid", person_num: 8) }, on: :after_log, if: proc { details_known?(8).zero? } validate :validate_needs_type_present, on: :after_log validate :validate_data_types, on: :after_log @@ -580,12 +579,12 @@ class BulkUpload::Lettings::Year2026::RowParser !general_needs? ? :field_6.to_s : nil, # location # TODO: CLDC-4119: remove location from hash !supported_housing? ? "field_23" : nil, # postcode # TODO: CLDC-4119: add postcode to hash for supported housing !supported_housing? ? "field_24" : nil, # postcode # TODO: CLDC-4119: add postcode to hash for supported housing - "field_42", # age1 - "field_43", # sexrab1 - "field_46", # ecstat1 + "field_41", # age1 + "field_42", # sexrab1 + "field_45", # ecstat1 ) - if [field_124, field_125, field_126, field_127].all?(&:present?) - hash.merge({ "tcharge" => [field_124, field_125, field_126, field_127].sum }) + if [field_123, field_124, field_125, field_126].all?(&:present?) + hash.merge({ "tcharge" => [field_123, field_124, field_125, field_126].sum }) else hash end @@ -594,7 +593,7 @@ class BulkUpload::Lettings::Year2026::RowParser def add_duplicate_found_in_spreadsheet_errors spreadsheet_duplicate_hash.each_key do |field| if field == "tcharge" - %w[field_124 field_125 field_126 field_127].each do |sub_field| + %w[field_123 field_124 field_125 field_126].each do |sub_field| errors.add(sub_field, I18n.t("#{ERROR_BASE_KEY}.spreadsheet_dupe"), category: :setup) end else @@ -703,14 +702,14 @@ private end def validate_nationality - if field_45.present? && !valid_nationality_options.include?(field_45.to_s) - errors.add(:field_45, I18n.t("#{ERROR_BASE_KEY}.nationality.invalid")) + if field_44.present? && !valid_nationality_options.include?(field_44.to_s) + errors.add(:field_44, I18n.t("#{ERROR_BASE_KEY}.nationality.invalid")) end end def validate_reasonpref_reason_values valid_reasonpref_reason_options = %w[0 1] - %w[field_107 field_108 field_109 field_110 field_111].each do |field| + %w[field_106 field_107 field_108 field_109 field_110].each do |field| next unless send(field).present? && !valid_reasonpref_reason_options.include?(send(field).to_s) question_text = QUESTIONS[field.to_sym] @@ -721,9 +720,9 @@ private def validate_prevten_value_when_renewal return unless renewal? - return if field_100.blank? || [6, 30, 31, 32, 33, 34, 35, 38].include?(field_100) + return if field_99.blank? || [6, 30, 31, 32, 33, 34, 35, 38].include?(field_99) - errors.add(:field_100, I18n.t("#{ERROR_BASE_KEY}.prevten.invalid")) + errors.add(:field_99, I18n.t("#{ERROR_BASE_KEY}.prevten.invalid")) end def duplicate_check_fields @@ -748,41 +747,41 @@ private end def validate_no_and_dont_know_disabled_needs_conjunction - if field_83 == 1 && field_84 == 1 + if field_82 == 1 && field_83 == 1 + errors.add(:field_82, I18n.t("#{ERROR_BASE_KEY}.housingneeds.no_and_dont_know_disabled_needs_conjunction")) errors.add(:field_83, I18n.t("#{ERROR_BASE_KEY}.housingneeds.no_and_dont_know_disabled_needs_conjunction")) - errors.add(:field_84, I18n.t("#{ERROR_BASE_KEY}.housingneeds.no_and_dont_know_disabled_needs_conjunction")) end end def validate_dont_know_disabled_needs_conjunction - if field_84 == 1 && [field_79, field_80, field_81, field_82].count(1).positive? - %i[field_84 field_79 field_80 field_81 field_82].each do |field| + if field_83 == 1 && [field_78, field_79, field_80, field_81].count(1).positive? + %i[field_83 field_78 field_79 field_80 field_81].each do |field| errors.add(field, I18n.t("#{ERROR_BASE_KEY}.housingneeds.dont_know_disabled_needs_conjunction")) if send(field) == 1 end end end def validate_no_disabled_needs_conjunction - if field_83 == 1 && [field_79, field_80, field_81, field_82].count(1).positive? - %i[field_83 field_79 field_80 field_81 field_82].each do |field| + if field_82 == 1 && [field_78, field_79, field_80, field_81].count(1).positive? + %i[field_82 field_78 field_79 field_80 field_81].each do |field| errors.add(field, I18n.t("#{ERROR_BASE_KEY}.housingneeds.no_disabled_needs_conjunction")) if send(field) == 1 end end end def validate_only_one_housing_needs_type - if [field_79, field_80, field_81].count(1) > 1 - %i[field_79 field_80 field_81].each do |field| + if [field_78, field_79, field_80].count(1) > 1 + %i[field_78 field_79 field_80].each do |field| errors.add(field, I18n.t("#{ERROR_BASE_KEY}.housingneeds_type.only_one_option_permitted")) if send(field) == 1 end end end def validate_no_housing_needs_questions_answered - if [field_79, field_80, field_81, field_82, field_83, field_84].all?(&:blank?) - errors.add(:field_83, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "anybody with disabled access needs.")) - errors.add(:field_82, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "other access needs.")) - %i[field_79 field_80 field_81].each do |field| + if [field_78, field_79, field_80, field_81, field_82, field_83].all?(&:blank?) + errors.add(:field_82, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "anybody with disabled access needs.")) + errors.add(:field_81, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "other access needs.")) + %i[field_78 field_79 field_80].each do |field| errors.add(field, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "disabled access needs type.")) end end @@ -790,16 +789,16 @@ private def validate_reasonable_preference_dont_know if rp_dontknow_conflict? - errors.add(:field_111, I18n.t("#{ERROR_BASE_KEY}.reasonpref.conflict.dont_know")) - %i[field_107 field_108 field_109 field_110].each do |field| + errors.add(:field_110, I18n.t("#{ERROR_BASE_KEY}.reasonpref.conflict.dont_know")) + %i[field_106 field_107 field_108 field_109].each do |field| errors.add(field, I18n.t("#{ERROR_BASE_KEY}.reasonpref.conflict.other")) if send(field) == 1 end end end def validate_reasonable_preference_homeless - reason_fields = %i[field_107 field_108 field_109 field_110 field_111] - if field_106 == 1 && reason_fields.all? { |field| attributes[field.to_s].blank? } + reason_fields = %i[field_106 field_107 field_108 field_109 field_110] + if field_105 == 1 && reason_fields.all? { |field| attributes[field.to_s].blank? } reason_fields.each do |field| errors.add(field, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "reason for reasonable preference.")) end @@ -807,7 +806,7 @@ private end def validate_condition_effects - illness_option_fields = %i[field_94 field_88 field_91 field_86 field_87 field_89 field_90 field_93 field_92 field_95] + illness_option_fields = %i[field_93 field_87 field_90 field_85 field_86 field_88 field_89 field_92 field_91 field_94] if household_no_illness? illness_option_fields.each do |field| if attributes[field.to_s] == 1 @@ -822,12 +821,12 @@ private end def household_no_illness? - field_85 != 1 + field_84 != 1 end def validate_leaving_reason_for_renewal - if renewal? && ![50, 51, 52, 53].include?(field_98) - errors.add(:field_98, I18n.t("#{ERROR_BASE_KEY}.reason.renewal_reason_needed")) + if renewal? && ![50, 51, 52, 53].include?(field_97) + errors.add(:field_97, I18n.t("#{ERROR_BASE_KEY}.reason.renewal_reason_needed")) end end @@ -968,13 +967,13 @@ private end def validate_all_charges_given - return if supported_housing? && field_124 == 1 + return if supported_housing? && field_123 == 1 blank_charge_fields, other_charge_fields = { - field_124: "basic rent", - field_125: "service charge", - field_126: "personal service charge", - field_127: "support charge", + field_123: "basic rent", + field_124: "service charge", + field_125: "personal service charge", + field_126: "support charge", }.partition { |field, _| public_send(field).blank? }.map(&:to_h) blank_charge_fields.each do |field, charge| @@ -990,7 +989,7 @@ private end def all_charges_given? - field_124.present? && field_125.present? && field_126.present? && field_127.present? + field_123.present? && field_124.present? && field_125.present? && field_126.present? end def setup_question?(question) @@ -1011,52 +1010,52 @@ private errors.add(:field_23, error_message) unless supported_housing? # postcode_full # TODO: CLDC-4119: add postcode to error fields for supported housing errors.add(:field_24, error_message) unless supported_housing? # postcode_full # TODO: CLDC-4119: add postcode to error fields for supported housing errors.add(:field_25, error_message) unless supported_housing? # la # TODO: CLDC-4119: add LA to error fields for supported housing - errors.add(:field_42, error_message) # age1 - errors.add(:field_43, error_message) # sexrab1 - errors.add(:field_46, error_message) # ecstat1 - errors.add(:field_122, error_message) unless general_needs? # household_charge - errors.add(:field_124, error_message) # brent - errors.add(:field_125, error_message) # scharge - errors.add(:field_126, error_message) # pscharge - errors.add(:field_127, error_message) # chcharge + errors.add(:field_41, error_message) # age1 + errors.add(:field_42, error_message) # sexrab1 + errors.add(:field_45, error_message) # ecstat1 + errors.add(:field_121, error_message) unless general_needs? # household_charge + errors.add(:field_123, error_message) # brent + errors.add(:field_124, error_message) # scharge + errors.add(:field_125, error_message) # pscharge + errors.add(:field_126, error_message) # chcharge end end def field_referral_register_la_valid? if owning_organisation&.la? - [1, 2, 3, 4].include?(field_116) + [1, 2, 3, 4].include?(field_115) else - field_116.blank? + field_115.blank? end end def field_referral_register_prp_valid? if owning_organisation&.prp? - [5, 6, 7, 8, 9].include?(field_146) + [5, 6, 7, 8, 9].include?(field_145) else - field_146.blank? + field_145.blank? end end def field_referral_noms_valid? - case field_146 + case field_145 when 6 - [1, 2, 3, 4].include?(field_147) + [1, 2, 3, 4].include?(field_146) when 7 - [5, 6, 7, 8].include?(field_147) + [5, 6, 7, 8].include?(field_146) else - field_147.blank? + field_146.blank? end end def field_referral_org_valid? - case field_147 + case field_146 when 1 - [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].include?(field_148) + [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].include?(field_147) when 7 - [11, 12, 13, 14, 15, 16, 17, 18, 19, 20].include?(field_148) + [11, 12, 13, 14, 15, 16, 17, 18, 19, 20].include?(field_147) else - field_148.blank? + field_147.blank? end end @@ -1068,7 +1067,7 @@ private return if renewal? return if referral_fields_valid? - %i[field_116 field_146 field_147 field_148].each do |field| + %i[field_115 field_145 field_146 field_147].each do |field| errors.add(field, I18n.t("#{ERROR_BASE_KEY}.referral.invalid_option")) end end @@ -1094,140 +1093,139 @@ private rent_type: %i[field_11], startdate: %i[field_8 field_9 field_10], unittype_gn: %i[field_26], - builtype: %i[field_27], - wchair: %i[field_28], - beds: %i[field_29], - joint: %i[field_37], - startertenancy: %i[field_38], - tenancy: %i[field_39], - tenancyother: %i[field_40], - tenancylength: %i[field_41], + wchair: %i[field_27], + beds: %i[field_28], + joint: %i[field_36], + startertenancy: %i[field_37], + tenancy: %i[field_38], + tenancyother: %i[field_39], + tenancylength: %i[field_40], declaration: %i[field_15], - age1_known: %i[field_42], - age1: %i[field_42], - age2_known: %i[field_48], - age2: %i[field_48], - age3_known: %i[field_52], - age3: %i[field_52], - age4_known: %i[field_56], - age4: %i[field_56], - age5_known: %i[field_60], - age5: %i[field_60], - age6_known: %i[field_64], - age6: %i[field_64], - age7_known: %i[field_68], - age7: %i[field_68], - age8_known: %i[field_72], - age8: %i[field_72], - - sexrab1: %i[field_43], - sexrab2: %i[field_49], - sexrab3: %i[field_53], - sexrab4: %i[field_57], - sexrab5: %i[field_61], - sexrab6: %i[field_65], - sexrab7: %i[field_69], - sexrab8: %i[field_73], - - ethnic_group: %i[field_44], - ethnic: %i[field_44], - nationality_all: %i[field_45], - nationality_all_group: %i[field_45], - - relat2: %i[field_47], - relat3: %i[field_51], - relat4: %i[field_55], - relat5: %i[field_59], - relat6: %i[field_63], - relat7: %i[field_67], - relat8: %i[field_71], - - ecstat1: %i[field_46], - ecstat2: %i[field_50], - ecstat3: %i[field_54], - ecstat4: %i[field_58], - ecstat5: %i[field_62], - ecstat6: %i[field_66], - ecstat7: %i[field_70], - ecstat8: %i[field_74], - - armedforces: %i[field_75], - leftreg: %i[field_76], - reservist: %i[field_77], - preg_occ: %i[field_78], - housingneeds: %i[field_78], - - illness: %i[field_85], - - layear: %i[field_96], - waityear: %i[field_97], - reason: %i[field_98], - reasonother: %i[field_99], - prevten: %i[field_100], - homeless: %i[field_101], - - prevloc: %i[field_105], - previous_la_known: %i[field_105], - ppcodenk: %i[field_102], - ppostcode_full: %i[field_103 field_104], - - reasonpref: %i[field_106], - rp_homeless: %i[field_107], - rp_insan_unsat: %i[field_108], - rp_medwel: %i[field_109], - rp_hardship: %i[field_110], - rp_dontknow: %i[field_111], - - cbl: %i[field_112], - cap: %i[field_113], - chr: %i[field_114], - accessible_register: %i[field_115], - letting_allocation: %i[field_112 field_113 field_114 field_115], - - referral_register: %i[field_116 field_146], - referral_noms: %i[field_147], - referral_org: %i[field_148], - - net_income_known: %i[field_117], - incfreq: %i[field_118], - earnings: %i[field_119], - hb: %i[field_120], - benefits: %i[field_121], - - period: %i[field_123], - brent: %i[field_124], - scharge: %i[field_125], - pscharge: %i[field_126], - supcharg: %i[field_127], - tcharge: %i[field_124 field_125 field_126 field_127], - household_charge: %i[field_122], - hbrentshortfall: %i[field_128], - tshortfall: %i[field_129], + age1_known: %i[field_41], + age1: %i[field_41], + age2_known: %i[field_47], + age2: %i[field_47], + age3_known: %i[field_51], + age3: %i[field_51], + age4_known: %i[field_55], + age4: %i[field_55], + age5_known: %i[field_59], + age5: %i[field_59], + age6_known: %i[field_63], + age6: %i[field_63], + age7_known: %i[field_67], + age7: %i[field_67], + age8_known: %i[field_71], + age8: %i[field_71], + + sexrab1: %i[field_42], + sexrab2: %i[field_48], + sexrab3: %i[field_52], + sexrab4: %i[field_56], + sexrab5: %i[field_60], + sexrab6: %i[field_64], + sexrab7: %i[field_68], + sexrab8: %i[field_72], + + ethnic_group: %i[field_43], + ethnic: %i[field_43], + nationality_all: %i[field_44], + nationality_all_group: %i[field_44], + + relat2: %i[field_46], + relat3: %i[field_50], + relat4: %i[field_54], + relat5: %i[field_58], + relat6: %i[field_62], + relat7: %i[field_66], + relat8: %i[field_70], + + ecstat1: %i[field_45], + ecstat2: %i[field_49], + ecstat3: %i[field_53], + ecstat4: %i[field_57], + ecstat5: %i[field_61], + ecstat6: %i[field_65], + ecstat7: %i[field_69], + ecstat8: %i[field_73], + + armedforces: %i[field_74], + leftreg: %i[field_75], + reservist: %i[field_76], + preg_occ: %i[field_77], + housingneeds: %i[field_77], + + illness: %i[field_84], + + layear: %i[field_95], + waityear: %i[field_96], + reason: %i[field_97], + reasonother: %i[field_98], + prevten: %i[field_99], + homeless: %i[field_100], + + prevloc: %i[field_104], + previous_la_known: %i[field_104], + ppcodenk: %i[field_101], + ppostcode_full: %i[field_102 field_103], + + reasonpref: %i[field_105], + rp_homeless: %i[field_106], + rp_insan_unsat: %i[field_107], + rp_medwel: %i[field_108], + rp_hardship: %i[field_109], + rp_dontknow: %i[field_110], + + cbl: %i[field_111], + cap: %i[field_112], + chr: %i[field_113], + accessible_register: %i[field_114], + letting_allocation: %i[field_111 field_112 field_113 field_114], + + referral_register: %i[field_115 field_145], + referral_noms: %i[field_146], + referral_org: %i[field_147], + + net_income_known: %i[field_116], + incfreq: %i[field_117], + earnings: %i[field_118], + hb: %i[field_119], + benefits: %i[field_120], + + period: %i[field_122], + brent: %i[field_123], + scharge: %i[field_124], + pscharge: %i[field_125], + supcharg: %i[field_126], + tcharge: %i[field_123 field_124 field_125 field_126], + household_charge: %i[field_121], + hbrentshortfall: %i[field_127], + tshortfall: %i[field_128], unitletas: %i[field_17], rsnvac: %i[field_16], - sheltered: %i[field_36], - - illness_type_1: %i[field_94], - illness_type_2: %i[field_88], - illness_type_3: %i[field_91], - illness_type_4: %i[field_86], - illness_type_5: %i[field_87], - illness_type_6: %i[field_89], - illness_type_7: %i[field_90], - illness_type_8: %i[field_93], - illness_type_9: %i[field_92], - illness_type_10: %i[field_95], + sheltered: %i[field_35], + + illness_type_1: %i[field_93], + illness_type_2: %i[field_87], + illness_type_3: %i[field_90], + illness_type_4: %i[field_85], + illness_type_5: %i[field_86], + illness_type_6: %i[field_88], + illness_type_7: %i[field_89], + illness_type_8: %i[field_92], + illness_type_9: %i[field_91], + illness_type_10: %i[field_94], irproduct_other: %i[field_12], propcode: %i[field_14], - majorrepairs: %i[field_33 field_34 field_35], - mrcdate: %i[field_33 field_34 field_35], + majorrepairs: %i[field_32 field_33 field_34], + mrcdate: %i[field_32 field_33 field_34], - voiddate: %i[field_30 field_31 field_32], + voiddate: %i[field_29 field_30 field_31], uprn: [:field_18], address_line1: [:field_19], @@ -1236,22 +1234,22 @@ private county: [:field_22], uprn_selection: [:field_19], - gender_same_as_sex1: %i[field_130], - gender_same_as_sex2: %i[field_131], - gender_same_as_sex3: %i[field_132], - gender_same_as_sex4: %i[field_133], - gender_same_as_sex5: %i[field_134], - gender_same_as_sex6: %i[field_135], - gender_same_as_sex7: %i[field_136], - gender_same_as_sex8: %i[field_137], - gender_description1: %i[field_138], - gender_description2: %i[field_139], - gender_description3: %i[field_140], - gender_description4: %i[field_141], - gender_description5: %i[field_142], - gender_description6: %i[field_143], - gender_description7: %i[field_144], - gender_description8: %i[field_145], + gender_same_as_sex1: %i[field_129], + gender_same_as_sex2: %i[field_130], + gender_same_as_sex3: %i[field_131], + gender_same_as_sex4: %i[field_132], + gender_same_as_sex5: %i[field_133], + gender_same_as_sex6: %i[field_134], + gender_same_as_sex7: %i[field_135], + gender_same_as_sex8: %i[field_136], + gender_description1: %i[field_137], + gender_description2: %i[field_138], + gender_description3: %i[field_139], + gender_description4: %i[field_140], + gender_description5: %i[field_141], + gender_description6: %i[field_142], + gender_description7: %i[field_143], + gender_description8: %i[field_144], }.compact end @@ -1279,70 +1277,69 @@ private attributes["rent_type"] = RENT_TYPE_BU_MAPPING[field_11] attributes["startdate"] = startdate attributes["unittype_gn"] = field_26 - attributes["builtype"] = field_27 - attributes["wchair"] = field_28 - attributes["beds"] = field_26 == 2 ? 1 : field_29 - attributes["joint"] = field_37 - attributes["startertenancy"] = field_38 - attributes["tenancy"] = field_39 - attributes["tenancyother"] = field_40 - attributes["tenancylength"] = field_41 + attributes["wchair"] = field_27 + attributes["beds"] = field_26 == 2 ? 1 : field_28 + attributes["joint"] = field_36 + attributes["startertenancy"] = field_37 + attributes["tenancy"] = field_38 + attributes["tenancyother"] = field_39 + attributes["tenancylength"] = field_40 attributes["declaration"] = field_15 attributes["age1_known"] = age1_known? - attributes["age1"] = field_42 if attributes["age1_known"]&.zero? && field_42&.match(/\A\d{1,3}\z|\AR\z/) + attributes["age1"] = field_41 if attributes["age1_known"]&.zero? && field_41&.match(/\A\d{1,3}\z|\AR\z/) attributes["age2_known"] = age2_known? - attributes["age2"] = field_48 if attributes["age2_known"]&.zero? && field_48&.match(/\A\d{1,3}\z|\AR\z/) + attributes["age2"] = field_47 if attributes["age2_known"]&.zero? && field_47&.match(/\A\d{1,3}\z|\AR\z/) attributes["age3_known"] = age3_known? - attributes["age3"] = field_52 if attributes["age3_known"]&.zero? && field_52&.match(/\A\d{1,3}\z|\AR\z/) + attributes["age3"] = field_51 if attributes["age3_known"]&.zero? && field_51&.match(/\A\d{1,3}\z|\AR\z/) attributes["age4_known"] = age4_known? - attributes["age4"] = field_56 if attributes["age4_known"]&.zero? && field_56&.match(/\A\d{1,3}\z|\AR\z/) + attributes["age4"] = field_55 if attributes["age4_known"]&.zero? && field_55&.match(/\A\d{1,3}\z|\AR\z/) attributes["age5_known"] = age5_known? - attributes["age5"] = field_60 if attributes["age5_known"]&.zero? && field_60&.match(/\A\d{1,3}\z|\AR\z/) + attributes["age5"] = field_59 if attributes["age5_known"]&.zero? && field_59&.match(/\A\d{1,3}\z|\AR\z/) attributes["age6_known"] = age6_known? - attributes["age6"] = field_64 if attributes["age6_known"]&.zero? && field_64&.match(/\A\d{1,3}\z|\AR\z/) + attributes["age6"] = field_63 if attributes["age6_known"]&.zero? && field_63&.match(/\A\d{1,3}\z|\AR\z/) attributes["age7_known"] = age7_known? - attributes["age7"] = field_68 if attributes["age7_known"]&.zero? && field_68&.match(/\A\d{1,3}\z|\AR\z/) + attributes["age7"] = field_67 if attributes["age7_known"]&.zero? && field_67&.match(/\A\d{1,3}\z|\AR\z/) attributes["age8_known"] = age8_known? - attributes["age8"] = field_72 if attributes["age8_known"]&.zero? && field_72&.match(/\A\d{1,3}\z|\AR\z/) + attributes["age8"] = field_71 if attributes["age8_known"]&.zero? && field_71&.match(/\A\d{1,3}\z|\AR\z/) - attributes["sexrab1"] = field_43 - attributes["sexrab2"] = field_49 - attributes["sexrab3"] = field_53 - attributes["sexrab4"] = field_57 - attributes["sexrab5"] = field_61 - attributes["sexrab6"] = field_65 - attributes["sexrab7"] = field_69 - attributes["sexrab8"] = field_73 + attributes["sexrab1"] = field_42 + attributes["sexrab2"] = field_48 + attributes["sexrab3"] = field_52 + attributes["sexrab4"] = field_56 + attributes["sexrab5"] = field_60 + attributes["sexrab6"] = field_64 + attributes["sexrab7"] = field_68 + attributes["sexrab8"] = field_72 attributes["ethnic_group"] = ethnic_group_from_ethnic - attributes["ethnic"] = field_44 - attributes["nationality_all"] = field_45 if field_45.present? && valid_nationality_options.include?(field_45.to_s) + attributes["ethnic"] = field_43 + attributes["nationality_all"] = field_44 if field_44.present? && valid_nationality_options.include?(field_44.to_s) attributes["nationality_all_group"] = nationality_group(attributes["nationality_all"]) - attributes["relat2"] = relationship_from_input_value(field_47) - attributes["relat3"] = relationship_from_input_value(field_51) - attributes["relat4"] = relationship_from_input_value(field_55) - attributes["relat5"] = relationship_from_input_value(field_59) - attributes["relat6"] = relationship_from_input_value(field_63) - attributes["relat7"] = relationship_from_input_value(field_67) - attributes["relat8"] = relationship_from_input_value(field_71) - - attributes["ecstat1"] = field_46 - attributes["ecstat2"] = field_50 - attributes["ecstat3"] = field_54 - attributes["ecstat4"] = field_58 - attributes["ecstat5"] = field_62 - attributes["ecstat6"] = field_66 - attributes["ecstat7"] = field_70 - attributes["ecstat8"] = field_74 + attributes["relat2"] = relationship_from_input_value(field_46) + attributes["relat3"] = relationship_from_input_value(field_50) + attributes["relat4"] = relationship_from_input_value(field_54) + attributes["relat5"] = relationship_from_input_value(field_58) + attributes["relat6"] = relationship_from_input_value(field_62) + attributes["relat7"] = relationship_from_input_value(field_66) + attributes["relat8"] = relationship_from_input_value(field_70) + + attributes["ecstat1"] = field_45 + attributes["ecstat2"] = field_49 + attributes["ecstat3"] = field_53 + attributes["ecstat4"] = field_57 + attributes["ecstat5"] = field_61 + attributes["ecstat6"] = field_65 + attributes["ecstat7"] = field_69 + attributes["ecstat8"] = field_73 attributes["details_known_2"] = details_known?(2) attributes["details_known_3"] = details_known?(3) @@ -1352,36 +1349,36 @@ private attributes["details_known_7"] = details_known?(7) attributes["details_known_8"] = details_known?(8) - attributes["armedforces"] = field_75 + attributes["armedforces"] = field_74 attributes["leftreg"] = leftreg - attributes["reservist"] = field_77 + attributes["reservist"] = field_76 - attributes["preg_occ"] = field_78 + attributes["preg_occ"] = field_77 attributes["housingneeds"] = housingneeds attributes["housingneeds_type"] = housingneeds_type attributes["housingneeds_other"] = housingneeds_other - attributes["illness"] = field_85 + attributes["illness"] = field_84 - attributes["layear"] = field_96 - attributes["waityear"] = field_97 - attributes["reason"] = field_98 - attributes["reasonother"] = field_99 if reason_is_other? - attributes["prevten"] = field_100 - attributes["homeless"] = field_101 + attributes["layear"] = field_95 + attributes["waityear"] = field_96 + attributes["reason"] = field_97 + attributes["reasonother"] = field_98 if reason_is_other? + attributes["prevten"] = field_99 + attributes["homeless"] = field_100 attributes["prevloc"] = prevloc attributes["previous_la_known"] = previous_la_known attributes["ppcodenk"] = ppcodenk attributes["ppostcode_full"] = ppostcode_full - attributes["reasonpref"] = field_106 - attributes["rp_homeless"] = field_107 unless rp_dontknow_conflict? - attributes["rp_insan_unsat"] = field_108 unless rp_dontknow_conflict? - attributes["rp_medwel"] = field_109 unless rp_dontknow_conflict? - attributes["rp_hardship"] = field_110 unless rp_dontknow_conflict? - attributes["rp_dontknow"] = field_111 unless rp_dontknow_conflict? + attributes["reasonpref"] = field_105 + attributes["rp_homeless"] = field_106 unless rp_dontknow_conflict? + attributes["rp_insan_unsat"] = field_107 unless rp_dontknow_conflict? + attributes["rp_medwel"] = field_108 unless rp_dontknow_conflict? + attributes["rp_hardship"] = field_109 unless rp_dontknow_conflict? + attributes["rp_dontknow"] = field_110 unless rp_dontknow_conflict? attributes["cbl"] = cbl attributes["chr"] = chr @@ -1395,36 +1392,36 @@ private attributes["net_income_known"] = net_income_known attributes["earnings"] = earnings - attributes["incfreq"] = field_118 - attributes["hb"] = field_120 - attributes["benefits"] = field_121 - - attributes["period"] = field_123 - attributes["brent"] = field_124 if all_charges_given? - attributes["scharge"] = field_125 if all_charges_given? - attributes["pscharge"] = field_126 if all_charges_given? - attributes["supcharg"] = field_127 if all_charges_given? - attributes["household_charge"] = supported_housing? ? field_122 : nil - attributes["hbrentshortfall"] = field_128 + attributes["incfreq"] = field_117 + attributes["hb"] = field_119 + attributes["benefits"] = field_120 + + attributes["period"] = field_122 + attributes["brent"] = field_123 if all_charges_given? + attributes["scharge"] = field_124 if all_charges_given? + attributes["pscharge"] = field_125 if all_charges_given? + attributes["supcharg"] = field_126 if all_charges_given? + attributes["household_charge"] = supported_housing? ? field_121 : nil + attributes["hbrentshortfall"] = field_127 attributes["tshortfall_known"] = tshortfall_known - attributes["tshortfall"] = field_129 + attributes["tshortfall"] = field_128 attributes["hhmemb"] = hhmemb attributes["unitletas"] = field_17 attributes["rsnvac"] = rsnvac - attributes["sheltered"] = field_36 - - attributes["illness_type_1"] = field_94 - attributes["illness_type_2"] = field_88 - attributes["illness_type_3"] = field_91 - attributes["illness_type_4"] = field_86 - attributes["illness_type_5"] = field_87 - attributes["illness_type_6"] = field_89 - attributes["illness_type_7"] = field_90 - attributes["illness_type_8"] = field_93 - attributes["illness_type_9"] = field_92 - attributes["illness_type_10"] = field_95 + attributes["sheltered"] = field_35 + + attributes["illness_type_1"] = field_93 + attributes["illness_type_2"] = field_87 + attributes["illness_type_3"] = field_90 + attributes["illness_type_4"] = field_85 + attributes["illness_type_5"] = field_86 + attributes["illness_type_6"] = field_88 + attributes["illness_type_7"] = field_89 + attributes["illness_type_8"] = field_92 + attributes["illness_type_9"] = field_91 + attributes["illness_type_10"] = field_94 attributes["irproduct_other"] = field_12 if RENT_TYPE_BU_MAPPING[field_11] == 5 @@ -1459,22 +1456,22 @@ private attributes["postcode_full_input"] = postcode_full attributes["select_best_address_match"] = true if field_18.blank? - attributes["gender_same_as_sex1"] = field_130 - attributes["gender_description1"] = field_131 - attributes["gender_same_as_sex2"] = field_132 - attributes["gender_description2"] = field_133 - attributes["gender_same_as_sex3"] = field_134 - attributes["gender_description3"] = field_135 - attributes["gender_same_as_sex4"] = field_136 - attributes["gender_description4"] = field_137 - attributes["gender_same_as_sex5"] = field_138 - attributes["gender_description5"] = field_139 - attributes["gender_same_as_sex6"] = field_140 - attributes["gender_description6"] = field_141 - attributes["gender_same_as_sex7"] = field_142 - attributes["gender_description7"] = field_143 - attributes["gender_same_as_sex8"] = field_144 - attributes["gender_description8"] = field_145 + attributes["gender_same_as_sex1"] = field_129 + attributes["gender_description1"] = field_130 + attributes["gender_same_as_sex2"] = field_131 + attributes["gender_description2"] = field_132 + attributes["gender_same_as_sex3"] = field_133 + attributes["gender_description3"] = field_134 + attributes["gender_same_as_sex4"] = field_135 + attributes["gender_description4"] = field_136 + attributes["gender_same_as_sex5"] = field_137 + attributes["gender_description5"] = field_138 + attributes["gender_same_as_sex6"] = field_139 + attributes["gender_description6"] = field_140 + attributes["gender_same_as_sex7"] = field_141 + attributes["gender_description7"] = field_142 + attributes["gender_same_as_sex8"] = field_143 + attributes["gender_description8"] = field_144 attributes end @@ -1538,9 +1535,9 @@ private end def ethnic_group_from_ethnic - return nil if field_44.blank? + return nil if field_43.blank? - case field_44 + case field_43 when 1, 2, 3, 18, 20 0 when 4, 5, 6, 7 @@ -1557,19 +1554,19 @@ private end def age1_known? - return 1 if field_42 == "R" + return 1 if field_41 == "R" 0 end [ - { person: 2, field: :field_48 }, - { person: 3, field: :field_52 }, - { person: 4, field: :field_56 }, - { person: 5, field: :field_60 }, - { person: 6, field: :field_64 }, - { person: 7, field: :field_68 }, - { person: 8, field: :field_72 }, + { person: 2, field: :field_47 }, + { person: 3, field: :field_51 }, + { person: 4, field: :field_55 }, + { person: 5, field: :field_59 }, + { person: 6, field: :field_63 }, + { person: 7, field: :field_67 }, + { person: 8, field: :field_71 }, ].each do |hash| define_method("age#{hash[:person]}_known?") do return 1 if public_send(hash[:field]) == "R" @@ -1582,53 +1579,53 @@ private end def person_2_present? - field_47.present? || field_48.present? || field_49.present? || field_132.present? || field_133.present? + field_46.present? || field_47.present? || field_48.present? || field_131.present? || field_132.present? end def person_3_present? - field_51.present? || field_52.present? || field_53.present? || field_134.present? || field_135.present? + field_50.present? || field_51.present? || field_52.present? || field_133.present? || field_134.present? end def person_4_present? - field_55.present? || field_56.present? || field_57.present? || field_136.present? || field_137.present? + field_54.present? || field_55.present? || field_56.present? || field_135.present? || field_136.present? end def person_5_present? - field_59.present? || field_60.present? || field_61.present? || field_138.present? || field_139.present? + field_58.present? || field_59.present? || field_60.present? || field_137.present? || field_138.present? end def person_6_present? - field_63.present? || field_64.present? || field_65.present? || field_140.present? || field_141.present? + field_62.present? || field_63.present? || field_64.present? || field_139.present? || field_140.present? end def person_7_present? - field_67.present? || field_68.present? || field_69.present? || field_142.present? || field_143.present? + field_66.present? || field_67.present? || field_68.present? || field_141.present? || field_142.present? end def person_8_present? - field_71.present? || field_72.present? || field_73.present? || field_144.present? || field_145.present? + field_70.present? || field_71.present? || field_72.present? || field_143.present? || field_144.present? end def leftreg - field_76 + field_75 end def housingneeds - if field_83 == 1 + if field_82 == 1 2 - elsif field_84 == 1 + elsif field_83 == 1 3 - elsif field_83.blank? || field_83&.zero? + elsif field_82.blank? || field_82&.zero? 1 end end def housingneeds_type - if field_79 == 1 + if field_78 == 1 0 - elsif field_80 == 1 + elsif field_79 == 1 1 - elsif field_81 == 1 + elsif field_80 == 1 2 else 3 @@ -1636,12 +1633,12 @@ private end def housingneeds_other - return 1 if field_82 == 1 - return 0 if [field_79, field_80, field_81].include?(1) + return 1 if field_81 == 1 + return 0 if [field_78, field_79, field_80].include?(1) end def prevloc - field_105 + field_104 end def previous_la_known @@ -1649,7 +1646,7 @@ private end def ppcodenk - case field_102 + case field_101 when 1 0 when 2 @@ -1658,11 +1655,11 @@ private end def ppostcode_full - "#{field_103} #{field_104}".strip.gsub(/\s+/, " ") + "#{field_102} #{field_103}".strip.gsub(/\s+/, " ") end def cbl - case field_112 + case field_111 when 2 0 when 1 @@ -1671,7 +1668,7 @@ private end def cap - case field_113 + case field_112 when 2 0 when 1 @@ -1680,7 +1677,7 @@ private end def chr - case field_114 + case field_113 when 2 0 when 1 @@ -1689,7 +1686,7 @@ private end def accessible_register - case field_115 + case field_114 when 2 0 when 1 @@ -1702,7 +1699,7 @@ private end def net_income_known - case field_117 + case field_116 when 1 0 when 2 @@ -1713,11 +1710,11 @@ private end def earnings - field_119.round if field_119.present? + field_118.round if field_118.present? end def tshortfall_known - field_128 == 1 ? 0 : 1 + field_127 == 1 ? 0 : 1 end def hhmemb @@ -1737,15 +1734,15 @@ private end def mrcdate - year = field_35.to_s.strip.length.between?(1, 2) ? field_35 + 2000 : field_35 - Date.new(year, field_34, field_33) if field_35.present? && field_34.present? && field_33.present? + year = field_34.to_s.strip.length.between?(1, 2) ? field_34 + 2000 : field_34 + Date.new(year, field_33, field_32) if field_34.present? && field_33.present? && field_32.present? rescue Date::Error Date.new end def voiddate - year = field_32.to_s.strip.length.between?(1, 2) ? field_32 + 2000 : field_32 - Date.new(year, field_31, field_30) if field_32.present? && field_31.present? && field_30.present? + year = field_31.to_s.strip.length.between?(1, 2) ? field_31 + 2000 : field_31 + Date.new(year, field_30, field_29) if field_31.present? && field_30.present? && field_29.present? rescue Date::Error Date.new end @@ -1772,7 +1769,7 @@ private end def reason_is_other? - field_98 == 20 + field_97 == 20 end def bulk_upload_organisation @@ -1791,10 +1788,10 @@ private end def rp_dontknow_conflict? - other_reason_fields = %i[field_107 field_108 field_109 field_110] - if field_106 == 1 + other_reason_fields = %i[field_106 field_107 field_108 field_109] + if field_105 == 1 selected_reasons = other_reason_fields.select { |field| send(field) == 1 } - dont_know_selected = field_111 == 1 + dont_know_selected = field_110 == 1 return true if selected_reasons.any? && dont_know_selected end @@ -1810,9 +1807,9 @@ private return unless referral_fields_valid? if owning_organisation.la? - field_116 + field_115 else - field_146 + field_145 end end @@ -1821,7 +1818,7 @@ private return unless referral_fields_valid? if owning_organisation.prp? - field_147 + field_146 end end @@ -1830,7 +1827,7 @@ private return unless referral_fields_valid? if owning_organisation.prp? - field_148 + field_147 end end end diff --git a/spec/services/bulk_upload/lettings/year2026/csv_parser_spec.rb b/spec/services/bulk_upload/lettings/year2026/csv_parser_spec.rb index 14d2ede4b..d127767e0 100644 --- a/spec/services/bulk_upload/lettings/year2026/csv_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2026/csv_parser_spec.rb @@ -244,10 +244,10 @@ RSpec.describe BulkUpload::Lettings::Year2026::CsvParser do end it "returns correct column" do - expect(service.column_for_field("field_5")).to eql("AA") - expect(service.column_for_field("field_22")).to eql("BK") - expect(service.column_for_field("field_26")).to eql("BZ") - expect(service.column_for_field("field_25")).to eql("S") + expect(service.column_for_field("field_5")).to eql("T") + expect(service.column_for_field("field_22")).to eql("BG") + expect(service.column_for_field("field_26")).to eql("BX") + expect(service.column_for_field("field_25")).to eql("F") end end end diff --git a/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb b/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb index 8f0e4b0b8..8fa0ec40c 100644 --- a/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb @@ -119,7 +119,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when calling the method multiple times" do - let(:attributes) { { bulk_upload:, field_129: 2 } } + let(:attributes) { { bulk_upload:, field_128: 2 } } it "does not add keep adding errors to the pile" do parser.valid? @@ -144,127 +144,126 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do field_26: "2", field_27: "1", field_28: "1", - field_29: "1", - field_37: "2", - field_38: "1", - field_39: "2", + field_36: "2", + field_37: "1", + field_38: "2", field_15: "1", - field_42: "42", - field_48: "41", - field_52: "17", - field_56: "18", - field_60: "16", - field_64: "14", - field_68: "12", - field_72: "20", - - field_43: "F", - field_49: "M", - field_53: "F", - field_57: "M", - field_61: "F", - field_65: "M", - field_69: "F", - field_73: "M", - - field_44: "17", - field_45: "826", - - field_47: "1", - field_51: "2", - field_55: "2", - field_59: "3", - field_63: "2", - field_67: "2", - field_71: "2", + field_41: "42", + field_47: "41", + field_51: "17", + field_55: "18", + field_59: "16", + field_63: "14", + field_67: "12", + field_71: "20", + + field_42: "F", + field_48: "M", + field_52: "F", + field_56: "M", + field_60: "F", + field_64: "M", + field_68: "F", + field_72: "M", + + field_43: "17", + field_44: "826", field_46: "1", field_50: "2", - field_54: "7", - field_58: "7", - field_62: "8", - field_66: "9", - field_70: "0", - field_74: "10", - - field_75: "1", - field_76: "4", + field_54: "2", + field_58: "3", + field_62: "2", + field_66: "2", + field_70: "2", + + field_45: "1", + field_49: "2", + field_53: "7", + field_57: "7", + field_61: "8", + field_65: "9", + field_69: "0", + field_73: "10", + + field_74: "1", + field_75: "4", + field_76: "1", + field_77: "1", field_78: "1", - - field_79: "1", + field_79: "0", field_80: "0", - field_81: "0", - field_82: "1", - field_83: "0", + field_81: "1", + field_82: "0", - field_85: "3", + field_84: "3", - field_96: "11", - field_97: "2", - field_98: "31", - field_100: "3", - field_101: "11", + field_95: "11", + field_96: "2", + field_97: "31", + field_99: "3", + field_100: "11", - field_102: "1", - field_103: "EC1N", - field_104: "2TD", + field_101: "1", + field_102: "EC1N", + field_103: "2TD", + field_105: "1", field_106: "1", - field_107: "1", - field_108: "", - field_109: "1", + field_107: "", + field_108: "1", + field_109: "", field_110: "", - field_111: "", - field_112: "1", + field_111: "1", + field_112: "2", field_113: "2", field_114: "2", - field_115: "2", - - field_116: "1", - field_117: "1", - field_118: "2", - field_119: "2300", - field_120: "1", - field_121: "4", + field_115: "1", - field_123: "4", - field_124: "1234.56", - field_125: "43.32", - field_126: "13.14", - field_127: "101.11", - field_128: "1", - field_129: "34.56", + field_116: "1", + field_117: "2", + field_118: "2300", + field_119: "1", + field_120: "4", + + field_122: "4", + field_123: "1234.56", + field_124: "43.32", + field_125: "13.14", + field_126: "101.11", + field_127: "1", + field_128: "34.56", field_16: "15", - field_30: now.day.to_s, - field_31: now.month.to_s, - field_32: now.strftime("%g"), + field_29: now.day.to_s, + field_30: now.month.to_s, + field_31: now.strftime("%g"), field_4: "1", field_18: "12", - field_130: "1", - field_131: "", - field_132: "2", - field_133: "identity", - field_134: "3", - field_135: "", - field_136: "1", - field_137: "", - field_138: "2", - field_139: "identity", - field_140: "3", - field_141: "", - field_142: "1", - field_143: "", - field_144: "2", - field_145: "identity", + field_129: "1", + field_130: "", + field_131: "2", + field_132: "identity", + field_133: "3", + field_134: "", + field_135: "1", + field_136: "", + field_137: "2", + field_138: "identity", + field_139: "3", + field_140: "", + field_141: "1", + field_142: "", + field_143: "2", + field_144: "identity", } end @@ -314,13 +313,13 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_23, # postcode_full :field_24, # postcode_full :field_25, # LA - :field_42, # age1 - :field_43, # sexrab1 - :field_46, # ecstat1 - :field_124, # brent - :field_125, # scharge - :field_126, # pscharge - :field_127, # supcharg + :field_41, # age1 + :field_42, # sexrab1 + :field_45, # ecstat1 + :field_123, # brent + :field_124, # scharge + :field_125, # pscharge + :field_126, # supcharg ].each do |field| expect(parser.errors[field]).to include(error_message) end @@ -345,7 +344,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when a supported housing log already exists in the db" do # TODO: CLDC-4119: Beware! The `postcode_full` method in the `LettingsLog` class may cause issues with these supported housing log duplicate detection tests after postcode is added. See comment on the `postcode_full` method for details. - let(:attributes) { valid_attributes.merge({ field_4: "2", field_5: "S#{scheme.id}", field_6: location.old_visible_id, field_36: 3, field_122: 0 }) } + let(:attributes) { valid_attributes.merge({ field_4: "2", field_5: "S#{scheme.id}", field_6: location.old_visible_id, field_35: 3, field_121: 0 }) } before do parser.log.save! @@ -368,13 +367,13 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_10, # startdate :field_13, # tenancycode :field_6, # location - :field_42, # age1 - :field_43, # sexrab1 - :field_46, # ecstat1 - :field_124, # brent - :field_125, # scharge - :field_126, # pscharge - :field_127, # supcharg + :field_41, # age1 + :field_42, # sexrab1 + :field_45, # ecstat1 + :field_123, # brent + :field_124, # scharge + :field_125, # pscharge + :field_126, # supcharg ].each do |field| expect(parser.errors[field]).to include(error_message) end @@ -410,13 +409,13 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_10, # startdate :field_13, # tenancycode :field_6, # location - :field_42, # age1 - :field_43, # sexrab1 - :field_46, # ecstat1 - :field_124, # brent - :field_125, # scharge - :field_126, # pscharge - :field_127, # supcharg + :field_41, # age1 + :field_42, # sexrab1 + :field_45, # ecstat1 + :field_123, # brent + :field_124, # scharge + :field_125, # pscharge + :field_126, # supcharg ].each do |field| expect(parser.errors[field]).to include(error_message) end @@ -453,9 +452,9 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_10, # startdate :field_13, # tenancycode :field_6, # location - :field_42, # age1 - :field_43, # sexrab1 - :field_46, # ecstat1 + :field_41, # age1 + :field_42, # sexrab1 + :field_45, # ecstat1 ].each do |field| expect(parser.errors[field]).to include(error_message) end @@ -474,8 +473,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do field_11: "2", field_6: location.id, field_1: owning_org.old_visible_id, - field_122: 0, - field_36: 4 }) + field_121: 0, + field_35: 4 }) end before do @@ -499,10 +498,10 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_10, # startdate :field_13, # tenancycode :field_6, # location - :field_42, # age1 - :field_43, # sexrab1 - :field_46, # ecstat1 - :field_122, # household_charge + :field_41, # age1 + :field_42, # sexrab1 + :field_45, # ecstat1 + :field_121, # household_charge ].each do |field| expect(parser.errors[field]).to include(error_message) end @@ -518,9 +517,9 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do let(:attributes) do setup_section_params.merge({ field_5: nil, field_6: nil, - field_124: 300, - field_123: 1, - field_29: 1, + field_123: 300, + field_122: 1, + field_28: 1, field_4: 1, field_11: "2", field_25: "E09000008" }) @@ -553,9 +552,9 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_23, # postcode_full :field_24, # postcode_full :field_25, # LA - :field_42, # age1 - :field_43, # sexrab1 - :field_46, # ecstat1 + :field_41, # age1 + :field_42, # sexrab1 + :field_45, # ecstat1 ].each do |field| expect(parser.errors[field]).to be_blank end @@ -588,8 +587,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "with a valid ethnic value" do - context "when field_44 is 20" do - let(:attributes) { valid_attributes.merge({ field_44: "20" }) } + context "when field_43 is 20" do + let(:attributes) { valid_attributes.merge({ field_43: "20" }) } it "is correctly sets ethnic and ethnic group" do expect(parser.log.ethnic).to eq(20) @@ -609,43 +608,43 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do context "when there is a :skip_bu_error error" do let(:managing_org) { create(:organisation, :with_old_visible_id, rent_periods: [4, 1]) } - let(:attributes) { valid_attributes.merge({ field_123: 3, field_127: 80 }) } + let(:attributes) { valid_attributes.merge({ field_122: 3, field_126: 80 }) } it "does not add that error" do parser.valid? expect(parser.log.errors.map(&:attribute).sort).to eql(%i[managing_organisation_id period]) - expect(parser.errors.map(&:attribute)).to eql(%i[field_123]) + expect(parser.errors.map(&:attribute)).to eql(%i[field_122]) end end end describe "#validate_nulls" do context "when non-setup questions are null" do - let(:attributes) { setup_section_params.merge({ field_43: "" }) } + let(:attributes) { setup_section_params.merge({ field_42: "" }) } it "fetches the question's check_answer_label if it exists" do parser.valid? - expect(parser.errors[:field_43]).to eql([I18n.t("validations.lettings.2026.bulk_upload.not_answered", question: "lead tenant’s sex registered at birth.")]) + expect(parser.errors[:field_42]).to eql([I18n.t("validations.lettings.2026.bulk_upload.not_answered", question: "lead tenant’s sex registered at birth.")]) end end context "when other null error is added" do - let(:attributes) { setup_section_params.merge({ field_112: nil }) } + let(:attributes) { setup_section_params.merge({ field_111: nil }) } it "only has one error added to the field" do parser.valid? - expect(parser.errors[:field_112]).to eql([I18n.t("validations.lettings.2026.bulk_upload.not_answered", question: "was the letting made under the Choice-Based Lettings (CBL)?")]) + expect(parser.errors[:field_111]).to eql([I18n.t("validations.lettings.2026.bulk_upload.not_answered", question: "was the letting made under the Choice-Based Lettings (CBL)?")]) end end context "when an invalid value error has been added" do - let(:attributes) { setup_section_params.merge({ field_115: "100" }) } + let(:attributes) { setup_section_params.merge({ field_114: "100" }) } it "does not add an additional error" do parser.valid? - expect(parser.errors[:field_115].length).to eq(1) - expect(parser.errors[:field_115]).to include(match I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: "")) + expect(parser.errors[:field_114].length).to eq(1) + expect(parser.errors[:field_114]).to include(match I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: "")) end end end @@ -894,171 +893,172 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - describe "#field_98" do # leaving reason + describe "#field_97" do # leaving reason context "when field_7 is 1 meaning it is a renewal" do - context "when field_98 is 50" do - let(:attributes) { { bulk_upload:, field_98: "50", field_7: "1" } } + context "when field_97 is 50" do + let(:attributes) { { bulk_upload:, field_97: "50", field_7: "1" } } it "is permitted" do parser.valid? - expect(parser.errors[:field_98]).to be_blank + expect(parser.errors[:field_97]).to be_blank end end - context "when field_98 is 51" do - let(:attributes) { { bulk_upload:, field_98: "51", field_7: "1" } } + context "when field_97 is 51" do + let(:attributes) { { bulk_upload:, field_97: "51", field_7: "1" } } it "is permitted" do parser.valid? - expect(parser.errors[:field_98]).to be_blank + expect(parser.errors[:field_97]).to be_blank end end - context "when field_98 is 52" do - let(:attributes) { { bulk_upload:, field_98: "52", field_7: "1" } } + context "when field_97 is 52" do + let(:attributes) { { bulk_upload:, field_97: "52", field_7: "1" } } it "is permitted" do parser.valid? - expect(parser.errors[:field_98]).to be_blank + expect(parser.errors[:field_97]).to be_blank end end - context "when field_98 is 53" do - let(:attributes) { { bulk_upload:, field_98: "53", field_7: "1" } } + context "when field_97 is 53" do + let(:attributes) { { bulk_upload:, field_97: "53", field_7: "1" } } it "is permitted" do parser.valid? - expect(parser.errors[:field_98]).to be_blank + expect(parser.errors[:field_97]).to be_blank end end - context "when field_98 is not 50, 51, 52 or 53" do - let(:attributes) { { bulk_upload:, field_98: "1", field_7: "1" } } + context "when field_97 is not 50, 51, 52 or 53" do + let(:attributes) { { bulk_upload:, field_97: "1", field_7: "1" } } it "is not permitted" do parser.valid? - expect(parser.errors[:field_98]).to include(I18n.t("validations.lettings.2026.bulk_upload.reason.renewal_reason_needed")) + expect(parser.errors[:field_97]).to include(I18n.t("validations.lettings.2026.bulk_upload.reason.renewal_reason_needed")) end end end context "when no longer a valid option from previous year" do - let(:attributes) { setup_section_params.merge({ field_98: "7" }) } + let(:attributes) { setup_section_params.merge({ field_97: "7" }) } it "returns an error" do parser.valid? - expect(parser.errors[:field_98]).to include(I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: "what is the tenant’s main reason for the household leaving their last settled home?")) + expect(parser.errors[:field_97]).to include(I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: "what is the tenant’s main reason for the household leaving their last settled home?")) end end end - describe "#field_79, #field_80, #field_81" do + describe "#field_78, #field_79, #field_80" do context "when one item selected" do - let(:attributes) { { bulk_upload:, field_79: "1" } } + let(:attributes) { { bulk_upload:, field_78: "1" } } it "is permitted" do parser.valid? + expect(parser.errors[:field_78]).to be_blank expect(parser.errors[:field_79]).to be_blank expect(parser.errors[:field_80]).to be_blank - expect(parser.errors[:field_81]).to be_blank end end context "when more than one item selected" do - let(:attributes) { { bulk_upload:, field_79: "1", field_80: "1" } } + let(:attributes) { { bulk_upload:, field_78: "1", field_79: "1" } } it "is not permitted" do parser.valid? + expect(parser.errors[:field_78]).to be_present expect(parser.errors[:field_79]).to be_present - expect(parser.errors[:field_80]).to be_present end end end - describe "#field_83" do + describe "#field_82" do context "when 1 and another disability field selected" do - let(:attributes) { { bulk_upload:, field_83: "1", field_82: "1" } } + let(:attributes) { { bulk_upload:, field_82: "1", field_81: "1" } } it "is not permitted" do parser.valid? - expect(parser.errors[:field_83]).to be_present + expect(parser.errors[:field_82]).to be_present end end end - describe "#field_84" do + describe "#field_83" do context "when 1 and another disability field selected" do - let(:attributes) { { bulk_upload:, field_84: "1", field_82: "1" } } + let(:attributes) { { bulk_upload:, field_83: "1", field_81: "1" } } it "is not permitted" do parser.valid? - expect(parser.errors[:field_84]).to be_present + expect(parser.errors[:field_83]).to be_present end end end - describe "#field_83, #field_84" do + describe "#field_82, #field_83" do context "when both 1" do - let(:attributes) { { bulk_upload:, field_83: "1", field_84: "1" } } + let(:attributes) { { bulk_upload:, field_82: "1", field_83: "1" } } it "is not permitted" do parser.valid? + expect(parser.errors[:field_82]).to be_present expect(parser.errors[:field_83]).to be_present - expect(parser.errors[:field_84]).to be_present end end end - describe "#field_79 - #field_84" do + describe "#field_78 - #field_83" do context "when all blank" do - let(:attributes) { setup_section_params.merge({ field_79: nil, field_80: nil, field_81: nil, field_82: nil, field_83: nil, field_84: nil }) } + let(:attributes) { setup_section_params.merge({ field_78: nil, field_79: nil, field_80: nil, field_81: nil, field_82: nil, field_83: nil }) } it "adds errors to correct fields" do parser.valid? + expect(parser.errors[:field_78]).to be_present expect(parser.errors[:field_79]).to be_present expect(parser.errors[:field_80]).to be_present expect(parser.errors[:field_81]).to be_present expect(parser.errors[:field_82]).to be_present - expect(parser.errors[:field_83]).to be_present end end - context "when one item selected and field_82 is blank" do - let(:attributes) { setup_section_params.merge({ field_79: "1", field_82: nil }) } + context "when one item selected and field_81 is blank" do + let(:attributes) { setup_section_params.merge({ field_78: "1", field_81: nil }) } it "sets other disabled access needs as no" do parser.valid? - expect(parser.errors[:field_79]).to be_blank - expect(parser.errors[:field_82]).to be_blank + expect(parser.errors[:field_78]).to be_blank + expect(parser.errors[:field_81]).to be_blank expect(parser.log.housingneeds_other).to eq(0) end end end - describe "#field_85, field_94 - 99" do + describe "#field_84, field_93 - 99" do context "when no illness but illnesses answered" do - let(:attributes) { { bulk_upload:, field_85: "2", field_86: "1", field_87: "1", field_88: "1" } } + let(:attributes) { { bulk_upload:, field_84: "2", field_85: "1", field_86: "1", field_87: "1" } } it "errors added to correct fields" do parser.valid? + expect(parser.errors[:field_85]).to be_present expect(parser.errors[:field_86]).to be_present expect(parser.errors[:field_87]).to be_present - expect(parser.errors[:field_88]).to be_present + expect(parser.errors[:field_88]).not_to be_present expect(parser.errors[:field_89]).not_to be_present expect(parser.errors[:field_90]).not_to be_present expect(parser.errors[:field_91]).not_to be_present expect(parser.errors[:field_92]).not_to be_present expect(parser.errors[:field_93]).not_to be_present expect(parser.errors[:field_94]).not_to be_present - expect(parser.errors[:field_95]).not_to be_present end end context "when illness but no illnesses answered" do - let(:attributes) { { bulk_upload:, field_85: "1", field_86: nil, field_87: nil, field_88: nil, field_89: nil, field_90: nil, field_91: nil, field_92: nil, field_93: nil, field_94: nil, field_95: nil } } + let(:attributes) { { bulk_upload:, field_84: "1", field_85: nil, field_86: nil, field_87: nil, field_88: nil, field_89: nil, field_90: nil, field_91: nil, field_92: nil, field_93: nil, field_94: nil } } it "errors added to correct fields" do parser.valid? + expect(parser.errors[:field_85]).to be_present expect(parser.errors[:field_86]).to be_present expect(parser.errors[:field_87]).to be_present expect(parser.errors[:field_88]).to be_present @@ -1068,39 +1068,38 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do expect(parser.errors[:field_92]).to be_present expect(parser.errors[:field_93]).to be_present expect(parser.errors[:field_94]).to be_present - expect(parser.errors[:field_95]).to be_present end end end - describe "#field_100" do + describe "#field_99" do context "when log is a renewal and field 100 is an invalid value" do - let(:attributes) { { bulk_upload:, field_7: 1, field_100: 4 } } + let(:attributes) { { bulk_upload:, field_7: 1, field_99: 4 } } it "adds an error to field 100" do parser.valid? - expect(parser.errors[:field_100]).to be_present - expect(parser.errors[:field_100]).to include(I18n.t("validations.lettings.2026.bulk_upload.prevten.invalid")) + expect(parser.errors[:field_99]).to be_present + expect(parser.errors[:field_99]).to include(I18n.t("validations.lettings.2026.bulk_upload.prevten.invalid")) end end context "when log is a renewal and field 100 is a valid value" do - let(:attributes) { { bulk_upload:, field_7: 1, field_100: 38 } } + let(:attributes) { { bulk_upload:, field_7: 1, field_99: 38 } } it "does not add an error" do parser.valid? - expect(parser.errors[:field_100]).to be_blank + expect(parser.errors[:field_99]).to be_blank end end end - describe "#field_112 - 115 (lettings allocation methods)" do - %i[field_112 field_113 field_114 field_115].each do |field| + describe "#field_111 - 115 (lettings allocation methods)" do + %i[field_111 field_112 field_113 field_114].each do |field| context "when only #{field} is not given" do let(:attributes) do override = {} override[field] = "" - { bulk_upload:, field_112: "2", field_113: "1", field_114: "2", field_115: "1" }.merge(override) + { bulk_upload:, field_111: "2", field_112: "1", field_113: "2", field_114: "1" }.merge(override) end it "adds an error to #{field}" do @@ -1111,35 +1110,35 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - describe "#field_101, field_106 - 15" do + describe "#field_100, field_105 - 15" do context "when there is a reasonable preference but none is given" do - let(:attributes) { { bulk_upload:, field_106: "1", field_107: nil, field_108: nil, field_109: nil, field_110: nil, field_111: nil } } + let(:attributes) { { bulk_upload:, field_105: "1", field_106: nil, field_107: nil, field_108: nil, field_109: nil, field_110: nil } } it "is not permitted" do parser.valid? + expect(parser.errors[:field_106]).to be_present expect(parser.errors[:field_107]).to be_present expect(parser.errors[:field_108]).to be_present expect(parser.errors[:field_109]).to be_present expect(parser.errors[:field_110]).to be_present - expect(parser.errors[:field_111]).to be_present end end context "when some reasonable preference options are set as invalid values" do - let(:attributes) { setup_section_params.merge({ bulk_upload:, field_106: "2", field_107: "2", field_108: "3", field_109: "2", field_110: "3", field_111: "-4" }) } + let(:attributes) { setup_section_params.merge({ bulk_upload:, field_105: "2", field_106: "2", field_107: "3", field_108: "2", field_109: "3", field_110: "-4" }) } it "adds errors" do parser.valid? + expect(parser.errors[:field_106]).to be_present expect(parser.errors[:field_107]).to be_present expect(parser.errors[:field_108]).to be_present expect(parser.errors[:field_109]).to be_present expect(parser.errors[:field_110]).to be_present - expect(parser.errors[:field_111]).to be_present end end context "when some reasonable preference options are selected" do - let(:attributes) { setup_section_params.merge({ bulk_upload:, field_106: "1", field_107: "1", field_108: nil, field_109: "1", field_110: nil, field_111: nil }) } + let(:attributes) { setup_section_params.merge({ bulk_upload:, field_105: "1", field_106: "1", field_107: nil, field_108: "1", field_109: nil, field_110: nil }) } it "sets the rest of the options to 0" do parser.valid? @@ -1152,7 +1151,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - describe "#field_116, field_146, field_147, field_148" do # referral + describe "#field_115, field_145, field_146, field_147" do # referral context "when org is LA" do let(:owning_org) { create(:organisation, :la, :with_old_visible_id) } @@ -1161,64 +1160,64 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do context "and not renewal" do let(:renewal_attributes) { org_attributes.merge({ field_7: nil }) } - context "and field_116 is valid" do - let(:attributes) { renewal_attributes.merge({ field_116: 1 }) } + context "and field_115 is valid" do + let(:attributes) { renewal_attributes.merge({ field_115: 1 }) } it "does not add an error" do parser.valid? - expect(parser.errors[:field_116]).to be_blank + expect(parser.errors[:field_115]).to be_blank + expect(parser.errors[:field_145]).to be_blank expect(parser.errors[:field_146]).to be_blank expect(parser.errors[:field_147]).to be_blank - expect(parser.errors[:field_148]).to be_blank end end - context "and field_116 is invalid" do - let(:attributes) { renewal_attributes.merge({ field_116: 5 }) } # PRP option + context "and field_115 is invalid" do + let(:attributes) { renewal_attributes.merge({ field_115: 5 }) } # PRP option it "adds errors to all referral fields" do parser.valid? - expect(parser.errors[:field_116]).to be_present + expect(parser.errors[:field_115]).to be_present + expect(parser.errors[:field_145]).to be_present expect(parser.errors[:field_146]).to be_present expect(parser.errors[:field_147]).to be_present - expect(parser.errors[:field_148]).to be_present end end - context "and field_116 is blank" do - let(:attributes) { renewal_attributes.merge({ field_116: nil }) } + context "and field_115 is blank" do + let(:attributes) { renewal_attributes.merge({ field_115: nil }) } it "adds errors to all referral fields" do parser.valid? - expect(parser.errors[:field_116]).to be_present + expect(parser.errors[:field_115]).to be_present + expect(parser.errors[:field_145]).to be_present expect(parser.errors[:field_146]).to be_present expect(parser.errors[:field_147]).to be_present - expect(parser.errors[:field_148]).to be_present end end context "and other fields are given" do - let(:attributes) { renewal_attributes.merge({ field_116: 1, field_146: 5, field_147: 1, field_144: 1 }) } + let(:attributes) { renewal_attributes.merge({ field_115: 1, field_145: 5, field_146: 1, field_143: 1 }) } it "adds errors to all referral fields" do parser.valid? - expect(parser.errors[:field_116]).to be_present + expect(parser.errors[:field_115]).to be_present + expect(parser.errors[:field_145]).to be_present expect(parser.errors[:field_146]).to be_present expect(parser.errors[:field_147]).to be_present - expect(parser.errors[:field_148]).to be_present end end end context "and is renewal" do - let(:attributes) { org_attributes.merge({ field_7: 1, field_116: 1, field_146: 5, field_147: 1, field_148: 1 }) } + let(:attributes) { org_attributes.merge({ field_7: 1, field_115: 1, field_145: 5, field_146: 1, field_147: 1 }) } it "does not add an error for referral fields" do parser.valid? - expect(parser.errors[:field_116]).to be_blank + expect(parser.errors[:field_115]).to be_blank + expect(parser.errors[:field_145]).to be_blank expect(parser.errors[:field_146]).to be_blank expect(parser.errors[:field_147]).to be_blank - expect(parser.errors[:field_148]).to be_blank end end end @@ -1231,141 +1230,141 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do context "and not renewal" do let(:renewal_attributes) { org_attributes.merge({ field_7: nil }) } - context "and field_146 is valid and does not expect an answer for field_147" do - let(:attributes) { renewal_attributes.merge({ field_146: 5 }) } + context "and field_145 is valid and does not expect an answer for field_146" do + let(:attributes) { renewal_attributes.merge({ field_145: 5 }) } it "does not add an error" do parser.valid? - expect(parser.errors[:field_116]).to be_blank + expect(parser.errors[:field_115]).to be_blank + expect(parser.errors[:field_145]).to be_blank expect(parser.errors[:field_146]).to be_blank expect(parser.errors[:field_147]).to be_blank - expect(parser.errors[:field_148]).to be_blank end context "and later fields are given" do - let(:attributes) { renewal_attributes.merge({ field_146: 5, field_147: 1, field_148: 1 }) } + let(:attributes) { renewal_attributes.merge({ field_145: 5, field_146: 1, field_147: 1 }) } it "adds errors to all referral fields" do parser.valid? - expect(parser.errors[:field_116]).to be_present + expect(parser.errors[:field_115]).to be_present + expect(parser.errors[:field_145]).to be_present expect(parser.errors[:field_146]).to be_present expect(parser.errors[:field_147]).to be_present - expect(parser.errors[:field_148]).to be_present end end end - context "and field_146 is invalid" do - let(:attributes) { renewal_attributes.merge({ field_146: 1 }) } # LA option + context "and field_145 is invalid" do + let(:attributes) { renewal_attributes.merge({ field_145: 1 }) } # LA option it "adds errors to all referral fields" do parser.valid? - expect(parser.errors[:field_116]).to be_present + expect(parser.errors[:field_115]).to be_present + expect(parser.errors[:field_145]).to be_present expect(parser.errors[:field_146]).to be_present expect(parser.errors[:field_147]).to be_present - expect(parser.errors[:field_148]).to be_present end end - context "and field_146 is blank" do - let(:attributes) { renewal_attributes.merge({ field_146: nil }) } + context "and field_145 is blank" do + let(:attributes) { renewal_attributes.merge({ field_145: nil }) } it "adds errors to all referral fields" do parser.valid? - expect(parser.errors[:field_116]).to be_present + expect(parser.errors[:field_115]).to be_present + expect(parser.errors[:field_145]).to be_present expect(parser.errors[:field_146]).to be_present expect(parser.errors[:field_147]).to be_present - expect(parser.errors[:field_148]).to be_present end end - context "and field_146 is valid and expects an answer for field_147" do - let(:field_146_attributes) { renewal_attributes.merge({ field_146: 6 }) } + context "and field_145 is valid and expects an answer for field_146" do + let(:field_146_attributes) { renewal_attributes.merge({ field_145: 6 }) } - context "and field_147 is valid and does not expect an answer for field_148" do - let(:attributes) { field_146_attributes.merge({ field_147: 2 }) } + context "and field_146 is valid and does not expect an answer for field_147" do + let(:attributes) { field_146_attributes.merge({ field_146: 2 }) } it "does not add an error" do parser.valid? - expect(parser.errors[:field_116]).to be_blank + expect(parser.errors[:field_115]).to be_blank + expect(parser.errors[:field_145]).to be_blank expect(parser.errors[:field_146]).to be_blank expect(parser.errors[:field_147]).to be_blank - expect(parser.errors[:field_148]).to be_blank end context "and later fields are given" do - let(:attributes) { field_146_attributes.merge({ field_147: 2, field_148: 1 }) } + let(:attributes) { field_146_attributes.merge({ field_146: 2, field_147: 1 }) } it "adds errors to all referral fields" do parser.valid? - expect(parser.errors[:field_116]).to be_present + expect(parser.errors[:field_115]).to be_present + expect(parser.errors[:field_145]).to be_present expect(parser.errors[:field_146]).to be_present expect(parser.errors[:field_147]).to be_present - expect(parser.errors[:field_148]).to be_present end end end - context "and field_147 is invalid" do - let(:attributes) { field_146_attributes.merge({ field_147: 5 }) } # needs field_146 to be 7 + context "and field_146 is invalid" do + let(:attributes) { field_146_attributes.merge({ field_146: 5 }) } # needs field_145 to be 7 it "adds errors to all referral fields" do parser.valid? - expect(parser.errors[:field_116]).to be_present + expect(parser.errors[:field_115]).to be_present + expect(parser.errors[:field_145]).to be_present expect(parser.errors[:field_146]).to be_present expect(parser.errors[:field_147]).to be_present - expect(parser.errors[:field_148]).to be_present end end - context "and field_147 is blank" do - let(:attributes) { field_146_attributes.merge({ field_147: nil }) } + context "and field_146 is blank" do + let(:attributes) { field_146_attributes.merge({ field_146: nil }) } it "adds errors to all referral fields" do parser.valid? - expect(parser.errors[:field_116]).to be_present + expect(parser.errors[:field_115]).to be_present + expect(parser.errors[:field_145]).to be_present expect(parser.errors[:field_146]).to be_present expect(parser.errors[:field_147]).to be_present - expect(parser.errors[:field_148]).to be_present end end - context "and field_147 is valid and expects an answer for field_148" do - let(:field_147_attributes) { field_146_attributes.merge({ field_147: 1 }) } + context "and field_146 is valid and expects an answer for field_147" do + let(:field_147_attributes) { field_146_attributes.merge({ field_146: 1 }) } - context "and field_148 is valid" do - let(:attributes) { field_147_attributes.merge({ field_148: 1 }) } + context "and field_147 is valid" do + let(:attributes) { field_147_attributes.merge({ field_147: 1 }) } it "does not add an error" do parser.valid? - expect(parser.errors[:field_116]).to be_blank + expect(parser.errors[:field_115]).to be_blank + expect(parser.errors[:field_145]).to be_blank expect(parser.errors[:field_146]).to be_blank expect(parser.errors[:field_147]).to be_blank - expect(parser.errors[:field_148]).to be_blank end end - context "and field_148 is invalid" do - let(:attributes) { field_147_attributes.merge({ field_148: 11 }) } # needs field_147 to be 7 + context "and field_147 is invalid" do + let(:attributes) { field_147_attributes.merge({ field_147: 11 }) } # needs field_146 to be 7 it "adds errors to all referral fields" do parser.valid? - expect(parser.errors[:field_116]).to be_present + expect(parser.errors[:field_115]).to be_present + expect(parser.errors[:field_145]).to be_present expect(parser.errors[:field_146]).to be_present expect(parser.errors[:field_147]).to be_present - expect(parser.errors[:field_148]).to be_present end end - context "and field_148 is blank" do - let(:attributes) { field_147_attributes.merge({ field_148: nil }) } + context "and field_147 is blank" do + let(:attributes) { field_147_attributes.merge({ field_147: nil }) } it "adds errors to all referral fields" do parser.valid? - expect(parser.errors[:field_116]).to be_present + expect(parser.errors[:field_115]).to be_present + expect(parser.errors[:field_145]).to be_present expect(parser.errors[:field_146]).to be_present expect(parser.errors[:field_147]).to be_present - expect(parser.errors[:field_148]).to be_present end end end @@ -1373,14 +1372,14 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "and is renewal" do - let(:attributes) { org_attributes.merge({ field_7: 1, field_116: 1, field_146: 5, field_147: 1, field_148: 1 }) } + let(:attributes) { org_attributes.merge({ field_7: 1, field_115: 1, field_145: 5, field_146: 1, field_147: 1 }) } it "does not add an error for referral fields" do parser.valid? - expect(parser.errors[:field_116]).to be_blank + expect(parser.errors[:field_115]).to be_blank + expect(parser.errors[:field_145]).to be_blank expect(parser.errors[:field_146]).to be_blank expect(parser.errors[:field_147]).to be_blank - expect(parser.errors[:field_148]).to be_blank end end end @@ -1959,20 +1958,20 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - describe "#field_48" do # age2 + describe "#field_47" do # age2 context "when null but gender given" do - let(:attributes) { setup_section_params.merge({ field_48: "", field_49: "F" }) } + let(:attributes) { setup_section_params.merge({ field_47: "", field_48: "F" }) } it "returns an error" do parser.valid? - expect(parser.errors[:field_48]).to be_present + expect(parser.errors[:field_47]).to be_present end end end - describe "#field_45" do - context "when field_45 is a 3 digit nationality code" do - let(:attributes) { setup_section_params.merge({ field_45: "036" }) } + describe "#field_44" do + context "when field_44 is a 3 digit nationality code" do + let(:attributes) { setup_section_params.merge({ field_44: "036" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(36) @@ -1980,8 +1979,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when field_45 is a nationality code without the trailing 0s" do - let(:attributes) { setup_section_params.merge({ field_45: "36" }) } + context "when field_44 is a nationality code without the trailing 0s" do + let(:attributes) { setup_section_params.merge({ field_44: "36" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(36) @@ -1989,8 +1988,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when field_45 is a nationality code with trailing 0s" do - let(:attributes) { setup_section_params.merge({ field_45: "0036" }) } + context "when field_44 is a nationality code with trailing 0s" do + let(:attributes) { setup_section_params.merge({ field_44: "0036" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(36) @@ -1998,8 +1997,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when field_45 is 0" do - let(:attributes) { setup_section_params.merge({ field_45: "0" }) } + context "when field_44 is 0" do + let(:attributes) { setup_section_params.merge({ field_44: "0" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(0) @@ -2007,8 +2006,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when field_45 is 000" do - let(:attributes) { setup_section_params.merge({ field_45: "000" }) } + context "when field_44 is 000" do + let(:attributes) { setup_section_params.merge({ field_44: "000" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(0) @@ -2016,8 +2015,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when field_45 is 0000" do - let(:attributes) { setup_section_params.merge({ field_45: "0000" }) } + context "when field_44 is 0000" do + let(:attributes) { setup_section_params.merge({ field_44: "0000" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(0) @@ -2025,8 +2024,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when field_45 is 826" do - let(:attributes) { setup_section_params.merge({ field_45: "826" }) } + context "when field_44 is 826" do + let(:attributes) { setup_section_params.merge({ field_44: "826" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(826) @@ -2034,8 +2033,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when field_45 is 826 with trailing 0s" do - let(:attributes) { setup_section_params.merge({ field_45: "0826" }) } + context "when field_44 is 826 with trailing 0s" do + let(:attributes) { setup_section_params.merge({ field_44: "0826" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(826) @@ -2043,79 +2042,79 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when field_45 is not a valid option" do - let(:attributes) { setup_section_params.merge({ field_45: "123123" }) } + context "when field_44 is not a valid option" do + let(:attributes) { setup_section_params.merge({ field_44: "123123" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(nil) expect(parser.log.nationality_all_group).to be(nil) end - it "adds an error to field_45" do + it "adds an error to field_44" do parser.valid? - expect(parser.errors["field_45"]).to include(I18n.t("validations.lettings.2026.bulk_upload.nationality.invalid")) + expect(parser.errors["field_44"]).to include(I18n.t("validations.lettings.2026.bulk_upload.nationality.invalid")) end end end describe "soft validations" do context "when soft validation is triggered" do - let(:attributes) { setup_section_params.merge({ field_42: 22, field_46: 5 }) } + let(:attributes) { setup_section_params.merge({ field_41: 22, field_45: 5 }) } it "adds an error to the relevant fields" do parser.valid? - expect(parser.errors.where(:field_42, category: :soft_validation)).to be_present - expect(parser.errors.where(:field_46, category: :soft_validation)).to be_present + expect(parser.errors.where(:field_41, category: :soft_validation)).to be_present + expect(parser.errors.where(:field_45, category: :soft_validation)).to be_present end it "populates with correct error message" do parser.valid? - expect(parser.errors.where(:field_42, category: :soft_validation).first.message).to eql("You told us this person is aged 22 years and retired. The minimum expected retirement age in England is 66.") - expect(parser.errors.where(:field_46, category: :soft_validation).first.message).to eql("You told us this person is aged 22 years and retired. The minimum expected retirement age in England is 66.") + expect(parser.errors.where(:field_41, category: :soft_validation).first.message).to eql("You told us this person is aged 22 years and retired. The minimum expected retirement age in England is 66.") + expect(parser.errors.where(:field_45, category: :soft_validation).first.message).to eql("You told us this person is aged 22 years and retired. The minimum expected retirement age in England is 66.") end end context "when a soft validation is triggered that relates both to fields that are and are not routed to" do - let(:attributes) { setup_section_params.merge({ field_78: "1", field_43: "M", field_49: "M", field_53: "M", field_130: 1, field_132: 1, field_134: 1 }) } + let(:attributes) { setup_section_params.merge({ field_77: "1", field_42: "M", field_48: "M", field_52: "M", field_129: 1, field_131: 1, field_133: 1 }) } it "adds errors to fields that are routed to" do parser.valid? - expect(parser.errors.where(:field_43, category: :soft_validation)).to be_present - expect(parser.errors.where(:field_130, category: :soft_validation)).to be_present - expect(parser.errors.where(:field_49, category: :soft_validation)).to be_present - expect(parser.errors.where(:field_132, category: :soft_validation)).to be_present + expect(parser.errors.where(:field_42, category: :soft_validation)).to be_present + expect(parser.errors.where(:field_129, category: :soft_validation)).to be_present + expect(parser.errors.where(:field_48, category: :soft_validation)).to be_present + expect(parser.errors.where(:field_131, category: :soft_validation)).to be_present end it "does not add errors to fields that are not routed to" do parser.valid? - expect(parser.errors.where(:field_157, category: :soft_validation)).not_to be_present - expect(parser.errors.where(:field_136, category: :soft_validation)).not_to be_present - expect(parser.errors.where(:field_161, category: :soft_validation)).not_to be_present - expect(parser.errors.where(:field_138, category: :soft_validation)).not_to be_present + expect(parser.errors.where(:field_156, category: :soft_validation)).not_to be_present + expect(parser.errors.where(:field_135, category: :soft_validation)).not_to be_present + expect(parser.errors.where(:field_160, category: :soft_validation)).not_to be_present + expect(parser.errors.where(:field_137, category: :soft_validation)).not_to be_present end end context "when soft validation is triggered and not required" do - let(:attributes) { setup_section_params.merge({ field_124: 120, field_125: 120, field_126: 120, field_127: 120, field_123: 1, field_29: 1, field_4: 1, field_11: "2", field_25: "E09000008" }) } + let(:attributes) { setup_section_params.merge({ field_123: 120, field_124: 120, field_125: 120, field_126: 120, field_122: 1, field_28: 1, field_4: 1, field_11: "2", field_25: "E09000008" }) } it "adds an error to the relevant fields" do parser.valid? - expect(parser.errors.where(:field_124, category: :soft_validation)).to be_present + expect(parser.errors.where(:field_123, category: :soft_validation)).to be_present end it "populates with correct error message" do parser.valid? - expect(parser.errors.where(:field_124, category: :soft_validation).count).to be(1) - expect(parser.errors.where(:field_124, category: :soft_validation).first.message).to eql("You told us the rent is £120.00 every week. This is higher than we would expect.") + expect(parser.errors.where(:field_123, category: :soft_validation).count).to be(1) + expect(parser.errors.where(:field_123, category: :soft_validation).first.message).to eql("You told us the rent is £120.00 every week. This is higher than we would expect.") end end context "when an invalid ecstat1 is given" do - let(:attributes) { setup_section_params.merge({ field_46: 11, field_119: 123, field_118: 1 }) } + let(:attributes) { setup_section_params.merge({ field_45: 11, field_118: 123, field_117: 1 }) } it "does not run net income soft validations validation" do parser.valid? - expect(parser.errors.where(:field_46).count).to be(1) + expect(parser.errors.where(:field_45).count).to be(1) end end end @@ -2232,14 +2231,14 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end [ - %w[age1_known details_known_1 age1 field_42 field_47 field_49], - %w[age2_known details_known_2 age2 field_48 field_47 field_49], - %w[age3_known details_known_3 age3 field_52 field_51 field_53], - %w[age4_known details_known_4 age4 field_56 field_55 field_57], - %w[age5_known details_known_5 age5 field_60 field_59 field_61], - %w[age6_known details_known_6 age6 field_64 field_63 field_65], - %w[age7_known details_known_7 age7 field_68 field_67 field_69], - %w[age8_known details_known_8 age8 field_72 field_71 field_73], + %w[age1_known details_known_1 age1 field_41 field_46 field_48], + %w[age2_known details_known_2 age2 field_47 field_46 field_48], + %w[age3_known details_known_3 age3 field_51 field_50 field_52], + %w[age4_known details_known_4 age4 field_55 field_54 field_56], + %w[age5_known details_known_5 age5 field_59 field_58 field_60], + %w[age6_known details_known_6 age6 field_63 field_62 field_64], + %w[age7_known details_known_7 age7 field_67 field_66 field_68], + %w[age8_known details_known_8 age8 field_71 field_70 field_72], ].each do |known, details_known, age, field, relationship, gender| describe "##{known} and ##{age}" do context "when #{field} is blank" do @@ -2341,141 +2340,141 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "#beds" do context "when property is a bedsit" do - let(:attributes) { setup_section_params.merge({ field_26: 2, field_29: 2 }) } + let(:attributes) { setup_section_params.merge({ field_26: 2, field_28: 2 }) } - it "sets value to 1 even if field_29 contradicts this" do + it "sets value to 1 even if field_28 contradicts this" do expect(parser.log.beds).to be(1) end end context "when property is not a bedsit" do - let(:attributes) { setup_section_params.merge({ field_26: 1, field_29: 2 }) } + let(:attributes) { setup_section_params.merge({ field_26: 1, field_28: 2 }) } - it "sets value to field_29" do + it "sets value to field_28" do expect(parser.log.beds).to be(2) end end end describe "#cbl" do - context "when field_112 is yes ie 1" do - let(:attributes) { { bulk_upload:, field_112: 1 } } + context "when field_111 is yes ie 1" do + let(:attributes) { { bulk_upload:, field_111: 1 } } it "sets value to 1" do expect(parser.log.cbl).to be(1) end end - context "when field_112 is no ie 2" do - let(:attributes) { { bulk_upload:, field_112: 2 } } + context "when field_111 is no ie 2" do + let(:attributes) { { bulk_upload:, field_111: 2 } } it "sets value to 0" do expect(parser.log.cbl).to be(0) end end - context "when field_112 is not a permitted value" do - let(:attributes) { { bulk_upload:, field_112: 3 } } + context "when field_111 is not a permitted value" do + let(:attributes) { { bulk_upload:, field_111: 3 } } it "adds an error" do parser.valid? - expect(parser.errors[:field_112]).to include(I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: "was the letting made under the Choice-Based Lettings (CBL)?")) + expect(parser.errors[:field_111]).to include(I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: "was the letting made under the Choice-Based Lettings (CBL)?")) end end end describe "#chr" do - context "when field_114 is yes ie 1" do - let(:attributes) { { bulk_upload:, field_114: 1 } } + context "when field_113 is yes ie 1" do + let(:attributes) { { bulk_upload:, field_113: 1 } } it "sets value to 1" do expect(parser.log.chr).to be(1) end end - context "when field_114 is no ie 2" do - let(:attributes) { { bulk_upload:, field_114: 2 } } + context "when field_113 is no ie 2" do + let(:attributes) { { bulk_upload:, field_113: 2 } } it "sets value to 0" do expect(parser.log.chr).to be(0) end end - context "when field_114 is not a permitted value" do - let(:attributes) { { bulk_upload:, field_114: 3 } } + context "when field_113 is not a permitted value" do + let(:attributes) { { bulk_upload:, field_113: 3 } } it "adds an error" do parser.valid? - expect(parser.errors[:field_114]).to include(I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: "was the letting made under the Common Housing Register (CHR)?")) + expect(parser.errors[:field_113]).to include(I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: "was the letting made under the Common Housing Register (CHR)?")) end end end describe "#cap" do - context "when field_113 is yes ie 1" do - let(:attributes) { { bulk_upload:, field_113: 1 } } + context "when field_112 is yes ie 1" do + let(:attributes) { { bulk_upload:, field_112: 1 } } it "sets value to 1" do expect(parser.log.cap).to be(1) end end - context "when field_113 is no ie 2" do - let(:attributes) { { bulk_upload:, field_113: 2 } } + context "when field_112 is no ie 2" do + let(:attributes) { { bulk_upload:, field_112: 2 } } it "sets value to 0" do expect(parser.log.cap).to be(0) end end - context "when field_113 is not a permitted value" do - let(:attributes) { { bulk_upload:, field_113: 3 } } + context "when field_112 is not a permitted value" do + let(:attributes) { { bulk_upload:, field_112: 3 } } it "adds an error" do parser.valid? - expect(parser.errors[:field_113]).to include(I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: "was the letting made under the Common Allocation Policy (CAP)?")) + expect(parser.errors[:field_112]).to include(I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: "was the letting made under the Common Allocation Policy (CAP)?")) end end end describe "#accessible_register" do - context "when field_115 is yes ie 1" do - let(:attributes) { { bulk_upload:, field_115: 1 } } + context "when field_114 is yes ie 1" do + let(:attributes) { { bulk_upload:, field_114: 1 } } it "sets value to 1" do expect(parser.log.accessible_register).to be(1) end end - context "when field_115 is no ie 2" do - let(:attributes) { { bulk_upload:, field_115: 2 } } + context "when field_114 is no ie 2" do + let(:attributes) { { bulk_upload:, field_114: 2 } } it "sets value to 0" do expect(parser.log.accessible_register).to be(0) end end - context "when field_115 is not a permitted value" do - let(:attributes) { { bulk_upload:, field_115: 3 } } + context "when field_114 is not a permitted value" do + let(:attributes) { { bulk_upload:, field_114: 3 } } it "adds an error" do parser.valid? - expect(parser.errors[:field_115]).to include(I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: "was the letting made under the Accessible Register?")) + expect(parser.errors[:field_114]).to include(I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: "was the letting made under the Accessible Register?")) end end end describe "#letting_allocation_unknown" do - context "when field_112, 113, 114, 115 are no ie 2" do - let(:attributes) { { bulk_upload:, field_112: 2, field_113: 2, field_114: 2, field_115: 2 } } + context "when field_111, 113, 114, 115 are no ie 2" do + let(:attributes) { { bulk_upload:, field_111: 2, field_112: 2, field_113: 2, field_114: 2 } } it "sets value to 1" do expect(parser.log.letting_allocation_unknown).to be(1) end end - context "when any one of field_112, 113, 114, 115 is yes ie 1" do - let(:attributes) { { bulk_upload:, field_115: 1 } } + context "when any one of field_111, 113, 114, 115 is yes ie 1" do + let(:attributes) { { bulk_upload:, field_114: 1 } } it "sets value to 0" do expect(parser.log.letting_allocation_unknown).to be(0) @@ -2497,14 +2496,14 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do let(:attributes) do { bulk_upload:, - field_43: "F", - field_49: "M", - field_53: "X", - field_57: "R", - field_61: "F", - field_65: "M", - field_69: "X", - field_73: "R", + field_42: "F", + field_48: "M", + field_52: "X", + field_56: "R", + field_60: "F", + field_64: "M", + field_68: "X", + field_72: "R", } end @@ -2524,14 +2523,14 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do let(:attributes) do { bulk_upload:, - field_46: "1", - field_50: "2", - field_54: "6", - field_58: "7", - field_62: "8", - field_66: "9", - field_70: "0", - field_74: "10", + field_45: "1", + field_49: "2", + field_53: "6", + field_57: "7", + field_61: "8", + field_65: "9", + field_69: "0", + field_73: "10", } end @@ -2551,13 +2550,13 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do let(:attributes) do { bulk_upload:, - field_47: "1", - field_51: "2", - field_55: "2", - field_59: "3", - field_63: "1", - field_67: "2", - field_71: "2", + field_46: "1", + field_50: "2", + field_54: "2", + field_58: "3", + field_62: "1", + field_66: "2", + field_70: "2", } end @@ -2574,7 +2573,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "#net_income_known" do context "when 1" do - let(:attributes) { { bulk_upload:, field_117: "1" } } + let(:attributes) { { bulk_upload:, field_116: "1" } } it "sets value from correct mapping" do expect(parser.log.net_income_known).to eq(0) @@ -2582,7 +2581,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when 2" do - let(:attributes) { { bulk_upload:, field_117: "2" } } + let(:attributes) { { bulk_upload:, field_116: "2" } } it "sets value from correct mapping" do expect(parser.log.net_income_known).to eq(1) @@ -2590,7 +2589,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when 3" do - let(:attributes) { { bulk_upload:, field_117: "3" } } + let(:attributes) { { bulk_upload:, field_116: "3" } } it "sets value from correct mapping" do expect(parser.log.net_income_known).to eq(2) @@ -2615,7 +2614,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#sheltered" do - let(:attributes) { { bulk_upload:, field_36: "1" } } + let(:attributes) { { bulk_upload:, field_35: "1" } } it "sets value from correct mapping" do expect(parser.log.sheltered).to eq(1) @@ -2624,16 +2623,16 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "illness fields" do mapping = [ - { attribute: :illness_type_1, field: :field_94 }, - { attribute: :illness_type_2, field: :field_88 }, - { attribute: :illness_type_3, field: :field_91 }, - { attribute: :illness_type_4, field: :field_86 }, - { attribute: :illness_type_5, field: :field_87 }, - { attribute: :illness_type_6, field: :field_89 }, - { attribute: :illness_type_7, field: :field_90 }, - { attribute: :illness_type_8, field: :field_93 }, - { attribute: :illness_type_9, field: :field_92 }, - { attribute: :illness_type_10, field: :field_95 }, + { attribute: :illness_type_1, field: :field_93 }, + { attribute: :illness_type_2, field: :field_87 }, + { attribute: :illness_type_3, field: :field_90 }, + { attribute: :illness_type_4, field: :field_85 }, + { attribute: :illness_type_5, field: :field_86 }, + { attribute: :illness_type_6, field: :field_88 }, + { attribute: :illness_type_7, field: :field_89 }, + { attribute: :illness_type_8, field: :field_92 }, + { attribute: :illness_type_9, field: :field_91 }, + { attribute: :illness_type_10, field: :field_94 }, ] mapping.each do |hash| @@ -2666,7 +2665,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#tenancyother" do - let(:attributes) { { bulk_upload:, field_40: "some other tenancy" } } + let(:attributes) { { bulk_upload:, field_39: "some other tenancy" } } it "sets value to given free text string" do expect(parser.log.tenancyother).to eql("some other tenancy") @@ -2674,7 +2673,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#tenancylength" do - let(:attributes) { { bulk_upload:, field_41: "2" } } + let(:attributes) { { bulk_upload:, field_40: "2" } } it "sets value to given free text string" do expect(parser.log.tenancylength).to eq(2) @@ -2682,7 +2681,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#earnings" do - let(:attributes) { { bulk_upload:, field_119: "104.50" } } + let(:attributes) { { bulk_upload:, field_118: "104.50" } } it "rounds to the nearest whole pound" do expect(parser.log.earnings).to eq(105) @@ -2691,7 +2690,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "#reasonother" do context "when reason is 'Other'" do - let(:attributes) { { bulk_upload:, field_98: "20", field_99: "some other reason" } } + let(:attributes) { { bulk_upload:, field_97: "20", field_98: "some other reason" } } it "is set to given free text string" do expect(parser.log.reasonother).to eql("some other reason") @@ -2699,7 +2698,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when reason is not 'Other'" do - let(:attributes) { { bulk_upload:, field_98: "50", field_99: "some other reason" } } + let(:attributes) { { bulk_upload:, field_97: "50", field_98: "some other reason" } } it "is set to nil" do expect(parser.log.reasonother).to be_nil @@ -2708,7 +2707,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#ppcodenk" do - let(:attributes) { { bulk_upload:, field_102: "2" } } + let(:attributes) { { bulk_upload:, field_101: "2" } } it "sets correct value from mapping" do expect(parser.log.ppcodenk).to eq(1) @@ -2717,7 +2716,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "#household_charge" do context "when log is general needs" do - let(:attributes) { { bulk_upload:, field_4: 1, field_122: "1" } } + let(:attributes) { { bulk_upload:, field_4: 1, field_121: "1" } } it "sets correct value from mapping" do expect(parser.log.household_charge).to eq(nil) @@ -2725,7 +2724,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when log is supported housing" do - let(:attributes) { { bulk_upload:, field_4: 2, field_122: "1" } } + let(:attributes) { { bulk_upload:, field_4: 2, field_121: "1" } } it "sets correct value from mapping" do expect(parser.log.household_charge).to eq(1) @@ -2734,14 +2733,14 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#supcharg" do - let(:attributes) { setup_section_params.merge({ field_124: "330", field_125: "0", field_126: "0", field_127: "123.45" }) } + let(:attributes) { setup_section_params.merge({ field_123: "330", field_124: "0", field_125: "0", field_126: "123.45" }) } it "sets value given" do expect(parser.log.supcharg).to eq(123.45) end context "when other charges are not given" do - let(:attributes) { setup_section_params.merge({ field_127: "123.45", field_124: nil, field_125: nil, field_126: nil }) } + let(:attributes) { setup_section_params.merge({ field_126: "123.45", field_123: nil, field_124: nil, field_125: nil }) } it "does not set charges values" do parser.log.save! @@ -2754,15 +2753,15 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do it "adds an error to all missing charges" do parser.valid? - expect(parser.errors[:field_124]).to eql([I18n.t("validations.lettings.2026.bulk_upload.charges.missing_charges", sentence_fragment: "basic rent")]) - expect(parser.errors[:field_125]).to eql([I18n.t("validations.lettings.2026.bulk_upload.charges.missing_charges", sentence_fragment: "service charge")]) - expect(parser.errors[:field_126]).to eql([I18n.t("validations.lettings.2026.bulk_upload.charges.missing_charges", sentence_fragment: "personal service charge")]) - expect(parser.errors[:field_127]).to eql([I18n.t("validations.lettings.2026.bulk_upload.charges.related_to_missing_charge")]) + expect(parser.errors[:field_123]).to eql([I18n.t("validations.lettings.2026.bulk_upload.charges.missing_charges", sentence_fragment: "basic rent")]) + expect(parser.errors[:field_124]).to eql([I18n.t("validations.lettings.2026.bulk_upload.charges.missing_charges", sentence_fragment: "service charge")]) + expect(parser.errors[:field_125]).to eql([I18n.t("validations.lettings.2026.bulk_upload.charges.missing_charges", sentence_fragment: "personal service charge")]) + expect(parser.errors[:field_126]).to eql([I18n.t("validations.lettings.2026.bulk_upload.charges.related_to_missing_charge")]) end end context "when supscharg is not given" do - let(:attributes) { setup_section_params.merge({ field_123: 1, field_124: "350.45", field_125: "0", field_126: "0", field_127: nil }) } + let(:attributes) { setup_section_params.merge({ field_122: 1, field_123: "350.45", field_124: "0", field_125: "0", field_126: nil }) } it "does not set charges values" do parser.log.save! @@ -2776,16 +2775,16 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do it "adds an error to all charges" do parser.valid? + expect(parser.errors[:field_123]).to eql([I18n.t("validations.lettings.2026.bulk_upload.charges.related_to_missing_charge")]) expect(parser.errors[:field_124]).to eql([I18n.t("validations.lettings.2026.bulk_upload.charges.related_to_missing_charge")]) expect(parser.errors[:field_125]).to eql([I18n.t("validations.lettings.2026.bulk_upload.charges.related_to_missing_charge")]) - expect(parser.errors[:field_126]).to eql([I18n.t("validations.lettings.2026.bulk_upload.charges.related_to_missing_charge")]) - expect(parser.errors[:field_127]).to eql([I18n.t("validations.lettings.2026.bulk_upload.charges.missing_charges", sentence_fragment: "support charge")]) + expect(parser.errors[:field_126]).to eql([I18n.t("validations.lettings.2026.bulk_upload.charges.missing_charges", sentence_fragment: "support charge")]) end end end describe "#pscharge" do - let(:attributes) { { bulk_upload:, field_124: "111.45", field_125: "0", field_126: "123.45", field_127: "0" } } + let(:attributes) { { bulk_upload:, field_123: "111.45", field_124: "0", field_125: "123.45", field_126: "0" } } it "sets value given" do expect(parser.log.pscharge).to eq(123.45) @@ -2793,7 +2792,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#scharge" do - let(:attributes) { { bulk_upload:, field_124: "111.45", field_125: "123.45", field_126: "0", field_127: "0" } } + let(:attributes) { { bulk_upload:, field_123: "111.45", field_124: "123.45", field_125: "0", field_126: "0" } } it "sets value given" do expect(parser.log.scharge).to eq(123.45) @@ -2810,7 +2809,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "#mrcdate" do context "when valid" do - let(:attributes) { { bulk_upload:, field_33: "13", field_34: "12", field_35: "22" } } + let(:attributes) { { bulk_upload:, field_32: "13", field_33: "12", field_34: "22" } } it "sets value given" do expect(parser.log.mrcdate).to eq(Date.new(2022, 12, 13)) @@ -2818,7 +2817,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when valid (4 digit year)" do - let(:attributes) { { bulk_upload:, field_33: "13", field_34: "12", field_35: "2022" } } + let(:attributes) { { bulk_upload:, field_32: "13", field_33: "12", field_34: "2022" } } it "sets value given" do expect(parser.log.mrcdate).to eq(Date.new(2022, 12, 13)) @@ -2826,7 +2825,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when invalid" do - let(:attributes) { { bulk_upload:, field_33: "13", field_34: "13", field_35: "22" } } + let(:attributes) { { bulk_upload:, field_32: "13", field_33: "13", field_34: "22" } } it "does not raise an error" do expect { parser.log.mrcdate }.not_to raise_error @@ -2836,7 +2835,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "#majorrepairs" do context "when mrcdate given" do - let(:attributes) { { bulk_upload:, field_33: "13", field_34: "12", field_35: "22" } } + let(:attributes) { { bulk_upload:, field_32: "13", field_33: "12", field_34: "22" } } it "sets #majorrepairs to 1" do expect(parser.log.majorrepairs).to eq(1) @@ -2844,7 +2843,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when mrcdate not given" do - let(:attributes) { { bulk_upload:, field_33: "", field_34: "", field_35: "", field_4: 1 } } + let(:attributes) { { bulk_upload:, field_32: "", field_33: "", field_34: "", field_4: 1 } } it "sets #majorrepairs to 0" do expect(parser.log.majorrepairs).to eq(0) @@ -2854,7 +2853,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "#voiddate" do context "when valid" do - let(:attributes) { { bulk_upload:, field_30: "13", field_31: "12", field_32: "22" } } + let(:attributes) { { bulk_upload:, field_29: "13", field_30: "12", field_31: "22" } } it "sets value given" do expect(parser.log.voiddate).to eq(Date.new(2022, 12, 13)) @@ -2862,7 +2861,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when valid (4 digit year)" do - let(:attributes) { { bulk_upload:, field_30: "13", field_31: "12", field_32: "2022" } } + let(:attributes) { { bulk_upload:, field_29: "13", field_30: "12", field_31: "2022" } } it "sets value given" do expect(parser.log.voiddate).to eq(Date.new(2022, 12, 13)) @@ -2870,7 +2869,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when invalid" do - let(:attributes) { { bulk_upload:, field_30: "13", field_31: "13", field_32: "22" } } + let(:attributes) { { bulk_upload:, field_29: "13", field_30: "13", field_31: "22" } } it "does not raise an error" do expect { parser.log.voiddate }.not_to raise_error @@ -2911,7 +2910,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#prevloc" do - let(:attributes) { { bulk_upload:, field_105: "E07000223" } } + let(:attributes) { { bulk_upload:, field_104: "E07000223" } } it "sets to given value" do expect(parser.log.prevloc).to eql("E07000223") @@ -2920,7 +2919,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "#previous_la_known" do context "when known" do - let(:attributes) { { bulk_upload:, field_105: "E07000223" } } + let(:attributes) { { bulk_upload:, field_104: "E07000223" } } it "sets to 1" do expect(parser.log.previous_la_known).to eq(1) @@ -2928,7 +2927,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when not known" do - let(:attributes) { { bulk_upload:, field_105: "", field_4: 1 } } + let(:attributes) { { bulk_upload:, field_104: "", field_4: 1 } } it "sets to 0" do expect(parser.log.previous_la_known).to eq(0) @@ -2956,7 +2955,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "#housingneeds" do context "when no disabled needs" do - let(:attributes) { { bulk_upload:, field_83: "1" } } + let(:attributes) { { bulk_upload:, field_82: "1" } } it "sets to 2" do expect(parser.log.housingneeds).to eq(2) @@ -2964,7 +2963,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when dont know about disabled needs" do - let(:attributes) { { bulk_upload:, field_84: "1" } } + let(:attributes) { { bulk_upload:, field_83: "1" } } it "sets to 3" do expect(parser.log.housingneeds).to eq(3) @@ -2972,7 +2971,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when housingneeds are given" do - let(:attributes) { { bulk_upload:, field_83: "0", field_81: "1", field_82: "1" } } + let(:attributes) { { bulk_upload:, field_82: "0", field_80: "1", field_81: "1" } } it "sets correct housingneeds" do expect(parser.log.housingneeds).to eq(1) @@ -2981,8 +2980,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when housingneeds are given and field_82 is nil" do - let(:attributes) { { bulk_upload:, field_83: nil, field_81: "1", field_82: "1" } } + context "when housingneeds are given and field_81 is nil" do + let(:attributes) { { bulk_upload:, field_82: nil, field_80: "1", field_81: "1" } } it "sets correct housingneeds" do expect(parser.log.housingneeds).to eq(1) @@ -2992,7 +2991,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when housingneeds are not given" do - let(:attributes) { { bulk_upload:, field_79: nil, field_80: nil, field_81: nil, field_83: nil } } + let(:attributes) { { bulk_upload:, field_78: nil, field_79: nil, field_80: nil, field_82: nil } } it "sets correct housingneeds" do expect(parser.log.housingneeds).to eq(1) @@ -3001,106 +3000,106 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when housingneeds a and b are selected" do - let(:attributes) { { bulk_upload:, field_79: "1", field_80: "1" } } + let(:attributes) { { bulk_upload:, field_78: "1", field_79: "1" } } it "sets error on housingneeds a and b" do parser.valid? + expect(parser.errors[:field_78]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds_type.only_one_option_permitted")) expect(parser.errors[:field_79]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds_type.only_one_option_permitted")) - expect(parser.errors[:field_80]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds_type.only_one_option_permitted")) - expect(parser.errors[:field_81]).to be_blank + expect(parser.errors[:field_80]).to be_blank end end context "when housingneeds a and c are selected" do - let(:attributes) { { bulk_upload:, field_79: "1", field_81: "1" } } + let(:attributes) { { bulk_upload:, field_78: "1", field_80: "1" } } it "sets error on housingneeds a and c" do parser.valid? - expect(parser.errors[:field_79]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds_type.only_one_option_permitted")) - expect(parser.errors[:field_81]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds_type.only_one_option_permitted")) - expect(parser.errors[:field_80]).to be_blank + expect(parser.errors[:field_78]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds_type.only_one_option_permitted")) + expect(parser.errors[:field_80]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds_type.only_one_option_permitted")) + expect(parser.errors[:field_79]).to be_blank end end context "when housingneeds b and c are selected" do - let(:attributes) { { bulk_upload:, field_80: "1", field_81: "1" } } + let(:attributes) { { bulk_upload:, field_79: "1", field_80: "1" } } it "sets error on housingneeds b and c" do parser.valid? + expect(parser.errors[:field_79]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds_type.only_one_option_permitted")) expect(parser.errors[:field_80]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds_type.only_one_option_permitted")) - expect(parser.errors[:field_81]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds_type.only_one_option_permitted")) - expect(parser.errors[:field_79]).to be_blank + expect(parser.errors[:field_78]).to be_blank end end context "when housingneeds a and g are selected" do - let(:attributes) { { bulk_upload:, field_79: "1", field_83: "1" } } + let(:attributes) { { bulk_upload:, field_78: "1", field_82: "1" } } it "sets error on housingneeds a and g" do parser.valid? - expect(parser.errors[:field_83]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds.no_disabled_needs_conjunction")) - expect(parser.errors[:field_79]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds.no_disabled_needs_conjunction")) + expect(parser.errors[:field_82]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds.no_disabled_needs_conjunction")) + expect(parser.errors[:field_78]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds.no_disabled_needs_conjunction")) + expect(parser.errors[:field_79]).to be_blank expect(parser.errors[:field_80]).to be_blank - expect(parser.errors[:field_81]).to be_blank end end context "when only housingneeds g is selected" do - let(:attributes) { { bulk_upload:, field_79: "0", field_83: "1" } } + let(:attributes) { { bulk_upload:, field_78: "0", field_82: "1" } } it "does not add any housingneeds errors" do parser.valid? - expect(parser.errors[:field_55]).to be_blank + expect(parser.errors[:field_54]).to be_blank + expect(parser.errors[:field_78]).to be_blank expect(parser.errors[:field_79]).to be_blank expect(parser.errors[:field_80]).to be_blank - expect(parser.errors[:field_81]).to be_blank end end context "when housingneeds a and h are selected" do - let(:attributes) { { bulk_upload:, field_79: "1", field_84: "1" } } + let(:attributes) { { bulk_upload:, field_78: "1", field_83: "1" } } it "sets error on housingneeds a and h" do parser.valid? - expect(parser.errors[:field_84]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds.dont_know_disabled_needs_conjunction")) - expect(parser.errors[:field_79]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds.dont_know_disabled_needs_conjunction")) + expect(parser.errors[:field_83]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds.dont_know_disabled_needs_conjunction")) + expect(parser.errors[:field_78]).to include(I18n.t("validations.lettings.2026.bulk_upload.housingneeds.dont_know_disabled_needs_conjunction")) + expect(parser.errors[:field_79]).to be_blank expect(parser.errors[:field_80]).to be_blank - expect(parser.errors[:field_81]).to be_blank end end context "when only housingneeds h is selected" do - let(:attributes) { { bulk_upload:, field_79: "0", field_84: "1" } } + let(:attributes) { { bulk_upload:, field_78: "0", field_83: "1" } } it "does not add any housingneeds errors" do parser.valid? - expect(parser.errors[:field_84]).to be_blank + expect(parser.errors[:field_83]).to be_blank + expect(parser.errors[:field_78]).to be_blank expect(parser.errors[:field_79]).to be_blank expect(parser.errors[:field_80]).to be_blank - expect(parser.errors[:field_81]).to be_blank end end end describe "#housingneeds_type" do - context "when field_79 is 1" do - let(:attributes) { { bulk_upload:, field_79: "1" } } + context "when field_78 is 1" do + let(:attributes) { { bulk_upload:, field_78: "1" } } it "set to 0" do expect(parser.log.housingneeds_type).to eq(0) end end - context "when field_80 is 1" do - let(:attributes) { { bulk_upload:, field_80: "1" } } + context "when field_79 is 1" do + let(:attributes) { { bulk_upload:, field_79: "1" } } it "set to 1" do expect(parser.log.housingneeds_type).to eq(1) end end - context "when field_81 is 1" do - let(:attributes) { { bulk_upload:, field_81: "1" } } + context "when field_80 is 1" do + let(:attributes) { { bulk_upload:, field_80: "1" } } it "set to 2" do expect(parser.log.housingneeds_type).to eq(2) @@ -3109,8 +3108,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#housingneeds_other" do - context "when field_54 is 1" do - let(:attributes) { { bulk_upload:, field_82: "1" } } + context "when field_53 is 1" do + let(:attributes) { { bulk_upload:, field_81: "1" } } it "sets to 1" do expect(parser.log.housingneeds_other).to eq(1)