From a61713413beb36deca153299190f579b72bfb8c4 Mon Sep 17 00:00:00 2001 From: Samuel Young Date: Mon, 5 Jan 2026 16:03:58 +0000 Subject: [PATCH 01/14] CLDC-4136: Hide question on UI flow --- app/models/form/lettings/pages/property_building_type.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/models/form/lettings/pages/property_building_type.rb b/app/models/form/lettings/pages/property_building_type.rb index ff3d76e0b..a143f66dd 100644 --- a/app/models/form/lettings/pages/property_building_type.rb +++ b/app/models/form/lettings/pages/property_building_type.rb @@ -2,7 +2,9 @@ class Form::Lettings::Pages::PropertyBuildingType < ::Form::Page def initialize(id, hsh, subsection) super @id = "property_building_type" - @depends_on = [{ "is_general_needs?" => true }] + @depends_on = [ + { "is_general_needs?" => true, "form.start_year_2026_or_later?" => false }, + ] end def questions From 0a55e17533deffcd949d154b4b74afa1a60a0ffe Mon Sep 17 00:00:00 2001 From: Samuel Young Date: Mon, 5 Jan 2026 16:07:39 +0000 Subject: [PATCH 02/14] CLDC-4136: Hide question from CDS export --- .../exports/lettings_log_export_constants.rb | 4 + .../exports/lettings_log_export_service.rb | 3 +- .../exports/general_needs_log_26_27.xml | 175 ++++++++++++++++++ .../lettings_log_export_service_spec.rb | 36 +++- 4 files changed, 215 insertions(+), 3 deletions(-) create mode 100644 spec/fixtures/exports/general_needs_log_26_27.xml diff --git a/app/services/exports/lettings_log_export_constants.rb b/app/services/exports/lettings_log_export_constants.rb index b0298e6ca..1698fb0a1 100644 --- a/app/services/exports/lettings_log_export_constants.rb +++ b/app/services/exports/lettings_log_export_constants.rb @@ -199,4 +199,8 @@ module Exports::LettingsLogExportConstants "carehome_charges_value_check", "chcharge" ] + + PRE_2026_EXPORT_FIELDS = Set[ + "builtype" + ] end diff --git a/app/services/exports/lettings_log_export_service.rb b/app/services/exports/lettings_log_export_service.rb index 89b041104..5e67b4854 100644 --- a/app/services/exports/lettings_log_export_service.rb +++ b/app/services/exports/lettings_log_export_service.rb @@ -170,7 +170,8 @@ module Exports !EXPORT_FIELDS.include?(field_name) || (lettings_log.form.start_year_2024_or_later? && PRE_2024_EXPORT_FIELDS.include?(field_name)) || (!lettings_log.form.start_year_2024_or_later? && POST_2024_EXPORT_FIELDS.include?(field_name)) || - (lettings_log.form.start_year_2025_or_later? && PRE_2025_EXPORT_FIELDS.include?(field_name)) + (lettings_log.form.start_year_2025_or_later? && PRE_2025_EXPORT_FIELDS.include?(field_name)) || + (lettings_log.form.start_year_2026_or_later? && PRE_2026_EXPORT_FIELDS.include?(field_name)) end def build_export_xml(lettings_logs) diff --git a/spec/fixtures/exports/general_needs_log_26_27.xml b/spec/fixtures/exports/general_needs_log_26_27.xml new file mode 100644 index 000000000..cc42c8f9b --- /dev/null +++ b/spec/fixtures/exports/general_needs_log_26_27.xml @@ -0,0 +1,175 @@ + + +
+ 2 + BZ737 + 35 + F + 2 + 6 + 0 + 2 + 32 + M + 6 + + + + + + + + + + + + + + + + + + + 1 + 4 + 4 + 1 + 1 + 2 + 1 + 5 + 4 + A1 1AA + 6 + 7 + 3 + 1 + 268 + 1 + 1 + 2 + 2 + 7 + AA1 1AA + 1 + 0 + 1 + 0 + + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 0 + 1 + 0 + 0 + 0 + + + + 4 + 123 + E09000033 + E07000105 + 6 + 1 + 2022-05-05T10:36:49+01:00 + 0 + 2026-04-03T00:00:00+01:00 + 1 + 2 + 2021-11-03T00:00:00+00:00 + 2 + 1 + 7 + 0 + 0 + 2 + + 2 + 200.0 + 50.0 + 40.0 + 35.0 + 325.0 + 12.0 + 0 + 1 + 0 + 100.0 + 25.0 + 20.0 + 17.5 + 162.5 + 6.0 + 0 + 1 + + 2 + P + + + + + + + + 2 + + 3 + + 4 + 2 + 1429 + 1 + 1 + 1 + 1 + 1, Test Street + + Test Town + + + 2 + + + + + 0 + 826 + address line 1 as entered + address line 2 as entered + town or city as entered + county as entered + AB1 2CD + la as entered + {id} + {owning_org_id} + {owning_org_name} + 1234 + {managing_org_id} + {managing_org_name} + 1234 + 2026-04-03T00:00:00+01:00 + 2026-04-03T00:00:00+01:00 + {log_id} + test1@example.com + test1@example.com + + 2 + 1 + +
diff --git a/spec/services/exports/lettings_log_export_service_spec.rb b/spec/services/exports/lettings_log_export_service_spec.rb index 02c7f4a2b..613d64dd0 100644 --- a/spec/services/exports/lettings_log_export_service_spec.rb +++ b/spec/services/exports/lettings_log_export_service_spec.rb @@ -419,7 +419,7 @@ RSpec.describe Exports::LettingsLogExportService do end end - context "with 24/25 collection period" do + context "with 24/25 collection period", metadata: { year: 24 } do let(:start_time) { Time.zone.local(2024, 4, 3) } before do @@ -451,7 +451,7 @@ RSpec.describe Exports::LettingsLogExportService do end end - context "with 25/26 collection period" do + context "with 25/26 collection period", metadata: { year: 25 } do let(:start_time) { Time.zone.local(2025, 4, 3) } before do @@ -483,6 +483,38 @@ RSpec.describe Exports::LettingsLogExportService do end end + context "with 26/27 collection period", metadata: { year: 26 } do + let(:start_time) { Time.zone.local(2026, 4, 3) } + + before do + Timecop.freeze(start_time) + Singleton.__init__(FormHandler) + end + + after do + Timecop.unfreeze + Singleton.__init__(FormHandler) + end + + context "and one lettings log is available for export" do + let!(:lettings_log) { FactoryBot.create(:lettings_log, :completed, startdate: Time.zone.local(2026, 4, 3), assigned_to: user, age1: 35, sex1: "F", age2: 32, sex2: "M", ppostcode_full: "A1 1AA", nationality_all_group: 13, propcode: "123", postcode_full: "SE2 6RT", tenancycode: "BZ737", voiddate: Time.zone.local(2021, 11, 3), mrcdate: Time.zone.local(2022, 5, 5, 10, 36, 49), tenancylength: 5, underoccupation_benefitcap: 4, creation_method: 2, bulk_upload_id: 1, address_line1_as_entered: "address line 1 as entered", address_line2_as_entered: "address line 2 as entered", town_or_city_as_entered: "town or city as entered", county_as_entered: "county as entered", postcode_full_as_entered: "AB1 2CD", la_as_entered: "la as entered", manual_address_entry_selected: false, uprn: "1", uprn_known: 1) } + let(:expected_zip_filename) { "core_2026_2027_apr_mar_f0001_inc0001.zip" } + let(:expected_data_filename) { "core_2026_2027_apr_mar_f0001_inc0001_pt001.xml" } + let(:xml_export_file) { File.open("spec/fixtures/exports/general_needs_log_26_27.xml", "r:UTF-8") } + + it "generates an XML export file with the expected content within the ZIP file" do + expected_content = replace_entity_ids(lettings_log, xml_export_file.read) + expect(storage_service).to receive(:write_file).with(expected_zip_filename, any_args) do |_, content| + entry = Zip::File.open_buffer(content).find_entry(expected_data_filename) + expect(entry).not_to be_nil + expect(entry.get_input_stream.read).to have_same_xml_contents_as(expected_content) + end + + export_service.export_xml_lettings_logs + end + end + end + context "and one lettings log has not been updated in the time range" do let(:expected_zip_filename) { "core_#{current_collection_start_year}_#{current_collection_end_year}_apr_mar_f0001_inc0001.zip" } let(:start_time) { current_collection_start_date } From 543dc58e3b18da2efcc54e29600e8505fbe48eb0 Mon Sep 17 00:00:00 2001 From: Samuel Young Date: Mon, 5 Jan 2026 16:42:25 +0000 Subject: [PATCH 03/14] CLDC-4136: Hide question from log download csv --- app/services/csv/lettings_log_csv_service.rb | 3 + .../lettings_log_csv_export_codes_26.csv | 3 + .../lettings_log_csv_export_labels_26.csv | 3 + ...gs_log_csv_export_non_support_codes_26.csv | 3 + ...s_log_csv_export_non_support_labels_26.csv | 3 + .../csv/lettings_log_csv_service_spec.rb | 192 ++++++++++++++++++ 6 files changed, 207 insertions(+) create mode 100644 spec/fixtures/files/lettings_log_csv_export_codes_26.csv create mode 100644 spec/fixtures/files/lettings_log_csv_export_labels_26.csv create mode 100644 spec/fixtures/files/lettings_log_csv_export_non_support_codes_26.csv create mode 100644 spec/fixtures/files/lettings_log_csv_export_non_support_labels_26.csv diff --git a/app/services/csv/lettings_log_csv_service.rb b/app/services/csv/lettings_log_csv_service.rb index 2da392fb0..67a398adf 100644 --- a/app/services/csv/lettings_log_csv_service.rb +++ b/app/services/csv/lettings_log_csv_service.rb @@ -264,6 +264,8 @@ module Csv "uprn" => %w[uprn_known uprn], }.freeze + IGNORED_ATTRIBUTES_2026 = %w[builtype].freeze + def attribute_mappings if @year >= 2024 ATTRIBUTE_MAPPINGS.merge(ATTRIBUTE_MAPPINGS_2024) @@ -282,6 +284,7 @@ module Csv ordered_questions = FormHandler.instance.ordered_questions_for_year(@year, "lettings") soft_validations_attributes = soft_validations_attributes(ordered_questions) ordered_questions.reject! { |q| q.id.match?(/age\d_known|nationality_all_group|rent_value_check/) } + ordered_questions.reject! { |q| IGNORED_ATTRIBUTES_2026.include?(q.id) } if @year >= 2026 attributes = insert_derived_and_related_attributes(ordered_questions) order_address_fields_for_support(attributes) final_attributes = non_question_fields + attributes + SCHEME_AND_LOCATION_ATTRIBUTES diff --git a/spec/fixtures/files/lettings_log_csv_export_codes_26.csv b/spec/fixtures/files/lettings_log_csv_export_codes_26.csv new file mode 100644 index 000000000..1a17f38f2 --- /dev/null +++ b/spec/fixtures/files/lettings_log_csv_export_codes_26.csv @@ -0,0 +1,3 @@ +Log ID,Status of log,ID of a set of duplicate logs,User the log is created by,User the log is assigned to,Is the user in the assigned_to column the data protection officer?,Time and date the log was created,User who last updated the log,Time and date the log was last updated,Was the log submitted in-service or via bulk upload?,Year collection period opened,ID of a set of bulk uploaded logs,Which organisation owns this property?,Which organisation manages this letting?,What is the needs type?,What is the letting type?,Is this letting a renewal?,What is the tenancy start date?,"What is the rent type? (grouped into SR, IR or AR)",What is the rent type?,Which type of Intermediate Rent is this letting?,Which 'Other' type of Intermediate Rent is this letting?,Is this a London Affordable Rent letting?,What is the tenant code?,What is the property reference?,Has the tenant seen the MHCLG privacy notice?,Is this the first time the property has been let as social housing?,What rent product was the property most recently let as?,What is the reason for the property being vacant?,Is this property new to the social rented sector?,"If known, property's UPRN",Address line 1,Address line 2,Town or City,County,Postcode,The internal value to indicate if the LA was inferred from the postcode,What is the property's local authority?,Local authority code,Is the UPRN known?,UPRN of the address selected,Was the 'No address found' page seen?,Address line 1 input from address matching feature,Postcode input from address matching feature,Address line 1 entered in bulk upload file,Address line 2 entered in bulk upload file,Town or city entered in bulk upload file,County entered in bulk upload file,Postcode entered in bulk upload file,Local authority entered in bulk upload file,What type of unit is the property?,Is the property built or adapted to wheelchair-user standards?,How many bedrooms does the property have?,What is the void date?,Number of days the property was vacant,The following soft validation was confirmed: You told us that the property has been vacant for more than 2 years. This is higher than we would expect.,Were any major repairs carried out during the void period?,What date were any major repairs completed on?,The following soft validation was confirmed: You told us the property has been vacant for 2 years. This is higher than we would expect.,Is this letting in sheltered accommodation?,Is this a joint tenancy?,Is this a starter tenancy?,What is the type of tenancy?,"If 'Other', what is the type of tenancy?",What is the length of the fixed-term tenancy to the nearest year?,How many people live in the household at this letting?,The following soft validation was confirmed: You told us somebody in the household is pregnant. You also told us there are no female tenants living at the property.,"Where household characteristics have a 'Refused' option for some or all of: AGE1-AGE8, SEX1-SEX8, RELAT2-RELAT8, ECSTAT1-ECSTAT8","Type of household 1 = 1 elder; 2 = 2 adults, including elder(s); 3 = 1 adult; 4 = 2 adults; 5 = 1 adult & 1+ children; 6 = 2+ adults & 1+ children; 9 = Other",Total number of dependent children in the household (Sum of when RELAT2-8 = C),Total number of elders in household (Sum of when AGE1-8 >= 60),Total number of adults in household,What is the lead tenant's age?,The following soft validation was confirmed: You told us this person is aged %{age} years and retired. The minimum expected retirement age for %{gender} in England is %{age}.,Which of these best describes the lead tenant's gender identity?,What is the lead tenant's ethnic group?,Which of these best describes the lead tenant's ethnic background?,What is the lead tenant's nationality?,Which of these best describes the lead tenant's working situation?,Are the details of tenant 2 known?,What is person 2's relationship to the lead tenant?,"The following soft validation was confirmed: You said that [person X]'s relationship to lead tenant is partner, and that their age is [AGEX]. Are you sure this is correct?",The following soft validation was confirmed: You said that more than one person in the household is the partner of the lead tenant. Are you sure this is correct?,What is person 2's age?,Which of these best describes person 2's gender identity?,Which of these best describes person 2's working situation?,Are the details of tenant 3 known?,What is person 3's relationship to the lead tenant?,What is person 3's age?,Which of these best describes person 3's gender identity?,Which of these best describes person 3's working situation?,Are the details of tenant 4 known?,What is person 4's relationship to the lead tenant?,What is person 4's age?,Which of these best describes person 4's gender identity?,Which of these best describes person 4's working situation?,Are the details of tenant 5 known?,What is person 5's relationship to the lead tenant?,What is person 5's age?,Which of these best describes person 5's gender identity?,Which of these best describes person 5's working situation?,Are the details of tenant 6 known?,What is person 6's relationship to the lead tenant?,What is person 6's age?,Which of these best describes person 6's gender identity?,Which of these best describes person 6's working situation?,Are the details of tenant 7 known?,What is person 7's relationship to the lead tenant?,What is person 7's age?,Which of these best describes person 7's gender identity?,Which of these best describes person 7's working situation?,Are the details of tenant 8 known?,What is person 8's relationship to the lead tenant?,What is person 8's age?,Which of these best describes person 8's gender identity?,Which of these best describes person 8's working situation?,Does anybody in the household have links to the UK armed forces?,Is this person still serving in the UK armed forces?,Was this person seriously injured or ill as a result of serving in the UK armed forces?,Is anybody in the household pregnant?,Does anybody in the household have any disabled access needs?,"What access needs do they have? (Fully wheelchair-accessible housing, Level access housing or Wheelchair access to essential rooms)",Disabled access needs a) Fully wheelchair-accessible housing,Disabled access needs b) Wheelchair access to essential rooms,Disabled access needs c) Level access housing,Disabled access needs f) Other disabled access needs,Disabled access needs g) No disabled access needs,Disabled access needs h) Don't know,Do they have any other disabled access needs?,Does anybody in the household have a physical or mental health condition (or other illness) expected to last 12 months or more?,Does this person's condition affect their dexterity?,Does this person's condition affect their learning or understanding or concentrating?,Does this person's condition affect their hearing?,Does this person's condition affect their memory?,Does this person's condition affect their mental health?,Does this person's condition affect their mobility?,Does this person's condition affect them socially or behaviourally?,Does this person's condition affect their stamina or breathing or fatigue?,Does this person's condition affect their vision?,Does this person's condition affect them in another way?,How long has the household continuously lived in the local authority area of the new letting?,How long has the household been on the local authority waiting list for the new letting?,What is the tenant's main reason for the household leaving their last settled home?,"If 'Other', what was the main reason for leaving their last settled home?",The soft validation was confirmed,Where was the household immediately before this letting?,Did the household experience homelessness immediately before this letting?,Previous postcode unknown or previous accommodation was temporary,What is the postcode of the household's last settled home?,Was the local authority of the household's last settled home known?,The internal value to indicate if the previous LA was inferred from the postcode,Previous location LA name,Previous location's ONS LA Code,Was the household given reasonable preference by the local authority?,Reasonable preference reason - They were homeless or about to lose their home (within 56 days),"Reasonable preference reason - They were living in insanitary, overcrowded or unisatisfactory housing",Reasonable preference reason - They needed to move on medical and welfare reasons (including disability),Reasonable preference reason - They needed to move to avoid hardship to themselves or others,Reasonable preference reason - Don't Know,Was the letting made under Choice-Based Lettings (CBL)?,Was the letting made under the Common Allocation Policy (CAP)?,Was the letting made under the Common Housing Register (CHR)?,Was the letting made under the Accessible Register?,"The letting was not allocated under CBL, CAP, CHR or Accessible Register.",,What was the source of referral for this letting?,"The following soft validation was confirmed: Are you sure? This is a general needs log, and this referral type is for supported housing.",Do you know the household's combined income after tax?,Was the household income refused?,How often does the household receive income?,How much income does the household have in total?,Populated when someone hits the soft validation and confirmed in the service,Is the tenant likely to be receiving any of these housing-related benefits?,"Does the tenant receive housing-related benefits? Yes if hb = Universal Credit housing element or Housing benefit, No if hb = Don't Know, Neither, Tenant prefers not to say or blank","How much of the household's income is from Universal Credit, state pensions or benefits?",Does the household pay rent or other charges for the accommodation?,Does the household pay rent or other charges for the accommodation? - flag for when household_charge is answered no,How often does the household pay rent and other charges?,What is the basic rent?,Weekly rent,Populated when the soft validation and confirmed in the service,What is the service charge?,Weekly service charge,What is the personal service charge?,Weekly personal service charge,What is the support charge?,Weekly support charge,Total charge to the tenant,Weekly total charge to the tenant,Populated when the soft validation and confirmed in the service,Populated when the soft validation and confirmed in the service,Populated when the soft validation and confirmed in the service,"After the household has received any housing-related benefits, will they still need to pay for rent and charges?",Can you estimate the outstanding amount?,Estimated outstanding amount,Weekly total rent shortfall charge for tenant receiving housing benefit,What scheme does this letting belong to?,"From scheme code, we map to the scheme name",Does the scheme contain confidential information?,"What is this type of scheme? (Direct access hostel), Foyer, Housing for older people or Other supported housing",Is this scheme registered under the Care Standards Act 2000?,Which organisation owns the housing stock for this scheme?,What client group is this scheme intended for?,Does this scheme provide for another client group?,What is the other client group?,What support does this scheme provide?,Intended length of stay,Date scheme was created,Which location is this letting for?,What is the postcode for this location?,What is the name of this location?,How many units are at this location?,What is the most common type of unit at this location?,What are the mobility standards for the majority of the units in this location?,What is the local authority of this postcode?,When did the first property in this location become available under this scheme? +id,status,duplicate_set_id,created_by,assigned_to,is_dpo,created_at,updated_by,updated_at,creation_method,collection_start_year,bulk_upload_id,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,declaration,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,uprn,address_line1,address_line2,town_or_city,county,postcode_full,is_la_inferred,la_label,la,uprn_known,uprn_selection,address_search_value_check,address_line1_input,postcode_full_input,address_line1_as_entered,address_line2_as_entered,town_or_city_as_entered,county_as_entered,postcode_full_as_entered,la_as_entered,unittype_gn,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,sheltered,joint,startertenancy,tenancy,tenancyother,tenancylength,hhmemb,pregnancy_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sex1,ethnic_group,ethnic,nationality_all,ecstat1,details_known_2,relat2,partner_under_16_value_check,multiple_partners_value_check,age2,sex2,ecstat2,details_known_3,relat3,age3,sex3,ecstat3,details_known_4,relat4,age4,sex4,ecstat4,details_known_5,relat5,age5,sex5,ecstat5,details_known_6,relat6,age6,sex6,ecstat6,details_known_7,relat7,age7,sex7,ecstat7,details_known_8,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,reasonother_value_check,prevten,homeless,ppcodenk,ppostcode_full,previous_la_known,is_previous_la_inferred,prevloc_label,prevloc,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,accessible_register,letting_allocation_none,referral_type,referral,referral_value_check,net_income_known,incref,incfreq,earnings,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,brent,wrent,rent_value_check,scharge,wscharge,pscharge,wpschrge,supcharg,wsupchrg,tcharge,wtcharge,scharge_value_check,pscharge_value_check,supcharg_value_check,hbrentshortfall,tshortfall_known,tshortfall,wtshortfall,scheme_code,scheme_service_name,scheme_confidential,SCHTYPE,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_local_authority,location_startdate +,in_progress,,s.port@jeemayle.com,s.port@jeemayle.com,false,2025-04-01T00:00:00+01:00,,2025-04-01T00:00:00+01:00,1,2025,,MHCLG,MHCLG,1,7,0,2025-04-01,2,2,,,2,HIJKLMN,ABCDEFG,1,0,2,6,2,,Address line 1,,London,,NW9 5LL,false,Barnet,E09000003,0,,,,,address line 1 as entered,address line 2 as entered,town or city as entered,county as entered,AB1 2CD,la as entered,7,1,3,2025-03-30,1,,1,2025-03-31,,,3,1,4,,2,4,,1,4,0,0,2,35,,F,0,2,36,0,0,P,,,32,M,6,1,R,-9,R,10,0,R,-9,R,10,,,,,,,,,,,,,,,,,,,,,1,4,1,2,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,2,7,4,,,6,1,0,TN23 6LZ,1,false,Ashford,E07000105,1,0,1,0,0,0,0,0,1,0,0,,,,0,0,1,268,,6,1,1,,,2,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,,,,1,0,12.0,6.0,,,,,,,,,,,,,,,,,,,, diff --git a/spec/fixtures/files/lettings_log_csv_export_labels_26.csv b/spec/fixtures/files/lettings_log_csv_export_labels_26.csv new file mode 100644 index 000000000..e2ecf86e6 --- /dev/null +++ b/spec/fixtures/files/lettings_log_csv_export_labels_26.csv @@ -0,0 +1,3 @@ +Log ID,Status of log,ID of a set of duplicate logs,User the log is created by,User the log is assigned to,Is the user in the assigned_to column the data protection officer?,Time and date the log was created,User who last updated the log,Time and date the log was last updated,Was the log submitted in-service or via bulk upload?,Year collection period opened,ID of a set of bulk uploaded logs,Which organisation owns this property?,Which organisation manages this letting?,What is the needs type?,What is the letting type?,Is this letting a renewal?,What is the tenancy start date?,"What is the rent type? (grouped into SR, IR or AR)",What is the rent type?,Which type of Intermediate Rent is this letting?,Which 'Other' type of Intermediate Rent is this letting?,Is this a London Affordable Rent letting?,What is the tenant code?,What is the property reference?,Has the tenant seen the MHCLG privacy notice?,Is this the first time the property has been let as social housing?,What rent product was the property most recently let as?,What is the reason for the property being vacant?,Is this property new to the social rented sector?,"If known, property's UPRN",Address line 1,Address line 2,Town or City,County,Postcode,The internal value to indicate if the LA was inferred from the postcode,What is the property's local authority?,Local authority code,Is the UPRN known?,UPRN of the address selected,Was the 'No address found' page seen?,Address line 1 input from address matching feature,Postcode input from address matching feature,Address line 1 entered in bulk upload file,Address line 2 entered in bulk upload file,Town or city entered in bulk upload file,County entered in bulk upload file,Postcode entered in bulk upload file,Local authority entered in bulk upload file,What type of unit is the property?,Is the property built or adapted to wheelchair-user standards?,How many bedrooms does the property have?,What is the void date?,Number of days the property was vacant,The following soft validation was confirmed: You told us that the property has been vacant for more than 2 years. This is higher than we would expect.,Were any major repairs carried out during the void period?,What date were any major repairs completed on?,The following soft validation was confirmed: You told us the property has been vacant for 2 years. This is higher than we would expect.,Is this letting in sheltered accommodation?,Is this a joint tenancy?,Is this a starter tenancy?,What is the type of tenancy?,"If 'Other', what is the type of tenancy?",What is the length of the fixed-term tenancy to the nearest year?,How many people live in the household at this letting?,The following soft validation was confirmed: You told us somebody in the household is pregnant. You also told us there are no female tenants living at the property.,"Where household characteristics have a 'Refused' option for some or all of: AGE1-AGE8, SEX1-SEX8, RELAT2-RELAT8, ECSTAT1-ECSTAT8","Type of household 1 = 1 elder; 2 = 2 adults, including elder(s); 3 = 1 adult; 4 = 2 adults; 5 = 1 adult & 1+ children; 6 = 2+ adults & 1+ children; 9 = Other",Total number of dependent children in the household (Sum of when RELAT2-8 = C),Total number of elders in household (Sum of when AGE1-8 >= 60),Total number of adults in household,What is the lead tenant's age?,The following soft validation was confirmed: You told us this person is aged %{age} years and retired. The minimum expected retirement age for %{gender} in England is %{age}.,Which of these best describes the lead tenant's gender identity?,What is the lead tenant's ethnic group?,Which of these best describes the lead tenant's ethnic background?,What is the lead tenant's nationality?,Which of these best describes the lead tenant's working situation?,Are the details of tenant 2 known?,What is person 2's relationship to the lead tenant?,"The following soft validation was confirmed: You said that [person X]'s relationship to lead tenant is partner, and that their age is [AGEX]. Are you sure this is correct?",The following soft validation was confirmed: You said that more than one person in the household is the partner of the lead tenant. Are you sure this is correct?,What is person 2's age?,Which of these best describes person 2's gender identity?,Which of these best describes person 2's working situation?,Are the details of tenant 3 known?,What is person 3's relationship to the lead tenant?,What is person 3's age?,Which of these best describes person 3's gender identity?,Which of these best describes person 3's working situation?,Are the details of tenant 4 known?,What is person 4's relationship to the lead tenant?,What is person 4's age?,Which of these best describes person 4's gender identity?,Which of these best describes person 4's working situation?,Are the details of tenant 5 known?,What is person 5's relationship to the lead tenant?,What is person 5's age?,Which of these best describes person 5's gender identity?,Which of these best describes person 5's working situation?,Are the details of tenant 6 known?,What is person 6's relationship to the lead tenant?,What is person 6's age?,Which of these best describes person 6's gender identity?,Which of these best describes person 6's working situation?,Are the details of tenant 7 known?,What is person 7's relationship to the lead tenant?,What is person 7's age?,Which of these best describes person 7's gender identity?,Which of these best describes person 7's working situation?,Are the details of tenant 8 known?,What is person 8's relationship to the lead tenant?,What is person 8's age?,Which of these best describes person 8's gender identity?,Which of these best describes person 8's working situation?,Does anybody in the household have links to the UK armed forces?,Is this person still serving in the UK armed forces?,Was this person seriously injured or ill as a result of serving in the UK armed forces?,Is anybody in the household pregnant?,Does anybody in the household have any disabled access needs?,"What access needs do they have? (Fully wheelchair-accessible housing, Level access housing or Wheelchair access to essential rooms)",Disabled access needs a) Fully wheelchair-accessible housing,Disabled access needs b) Wheelchair access to essential rooms,Disabled access needs c) Level access housing,Disabled access needs f) Other disabled access needs,Disabled access needs g) No disabled access needs,Disabled access needs h) Don't know,Do they have any other disabled access needs?,Does anybody in the household have a physical or mental health condition (or other illness) expected to last 12 months or more?,Does this person's condition affect their dexterity?,Does this person's condition affect their learning or understanding or concentrating?,Does this person's condition affect their hearing?,Does this person's condition affect their memory?,Does this person's condition affect their mental health?,Does this person's condition affect their mobility?,Does this person's condition affect them socially or behaviourally?,Does this person's condition affect their stamina or breathing or fatigue?,Does this person's condition affect their vision?,Does this person's condition affect them in another way?,How long has the household continuously lived in the local authority area of the new letting?,How long has the household been on the local authority waiting list for the new letting?,What is the tenant's main reason for the household leaving their last settled home?,"If 'Other', what was the main reason for leaving their last settled home?",The soft validation was confirmed,Where was the household immediately before this letting?,Did the household experience homelessness immediately before this letting?,Previous postcode unknown or previous accommodation was temporary,What is the postcode of the household's last settled home?,Was the local authority of the household's last settled home known?,The internal value to indicate if the previous LA was inferred from the postcode,Previous location LA name,Previous location's ONS LA Code,Was the household given reasonable preference by the local authority?,Reasonable preference reason - They were homeless or about to lose their home (within 56 days),"Reasonable preference reason - They were living in insanitary, overcrowded or unisatisfactory housing",Reasonable preference reason - They needed to move on medical and welfare reasons (including disability),Reasonable preference reason - They needed to move to avoid hardship to themselves or others,Reasonable preference reason - Don't Know,Was the letting made under Choice-Based Lettings (CBL)?,Was the letting made under the Common Allocation Policy (CAP)?,Was the letting made under the Common Housing Register (CHR)?,Was the letting made under the Accessible Register?,"The letting was not allocated under CBL, CAP, CHR or Accessible Register.",,What was the source of referral for this letting?,"The following soft validation was confirmed: Are you sure? This is a general needs log, and this referral type is for supported housing.",Do you know the household's combined income after tax?,Was the household income refused?,How often does the household receive income?,How much income does the household have in total?,Populated when someone hits the soft validation and confirmed in the service,Is the tenant likely to be receiving any of these housing-related benefits?,"Does the tenant receive housing-related benefits? Yes if hb = Universal Credit housing element or Housing benefit, No if hb = Don't Know, Neither, Tenant prefers not to say or blank","How much of the household's income is from Universal Credit, state pensions or benefits?",Does the household pay rent or other charges for the accommodation?,Does the household pay rent or other charges for the accommodation? - flag for when household_charge is answered no,How often does the household pay rent and other charges?,What is the basic rent?,Weekly rent,Populated when the soft validation and confirmed in the service,What is the service charge?,Weekly service charge,What is the personal service charge?,Weekly personal service charge,What is the support charge?,Weekly support charge,Total charge to the tenant,Weekly total charge to the tenant,Populated when the soft validation and confirmed in the service,Populated when the soft validation and confirmed in the service,Populated when the soft validation and confirmed in the service,"After the household has received any housing-related benefits, will they still need to pay for rent and charges?",Can you estimate the outstanding amount?,Estimated outstanding amount,Weekly total rent shortfall charge for tenant receiving housing benefit,What scheme does this letting belong to?,"From scheme code, we map to the scheme name",Does the scheme contain confidential information?,"What is this type of scheme? (Direct access hostel), Foyer, Housing for older people or Other supported housing",Is this scheme registered under the Care Standards Act 2000?,Which organisation owns the housing stock for this scheme?,What client group is this scheme intended for?,Does this scheme provide for another client group?,What is the other client group?,What support does this scheme provide?,Intended length of stay,Date scheme was created,Which location is this letting for?,What is the postcode for this location?,What is the name of this location?,How many units are at this location?,What is the most common type of unit at this location?,What are the mobility standards for the majority of the units in this location?,What is the local authority of this postcode?,When did the first property in this location become available under this scheme? +id,status,duplicate_set_id,created_by,assigned_to,is_dpo,created_at,updated_by,updated_at,creation_method,collection_start_year,bulk_upload_id,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,declaration,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,uprn,address_line1,address_line2,town_or_city,county,postcode_full,is_la_inferred,la_label,la,uprn_known,uprn_selection,address_search_value_check,address_line1_input,postcode_full_input,address_line1_as_entered,address_line2_as_entered,town_or_city_as_entered,county_as_entered,postcode_full_as_entered,la_as_entered,unittype_gn,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,sheltered,joint,startertenancy,tenancy,tenancyother,tenancylength,hhmemb,pregnancy_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sex1,ethnic_group,ethnic,nationality_all,ecstat1,details_known_2,relat2,partner_under_16_value_check,multiple_partners_value_check,age2,sex2,ecstat2,details_known_3,relat3,age3,sex3,ecstat3,details_known_4,relat4,age4,sex4,ecstat4,details_known_5,relat5,age5,sex5,ecstat5,details_known_6,relat6,age6,sex6,ecstat6,details_known_7,relat7,age7,sex7,ecstat7,details_known_8,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,reasonother_value_check,prevten,homeless,ppcodenk,ppostcode_full,previous_la_known,is_previous_la_inferred,prevloc_label,prevloc,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,accessible_register,letting_allocation_none,referral_type,referral,referral_value_check,net_income_known,incref,incfreq,earnings,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,brent,wrent,rent_value_check,scharge,wscharge,pscharge,wpschrge,supcharg,wsupchrg,tcharge,wtcharge,scharge_value_check,pscharge_value_check,supcharg_value_check,hbrentshortfall,tshortfall_known,tshortfall,wtshortfall,scheme_code,scheme_service_name,scheme_confidential,SCHTYPE,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_local_authority,location_startdate +,in_progress,,s.port@jeemayle.com,s.port@jeemayle.com,false,2025-04-01T00:00:00+01:00,,2025-04-01T00:00:00+01:00,single log,2025,,MHCLG,MHCLG,General needs,Affordable rent general needs local authority,No,2025-04-01,Affordable Rent,Affordable Rent,,,No,HIJKLMN,ABCDEFG,Yes,No,Affordable rent basis,Tenant abandoned property,No,,Address line 1,,London,,NW9 5LL,No,Barnet,E09000003,No,,,,,address line 1 as entered,address line 2 as entered,town or city as entered,county as entered,AB1 2CD,la as entered,House,Yes,3,2025-03-30,1,,Yes,2025-03-31,,,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,4,,Yes,4,0,0,2,35,,Female,White,Irish,Australia,Other,Yes,Yes,,,32,Male,Not seeking work,No,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Yes,Tenant prefers not to say,Not known,Person prefers not to say,Person prefers not to say,,,,,,,,,,,,,,,,,,,,,Yes – the person is a current or former regular,No – they left up to and including 5 years ago,Yes,No,Yes,Fully wheelchair accessible housing,Yes,No,No,No,No,No,No,Yes,No,No,Yes,No,No,No,No,No,No,No,Less than 1 year,1 year but under 2 years,Loss of tied accommodation,,,Other supported housing,No,Yes,TN23 6LZ,Yes,No,Ashford,E07000105,Yes,,Yes,,,,No,No,Yes,No,No,,,,Yes,No,Weekly,268,,Universal Credit housing element,Yes,All,,,Every 2 weeks,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,,,,Yes,Yes,12.0,6.0,,,,,,,,,,,,,,,,,,,, diff --git a/spec/fixtures/files/lettings_log_csv_export_non_support_codes_26.csv b/spec/fixtures/files/lettings_log_csv_export_non_support_codes_26.csv new file mode 100644 index 000000000..620ef87b7 --- /dev/null +++ b/spec/fixtures/files/lettings_log_csv_export_non_support_codes_26.csv @@ -0,0 +1,3 @@ +Log ID,Status of log,ID of a set of duplicate logs,User the log is assigned to,Is the user in the assigned_to column the data protection officer?,Time and date the log was created,User who last updated the log,Time and date the log was last updated,Was the log submitted in-service or via bulk upload?,Year collection period opened,ID of a set of bulk uploaded logs,Which organisation owns this property?,Which organisation manages this letting?,What is the needs type?,What is the letting type?,Is this letting a renewal?,What is the tenancy start date?,"What is the rent type? (grouped into SR, IR or AR)",What is the rent type?,Which type of Intermediate Rent is this letting?,Which 'Other' type of Intermediate Rent is this letting?,Is this a London Affordable Rent letting?,What is the tenant code?,What is the property reference?,Has the tenant seen the MHCLG privacy notice?,Is this the first time the property has been let as social housing?,What rent product was the property most recently let as?,What is the reason for the property being vacant?,Is this property new to the social rented sector?,Is the UPRN known?,"If known, property's UPRN",Address line 1,Address line 2,Town or City,County,Postcode,What is the property's local authority?,What type of unit is the property?,Is the property built or adapted to wheelchair-user standards?,How many bedrooms does the property have?,What is the void date?,Number of days the property was vacant,Were any major repairs carried out during the void period?,What date were any major repairs completed on?,Is this letting in sheltered accommodation?,Is this a joint tenancy?,Is this a starter tenancy?,What is the type of tenancy?,"If 'Other', what is the type of tenancy?",What is the length of the fixed-term tenancy to the nearest year?,How many people live in the household at this letting?,"Where household characteristics have a 'Refused' option for some or all of: AGE1-AGE8, SEX1-SEX8, RELAT2-RELAT8, ECSTAT1-ECSTAT8",What is the lead tenant's age?,Which of these best describes the lead tenant's gender identity?,What is the lead tenant's ethnic group?,Which of these best describes the lead tenant's ethnic background?,What is the lead tenant's nationality?,Which of these best describes the lead tenant's working situation?,What is person 2's relationship to the lead tenant?,What is person 2's age?,Which of these best describes person 2's gender identity?,Which of these best describes person 2's working situation?,What is person 3's relationship to the lead tenant?,What is person 3's age?,Which of these best describes person 3's gender identity?,Which of these best describes person 3's working situation?,What is person 4's relationship to the lead tenant?,What is person 4's age?,Which of these best describes person 4's gender identity?,Which of these best describes person 4's working situation?,What is person 5's relationship to the lead tenant?,What is person 5's age?,Which of these best describes person 5's gender identity?,Which of these best describes person 5's working situation?,What is person 6's relationship to the lead tenant?,What is person 6's age?,Which of these best describes person 6's gender identity?,Which of these best describes person 6's working situation?,What is person 7's relationship to the lead tenant?,What is person 7's age?,Which of these best describes person 7's gender identity?,Which of these best describes person 7's working situation?,What is person 8's relationship to the lead tenant?,What is person 8's age?,Which of these best describes person 8's gender identity?,Which of these best describes person 8's working situation?,Does anybody in the household have links to the UK armed forces?,Is this person still serving in the UK armed forces?,Was this person seriously injured or ill as a result of serving in the UK armed forces?,Is anybody in the household pregnant?,Does anybody in the household have any disabled access needs?,"What access needs do they have? (Fully wheelchair-accessible housing, Level access housing or Wheelchair access to essential rooms)",Disabled access needs a) Fully wheelchair-accessible housing,Disabled access needs b) Wheelchair access to essential rooms,Disabled access needs c) Level access housing,Disabled access needs f) Other disabled access needs,Disabled access needs g) No disabled access needs,Disabled access needs h) Don't know,Do they have any other disabled access needs?,Does anybody in the household have a physical or mental health condition (or other illness) expected to last 12 months or more?,Does this person's condition affect their dexterity?,Does this person's condition affect their learning or understanding or concentrating?,Does this person's condition affect their hearing?,Does this person's condition affect their memory?,Does this person's condition affect their mental health?,Does this person's condition affect their mobility?,Does this person's condition affect them socially or behaviourally?,Does this person's condition affect their stamina or breathing or fatigue?,Does this person's condition affect their vision?,Does this person's condition affect them in another way?,How long has the household continuously lived in the local authority area of the new letting?,How long has the household been on the local authority waiting list for the new letting?,What is the tenant's main reason for the household leaving their last settled home?,"If 'Other', what was the main reason for leaving their last settled home?",Where was the household immediately before this letting?,Did the household experience homelessness immediately before this letting?,Previous postcode unknown or previous accommodation was temporary,What is the postcode of the household's last settled home?,Previous location LA name,Was the household given reasonable preference by the local authority?,Reasonable preference reason - They were homeless or about to lose their home (within 56 days),"Reasonable preference reason - They were living in insanitary, overcrowded or unisatisfactory housing",Reasonable preference reason - They needed to move on medical and welfare reasons (including disability),Reasonable preference reason - They needed to move to avoid hardship to themselves or others,Reasonable preference reason - Don't Know,Was the letting made under Choice-Based Lettings (CBL)?,Was the letting made under the Common Allocation Policy (CAP)?,Was the letting made under the Common Housing Register (CHR)?,Was the letting made under the Accessible Register?,"The letting was not allocated under CBL, CAP, CHR or Accessible Register.",,What was the source of referral for this letting?,Was the household income refused?,How often does the household receive income?,How much income does the household have in total?,Is the tenant likely to be receiving any of these housing-related benefits?,"Does the tenant receive housing-related benefits? Yes if hb = Universal Credit housing element or Housing benefit, No if hb = Don't Know, Neither, Tenant prefers not to say or blank","How much of the household's income is from Universal Credit, state pensions or benefits?",Does the household pay rent or other charges for the accommodation?,Does the household pay rent or other charges for the accommodation? - flag for when household_charge is answered no,How often does the household pay rent and other charges?,What is the basic rent?,What is the service charge?,What is the personal service charge?,What is the support charge?,Total charge to the tenant,"After the household has received any housing-related benefits, will they still need to pay for rent and charges?",Estimated outstanding amount,What scheme does this letting belong to?,"From scheme code, we map to the scheme name",Does the scheme contain confidential information?,"What is this type of scheme? (Direct access hostel), Foyer, Housing for older people or Other supported housing",Is this scheme registered under the Care Standards Act 2000?,Which organisation owns the housing stock for this scheme?,What client group is this scheme intended for?,Does this scheme provide for another client group?,What is the other client group?,What support does this scheme provide?,Intended length of stay,Date scheme was created,Which location is this letting for?,What is the postcode for this location?,What is the name of this location?,How many units are at this location?,What is the most common type of unit at this location?,What are the mobility standards for the majority of the units in this location?,What is the local authority of this postcode?,When did the first property in this location become available under this scheme? +id,status,duplicate_set_id,assigned_to,is_dpo,created_at,updated_by,updated_at,creation_method,collection_start_year,bulk_upload_id,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,declaration,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,uprn_known,uprn,address_line1,address_line2,town_or_city,county,postcode_full,la_label,unittype_gn,wchair,beds,voiddate,vacdays,majorrepairs,mrcdate,sheltered,joint,startertenancy,tenancy,tenancyother,tenancylength,hhmemb,refused,age1,sex1,ethnic_group,ethnic,nationality_all,ecstat1,relat2,age2,sex2,ecstat2,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,relat7,age7,sex7,ecstat7,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,prevten,homeless,ppcodenk,ppostcode_full,prevloc_label,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,accessible_register,letting_allocation_none,referral_type,referral,incref,incfreq,earnings,hb,has_benefits,benefits,household_charge,nocharge,period,brent,scharge,pscharge,supcharg,tcharge,hbrentshortfall,tshortfall,scheme_code,scheme_service_name,scheme_confidential,SCHTYPE,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_local_authority,location_startdate +,in_progress,,choreographer@owtluk.com,false,2025-04-01T00:00:00+01:00,,2025-04-01T00:00:00+01:00,1,2025,,MHCLG,MHCLG,1,7,0,2025-04-01,2,2,,,2,HIJKLMN,ABCDEFG,1,0,2,6,2,0,,Address line 1,,London,,NW9 5LL,Barnet,7,1,3,2025-03-30,1,1,2025-03-31,,3,1,4,,2,4,1,35,F,0,2,36,0,P,32,M,6,R,-9,R,10,R,-9,R,10,,,,,,,,,,,,,,,,,1,4,1,2,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,2,7,4,,6,1,0,TN23 6LZ,Ashford,1,0,1,0,0,0,0,0,1,0,0,,,0,1,268,6,1,1,,,2,200.0,50.0,40.0,35.0,325.0,1,12.0,,,,,,,,,,,,,,,,,,,, diff --git a/spec/fixtures/files/lettings_log_csv_export_non_support_labels_26.csv b/spec/fixtures/files/lettings_log_csv_export_non_support_labels_26.csv new file mode 100644 index 000000000..20cbc0ec4 --- /dev/null +++ b/spec/fixtures/files/lettings_log_csv_export_non_support_labels_26.csv @@ -0,0 +1,3 @@ +Log ID,Status of log,ID of a set of duplicate logs,User the log is assigned to,Is the user in the assigned_to column the data protection officer?,Time and date the log was created,User who last updated the log,Time and date the log was last updated,Was the log submitted in-service or via bulk upload?,Year collection period opened,ID of a set of bulk uploaded logs,Which organisation owns this property?,Which organisation manages this letting?,What is the needs type?,What is the letting type?,Is this letting a renewal?,What is the tenancy start date?,"What is the rent type? (grouped into SR, IR or AR)",What is the rent type?,Which type of Intermediate Rent is this letting?,Which 'Other' type of Intermediate Rent is this letting?,Is this a London Affordable Rent letting?,What is the tenant code?,What is the property reference?,Has the tenant seen the MHCLG privacy notice?,Is this the first time the property has been let as social housing?,What rent product was the property most recently let as?,What is the reason for the property being vacant?,Is this property new to the social rented sector?,Is the UPRN known?,"If known, property's UPRN",Address line 1,Address line 2,Town or City,County,Postcode,What is the property's local authority?,What type of unit is the property?,Is the property built or adapted to wheelchair-user standards?,How many bedrooms does the property have?,What is the void date?,Number of days the property was vacant,Were any major repairs carried out during the void period?,What date were any major repairs completed on?,Is this letting in sheltered accommodation?,Is this a joint tenancy?,Is this a starter tenancy?,What is the type of tenancy?,"If 'Other', what is the type of tenancy?",What is the length of the fixed-term tenancy to the nearest year?,How many people live in the household at this letting?,"Where household characteristics have a 'Refused' option for some or all of: AGE1-AGE8, SEX1-SEX8, RELAT2-RELAT8, ECSTAT1-ECSTAT8",What is the lead tenant's age?,Which of these best describes the lead tenant's gender identity?,What is the lead tenant's ethnic group?,Which of these best describes the lead tenant's ethnic background?,What is the lead tenant's nationality?,Which of these best describes the lead tenant's working situation?,What is person 2's relationship to the lead tenant?,What is person 2's age?,Which of these best describes person 2's gender identity?,Which of these best describes person 2's working situation?,What is person 3's relationship to the lead tenant?,What is person 3's age?,Which of these best describes person 3's gender identity?,Which of these best describes person 3's working situation?,What is person 4's relationship to the lead tenant?,What is person 4's age?,Which of these best describes person 4's gender identity?,Which of these best describes person 4's working situation?,What is person 5's relationship to the lead tenant?,What is person 5's age?,Which of these best describes person 5's gender identity?,Which of these best describes person 5's working situation?,What is person 6's relationship to the lead tenant?,What is person 6's age?,Which of these best describes person 6's gender identity?,Which of these best describes person 6's working situation?,What is person 7's relationship to the lead tenant?,What is person 7's age?,Which of these best describes person 7's gender identity?,Which of these best describes person 7's working situation?,What is person 8's relationship to the lead tenant?,What is person 8's age?,Which of these best describes person 8's gender identity?,Which of these best describes person 8's working situation?,Does anybody in the household have links to the UK armed forces?,Is this person still serving in the UK armed forces?,Was this person seriously injured or ill as a result of serving in the UK armed forces?,Is anybody in the household pregnant?,Does anybody in the household have any disabled access needs?,"What access needs do they have? (Fully wheelchair-accessible housing, Level access housing or Wheelchair access to essential rooms)",Disabled access needs a) Fully wheelchair-accessible housing,Disabled access needs b) Wheelchair access to essential rooms,Disabled access needs c) Level access housing,Disabled access needs f) Other disabled access needs,Disabled access needs g) No disabled access needs,Disabled access needs h) Don't know,Do they have any other disabled access needs?,Does anybody in the household have a physical or mental health condition (or other illness) expected to last 12 months or more?,Does this person's condition affect their dexterity?,Does this person's condition affect their learning or understanding or concentrating?,Does this person's condition affect their hearing?,Does this person's condition affect their memory?,Does this person's condition affect their mental health?,Does this person's condition affect their mobility?,Does this person's condition affect them socially or behaviourally?,Does this person's condition affect their stamina or breathing or fatigue?,Does this person's condition affect their vision?,Does this person's condition affect them in another way?,How long has the household continuously lived in the local authority area of the new letting?,How long has the household been on the local authority waiting list for the new letting?,What is the tenant's main reason for the household leaving their last settled home?,"If 'Other', what was the main reason for leaving their last settled home?",Where was the household immediately before this letting?,Did the household experience homelessness immediately before this letting?,Previous postcode unknown or previous accommodation was temporary,What is the postcode of the household's last settled home?,Previous location LA name,Was the household given reasonable preference by the local authority?,Reasonable preference reason - They were homeless or about to lose their home (within 56 days),"Reasonable preference reason - They were living in insanitary, overcrowded or unisatisfactory housing",Reasonable preference reason - They needed to move on medical and welfare reasons (including disability),Reasonable preference reason - They needed to move to avoid hardship to themselves or others,Reasonable preference reason - Don't Know,Was the letting made under Choice-Based Lettings (CBL)?,Was the letting made under the Common Allocation Policy (CAP)?,Was the letting made under the Common Housing Register (CHR)?,Was the letting made under the Accessible Register?,"The letting was not allocated under CBL, CAP, CHR or Accessible Register.",,What was the source of referral for this letting?,Was the household income refused?,How often does the household receive income?,How much income does the household have in total?,Is the tenant likely to be receiving any of these housing-related benefits?,"Does the tenant receive housing-related benefits? Yes if hb = Universal Credit housing element or Housing benefit, No if hb = Don't Know, Neither, Tenant prefers not to say or blank","How much of the household's income is from Universal Credit, state pensions or benefits?",Does the household pay rent or other charges for the accommodation?,Does the household pay rent or other charges for the accommodation? - flag for when household_charge is answered no,How often does the household pay rent and other charges?,What is the basic rent?,What is the service charge?,What is the personal service charge?,What is the support charge?,Total charge to the tenant,"After the household has received any housing-related benefits, will they still need to pay for rent and charges?",Estimated outstanding amount,What scheme does this letting belong to?,"From scheme code, we map to the scheme name",Does the scheme contain confidential information?,"What is this type of scheme? (Direct access hostel), Foyer, Housing for older people or Other supported housing",Is this scheme registered under the Care Standards Act 2000?,Which organisation owns the housing stock for this scheme?,What client group is this scheme intended for?,Does this scheme provide for another client group?,What is the other client group?,What support does this scheme provide?,Intended length of stay,Date scheme was created,Which location is this letting for?,What is the postcode for this location?,What is the name of this location?,How many units are at this location?,What is the most common type of unit at this location?,What are the mobility standards for the majority of the units in this location?,What is the local authority of this postcode?,When did the first property in this location become available under this scheme? +id,status,duplicate_set_id,assigned_to,is_dpo,created_at,updated_by,updated_at,creation_method,collection_start_year,bulk_upload_id,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,declaration,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,uprn_known,uprn,address_line1,address_line2,town_or_city,county,postcode_full,la_label,unittype_gn,wchair,beds,voiddate,vacdays,majorrepairs,mrcdate,sheltered,joint,startertenancy,tenancy,tenancyother,tenancylength,hhmemb,refused,age1,sex1,ethnic_group,ethnic,nationality_all,ecstat1,relat2,age2,sex2,ecstat2,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,relat7,age7,sex7,ecstat7,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,prevten,homeless,ppcodenk,ppostcode_full,prevloc_label,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,accessible_register,letting_allocation_none,referral_type,referral,incref,incfreq,earnings,hb,has_benefits,benefits,household_charge,nocharge,period,brent,scharge,pscharge,supcharg,tcharge,hbrentshortfall,tshortfall,scheme_code,scheme_service_name,scheme_confidential,SCHTYPE,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_local_authority,location_startdate +,in_progress,,choreographer@owtluk.com,false,2025-04-01T00:00:00+01:00,,2025-04-01T00:00:00+01:00,single log,2025,,MHCLG,MHCLG,General needs,Affordable rent general needs local authority,No,2025-04-01,Affordable Rent,Affordable Rent,,,No,HIJKLMN,ABCDEFG,Yes,No,Affordable rent basis,Tenant abandoned property,No,No,,Address line 1,,London,,NW9 5LL,Barnet,House,Yes,3,2025-03-30,1,Yes,2025-03-31,,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,4,Yes,35,Female,White,Irish,Australia,Other,Yes,32,Male,Not seeking work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Tenant prefers not to say,Not known,Person prefers not to say,Person prefers not to say,,,,,,,,,,,,,,,,,Yes – the person is a current or former regular,No – they left up to and including 5 years ago,Yes,No,Yes,Fully wheelchair accessible housing,Yes,No,No,No,No,No,No,Yes,No,No,Yes,No,No,No,No,No,No,No,Less than 1 year,1 year but under 2 years,Loss of tied accommodation,,Other supported housing,No,Yes,TN23 6LZ,Ashford,Yes,,Yes,,,,No,No,Yes,No,No,,,No,Weekly,268,Universal Credit housing element,Yes,All,,,Every 2 weeks,200.0,50.0,40.0,35.0,325.0,Yes,12.0,,,,,,,,,,,,,,,,,,,, diff --git a/spec/services/csv/lettings_log_csv_service_spec.rb b/spec/services/csv/lettings_log_csv_service_spec.rb index bbd73d36d..302c82d51 100644 --- a/spec/services/csv/lettings_log_csv_service_spec.rb +++ b/spec/services/csv/lettings_log_csv_service_spec.rb @@ -194,6 +194,198 @@ RSpec.describe Csv::LettingsLogCsvService do end describe "the full CSV output" do + context "when the requested log year is 2026" do + let(:year) { 2026 } + let(:organisation) { create(:organisation, provider_type: "LA", name: "MHCLG") } + let(:log) do + create( + :lettings_log, + :ignore_validation_errors, + created_by: user, + assigned_to: user, + created_at: Time.zone.local(2025, 4, 1), + updated_at: Time.zone.local(2025, 4, 1), + owning_organisation: organisation, + managing_organisation: organisation, + needstype: 1, + renewal: 0, + startdate: Time.zone.local(2025, 4, 1), + rent_type: 1, + tenancycode: "HIJKLMN", + propcode: "ABCDEFG", + declaration: 1, + address_line1: "Address line 1", + town_or_city: "London", + postcode_full: "NW9 5LL", + la: "E09000003", + is_la_inferred: false, + address_line1_as_entered: "address line 1 as entered", + address_line2_as_entered: "address line 2 as entered", + town_or_city_as_entered: "town or city as entered", + county_as_entered: "county as entered", + postcode_full_as_entered: "AB1 2CD", + la_as_entered: "la as entered", + first_time_property_let_as_social_housing: 0, + unitletas: 2, + rsnvac: 6, + unittype_gn: 7, + wchair: 1, + beds: 3, + voiddate: Time.zone.local(2025, 3, 30), + majorrepairs: 1, + mrcdate: Time.zone.local(2025, 3, 31), + joint: 3, + startertenancy: 1, + tenancy: 4, + tenancylength: 2, + hhmemb: 4, + age1_known: 0, + age1: 35, + sex1: "F", + ethnic_group: 0, + ethnic: 2, + nationality_all: 36, + ecstat1: 0, + details_known_2: 0, + relat2: "P", + age2_known: 0, + age2: 32, + sex2: "M", + ecstat2: 6, + details_known_3: 1, + details_known_4: 0, + relat4: "R", + age4_known: 1, + sex4: "R", + ecstat4: 10, + armedforces: 1, + leftreg: 4, + reservist: 1, + preg_occ: 2, + housingneeds: 1, + housingneeds_type: 0, + housingneeds_a: 1, + housingneeds_b: 0, + housingneeds_c: 0, + housingneeds_f: 0, + housingneeds_g: 0, + housingneeds_h: 0, + housingneeds_other: 0, + illness: 1, + illness_type_1: 0, + illness_type_2: 1, + illness_type_3: 0, + illness_type_4: 0, + illness_type_5: 0, + illness_type_6: 0, + illness_type_7: 0, + illness_type_8: 0, + illness_type_9: 0, + illness_type_10: 0, + layear: 2, + waityear: 7, + reason: 4, + prevten: 6, + homeless: 1, + ppcodenk: 1, + ppostcode_full: "TN23 6LZ", + previous_la_known: 1, + prevloc: "E07000105", + reasonpref: 1, + rp_homeless: 0, + rp_insan_unsat: 1, + rp_medwel: 0, + rp_hardship: 0, + rp_dontknow: 0, + cbl: 0, + chr: 1, + cap: 0, + accessible_register: 0, + referral: 2, + net_income_known: 0, + incref: 0, + incfreq: 1, + earnings: 268, + hb: 6, + has_benefits: 1, + benefits: 1, + period: 2, + brent: 200, + scharge: 50, + pscharge: 40, + supcharg: 35, + tcharge: 325, + hbrentshortfall: 1, + tshortfall_known: 1, + tshortfall: 12, + ) + end + + context "when exporting with human readable labels" do + let(:export_type) { "labels" } + + context "when the current user is a support user" do + let(:user) { create(:user, :support, organisation:, email: "s.port@jeemayle.com") } + + it "exports the CSV with all values correct" do + expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_labels_26.csv") + values_to_delete = %w[id] + values_to_delete.each do |attribute| + index = attribute_line.index(attribute) + content_line[index] = nil + end + expect(csv).to eq expected_content + end + end + + context "when the current user is not a support user" do + let(:user) { create(:user, :data_provider, organisation:, email: "choreographer@owtluk.com") } + + it "exports the CSV with all values correct" do + expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_non_support_labels_26.csv") + values_to_delete = %w[id] + values_to_delete.each do |attribute| + index = attribute_line.index(attribute) + content_line[index] = nil + end + expect(csv).to eq expected_content + end + end + end + + context "when exporting values as codes" do + let(:export_type) { "codes" } + + context "when the current user is a support user" do + let(:user) { create(:user, :support, organisation:, email: "s.port@jeemayle.com") } + + it "exports the CSV with all values correct" do + expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_codes_26.csv") + values_to_delete = %w[id] + values_to_delete.each do |attribute| + index = attribute_line.index(attribute) + content_line[index] = nil + end + expect(csv).to eq expected_content + end + end + + context "when the current user is not a support user" do + let(:user) { create(:user, :data_provider, organisation:, email: "choreographer@owtluk.com") } + + it "exports the CSV with all values correct" do + expected_content = CSV.read("spec/fixtures/files/lettings_log_csv_export_non_support_codes_26.csv") + values_to_delete = %w[id] + values_to_delete.each do |attribute| + index = attribute_line.index(attribute) + content_line[index] = nil + end + expect(csv).to eq expected_content + end + end + end + end + context "when the requested log year is 2025" do let(:year) { 2025 } let(:organisation) { create(:organisation, provider_type: "LA", name: "MHCLG") } From 13df8062c269535518b6cd5a1a919ee6f4059997 Mon Sep 17 00:00:00 2001 From: Samuel Young Date: Tue, 6 Jan 2026 09:43:37 +0000 Subject: [PATCH 04/14] CLDC-4136: Remove question from BU parser relabel all following fields --- .../lettings/year2026/row_parser.rb | 872 +++++++++--------- .../lettings/year2026/row_parser_spec.rb | 768 +++++++-------- 2 files changed, 818 insertions(+), 822 deletions(-) diff --git a/app/services/bulk_upload/lettings/year2026/row_parser.rb b/app/services/bulk_upload/lettings/year2026/row_parser.rb index 84f6f57d9..f96856438 100644 --- a/app/services/bulk_upload/lettings/year2026/row_parser.rb +++ b/app/services/bulk_upload/lettings/year2026/row_parser.rb @@ -31,109 +31,108 @@ 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: "Which of these best describes the lead tenant’s gender identity?", - 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: "Which of these best describes person 2’s gender identity?", - 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: "Which of these best describes person 3’s gender identity?", - 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: "Which of these best describes person 4’s gender identity?", - 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: "Which of these best describes person 5’s gender identity?", - 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: "Which of these best describes person 6’s gender identity?", - 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: "Which of these best describes person 7’s gender identity?", - 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: "Which of these best describes person 8’s gender identity?", - 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: "Which of these best describes the lead tenant’s gender identity?", + 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: "Which of these best describes person 2’s gender identity?", + 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: "Which of these best describes person 3’s gender identity?", + 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: "Which of these best describes person 4’s gender identity?", + 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: "Which of these best describes person 5’s gender identity?", + 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: "Which of these best describes person 6’s gender identity?", + 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: "Which of these best describes person 7’s gender identity?", + 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: "Which of these best describes person 8’s gender identity?", + 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?", - 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_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?", + 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?", }.freeze RENT_TYPE_BU_MAPPING = { @@ -186,46 +185,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 @@ -250,14 +249,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 @@ -270,18 +269,17 @@ 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 validate :validate_valid_radio_option, on: :before_log @@ -348,7 +346,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, @@ -356,11 +354,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, @@ -368,11 +366,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, @@ -380,11 +378,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, @@ -392,18 +390,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 @@ -539,12 +537,12 @@ class BulkUpload::Lettings::Year2026::RowParser !general_needs? ? :field_6.to_s : nil, # location !supported_housing? ? "field_23" : nil, # postcode !supported_housing? ? "field_24" : nil, # postcode - "field_42", # age1 - "field_43", # sex1 - "field_46", # ecstat1 + "field_41", # age1 + "field_42", # sex1 + "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 @@ -553,7 +551,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 @@ -662,14 +660,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] @@ -680,9 +678,9 @@ private def validate_prevten_value_when_renewal return unless field_7 == 1 - 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 @@ -707,41 +705,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 @@ -749,16 +747,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 @@ -766,7 +764,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 @@ -781,12 +779,12 @@ private end def household_no_illness? - field_85 != 1 + field_84 != 1 end def validate_leaving_reason_for_renewal - if field_7 == 1 && ![50, 51, 52, 53].include?(field_98) - errors.add(:field_98, I18n.t("#{ERROR_BASE_KEY}.reason.renewal_reason_needed")) + if field_7 == 1 && ![50, 51, 52, 53].include?(field_97) + errors.add(:field_97, I18n.t("#{ERROR_BASE_KEY}.reason.renewal_reason_needed")) end end @@ -799,14 +797,14 @@ private end def validate_cannot_be_la_referral_if_general_needs_and_la - if field_116 == 4 && general_needs? && owning_organisation && owning_organisation.la? - errors.add :field_116, I18n.t("#{ERROR_BASE_KEY}.referral.general_needs_prp_referred_by_la") + if field_115 == 4 && general_needs? && owning_organisation && owning_organisation.la? + errors.add :field_115, I18n.t("#{ERROR_BASE_KEY}.referral.general_needs_prp_referred_by_la") end end def validate_la_with_local_housing_referral - if field_116 == 3 && owning_organisation && owning_organisation.la? - errors.add(:field_116, I18n.t("#{ERROR_BASE_KEY}.referral.nominated_by_local_ha_but_la")) + if field_115 == 3 && owning_organisation && owning_organisation.la? + errors.add(:field_115, I18n.t("#{ERROR_BASE_KEY}.referral.nominated_by_local_ha_but_la")) end end @@ -935,13 +933,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| @@ -957,7 +955,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) @@ -978,14 +976,14 @@ private errors.add(:field_23, error_message) unless supported_housing? # postcode_full errors.add(:field_24, error_message) unless supported_housing? # postcode_full errors.add(:field_25, error_message) unless supported_housing? # la - errors.add(:field_42, error_message) # age1 - errors.add(:field_43, error_message) # sex1 - 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) # sex1 + 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 @@ -1010,139 +1008,138 @@ 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], - - sex1: %i[field_43], - sex2: %i[field_49], - sex3: %i[field_53], - sex4: %i[field_57], - sex5: %i[field_61], - sex6: %i[field_65], - sex7: %i[field_69], - sex8: %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_type: %i[field_116], - referral: %i[field_116], - - 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], + + sex1: %i[field_42], + sex2: %i[field_48], + sex3: %i[field_52], + sex4: %i[field_56], + sex5: %i[field_60], + sex6: %i[field_64], + sex7: %i[field_68], + sex8: %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_type: %i[field_115], + referral: %i[field_115], + + 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], @@ -1177,70 +1174,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["sex1"] = field_43 - attributes["sex2"] = field_49 - attributes["sex3"] = field_53 - attributes["sex4"] = field_57 - attributes["sex5"] = field_61 - attributes["sex6"] = field_65 - attributes["sex7"] = field_69 - attributes["sex8"] = field_73 + attributes["sex1"] = field_42 + attributes["sex2"] = field_48 + attributes["sex3"] = field_52 + attributes["sex4"] = field_56 + attributes["sex5"] = field_60 + attributes["sex6"] = field_64 + attributes["sex7"] = field_68 + attributes["sex8"] = 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) @@ -1250,36 +1246,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 @@ -1288,40 +1284,40 @@ private attributes["letting_allocation_unknown"] = letting_allocation_unknown attributes["referral_type"] = referral_type - attributes["referral"] = field_116 + attributes["referral"] = field_115 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 @@ -1421,9 +1417,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 @@ -1440,19 +1436,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" @@ -1465,53 +1461,53 @@ private end def person_2_present? - field_47.present? || field_48.present? || field_49.present? + field_46.present? || field_47.present? || field_48.present? end def person_3_present? - field_51.present? || field_52.present? || field_53.present? + field_50.present? || field_51.present? || field_52.present? end def person_4_present? - field_55.present? || field_56.present? || field_57.present? + field_54.present? || field_55.present? || field_56.present? end def person_5_present? - field_59.present? || field_60.present? || field_61.present? + field_58.present? || field_59.present? || field_60.present? end def person_6_present? - field_63.present? || field_64.present? || field_65.present? + field_62.present? || field_63.present? || field_64.present? end def person_7_present? - field_67.present? || field_68.present? || field_69.present? + field_66.present? || field_67.present? || field_68.present? end def person_8_present? - field_71.present? || field_72.present? || field_73.present? + field_70.present? || field_71.present? || field_72.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 @@ -1519,12 +1515,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 @@ -1532,7 +1528,7 @@ private end def ppcodenk - case field_102 + case field_101 when 1 0 when 2 @@ -1541,11 +1537,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 @@ -1554,7 +1550,7 @@ private end def cap - case field_113 + case field_112 when 2 0 when 1 @@ -1563,7 +1559,7 @@ private end def chr - case field_114 + case field_113 when 2 0 when 1 @@ -1572,7 +1568,7 @@ private end def accessible_register - case field_115 + case field_114 when 2 0 when 1 @@ -1585,7 +1581,7 @@ private end def net_income_known - case field_117 + case field_116 when 1 0 when 2 @@ -1596,11 +1592,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 @@ -1620,15 +1616,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 @@ -1655,7 +1651,7 @@ private end def reason_is_other? - field_98 == 20 + field_97 == 20 end def bulk_upload_organisation @@ -1674,10 +1670,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 @@ -1696,7 +1692,7 @@ private } mapping.each do |key, values| - return key if values.include?(field_116) + return key if values.include?(field_115) end 0 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 4b705fbc7..88be57d87 100644 --- a/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb @@ -116,7 +116,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? @@ -140,107 +140,107 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do field_7: "2", field_26: "2", field_27: "1", + 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: "2", + field_84: "2", - 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: "2", + field_115: "2", - field_117: "1", - field_118: "2", - field_119: "2300", - field_120: "1", - field_121: "4", + field_116: "1", + field_117: "2", + field_118: "2300", + field_119: "1", + field_120: "4", - 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_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", @@ -294,13 +294,13 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_23, # postcode_full :field_24, # postcode_full :field_25, # postcode_full - :field_42, # age1 - :field_43, # sex1 - :field_46, # ecstat1 - :field_124, # brent - :field_125, # scharge - :field_126, # pscharge - :field_127, # supcharg + :field_41, # age1 + :field_42, # sex1 + :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 @@ -325,7 +325,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when a supported housing log already exists in the db" do - 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! @@ -348,13 +348,13 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_10, # startdate :field_13, # tenancycode :field_6, # location - :field_42, # age1 - :field_43, # sex1 - :field_46, # ecstat1 - :field_124, # brent - :field_125, # scharge - :field_126, # pscharge - :field_127, # supcharg + :field_41, # age1 + :field_42, # sex1 + :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 @@ -390,13 +390,13 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_10, # startdate :field_13, # tenancycode :field_6, # location - :field_42, # age1 - :field_43, # sex1 - :field_46, # ecstat1 - :field_124, # brent - :field_125, # scharge - :field_126, # pscharge - :field_127, # supcharg + :field_41, # age1 + :field_42, # sex1 + :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 @@ -433,9 +433,9 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_10, # startdate :field_13, # tenancycode :field_6, # location - :field_42, # age1 - :field_43, # sex1 - :field_46, # ecstat1 + :field_41, # age1 + :field_42, # sex1 + :field_45, # ecstat1 ].each do |field| expect(parser.errors[field]).to include(error_message) end @@ -454,8 +454,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 @@ -479,10 +479,10 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_10, # startdate :field_13, # tenancycode :field_6, # location - :field_42, # age1 - :field_43, # sex1 - :field_46, # ecstat1 - :field_122, # household_charge + :field_41, # age1 + :field_42, # sex1 + :field_45, # ecstat1 + :field_121, # household_charge ].each do |field| expect(parser.errors[field]).to include(error_message) end @@ -498,9 +498,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" }) @@ -533,9 +533,9 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_23, # postcode_full :field_24, # postcode_full :field_25, # LA - :field_42, # age1 - :field_43, # sex1 - :field_46, # ecstat1 + :field_41, # age1 + :field_42, # sex1 + :field_45, # ecstat1 ].each do |field| expect(parser.errors[field]).to be_blank end @@ -568,8 +568,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) @@ -589,43 +589,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 gender identity.")]) + expect(parser.errors[:field_42]).to eql([I18n.t("validations.lettings.2026.bulk_upload.not_answered", question: "lead tenant’s gender identity.")]) 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_116: "100" }) } + let(:attributes) { setup_section_params.merge({ field_115: "100" }) } it "does not add an additional error" do parser.valid? - expect(parser.errors[:field_116].length).to eq(1) - expect(parser.errors[:field_116]).to include(match I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: "")) + 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: "")) end end end @@ -874,171 +874,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 @@ -1048,39 +1049,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 @@ -1091,35 +1091,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? @@ -1132,43 +1132,43 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - describe "#field_116" do # referral + describe "#field_115" do # referral context "when 3 ie PRP nominated by LA and owning org is LA" do - let(:attributes) { { bulk_upload:, field_116: "3", field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id } } + let(:attributes) { { bulk_upload:, field_115: "3", field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id } } it "is not permitted" do parser.valid? - expect(parser.errors[:field_116]).to be_present + expect(parser.errors[:field_115]).to be_present end end context "when 4 ie referred by LA and is general needs and owning org is LA" do - let(:attributes) { { bulk_upload:, field_116: "4", field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id, field_4: "1" } } + let(:attributes) { { bulk_upload:, field_115: "4", field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id, field_4: "1" } } it "is not permitted" do parser.valid? - expect(parser.errors[:field_116]).to be_present + expect(parser.errors[:field_115]).to be_present end end context "when 4 ie referred by LA and is general needs and owning org is PRP" do let(:owning_org) { create(:organisation, :prp, :with_old_visible_id) } - let(:attributes) { { bulk_upload:, field_116: "4", field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id } } + let(:attributes) { { bulk_upload:, field_115: "4", field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id } } it "is permitted" do parser.valid? - expect(parser.errors[:field_116]).to be_blank + expect(parser.errors[:field_115]).to be_blank end end context "when 4 ie referred by LA and is not general needs" do let(:bulk_upload) { create(:bulk_upload, :lettings, user:) } - let(:attributes) { { bulk_upload:, field_116: "4", field_4: "2" } } + let(:attributes) { { bulk_upload:, field_115: "4", field_4: "2" } } it "is permitted" do parser.valid? - expect(parser.errors[:field_116]).to be_blank + expect(parser.errors[:field_115]).to be_blank end end end @@ -1694,20 +1694,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) @@ -1715,8 +1715,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) @@ -1724,8 +1724,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) @@ -1733,8 +1733,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) @@ -1742,8 +1742,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) @@ -1751,8 +1751,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) @@ -1760,8 +1760,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) @@ -1769,8 +1769,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) @@ -1778,75 +1778,75 @@ 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" }) } + let(:attributes) { setup_section_params.merge({ field_77: "1", field_42: "M", field_48: "M", field_52: "M" }) } it "adds errors to fields that are routed to" do parser.valid? - expect(parser.errors.where(:field_49, category: :soft_validation)).to be_present - expect(parser.errors.where(:field_53, category: :soft_validation)).to be_present + expect(parser.errors.where(:field_48, category: :soft_validation)).to be_present + expect(parser.errors.where(:field_52, 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_57, category: :soft_validation)).not_to be_present - expect(parser.errors.where(:field_61, category: :soft_validation)).not_to be_present + expect(parser.errors.where(:field_56, category: :soft_validation)).not_to be_present + expect(parser.errors.where(:field_60, 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 @@ -1971,14 +1971,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 @@ -2080,141 +2080,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) @@ -2236,14 +2236,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 @@ -2263,14 +2263,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 @@ -2290,13 +2290,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 @@ -2313,7 +2313,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) @@ -2321,7 +2321,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) @@ -2329,7 +2329,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) @@ -2354,7 +2354,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) @@ -2363,16 +2363,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| @@ -2405,7 +2405,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") @@ -2413,7 +2413,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) @@ -2421,7 +2421,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) @@ -2430,7 +2430,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") @@ -2438,7 +2438,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 @@ -2447,7 +2447,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) @@ -2456,7 +2456,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) @@ -2464,7 +2464,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) @@ -2473,14 +2473,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! @@ -2493,15 +2493,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! @@ -2515,16 +2515,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) @@ -2532,7 +2532,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) @@ -2549,7 +2549,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)) @@ -2557,7 +2557,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)) @@ -2565,7 +2565,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 @@ -2575,7 +2575,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) @@ -2583,7 +2583,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) @@ -2593,7 +2593,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)) @@ -2601,7 +2601,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)) @@ -2609,7 +2609,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 @@ -2650,7 +2650,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") @@ -2659,7 +2659,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) @@ -2667,7 +2667,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) @@ -2695,7 +2695,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) @@ -2703,7 +2703,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) @@ -2711,7 +2711,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) @@ -2720,8 +2720,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) @@ -2731,7 +2731,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) @@ -2740,106 +2740,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) @@ -2848,8 +2848,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) From ce82276a5db01d19ef32ea93b7c7a1b79228425d Mon Sep 17 00:00:00 2001 From: Samuel Young Date: Tue, 6 Jan 2026 10:54:36 +0000 Subject: [PATCH 05/14] fixup! CLDC-4136: Hide question from CDS export --- spec/services/csv/lettings_log_csv_service_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/services/csv/lettings_log_csv_service_spec.rb b/spec/services/csv/lettings_log_csv_service_spec.rb index 302c82d51..e9bdbea44 100644 --- a/spec/services/csv/lettings_log_csv_service_spec.rb +++ b/spec/services/csv/lettings_log_csv_service_spec.rb @@ -318,7 +318,7 @@ RSpec.describe Csv::LettingsLogCsvService do hbrentshortfall: 1, tshortfall_known: 1, tshortfall: 12, - ) + ) end context "when exporting with human readable labels" do From 124a0896efcaeebafd378ebff01c1d96eef58379 Mon Sep 17 00:00:00 2001 From: Samuel Young Date: Tue, 6 Jan 2026 10:54:49 +0000 Subject: [PATCH 06/14] fixup! CLDC-4136: Remove question from BU parser --- spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb | 1 - 1 file changed, 1 deletion(-) 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 88be57d87..b2f044618 100644 --- a/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb @@ -140,7 +140,6 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do field_7: "2", field_26: "2", field_27: "1", - field_27: "1", field_28: "1", field_36: "2", field_37: "1", From e5e536cb5a5ae75bd3c9b9a8ce11cb3d2f10d6dd Mon Sep 17 00:00:00 2001 From: Samuel Young Date: Wed, 7 Jan 2026 14:57:01 +0000 Subject: [PATCH 07/14] Revert "fixup! CLDC-4136: Remove question from BU parser" This reverts commit cda3ec109943d23120c6e55a05ae02026283d147. --- spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb | 1 + 1 file changed, 1 insertion(+) 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 b2f044618..88be57d87 100644 --- a/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb @@ -140,6 +140,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do field_7: "2", field_26: "2", field_27: "1", + field_27: "1", field_28: "1", field_36: "2", field_37: "1", From f5156aeeb3695a073edcc53c723e42ceaf2992dd Mon Sep 17 00:00:00 2001 From: Samuel Young Date: Wed, 7 Jan 2026 14:57:02 +0000 Subject: [PATCH 08/14] Revert "CLDC-4136: Remove question from BU parser" This reverts commit e4715ee976c6a4ade30a61b11f51af8bce211324. --- .../lettings/year2026/row_parser.rb | 872 +++++++++--------- .../lettings/year2026/row_parser_spec.rb | 768 +++++++-------- 2 files changed, 822 insertions(+), 818 deletions(-) diff --git a/app/services/bulk_upload/lettings/year2026/row_parser.rb b/app/services/bulk_upload/lettings/year2026/row_parser.rb index f96856438..84f6f57d9 100644 --- a/app/services/bulk_upload/lettings/year2026/row_parser.rb +++ b/app/services/bulk_upload/lettings/year2026/row_parser.rb @@ -31,108 +31,109 @@ 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: "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_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_30: "What is the void date?", field_31: "What is the void date?", - field_32: "What date were any major repairs completed on?", + field_32: "What is the void date?", field_33: "What date were any major repairs completed on?", field_34: "What date were any major repairs completed on?", - 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: "Which of these best describes the lead tenant’s gender identity?", - 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: "Which of these best describes person 2’s gender identity?", - 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: "Which of these best describes person 3’s gender identity?", - 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: "Which of these best describes person 4’s gender identity?", - 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: "Which of these best describes person 5’s gender identity?", - 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: "Which of these best describes person 6’s gender identity?", - 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: "Which of these best describes person 7’s gender identity?", - 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: "Which of these best describes person 8’s gender identity?", - 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_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: "Which of these best describes the lead tenant’s gender identity?", + 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: "Which of these best describes person 2’s gender identity?", + 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: "Which of these best describes person 3’s gender identity?", + 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: "Which of these best describes person 4’s gender identity?", + 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: "Which of these best describes person 5’s gender identity?", + 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: "Which of these best describes person 6’s gender identity?", + 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: "Which of these best describes person 7’s gender identity?", + 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: "Which of these best describes person 8’s gender identity?", + 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_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 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_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_103: "What is the postcode of the household’s last settled home?", - 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?", - 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_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?", + 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?", }.freeze RENT_TYPE_BU_MAPPING = { @@ -185,46 +186,46 @@ class BulkUpload::Lettings::Year2026::RowParser attribute :field_32, :integer attribute :field_33, :integer attribute :field_34, :integer - attribute :field_36, :integer + attribute :field_35, :integer attribute :field_37, :integer attribute :field_38, :integer - attribute :field_39, :string - attribute :field_40, :integer - attribute :field_35, :integer + attribute :field_39, :integer + attribute :field_40, :string + attribute :field_41, :integer + attribute :field_36, :integer attribute :field_15, :integer - attribute :field_41, :string attribute :field_42, :string - attribute :field_43, :integer + attribute :field_43, :string attribute :field_44, :integer attribute :field_45, :integer attribute :field_46, :integer - attribute :field_47, :string + attribute :field_47, :integer attribute :field_48, :string - attribute :field_49, :integer + attribute :field_49, :string attribute :field_50, :integer - attribute :field_51, :string + attribute :field_51, :integer attribute :field_52, :string - attribute :field_53, :integer + attribute :field_53, :string attribute :field_54, :integer - attribute :field_55, :string + attribute :field_55, :integer attribute :field_56, :string - attribute :field_57, :integer + attribute :field_57, :string attribute :field_58, :integer - attribute :field_59, :string + attribute :field_59, :integer attribute :field_60, :string - attribute :field_61, :integer + attribute :field_61, :string attribute :field_62, :integer - attribute :field_63, :string + attribute :field_63, :integer attribute :field_64, :string - attribute :field_65, :integer + attribute :field_65, :string attribute :field_66, :integer - attribute :field_67, :string + attribute :field_67, :integer attribute :field_68, :string - attribute :field_69, :integer + attribute :field_69, :string attribute :field_70, :integer - attribute :field_71, :string + attribute :field_71, :integer attribute :field_72, :string - attribute :field_73, :integer + attribute :field_73, :string attribute :field_74, :integer attribute :field_75, :integer attribute :field_76, :integer @@ -249,14 +250,14 @@ class BulkUpload::Lettings::Year2026::RowParser attribute :field_95, :integer attribute :field_96, :integer attribute :field_97, :integer - attribute :field_98, :string - attribute :field_99, :integer + attribute :field_98, :integer + attribute :field_99, :string attribute :field_100, :integer attribute :field_101, :integer - attribute :field_102, :string + attribute :field_102, :integer attribute :field_103, :string attribute :field_104, :string - attribute :field_105, :integer + attribute :field_105, :string attribute :field_106, :integer attribute :field_107, :integer attribute :field_108, :integer @@ -269,17 +270,18 @@ class BulkUpload::Lettings::Year2026::RowParser attribute :field_115, :integer attribute :field_116, :integer attribute :field_117, :integer - attribute :field_118, :decimal - attribute :field_119, :integer + attribute :field_118, :integer + attribute :field_119, :decimal attribute :field_120, :integer attribute :field_121, :integer attribute :field_122, :integer - attribute :field_123, :decimal + attribute :field_123, :integer attribute :field_124, :decimal attribute :field_125, :decimal attribute :field_126, :decimal - attribute :field_127, :integer - attribute :field_128, :decimal + attribute :field_127, :decimal + attribute :field_128, :integer + attribute :field_129, :decimal validate :validate_valid_radio_option, on: :before_log @@ -346,7 +348,7 @@ class BulkUpload::Lettings::Year2026::RowParser }, on: :after_log - validates :field_111, + validates :field_112, presence: { message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "was the letting made under the Choice-Based Lettings (CBL)?"), category: :not_answered, @@ -354,11 +356,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_111.present? }, + if: -> { field_112.present? }, }, on: :after_log - validates :field_112, + validates :field_113, presence: { message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "was the letting made under the Common Allocation Policy (CAP)?"), category: :not_answered, @@ -366,11 +368,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_112.present? }, + if: -> { field_113.present? }, }, on: :after_log - validates :field_113, + validates :field_114, presence: { message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "was the letting made under the Common Housing Register (CHR)?"), category: :not_answered, @@ -378,11 +380,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_113.present? }, + if: -> { field_114.present? }, }, on: :after_log - validates :field_114, + validates :field_115, presence: { message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "was the letting made under the Accessible Register?"), category: :not_answered, @@ -390,18 +392,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_114.present? }, + if: -> { field_115.present? }, }, on: :after_log - 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? } + 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? } validate :validate_needs_type_present, on: :after_log validate :validate_data_types, on: :after_log @@ -537,12 +539,12 @@ class BulkUpload::Lettings::Year2026::RowParser !general_needs? ? :field_6.to_s : nil, # location !supported_housing? ? "field_23" : nil, # postcode !supported_housing? ? "field_24" : nil, # postcode - "field_41", # age1 - "field_42", # sex1 - "field_45", # ecstat1 + "field_42", # age1 + "field_43", # sex1 + "field_46", # ecstat1 ) - if [field_123, field_124, field_125, field_126].all?(&:present?) - hash.merge({ "tcharge" => [field_123, field_124, field_125, field_126].sum }) + if [field_124, field_125, field_126, field_127].all?(&:present?) + hash.merge({ "tcharge" => [field_124, field_125, field_126, field_127].sum }) else hash end @@ -551,7 +553,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_123 field_124 field_125 field_126].each do |sub_field| + %w[field_124 field_125 field_126 field_127].each do |sub_field| errors.add(sub_field, I18n.t("#{ERROR_BASE_KEY}.spreadsheet_dupe"), category: :setup) end else @@ -660,14 +662,14 @@ private end def validate_nationality - if field_44.present? && !valid_nationality_options.include?(field_44.to_s) - errors.add(:field_44, I18n.t("#{ERROR_BASE_KEY}.nationality.invalid")) + if field_45.present? && !valid_nationality_options.include?(field_45.to_s) + errors.add(:field_45, I18n.t("#{ERROR_BASE_KEY}.nationality.invalid")) end end def validate_reasonpref_reason_values valid_reasonpref_reason_options = %w[0 1] - %w[field_106 field_107 field_108 field_109 field_110].each do |field| + %w[field_107 field_108 field_109 field_110 field_111].each do |field| next unless send(field).present? && !valid_reasonpref_reason_options.include?(send(field).to_s) question_text = QUESTIONS[field.to_sym] @@ -678,9 +680,9 @@ private def validate_prevten_value_when_renewal return unless field_7 == 1 - return if field_99.blank? || [6, 30, 31, 32, 33, 34, 35, 38].include?(field_99) + return if field_100.blank? || [6, 30, 31, 32, 33, 34, 35, 38].include?(field_100) - errors.add(:field_99, I18n.t("#{ERROR_BASE_KEY}.prevten.invalid")) + errors.add(:field_100, I18n.t("#{ERROR_BASE_KEY}.prevten.invalid")) end def duplicate_check_fields @@ -705,41 +707,41 @@ private end def validate_no_and_dont_know_disabled_needs_conjunction - if field_82 == 1 && field_83 == 1 - errors.add(:field_82, I18n.t("#{ERROR_BASE_KEY}.housingneeds.no_and_dont_know_disabled_needs_conjunction")) + if field_83 == 1 && field_84 == 1 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_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| + 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| 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_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| + 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| 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_78, field_79, field_80].count(1) > 1 - %i[field_78 field_79 field_80].each do |field| + if [field_79, field_80, field_81].count(1) > 1 + %i[field_79 field_80 field_81].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_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| + 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| errors.add(field, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "disabled access needs type.")) end end @@ -747,16 +749,16 @@ private def validate_reasonable_preference_dont_know if rp_dontknow_conflict? - 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_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, I18n.t("#{ERROR_BASE_KEY}.reasonpref.conflict.other")) if send(field) == 1 end end end def validate_reasonable_preference_homeless - 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 = %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.each do |field| errors.add(field, I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "reason for reasonable preference.")) end @@ -764,7 +766,7 @@ private end def validate_condition_effects - illness_option_fields = %i[field_93 field_87 field_90 field_85 field_86 field_88 field_89 field_92 field_91 field_94] + illness_option_fields = %i[field_94 field_88 field_91 field_86 field_87 field_89 field_90 field_93 field_92 field_95] if household_no_illness? illness_option_fields.each do |field| if attributes[field.to_s] == 1 @@ -779,12 +781,12 @@ private end def household_no_illness? - field_84 != 1 + field_85 != 1 end def validate_leaving_reason_for_renewal - if field_7 == 1 && ![50, 51, 52, 53].include?(field_97) - errors.add(:field_97, I18n.t("#{ERROR_BASE_KEY}.reason.renewal_reason_needed")) + if field_7 == 1 && ![50, 51, 52, 53].include?(field_98) + errors.add(:field_98, I18n.t("#{ERROR_BASE_KEY}.reason.renewal_reason_needed")) end end @@ -797,14 +799,14 @@ private end def validate_cannot_be_la_referral_if_general_needs_and_la - if field_115 == 4 && general_needs? && owning_organisation && owning_organisation.la? - errors.add :field_115, I18n.t("#{ERROR_BASE_KEY}.referral.general_needs_prp_referred_by_la") + if field_116 == 4 && general_needs? && owning_organisation && owning_organisation.la? + errors.add :field_116, I18n.t("#{ERROR_BASE_KEY}.referral.general_needs_prp_referred_by_la") end end def validate_la_with_local_housing_referral - if field_115 == 3 && owning_organisation && owning_organisation.la? - errors.add(:field_115, I18n.t("#{ERROR_BASE_KEY}.referral.nominated_by_local_ha_but_la")) + if field_116 == 3 && owning_organisation && owning_organisation.la? + errors.add(:field_116, I18n.t("#{ERROR_BASE_KEY}.referral.nominated_by_local_ha_but_la")) end end @@ -933,13 +935,13 @@ private end def validate_all_charges_given - return if supported_housing? && field_123 == 1 + return if supported_housing? && field_124 == 1 blank_charge_fields, other_charge_fields = { - field_123: "basic rent", - field_124: "service charge", - field_125: "personal service charge", - field_126: "support charge", + field_124: "basic rent", + field_125: "service charge", + field_126: "personal service charge", + field_127: "support charge", }.partition { |field, _| public_send(field).blank? }.map(&:to_h) blank_charge_fields.each do |field, charge| @@ -955,7 +957,7 @@ private end def all_charges_given? - field_123.present? && field_124.present? && field_125.present? && field_126.present? + field_124.present? && field_125.present? && field_126.present? && field_127.present? end def setup_question?(question) @@ -976,14 +978,14 @@ private errors.add(:field_23, error_message) unless supported_housing? # postcode_full errors.add(:field_24, error_message) unless supported_housing? # postcode_full errors.add(:field_25, error_message) unless supported_housing? # la - errors.add(:field_41, error_message) # age1 - errors.add(:field_42, error_message) # sex1 - 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 + errors.add(:field_42, error_message) # age1 + errors.add(:field_43, error_message) # sex1 + 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 end end @@ -1008,138 +1010,139 @@ private rent_type: %i[field_11], startdate: %i[field_8 field_9 field_10], unittype_gn: %i[field_26], - 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], + 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], declaration: %i[field_15], - 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], - - sex1: %i[field_42], - sex2: %i[field_48], - sex3: %i[field_52], - sex4: %i[field_56], - sex5: %i[field_60], - sex6: %i[field_64], - sex7: %i[field_68], - sex8: %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_type: %i[field_115], - referral: %i[field_115], - - 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], + 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], + + sex1: %i[field_43], + sex2: %i[field_49], + sex3: %i[field_53], + sex4: %i[field_57], + sex5: %i[field_61], + sex6: %i[field_65], + sex7: %i[field_69], + sex8: %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_type: %i[field_116], + referral: %i[field_116], + + 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], unitletas: %i[field_17], rsnvac: %i[field_16], - 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], + 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], irproduct_other: %i[field_12], propcode: %i[field_14], - majorrepairs: %i[field_32 field_33 field_34], - mrcdate: %i[field_32 field_33 field_34], + majorrepairs: %i[field_33 field_34 field_35], + mrcdate: %i[field_33 field_34 field_35], - voiddate: %i[field_29 field_30 field_31], + voiddate: %i[field_30 field_31 field_32], uprn: [:field_18], address_line1: [:field_19], @@ -1174,69 +1177,70 @@ private attributes["rent_type"] = RENT_TYPE_BU_MAPPING[field_11] attributes["startdate"] = startdate attributes["unittype_gn"] = field_26 - 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["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["declaration"] = field_15 attributes["age1_known"] = age1_known? - attributes["age1"] = field_41 if attributes["age1_known"]&.zero? && field_41&.match(/\A\d{1,3}\z|\AR\z/) + attributes["age1"] = field_42 if attributes["age1_known"]&.zero? && field_42&.match(/\A\d{1,3}\z|\AR\z/) attributes["age2_known"] = age2_known? - attributes["age2"] = field_47 if attributes["age2_known"]&.zero? && field_47&.match(/\A\d{1,3}\z|\AR\z/) + attributes["age2"] = field_48 if attributes["age2_known"]&.zero? && field_48&.match(/\A\d{1,3}\z|\AR\z/) attributes["age3_known"] = age3_known? - attributes["age3"] = field_51 if attributes["age3_known"]&.zero? && field_51&.match(/\A\d{1,3}\z|\AR\z/) + attributes["age3"] = field_52 if attributes["age3_known"]&.zero? && field_52&.match(/\A\d{1,3}\z|\AR\z/) attributes["age4_known"] = age4_known? - attributes["age4"] = field_55 if attributes["age4_known"]&.zero? && field_55&.match(/\A\d{1,3}\z|\AR\z/) + attributes["age4"] = field_56 if attributes["age4_known"]&.zero? && field_56&.match(/\A\d{1,3}\z|\AR\z/) attributes["age5_known"] = age5_known? - attributes["age5"] = field_59 if attributes["age5_known"]&.zero? && field_59&.match(/\A\d{1,3}\z|\AR\z/) + attributes["age5"] = field_60 if attributes["age5_known"]&.zero? && field_60&.match(/\A\d{1,3}\z|\AR\z/) attributes["age6_known"] = age6_known? - attributes["age6"] = field_63 if attributes["age6_known"]&.zero? && field_63&.match(/\A\d{1,3}\z|\AR\z/) + attributes["age6"] = field_64 if attributes["age6_known"]&.zero? && field_64&.match(/\A\d{1,3}\z|\AR\z/) attributes["age7_known"] = age7_known? - attributes["age7"] = field_67 if attributes["age7_known"]&.zero? && field_67&.match(/\A\d{1,3}\z|\AR\z/) + attributes["age7"] = field_68 if attributes["age7_known"]&.zero? && field_68&.match(/\A\d{1,3}\z|\AR\z/) attributes["age8_known"] = age8_known? - attributes["age8"] = field_71 if attributes["age8_known"]&.zero? && field_71&.match(/\A\d{1,3}\z|\AR\z/) + attributes["age8"] = field_72 if attributes["age8_known"]&.zero? && field_72&.match(/\A\d{1,3}\z|\AR\z/) - attributes["sex1"] = field_42 - attributes["sex2"] = field_48 - attributes["sex3"] = field_52 - attributes["sex4"] = field_56 - attributes["sex5"] = field_60 - attributes["sex6"] = field_64 - attributes["sex7"] = field_68 - attributes["sex8"] = field_72 + attributes["sex1"] = field_43 + attributes["sex2"] = field_49 + attributes["sex3"] = field_53 + attributes["sex4"] = field_57 + attributes["sex5"] = field_61 + attributes["sex6"] = field_65 + attributes["sex7"] = field_69 + attributes["sex8"] = field_73 attributes["ethnic_group"] = ethnic_group_from_ethnic - attributes["ethnic"] = field_43 - attributes["nationality_all"] = field_44 if field_44.present? && valid_nationality_options.include?(field_44.to_s) + attributes["ethnic"] = field_44 + attributes["nationality_all"] = field_45 if field_45.present? && valid_nationality_options.include?(field_45.to_s) attributes["nationality_all_group"] = nationality_group(attributes["nationality_all"]) - 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["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["details_known_2"] = details_known?(2) attributes["details_known_3"] = details_known?(3) @@ -1246,36 +1250,36 @@ private attributes["details_known_7"] = details_known?(7) attributes["details_known_8"] = details_known?(8) - attributes["armedforces"] = field_74 + attributes["armedforces"] = field_75 attributes["leftreg"] = leftreg - attributes["reservist"] = field_76 + attributes["reservist"] = field_77 - attributes["preg_occ"] = field_77 + attributes["preg_occ"] = field_78 attributes["housingneeds"] = housingneeds attributes["housingneeds_type"] = housingneeds_type attributes["housingneeds_other"] = housingneeds_other - attributes["illness"] = field_84 + attributes["illness"] = field_85 - 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["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["prevloc"] = prevloc attributes["previous_la_known"] = previous_la_known attributes["ppcodenk"] = ppcodenk attributes["ppostcode_full"] = ppostcode_full - 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["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["cbl"] = cbl attributes["chr"] = chr @@ -1284,40 +1288,40 @@ private attributes["letting_allocation_unknown"] = letting_allocation_unknown attributes["referral_type"] = referral_type - attributes["referral"] = field_115 + attributes["referral"] = field_116 attributes["net_income_known"] = net_income_known attributes["earnings"] = earnings - 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["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["tshortfall_known"] = tshortfall_known - attributes["tshortfall"] = field_128 + attributes["tshortfall"] = field_129 attributes["hhmemb"] = hhmemb attributes["unitletas"] = field_17 attributes["rsnvac"] = rsnvac - 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["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["irproduct_other"] = field_12 if RENT_TYPE_BU_MAPPING[field_11] == 5 @@ -1417,9 +1421,9 @@ private end def ethnic_group_from_ethnic - return nil if field_43.blank? + return nil if field_44.blank? - case field_43 + case field_44 when 1, 2, 3, 18, 20 0 when 4, 5, 6, 7 @@ -1436,19 +1440,19 @@ private end def age1_known? - return 1 if field_41 == "R" + return 1 if field_42 == "R" 0 end [ - { 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 }, + { 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 }, ].each do |hash| define_method("age#{hash[:person]}_known?") do return 1 if public_send(hash[:field]) == "R" @@ -1461,53 +1465,53 @@ private end def person_2_present? - field_46.present? || field_47.present? || field_48.present? + field_47.present? || field_48.present? || field_49.present? end def person_3_present? - field_50.present? || field_51.present? || field_52.present? + field_51.present? || field_52.present? || field_53.present? end def person_4_present? - field_54.present? || field_55.present? || field_56.present? + field_55.present? || field_56.present? || field_57.present? end def person_5_present? - field_58.present? || field_59.present? || field_60.present? + field_59.present? || field_60.present? || field_61.present? end def person_6_present? - field_62.present? || field_63.present? || field_64.present? + field_63.present? || field_64.present? || field_65.present? end def person_7_present? - field_66.present? || field_67.present? || field_68.present? + field_67.present? || field_68.present? || field_69.present? end def person_8_present? - field_70.present? || field_71.present? || field_72.present? + field_71.present? || field_72.present? || field_73.present? end def leftreg - field_75 + field_76 end def housingneeds - if field_82 == 1 + if field_83 == 1 2 - elsif field_83 == 1 + elsif field_84 == 1 3 - elsif field_82.blank? || field_82&.zero? + elsif field_83.blank? || field_83&.zero? 1 end end def housingneeds_type - if field_78 == 1 + if field_79 == 1 0 - elsif field_79 == 1 - 1 elsif field_80 == 1 + 1 + elsif field_81 == 1 2 else 3 @@ -1515,12 +1519,12 @@ private end def housingneeds_other - return 1 if field_81 == 1 - return 0 if [field_78, field_79, field_80].include?(1) + return 1 if field_82 == 1 + return 0 if [field_79, field_80, field_81].include?(1) end def prevloc - field_104 + field_105 end def previous_la_known @@ -1528,7 +1532,7 @@ private end def ppcodenk - case field_101 + case field_102 when 1 0 when 2 @@ -1537,11 +1541,11 @@ private end def ppostcode_full - "#{field_102} #{field_103}".strip.gsub(/\s+/, " ") + "#{field_103} #{field_104}".strip.gsub(/\s+/, " ") end def cbl - case field_111 + case field_112 when 2 0 when 1 @@ -1550,7 +1554,7 @@ private end def cap - case field_112 + case field_113 when 2 0 when 1 @@ -1559,7 +1563,7 @@ private end def chr - case field_113 + case field_114 when 2 0 when 1 @@ -1568,7 +1572,7 @@ private end def accessible_register - case field_114 + case field_115 when 2 0 when 1 @@ -1581,7 +1585,7 @@ private end def net_income_known - case field_116 + case field_117 when 1 0 when 2 @@ -1592,11 +1596,11 @@ private end def earnings - field_118.round if field_118.present? + field_119.round if field_119.present? end def tshortfall_known - field_127 == 1 ? 0 : 1 + field_128 == 1 ? 0 : 1 end def hhmemb @@ -1616,15 +1620,15 @@ private end def mrcdate - 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? + 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? rescue Date::Error Date.new end def voiddate - 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? + 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? rescue Date::Error Date.new end @@ -1651,7 +1655,7 @@ private end def reason_is_other? - field_97 == 20 + field_98 == 20 end def bulk_upload_organisation @@ -1670,10 +1674,10 @@ private end def rp_dontknow_conflict? - other_reason_fields = %i[field_106 field_107 field_108 field_109] - if field_105 == 1 + other_reason_fields = %i[field_107 field_108 field_109 field_110] + if field_106 == 1 selected_reasons = other_reason_fields.select { |field| send(field) == 1 } - dont_know_selected = field_110 == 1 + dont_know_selected = field_111 == 1 return true if selected_reasons.any? && dont_know_selected end @@ -1692,7 +1696,7 @@ private } mapping.each do |key, values| - return key if values.include?(field_115) + return key if values.include?(field_116) end 0 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 88be57d87..4b705fbc7 100644 --- a/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb @@ -116,7 +116,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when calling the method multiple times" do - let(:attributes) { { bulk_upload:, field_128: 2 } } + let(:attributes) { { bulk_upload:, field_129: 2 } } it "does not add keep adding errors to the pile" do parser.valid? @@ -140,107 +140,107 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do field_7: "2", field_26: "2", field_27: "1", - field_27: "1", field_28: "1", - field_36: "2", - field_37: "1", - field_38: "2", + field_29: "1", + field_37: "2", + field_38: "1", + field_39: "2", field_15: "1", - 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_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_46: "1", field_50: "2", - 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_54: "7", + field_58: "7", + field_62: "8", + field_66: "9", + field_70: "0", + field_74: "10", + + field_75: "1", + field_76: "4", field_77: "1", field_78: "1", - field_79: "0", + + field_79: "1", field_80: "0", - field_81: "1", - field_82: "0", + field_81: "0", + field_82: "1", + field_83: "0", - field_84: "2", + field_85: "2", - field_95: "11", - field_96: "2", - field_97: "31", - field_99: "3", - field_100: "11", + field_96: "11", + field_97: "2", + field_98: "31", + field_100: "3", + field_101: "11", - field_101: "1", - field_102: "EC1N", - field_103: "2TD", + field_102: "1", + field_103: "EC1N", + field_104: "2TD", - field_105: "1", field_106: "1", - field_107: "", - field_108: "1", - field_109: "", + field_107: "1", + field_108: "", + field_109: "1", field_110: "", + field_111: "", - field_111: "1", - field_112: "2", + field_112: "1", field_113: "2", field_114: "2", - field_115: "2", - field_116: "1", - field_117: "2", - field_118: "2300", - field_119: "1", - field_120: "4", + field_116: "2", + + field_117: "1", + field_118: "2", + field_119: "2300", + field_120: "1", + field_121: "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_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_16: "15", - field_29: now.day.to_s, - field_30: now.month.to_s, - field_31: now.strftime("%g"), + field_30: now.day.to_s, + field_31: now.month.to_s, + field_32: now.strftime("%g"), field_4: "1", @@ -294,13 +294,13 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_23, # postcode_full :field_24, # postcode_full :field_25, # postcode_full - :field_41, # age1 - :field_42, # sex1 - :field_45, # ecstat1 - :field_123, # brent - :field_124, # scharge - :field_125, # pscharge - :field_126, # supcharg + :field_42, # age1 + :field_43, # sex1 + :field_46, # ecstat1 + :field_124, # brent + :field_125, # scharge + :field_126, # pscharge + :field_127, # supcharg ].each do |field| expect(parser.errors[field]).to include(error_message) end @@ -325,7 +325,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when a supported housing log already exists in the db" do - 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 }) } + 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 }) } before do parser.log.save! @@ -348,13 +348,13 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_10, # startdate :field_13, # tenancycode :field_6, # location - :field_41, # age1 - :field_42, # sex1 - :field_45, # ecstat1 - :field_123, # brent - :field_124, # scharge - :field_125, # pscharge - :field_126, # supcharg + :field_42, # age1 + :field_43, # sex1 + :field_46, # ecstat1 + :field_124, # brent + :field_125, # scharge + :field_126, # pscharge + :field_127, # supcharg ].each do |field| expect(parser.errors[field]).to include(error_message) end @@ -390,13 +390,13 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_10, # startdate :field_13, # tenancycode :field_6, # location - :field_41, # age1 - :field_42, # sex1 - :field_45, # ecstat1 - :field_123, # brent - :field_124, # scharge - :field_125, # pscharge - :field_126, # supcharg + :field_42, # age1 + :field_43, # sex1 + :field_46, # ecstat1 + :field_124, # brent + :field_125, # scharge + :field_126, # pscharge + :field_127, # supcharg ].each do |field| expect(parser.errors[field]).to include(error_message) end @@ -433,9 +433,9 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_10, # startdate :field_13, # tenancycode :field_6, # location - :field_41, # age1 - :field_42, # sex1 - :field_45, # ecstat1 + :field_42, # age1 + :field_43, # sex1 + :field_46, # ecstat1 ].each do |field| expect(parser.errors[field]).to include(error_message) end @@ -454,8 +454,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do field_11: "2", field_6: location.id, field_1: owning_org.old_visible_id, - field_121: 0, - field_35: 4 }) + field_122: 0, + field_36: 4 }) end before do @@ -479,10 +479,10 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_10, # startdate :field_13, # tenancycode :field_6, # location - :field_41, # age1 - :field_42, # sex1 - :field_45, # ecstat1 - :field_121, # household_charge + :field_42, # age1 + :field_43, # sex1 + :field_46, # ecstat1 + :field_122, # household_charge ].each do |field| expect(parser.errors[field]).to include(error_message) end @@ -498,9 +498,9 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do let(:attributes) do setup_section_params.merge({ field_5: nil, field_6: nil, - field_123: 300, - field_122: 1, - field_28: 1, + field_124: 300, + field_123: 1, + field_29: 1, field_4: 1, field_11: "2", field_25: "E09000008" }) @@ -533,9 +533,9 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do :field_23, # postcode_full :field_24, # postcode_full :field_25, # LA - :field_41, # age1 - :field_42, # sex1 - :field_45, # ecstat1 + :field_42, # age1 + :field_43, # sex1 + :field_46, # ecstat1 ].each do |field| expect(parser.errors[field]).to be_blank end @@ -568,8 +568,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "with a valid ethnic value" do - context "when field_43 is 20" do - let(:attributes) { valid_attributes.merge({ field_43: "20" }) } + context "when field_44 is 20" do + let(:attributes) { valid_attributes.merge({ field_44: "20" }) } it "is correctly sets ethnic and ethnic group" do expect(parser.log.ethnic).to eq(20) @@ -589,43 +589,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_122: 3, field_126: 80 }) } + let(:attributes) { valid_attributes.merge({ field_123: 3, field_127: 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_122]) + expect(parser.errors.map(&:attribute)).to eql(%i[field_123]) end end end describe "#validate_nulls" do context "when non-setup questions are null" do - let(:attributes) { setup_section_params.merge({ field_42: "" }) } + let(:attributes) { setup_section_params.merge({ field_43: "" }) } it "fetches the question's check_answer_label if it exists" do parser.valid? - expect(parser.errors[:field_42]).to eql([I18n.t("validations.lettings.2026.bulk_upload.not_answered", question: "lead tenant’s gender identity.")]) + expect(parser.errors[:field_43]).to eql([I18n.t("validations.lettings.2026.bulk_upload.not_answered", question: "lead tenant’s gender identity.")]) end end context "when other null error is added" do - let(:attributes) { setup_section_params.merge({ field_111: nil }) } + let(:attributes) { setup_section_params.merge({ field_112: nil }) } it "only has one error added to the field" do parser.valid? - 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)?")]) + 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)?")]) 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_116: "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_116].length).to eq(1) + expect(parser.errors[:field_116]).to include(match I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: "")) end end end @@ -874,172 +874,171 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - describe "#field_97" do # leaving reason + describe "#field_98" do # leaving reason context "when field_7 is 1 meaning it is a renewal" do - context "when field_97 is 50" do - let(:attributes) { { bulk_upload:, field_97: "50", field_7: "1" } } + context "when field_98 is 50" do + let(:attributes) { { bulk_upload:, field_98: "50", field_7: "1" } } it "is permitted" do parser.valid? - expect(parser.errors[:field_97]).to be_blank + expect(parser.errors[:field_98]).to be_blank end end - context "when field_97 is 51" do - let(:attributes) { { bulk_upload:, field_97: "51", field_7: "1" } } + context "when field_98 is 51" do + let(:attributes) { { bulk_upload:, field_98: "51", field_7: "1" } } it "is permitted" do parser.valid? - expect(parser.errors[:field_97]).to be_blank + expect(parser.errors[:field_98]).to be_blank end end - context "when field_97 is 52" do - let(:attributes) { { bulk_upload:, field_97: "52", field_7: "1" } } + context "when field_98 is 52" do + let(:attributes) { { bulk_upload:, field_98: "52", field_7: "1" } } it "is permitted" do parser.valid? - expect(parser.errors[:field_97]).to be_blank + expect(parser.errors[:field_98]).to be_blank end end - context "when field_97 is 53" do - let(:attributes) { { bulk_upload:, field_97: "53", field_7: "1" } } + context "when field_98 is 53" do + let(:attributes) { { bulk_upload:, field_98: "53", field_7: "1" } } it "is permitted" do parser.valid? - expect(parser.errors[:field_97]).to be_blank + expect(parser.errors[:field_98]).to be_blank end end - context "when field_97 is not 50, 51, 52 or 53" do - let(:attributes) { { bulk_upload:, field_97: "1", field_7: "1" } } + context "when field_98 is not 50, 51, 52 or 53" do + let(:attributes) { { bulk_upload:, field_98: "1", field_7: "1" } } it "is not permitted" do parser.valid? - expect(parser.errors[:field_97]).to include(I18n.t("validations.lettings.2026.bulk_upload.reason.renewal_reason_needed")) + expect(parser.errors[:field_98]).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_97: "7" }) } + let(:attributes) { setup_section_params.merge({ field_98: "7" }) } it "returns an error" do parser.valid? - 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?")) + 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?")) end end end - describe "#field_78, #field_79, #field_80" do + describe "#field_79, #field_80, #field_81" do context "when one item selected" do - let(:attributes) { { bulk_upload:, field_78: "1" } } + let(:attributes) { { bulk_upload:, field_79: "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_78: "1", field_79: "1" } } + let(:attributes) { { bulk_upload:, field_79: "1", field_80: "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_82" do + describe "#field_83" do context "when 1 and another disability field selected" do - let(:attributes) { { bulk_upload:, field_82: "1", field_81: "1" } } + let(:attributes) { { bulk_upload:, field_83: "1", field_82: "1" } } it "is not permitted" do parser.valid? - expect(parser.errors[:field_82]).to be_present + expect(parser.errors[:field_83]).to be_present end end end - describe "#field_83" do + describe "#field_84" do context "when 1 and another disability field selected" do - let(:attributes) { { bulk_upload:, field_83: "1", field_81: "1" } } + let(:attributes) { { bulk_upload:, field_84: "1", field_82: "1" } } it "is not permitted" do parser.valid? - expect(parser.errors[:field_83]).to be_present + expect(parser.errors[:field_84]).to be_present end end end - describe "#field_82, #field_83" do + describe "#field_83, #field_84" do context "when both 1" do - let(:attributes) { { bulk_upload:, field_82: "1", field_83: "1" } } + let(:attributes) { { bulk_upload:, field_83: "1", field_84: "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_78 - #field_83" do + describe "#field_79 - #field_84" do context "when all blank" do - let(:attributes) { setup_section_params.merge({ field_78: nil, field_79: nil, field_80: nil, field_81: nil, field_82: nil, field_83: nil }) } + let(:attributes) { setup_section_params.merge({ field_79: nil, field_80: nil, field_81: nil, field_82: nil, field_83: nil, field_84: 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_81 is blank" do - let(:attributes) { setup_section_params.merge({ field_78: "1", field_81: nil }) } + context "when one item selected and field_82 is blank" do + let(:attributes) { setup_section_params.merge({ field_79: "1", field_82: nil }) } it "sets other disabled access needs as no" do parser.valid? - expect(parser.errors[:field_78]).to be_blank - expect(parser.errors[:field_81]).to be_blank + expect(parser.errors[:field_79]).to be_blank + expect(parser.errors[:field_82]).to be_blank expect(parser.log.housingneeds_other).to eq(0) end end end - describe "#field_84, field_93 - 99" do + describe "#field_85, field_94 - 99" do context "when no illness but illnesses answered" do - let(:attributes) { { bulk_upload:, field_84: "2", field_85: "1", field_86: "1", field_87: "1" } } + let(:attributes) { { bulk_upload:, field_85: "2", field_86: "1", field_87: "1", field_88: "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]).not_to be_present + expect(parser.errors[:field_88]).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_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 } } + 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 } } 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 @@ -1049,38 +1048,39 @@ 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_99" do + describe "#field_100" do context "when log is a renewal and field 100 is an invalid value" do - let(:attributes) { { bulk_upload:, field_7: 1, field_99: 4 } } + let(:attributes) { { bulk_upload:, field_7: 1, field_100: 4 } } it "adds an error to field 100" do parser.valid? - expect(parser.errors[:field_99]).to be_present - expect(parser.errors[:field_99]).to include(I18n.t("validations.lettings.2026.bulk_upload.prevten.invalid")) + expect(parser.errors[:field_100]).to be_present + expect(parser.errors[:field_100]).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_99: 38 } } + let(:attributes) { { bulk_upload:, field_7: 1, field_100: 38 } } it "does not add an error" do parser.valid? - expect(parser.errors[:field_99]).to be_blank + expect(parser.errors[:field_100]).to be_blank end end end - describe "#field_111 - 115 (lettings allocation methods)" do - %i[field_111 field_112 field_113 field_114].each do |field| + describe "#field_112 - 115 (lettings allocation methods)" do + %i[field_112 field_113 field_114 field_115].each do |field| context "when only #{field} is not given" do let(:attributes) do override = {} override[field] = "" - { bulk_upload:, field_111: "2", field_112: "1", field_113: "2", field_114: "1" }.merge(override) + { bulk_upload:, field_112: "2", field_113: "1", field_114: "2", field_115: "1" }.merge(override) end it "adds an error to #{field}" do @@ -1091,35 +1091,35 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - describe "#field_100, field_105 - 15" do + describe "#field_101, field_106 - 15" do context "when there is a reasonable preference but none is given" do - let(:attributes) { { bulk_upload:, field_105: "1", field_106: nil, field_107: nil, field_108: nil, field_109: nil, field_110: nil } } + let(:attributes) { { bulk_upload:, field_106: "1", field_107: nil, field_108: nil, field_109: nil, field_110: nil, field_111: 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_105: "2", field_106: "2", field_107: "3", field_108: "2", field_109: "3", field_110: "-4" }) } + 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" }) } 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_105: "1", field_106: "1", field_107: nil, field_108: "1", field_109: nil, field_110: nil }) } + 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 }) } it "sets the rest of the options to 0" do parser.valid? @@ -1132,43 +1132,43 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - describe "#field_115" do # referral + describe "#field_116" do # referral context "when 3 ie PRP nominated by LA and owning org is LA" do - let(:attributes) { { bulk_upload:, field_115: "3", field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id } } + let(:attributes) { { bulk_upload:, field_116: "3", field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id } } it "is not permitted" do parser.valid? - expect(parser.errors[:field_115]).to be_present + expect(parser.errors[:field_116]).to be_present end end context "when 4 ie referred by LA and is general needs and owning org is LA" do - let(:attributes) { { bulk_upload:, field_115: "4", field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id, field_4: "1" } } + let(:attributes) { { bulk_upload:, field_116: "4", field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id, field_4: "1" } } it "is not permitted" do parser.valid? - expect(parser.errors[:field_115]).to be_present + expect(parser.errors[:field_116]).to be_present end end context "when 4 ie referred by LA and is general needs and owning org is PRP" do let(:owning_org) { create(:organisation, :prp, :with_old_visible_id) } - let(:attributes) { { bulk_upload:, field_115: "4", field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id } } + let(:attributes) { { bulk_upload:, field_116: "4", field_1: owning_org.old_visible_id, field_2: owning_org.old_visible_id } } it "is permitted" do parser.valid? - expect(parser.errors[:field_115]).to be_blank + expect(parser.errors[:field_116]).to be_blank end end context "when 4 ie referred by LA and is not general needs" do let(:bulk_upload) { create(:bulk_upload, :lettings, user:) } - let(:attributes) { { bulk_upload:, field_115: "4", field_4: "2" } } + let(:attributes) { { bulk_upload:, field_116: "4", field_4: "2" } } it "is permitted" do parser.valid? - expect(parser.errors[:field_115]).to be_blank + expect(parser.errors[:field_116]).to be_blank end end end @@ -1694,20 +1694,20 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - describe "#field_47" do # age2 + describe "#field_48" do # age2 context "when null but gender given" do - let(:attributes) { setup_section_params.merge({ field_47: "", field_48: "F" }) } + let(:attributes) { setup_section_params.merge({ field_48: "", field_49: "F" }) } it "returns an error" do parser.valid? - expect(parser.errors[:field_47]).to be_present + expect(parser.errors[:field_48]).to be_present end end end - describe "#field_44" do - context "when field_44 is a 3 digit nationality code" do - let(:attributes) { setup_section_params.merge({ field_44: "036" }) } + describe "#field_45" do + context "when field_45 is a 3 digit nationality code" do + let(:attributes) { setup_section_params.merge({ field_45: "036" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(36) @@ -1715,8 +1715,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when field_44 is a nationality code without the trailing 0s" do - let(:attributes) { setup_section_params.merge({ field_44: "36" }) } + context "when field_45 is a nationality code without the trailing 0s" do + let(:attributes) { setup_section_params.merge({ field_45: "36" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(36) @@ -1724,8 +1724,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when field_44 is a nationality code with trailing 0s" do - let(:attributes) { setup_section_params.merge({ field_44: "0036" }) } + context "when field_45 is a nationality code with trailing 0s" do + let(:attributes) { setup_section_params.merge({ field_45: "0036" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(36) @@ -1733,8 +1733,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when field_44 is 0" do - let(:attributes) { setup_section_params.merge({ field_44: "0" }) } + context "when field_45 is 0" do + let(:attributes) { setup_section_params.merge({ field_45: "0" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(0) @@ -1742,8 +1742,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when field_44 is 000" do - let(:attributes) { setup_section_params.merge({ field_44: "000" }) } + context "when field_45 is 000" do + let(:attributes) { setup_section_params.merge({ field_45: "000" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(0) @@ -1751,8 +1751,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when field_44 is 0000" do - let(:attributes) { setup_section_params.merge({ field_44: "0000" }) } + context "when field_45 is 0000" do + let(:attributes) { setup_section_params.merge({ field_45: "0000" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(0) @@ -1760,8 +1760,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when field_44 is 826" do - let(:attributes) { setup_section_params.merge({ field_44: "826" }) } + context "when field_45 is 826" do + let(:attributes) { setup_section_params.merge({ field_45: "826" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(826) @@ -1769,8 +1769,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when field_44 is 826 with trailing 0s" do - let(:attributes) { setup_section_params.merge({ field_44: "0826" }) } + context "when field_45 is 826 with trailing 0s" do + let(:attributes) { setup_section_params.merge({ field_45: "0826" }) } it "is correctly set" do expect(parser.log.nationality_all).to be(826) @@ -1778,75 +1778,75 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when field_44 is not a valid option" do - let(:attributes) { setup_section_params.merge({ field_44: "123123" }) } + context "when field_45 is not a valid option" do + let(:attributes) { setup_section_params.merge({ field_45: "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_44" do + it "adds an error to field_45" do parser.valid? - expect(parser.errors["field_44"]).to include(I18n.t("validations.lettings.2026.bulk_upload.nationality.invalid")) + expect(parser.errors["field_45"]).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_41: 22, field_45: 5 }) } + let(:attributes) { setup_section_params.merge({ field_42: 22, field_46: 5 }) } it "adds an error to the relevant fields" do parser.valid? - expect(parser.errors.where(:field_41, category: :soft_validation)).to be_present - expect(parser.errors.where(:field_45, category: :soft_validation)).to be_present + expect(parser.errors.where(:field_42, category: :soft_validation)).to be_present + expect(parser.errors.where(:field_46, category: :soft_validation)).to be_present end it "populates with correct error message" do parser.valid? - 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.") + 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.") 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_77: "1", field_42: "M", field_48: "M", field_52: "M" }) } + let(:attributes) { setup_section_params.merge({ field_78: "1", field_43: "M", field_49: "M", field_53: "M" }) } it "adds errors to fields that are routed to" do parser.valid? - expect(parser.errors.where(:field_48, category: :soft_validation)).to be_present - expect(parser.errors.where(:field_52, category: :soft_validation)).to be_present + expect(parser.errors.where(:field_49, category: :soft_validation)).to be_present + expect(parser.errors.where(:field_53, 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_56, category: :soft_validation)).not_to be_present - expect(parser.errors.where(:field_60, category: :soft_validation)).not_to be_present + expect(parser.errors.where(:field_57, category: :soft_validation)).not_to be_present + expect(parser.errors.where(:field_61, 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_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" }) } + 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" }) } it "adds an error to the relevant fields" do parser.valid? - expect(parser.errors.where(:field_123, category: :soft_validation)).to be_present + expect(parser.errors.where(:field_124, category: :soft_validation)).to be_present end it "populates with correct error message" do parser.valid? - 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.") + 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.") end end context "when an invalid ecstat1 is given" do - let(:attributes) { setup_section_params.merge({ field_45: 11, field_118: 123, field_117: 1 }) } + let(:attributes) { setup_section_params.merge({ field_46: 11, field_119: 123, field_118: 1 }) } it "does not run net income soft validations validation" do parser.valid? - expect(parser.errors.where(:field_45).count).to be(1) + expect(parser.errors.where(:field_46).count).to be(1) end end end @@ -1971,14 +1971,14 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end [ - %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], + %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], ].each do |known, details_known, age, field, relationship, gender| describe "##{known} and ##{age}" do context "when #{field} is blank" do @@ -2080,141 +2080,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_28: 2 }) } + let(:attributes) { setup_section_params.merge({ field_26: 2, field_29: 2 }) } - it "sets value to 1 even if field_28 contradicts this" do + it "sets value to 1 even if field_29 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_28: 2 }) } + let(:attributes) { setup_section_params.merge({ field_26: 1, field_29: 2 }) } - it "sets value to field_28" do + it "sets value to field_29" do expect(parser.log.beds).to be(2) end end end describe "#cbl" do - context "when field_111 is yes ie 1" do - let(:attributes) { { bulk_upload:, field_111: 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.cbl).to be(1) end end - context "when field_111 is no ie 2" do - let(:attributes) { { bulk_upload:, field_111: 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.cbl).to be(0) end end - context "when field_111 is not a permitted value" do - let(:attributes) { { bulk_upload:, field_111: 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_111]).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_112]).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_113 is yes ie 1" do - let(:attributes) { { bulk_upload:, field_113: 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.chr).to be(1) end end - context "when field_113 is no ie 2" do - let(:attributes) { { bulk_upload:, field_113: 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.chr).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_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_113]).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_114]).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_112 is yes ie 1" do - let(:attributes) { { bulk_upload:, field_112: 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.cap).to be(1) end end - context "when field_112 is no ie 2" do - let(:attributes) { { bulk_upload:, field_112: 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.cap).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_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_112]).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_113]).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_114 is yes ie 1" do - let(:attributes) { { bulk_upload:, field_114: 1 } } + context "when field_115 is yes ie 1" do + let(:attributes) { { bulk_upload:, field_115: 1 } } it "sets value to 1" do expect(parser.log.accessible_register).to be(1) end end - context "when field_114 is no ie 2" do - let(:attributes) { { bulk_upload:, field_114: 2 } } + context "when field_115 is no ie 2" do + let(:attributes) { { bulk_upload:, field_115: 2 } } it "sets value to 0" do expect(parser.log.accessible_register).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_115 is not a permitted value" do + let(:attributes) { { bulk_upload:, field_115: 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 Accessible Register?")) + 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?")) end end end describe "#letting_allocation_unknown" do - 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 } } + 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 } } it "sets value to 1" do expect(parser.log.letting_allocation_unknown).to be(1) end end - context "when any one of field_111, 113, 114, 115 is yes ie 1" do - let(:attributes) { { bulk_upload:, field_114: 1 } } + context "when any one of field_112, 113, 114, 115 is yes ie 1" do + let(:attributes) { { bulk_upload:, field_115: 1 } } it "sets value to 0" do expect(parser.log.letting_allocation_unknown).to be(0) @@ -2236,14 +2236,14 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do let(:attributes) do { bulk_upload:, - field_42: "F", - field_48: "M", - field_52: "X", - field_56: "R", - field_60: "F", - field_64: "M", - field_68: "X", - field_72: "R", + field_43: "F", + field_49: "M", + field_53: "X", + field_57: "R", + field_61: "F", + field_65: "M", + field_69: "X", + field_73: "R", } end @@ -2263,14 +2263,14 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do let(:attributes) do { bulk_upload:, - field_45: "1", - field_49: "2", - field_53: "6", - field_57: "7", - field_61: "8", - field_65: "9", - field_69: "0", - field_73: "10", + field_46: "1", + field_50: "2", + field_54: "6", + field_58: "7", + field_62: "8", + field_66: "9", + field_70: "0", + field_74: "10", } end @@ -2290,13 +2290,13 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do let(:attributes) do { bulk_upload:, - field_46: "1", - field_50: "2", - field_54: "2", - field_58: "3", - field_62: "1", - field_66: "2", - field_70: "2", + field_47: "1", + field_51: "2", + field_55: "2", + field_59: "3", + field_63: "1", + field_67: "2", + field_71: "2", } end @@ -2313,7 +2313,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "#net_income_known" do context "when 1" do - let(:attributes) { { bulk_upload:, field_116: "1" } } + let(:attributes) { { bulk_upload:, field_117: "1" } } it "sets value from correct mapping" do expect(parser.log.net_income_known).to eq(0) @@ -2321,7 +2321,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when 2" do - let(:attributes) { { bulk_upload:, field_116: "2" } } + let(:attributes) { { bulk_upload:, field_117: "2" } } it "sets value from correct mapping" do expect(parser.log.net_income_known).to eq(1) @@ -2329,7 +2329,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when 3" do - let(:attributes) { { bulk_upload:, field_116: "3" } } + let(:attributes) { { bulk_upload:, field_117: "3" } } it "sets value from correct mapping" do expect(parser.log.net_income_known).to eq(2) @@ -2354,7 +2354,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#sheltered" do - let(:attributes) { { bulk_upload:, field_35: "1" } } + let(:attributes) { { bulk_upload:, field_36: "1" } } it "sets value from correct mapping" do expect(parser.log.sheltered).to eq(1) @@ -2363,16 +2363,16 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "illness fields" do mapping = [ - { 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 }, + { 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 }, ] mapping.each do |hash| @@ -2405,7 +2405,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#tenancyother" do - let(:attributes) { { bulk_upload:, field_39: "some other tenancy" } } + let(:attributes) { { bulk_upload:, field_40: "some other tenancy" } } it "sets value to given free text string" do expect(parser.log.tenancyother).to eql("some other tenancy") @@ -2413,7 +2413,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#tenancylength" do - let(:attributes) { { bulk_upload:, field_40: "2" } } + let(:attributes) { { bulk_upload:, field_41: "2" } } it "sets value to given free text string" do expect(parser.log.tenancylength).to eq(2) @@ -2421,7 +2421,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#earnings" do - let(:attributes) { { bulk_upload:, field_118: "104.50" } } + let(:attributes) { { bulk_upload:, field_119: "104.50" } } it "rounds to the nearest whole pound" do expect(parser.log.earnings).to eq(105) @@ -2430,7 +2430,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "#reasonother" do context "when reason is 'Other'" do - let(:attributes) { { bulk_upload:, field_97: "20", field_98: "some other reason" } } + let(:attributes) { { bulk_upload:, field_98: "20", field_99: "some other reason" } } it "is set to given free text string" do expect(parser.log.reasonother).to eql("some other reason") @@ -2438,7 +2438,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when reason is not 'Other'" do - let(:attributes) { { bulk_upload:, field_97: "50", field_98: "some other reason" } } + let(:attributes) { { bulk_upload:, field_98: "50", field_99: "some other reason" } } it "is set to nil" do expect(parser.log.reasonother).to be_nil @@ -2447,7 +2447,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#ppcodenk" do - let(:attributes) { { bulk_upload:, field_101: "2" } } + let(:attributes) { { bulk_upload:, field_102: "2" } } it "sets correct value from mapping" do expect(parser.log.ppcodenk).to eq(1) @@ -2456,7 +2456,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_121: "1" } } + let(:attributes) { { bulk_upload:, field_4: 1, field_122: "1" } } it "sets correct value from mapping" do expect(parser.log.household_charge).to eq(nil) @@ -2464,7 +2464,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when log is supported housing" do - let(:attributes) { { bulk_upload:, field_4: 2, field_121: "1" } } + let(:attributes) { { bulk_upload:, field_4: 2, field_122: "1" } } it "sets correct value from mapping" do expect(parser.log.household_charge).to eq(1) @@ -2473,14 +2473,14 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#supcharg" do - let(:attributes) { setup_section_params.merge({ field_123: "330", field_124: "0", field_125: "0", field_126: "123.45" }) } + let(:attributes) { setup_section_params.merge({ field_124: "330", field_125: "0", field_126: "0", field_127: "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_126: "123.45", field_123: nil, field_124: nil, field_125: nil }) } + let(:attributes) { setup_section_params.merge({ field_127: "123.45", field_124: nil, field_125: nil, field_126: nil }) } it "does not set charges values" do parser.log.save! @@ -2493,15 +2493,15 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do it "adds an error to all missing charges" do parser.valid? - 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")]) + 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")]) end end context "when supscharg is not given" do - let(:attributes) { setup_section_params.merge({ field_122: 1, field_123: "350.45", field_124: "0", field_125: "0", field_126: nil }) } + let(:attributes) { setup_section_params.merge({ field_123: 1, field_124: "350.45", field_125: "0", field_126: "0", field_127: nil }) } it "does not set charges values" do parser.log.save! @@ -2515,16 +2515,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.missing_charges", sentence_fragment: "support 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")]) end end end describe "#pscharge" do - let(:attributes) { { bulk_upload:, field_123: "111.45", field_124: "0", field_125: "123.45", field_126: "0" } } + let(:attributes) { { bulk_upload:, field_124: "111.45", field_125: "0", field_126: "123.45", field_127: "0" } } it "sets value given" do expect(parser.log.pscharge).to eq(123.45) @@ -2532,7 +2532,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#scharge" do - let(:attributes) { { bulk_upload:, field_123: "111.45", field_124: "123.45", field_125: "0", field_126: "0" } } + let(:attributes) { { bulk_upload:, field_124: "111.45", field_125: "123.45", field_126: "0", field_127: "0" } } it "sets value given" do expect(parser.log.scharge).to eq(123.45) @@ -2549,7 +2549,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "#mrcdate" do context "when valid" do - let(:attributes) { { bulk_upload:, field_32: "13", field_33: "12", field_34: "22" } } + let(:attributes) { { bulk_upload:, field_33: "13", field_34: "12", field_35: "22" } } it "sets value given" do expect(parser.log.mrcdate).to eq(Date.new(2022, 12, 13)) @@ -2557,7 +2557,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when valid (4 digit year)" do - let(:attributes) { { bulk_upload:, field_32: "13", field_33: "12", field_34: "2022" } } + let(:attributes) { { bulk_upload:, field_33: "13", field_34: "12", field_35: "2022" } } it "sets value given" do expect(parser.log.mrcdate).to eq(Date.new(2022, 12, 13)) @@ -2565,7 +2565,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when invalid" do - let(:attributes) { { bulk_upload:, field_32: "13", field_33: "13", field_34: "22" } } + let(:attributes) { { bulk_upload:, field_33: "13", field_34: "13", field_35: "22" } } it "does not raise an error" do expect { parser.log.mrcdate }.not_to raise_error @@ -2575,7 +2575,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "#majorrepairs" do context "when mrcdate given" do - let(:attributes) { { bulk_upload:, field_32: "13", field_33: "12", field_34: "22" } } + let(:attributes) { { bulk_upload:, field_33: "13", field_34: "12", field_35: "22" } } it "sets #majorrepairs to 1" do expect(parser.log.majorrepairs).to eq(1) @@ -2583,7 +2583,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when mrcdate not given" do - let(:attributes) { { bulk_upload:, field_32: "", field_33: "", field_34: "", field_4: 1 } } + let(:attributes) { { bulk_upload:, field_33: "", field_34: "", field_35: "", field_4: 1 } } it "sets #majorrepairs to 0" do expect(parser.log.majorrepairs).to eq(0) @@ -2593,7 +2593,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "#voiddate" do context "when valid" do - let(:attributes) { { bulk_upload:, field_29: "13", field_30: "12", field_31: "22" } } + let(:attributes) { { bulk_upload:, field_30: "13", field_31: "12", field_32: "22" } } it "sets value given" do expect(parser.log.voiddate).to eq(Date.new(2022, 12, 13)) @@ -2601,7 +2601,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when valid (4 digit year)" do - let(:attributes) { { bulk_upload:, field_29: "13", field_30: "12", field_31: "2022" } } + let(:attributes) { { bulk_upload:, field_30: "13", field_31: "12", field_32: "2022" } } it "sets value given" do expect(parser.log.voiddate).to eq(Date.new(2022, 12, 13)) @@ -2609,7 +2609,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when invalid" do - let(:attributes) { { bulk_upload:, field_29: "13", field_30: "13", field_31: "22" } } + let(:attributes) { { bulk_upload:, field_30: "13", field_31: "13", field_32: "22" } } it "does not raise an error" do expect { parser.log.voiddate }.not_to raise_error @@ -2650,7 +2650,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#prevloc" do - let(:attributes) { { bulk_upload:, field_104: "E07000223" } } + let(:attributes) { { bulk_upload:, field_105: "E07000223" } } it "sets to given value" do expect(parser.log.prevloc).to eql("E07000223") @@ -2659,7 +2659,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "#previous_la_known" do context "when known" do - let(:attributes) { { bulk_upload:, field_104: "E07000223" } } + let(:attributes) { { bulk_upload:, field_105: "E07000223" } } it "sets to 1" do expect(parser.log.previous_la_known).to eq(1) @@ -2667,7 +2667,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when not known" do - let(:attributes) { { bulk_upload:, field_104: "", field_4: 1 } } + let(:attributes) { { bulk_upload:, field_105: "", field_4: 1 } } it "sets to 0" do expect(parser.log.previous_la_known).to eq(0) @@ -2695,7 +2695,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do describe "#housingneeds" do context "when no disabled needs" do - let(:attributes) { { bulk_upload:, field_82: "1" } } + let(:attributes) { { bulk_upload:, field_83: "1" } } it "sets to 2" do expect(parser.log.housingneeds).to eq(2) @@ -2703,7 +2703,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when dont know about disabled needs" do - let(:attributes) { { bulk_upload:, field_83: "1" } } + let(:attributes) { { bulk_upload:, field_84: "1" } } it "sets to 3" do expect(parser.log.housingneeds).to eq(3) @@ -2711,7 +2711,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when housingneeds are given" do - let(:attributes) { { bulk_upload:, field_82: "0", field_80: "1", field_81: "1" } } + let(:attributes) { { bulk_upload:, field_83: "0", field_81: "1", field_82: "1" } } it "sets correct housingneeds" do expect(parser.log.housingneeds).to eq(1) @@ -2720,8 +2720,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - context "when housingneeds are given and field_81 is nil" do - let(:attributes) { { bulk_upload:, field_82: nil, field_80: "1", field_81: "1" } } + context "when housingneeds are given and field_82 is nil" do + let(:attributes) { { bulk_upload:, field_83: nil, field_81: "1", field_82: "1" } } it "sets correct housingneeds" do expect(parser.log.housingneeds).to eq(1) @@ -2731,7 +2731,7 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when housingneeds are not given" do - let(:attributes) { { bulk_upload:, field_78: nil, field_79: nil, field_80: nil, field_82: nil } } + let(:attributes) { { bulk_upload:, field_79: nil, field_80: nil, field_81: nil, field_83: nil } } it "sets correct housingneeds" do expect(parser.log.housingneeds).to eq(1) @@ -2740,106 +2740,106 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end context "when housingneeds a and b are selected" do - let(:attributes) { { bulk_upload:, field_78: "1", field_79: "1" } } + let(:attributes) { { bulk_upload:, field_79: "1", field_80: "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 be_blank + 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 end end context "when housingneeds a and c are selected" do - let(:attributes) { { bulk_upload:, field_78: "1", field_80: "1" } } + let(:attributes) { { bulk_upload:, field_79: "1", field_81: "1" } } it "sets error on housingneeds a and c" 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_80]).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_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 end end context "when housingneeds b and c are selected" do - let(:attributes) { { bulk_upload:, field_79: "1", field_80: "1" } } + let(:attributes) { { bulk_upload:, field_80: "1", field_81: "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_78]).to be_blank + 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 end end context "when housingneeds a and g are selected" do - let(:attributes) { { bulk_upload:, field_78: "1", field_82: "1" } } + let(:attributes) { { bulk_upload:, field_79: "1", field_83: "1" } } it "sets error on housingneeds a and g" do parser.valid? - 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_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_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_78: "0", field_82: "1" } } + let(:attributes) { { bulk_upload:, field_79: "0", field_83: "1" } } it "does not add any housingneeds errors" do parser.valid? - expect(parser.errors[:field_54]).to be_blank - expect(parser.errors[:field_78]).to be_blank + expect(parser.errors[:field_55]).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_78: "1", field_83: "1" } } + let(:attributes) { { bulk_upload:, field_79: "1", field_84: "1" } } it "sets error on housingneeds a and h" do parser.valid? - 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_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_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_78: "0", field_83: "1" } } + let(:attributes) { { bulk_upload:, field_79: "0", field_84: "1" } } it "does not add any housingneeds errors" do parser.valid? - expect(parser.errors[:field_83]).to be_blank - expect(parser.errors[:field_78]).to be_blank + expect(parser.errors[:field_84]).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_78 is 1" do - let(:attributes) { { bulk_upload:, field_78: "1" } } + context "when field_79 is 1" do + let(:attributes) { { bulk_upload:, field_79: "1" } } it "set to 0" do expect(parser.log.housingneeds_type).to eq(0) end end - context "when field_79 is 1" do - let(:attributes) { { bulk_upload:, field_79: "1" } } + context "when field_80 is 1" do + let(:attributes) { { bulk_upload:, field_80: "1" } } it "set to 1" do expect(parser.log.housingneeds_type).to eq(1) end end - context "when field_80 is 1" do - let(:attributes) { { bulk_upload:, field_80: "1" } } + context "when field_81 is 1" do + let(:attributes) { { bulk_upload:, field_81: "1" } } it "set to 2" do expect(parser.log.housingneeds_type).to eq(2) @@ -2848,8 +2848,8 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end describe "#housingneeds_other" do - context "when field_53 is 1" do - let(:attributes) { { bulk_upload:, field_81: "1" } } + context "when field_54 is 1" do + let(:attributes) { { bulk_upload:, field_82: "1" } } it "sets to 1" do expect(parser.log.housingneeds_other).to eq(1) From 01c38896b219b27cebf3bcd3d100f344d9c2ec8d Mon Sep 17 00:00:00 2001 From: Samuel Young Date: Wed, 7 Jan 2026 15:23:31 +0000 Subject: [PATCH 09/14] fixup! Revert "CLDC-4136: Remove question from BU parser" --- .../lettings/year2026/row_parser_spec.rb | 16 ---------------- 1 file changed, 16 deletions(-) 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 4b705fbc7..6e37c82b3 100644 --- a/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb +++ b/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb @@ -1678,22 +1678,6 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do end end - describe "#field_27" do - context "when null" do - let(:attributes) { setup_section_params.merge({ field_27: nil }) } - - it "returns an error" do - parser.valid? - expect(parser.errors[:field_27]).to be_present - end - - it "populates with correct error message" do - parser.valid? - expect(parser.errors[:field_27]).to eql([I18n.t("validations.lettings.2026.bulk_upload.not_answered", question: "type of building.")]) - end - end - end - describe "#field_48" do # age2 context "when null but gender given" do let(:attributes) { setup_section_params.merge({ field_48: "", field_49: "F" }) } From c70119954a14d55cf8b11762c72bbb6caef4b98e Mon Sep 17 00:00:00 2001 From: Samuel Young Date: Mon, 12 Jan 2026 17:13:15 +0000 Subject: [PATCH 10/14] fixup! CLDC-4136: Hide question on UI flow remove from question list instead --- app/models/form/lettings/pages/property_building_type.rb | 4 +--- app/models/form/lettings/subsections/property_information.rb | 2 +- app/services/csv/lettings_log_csv_service.rb | 3 --- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/app/models/form/lettings/pages/property_building_type.rb b/app/models/form/lettings/pages/property_building_type.rb index a143f66dd..ff3d76e0b 100644 --- a/app/models/form/lettings/pages/property_building_type.rb +++ b/app/models/form/lettings/pages/property_building_type.rb @@ -2,9 +2,7 @@ class Form::Lettings::Pages::PropertyBuildingType < ::Form::Page def initialize(id, hsh, subsection) super @id = "property_building_type" - @depends_on = [ - { "is_general_needs?" => true, "form.start_year_2026_or_later?" => false }, - ] + @depends_on = [{ "is_general_needs?" => true }] end def questions diff --git a/app/models/form/lettings/subsections/property_information.rb b/app/models/form/lettings/subsections/property_information.rb index 3b827bf48..b204fb00d 100644 --- a/app/models/form/lettings/subsections/property_information.rb +++ b/app/models/form/lettings/subsections/property_information.rb @@ -15,7 +15,7 @@ class Form::Lettings::Subsections::PropertyInformation < ::Form::Subsection (first_let_questions unless form.start_year_2025_or_later?), number_of_times_relet, Form::Lettings::Pages::PropertyUnitType.new(nil, nil, self), - Form::Lettings::Pages::PropertyBuildingType.new(nil, nil, self), + (Form::Lettings::Pages::PropertyBuildingType.new(nil, nil, self) unless form.start_year_2026_or_later?), Form::Lettings::Pages::PropertyWheelchairAccessible.new(nil, nil, self), Form::Lettings::Pages::PropertyNumberOfBedrooms.new(nil, nil, self), Form::Lettings::Pages::RentValueCheck.new("beds_rent_value_check", nil, self), diff --git a/app/services/csv/lettings_log_csv_service.rb b/app/services/csv/lettings_log_csv_service.rb index 67a398adf..2da392fb0 100644 --- a/app/services/csv/lettings_log_csv_service.rb +++ b/app/services/csv/lettings_log_csv_service.rb @@ -264,8 +264,6 @@ module Csv "uprn" => %w[uprn_known uprn], }.freeze - IGNORED_ATTRIBUTES_2026 = %w[builtype].freeze - def attribute_mappings if @year >= 2024 ATTRIBUTE_MAPPINGS.merge(ATTRIBUTE_MAPPINGS_2024) @@ -284,7 +282,6 @@ module Csv ordered_questions = FormHandler.instance.ordered_questions_for_year(@year, "lettings") soft_validations_attributes = soft_validations_attributes(ordered_questions) ordered_questions.reject! { |q| q.id.match?(/age\d_known|nationality_all_group|rent_value_check/) } - ordered_questions.reject! { |q| IGNORED_ATTRIBUTES_2026.include?(q.id) } if @year >= 2026 attributes = insert_derived_and_related_attributes(ordered_questions) order_address_fields_for_support(attributes) final_attributes = non_question_fields + attributes + SCHEME_AND_LOCATION_ATTRIBUTES From f7a6f9cb0de502c3f4da59ebc00a9ceabae4dd64 Mon Sep 17 00:00:00 2001 From: Samuel Young Date: Mon, 12 Jan 2026 17:26:30 +0000 Subject: [PATCH 11/14] fixup! CLDC-4136: Hide question from CDS export use correct year in dates --- spec/services/csv/lettings_log_csv_service_spec.rb | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/spec/services/csv/lettings_log_csv_service_spec.rb b/spec/services/csv/lettings_log_csv_service_spec.rb index e9bdbea44..a46fe6fc1 100644 --- a/spec/services/csv/lettings_log_csv_service_spec.rb +++ b/spec/services/csv/lettings_log_csv_service_spec.rb @@ -203,13 +203,13 @@ RSpec.describe Csv::LettingsLogCsvService do :ignore_validation_errors, created_by: user, assigned_to: user, - created_at: Time.zone.local(2025, 4, 1), - updated_at: Time.zone.local(2025, 4, 1), + created_at: Time.zone.local(2026, 4, 1), + updated_at: Time.zone.local(2026, 4, 1), owning_organisation: organisation, managing_organisation: organisation, needstype: 1, renewal: 0, - startdate: Time.zone.local(2025, 4, 1), + startdate: Time.zone.local(2026, 4, 1), rent_type: 1, tenancycode: "HIJKLMN", propcode: "ABCDEFG", @@ -424,9 +424,9 @@ RSpec.describe Csv::LettingsLogCsvService do builtype: 1, wchair: 1, beds: 3, - voiddate: Time.zone.local(2025, 3, 30), + voiddate: Time.zone.local(2026, 3, 30), majorrepairs: 1, - mrcdate: Time.zone.local(2025, 3, 31), + mrcdate: Time.zone.local(2026, 3, 31), joint: 3, startertenancy: 1, tenancy: 4, From f64d39df992f2ab0a0f66a83c95f83543bc432a6 Mon Sep 17 00:00:00 2001 From: Samuel Young Date: Tue, 13 Jan 2026 09:46:11 +0000 Subject: [PATCH 12/14] fixup! fixup! CLDC-4136: Hide question from CDS export use correct year in all dates --- spec/fixtures/files/lettings_log_csv_export_codes_26.csv | 2 +- spec/fixtures/files/lettings_log_csv_export_labels_26.csv | 2 +- .../lettings_log_csv_export_non_support_codes_26.csv | 2 +- .../lettings_log_csv_export_non_support_labels_26.csv | 2 +- spec/services/csv/lettings_log_csv_service_spec.rb | 8 ++++---- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/spec/fixtures/files/lettings_log_csv_export_codes_26.csv b/spec/fixtures/files/lettings_log_csv_export_codes_26.csv index 1a17f38f2..3a509f1c7 100644 --- a/spec/fixtures/files/lettings_log_csv_export_codes_26.csv +++ b/spec/fixtures/files/lettings_log_csv_export_codes_26.csv @@ -1,3 +1,3 @@ Log ID,Status of log,ID of a set of duplicate logs,User the log is created by,User the log is assigned to,Is the user in the assigned_to column the data protection officer?,Time and date the log was created,User who last updated the log,Time and date the log was last updated,Was the log submitted in-service or via bulk upload?,Year collection period opened,ID of a set of bulk uploaded logs,Which organisation owns this property?,Which organisation manages this letting?,What is the needs type?,What is the letting type?,Is this letting a renewal?,What is the tenancy start date?,"What is the rent type? (grouped into SR, IR or AR)",What is the rent type?,Which type of Intermediate Rent is this letting?,Which 'Other' type of Intermediate Rent is this letting?,Is this a London Affordable Rent letting?,What is the tenant code?,What is the property reference?,Has the tenant seen the MHCLG privacy notice?,Is this the first time the property has been let as social housing?,What rent product was the property most recently let as?,What is the reason for the property being vacant?,Is this property new to the social rented sector?,"If known, property's UPRN",Address line 1,Address line 2,Town or City,County,Postcode,The internal value to indicate if the LA was inferred from the postcode,What is the property's local authority?,Local authority code,Is the UPRN known?,UPRN of the address selected,Was the 'No address found' page seen?,Address line 1 input from address matching feature,Postcode input from address matching feature,Address line 1 entered in bulk upload file,Address line 2 entered in bulk upload file,Town or city entered in bulk upload file,County entered in bulk upload file,Postcode entered in bulk upload file,Local authority entered in bulk upload file,What type of unit is the property?,Is the property built or adapted to wheelchair-user standards?,How many bedrooms does the property have?,What is the void date?,Number of days the property was vacant,The following soft validation was confirmed: You told us that the property has been vacant for more than 2 years. This is higher than we would expect.,Were any major repairs carried out during the void period?,What date were any major repairs completed on?,The following soft validation was confirmed: You told us the property has been vacant for 2 years. This is higher than we would expect.,Is this letting in sheltered accommodation?,Is this a joint tenancy?,Is this a starter tenancy?,What is the type of tenancy?,"If 'Other', what is the type of tenancy?",What is the length of the fixed-term tenancy to the nearest year?,How many people live in the household at this letting?,The following soft validation was confirmed: You told us somebody in the household is pregnant. You also told us there are no female tenants living at the property.,"Where household characteristics have a 'Refused' option for some or all of: AGE1-AGE8, SEX1-SEX8, RELAT2-RELAT8, ECSTAT1-ECSTAT8","Type of household 1 = 1 elder; 2 = 2 adults, including elder(s); 3 = 1 adult; 4 = 2 adults; 5 = 1 adult & 1+ children; 6 = 2+ adults & 1+ children; 9 = Other",Total number of dependent children in the household (Sum of when RELAT2-8 = C),Total number of elders in household (Sum of when AGE1-8 >= 60),Total number of adults in household,What is the lead tenant's age?,The following soft validation was confirmed: You told us this person is aged %{age} years and retired. The minimum expected retirement age for %{gender} in England is %{age}.,Which of these best describes the lead tenant's gender identity?,What is the lead tenant's ethnic group?,Which of these best describes the lead tenant's ethnic background?,What is the lead tenant's nationality?,Which of these best describes the lead tenant's working situation?,Are the details of tenant 2 known?,What is person 2's relationship to the lead tenant?,"The following soft validation was confirmed: You said that [person X]'s relationship to lead tenant is partner, and that their age is [AGEX]. Are you sure this is correct?",The following soft validation was confirmed: You said that more than one person in the household is the partner of the lead tenant. Are you sure this is correct?,What is person 2's age?,Which of these best describes person 2's gender identity?,Which of these best describes person 2's working situation?,Are the details of tenant 3 known?,What is person 3's relationship to the lead tenant?,What is person 3's age?,Which of these best describes person 3's gender identity?,Which of these best describes person 3's working situation?,Are the details of tenant 4 known?,What is person 4's relationship to the lead tenant?,What is person 4's age?,Which of these best describes person 4's gender identity?,Which of these best describes person 4's working situation?,Are the details of tenant 5 known?,What is person 5's relationship to the lead tenant?,What is person 5's age?,Which of these best describes person 5's gender identity?,Which of these best describes person 5's working situation?,Are the details of tenant 6 known?,What is person 6's relationship to the lead tenant?,What is person 6's age?,Which of these best describes person 6's gender identity?,Which of these best describes person 6's working situation?,Are the details of tenant 7 known?,What is person 7's relationship to the lead tenant?,What is person 7's age?,Which of these best describes person 7's gender identity?,Which of these best describes person 7's working situation?,Are the details of tenant 8 known?,What is person 8's relationship to the lead tenant?,What is person 8's age?,Which of these best describes person 8's gender identity?,Which of these best describes person 8's working situation?,Does anybody in the household have links to the UK armed forces?,Is this person still serving in the UK armed forces?,Was this person seriously injured or ill as a result of serving in the UK armed forces?,Is anybody in the household pregnant?,Does anybody in the household have any disabled access needs?,"What access needs do they have? (Fully wheelchair-accessible housing, Level access housing or Wheelchair access to essential rooms)",Disabled access needs a) Fully wheelchair-accessible housing,Disabled access needs b) Wheelchair access to essential rooms,Disabled access needs c) Level access housing,Disabled access needs f) Other disabled access needs,Disabled access needs g) No disabled access needs,Disabled access needs h) Don't know,Do they have any other disabled access needs?,Does anybody in the household have a physical or mental health condition (or other illness) expected to last 12 months or more?,Does this person's condition affect their dexterity?,Does this person's condition affect their learning or understanding or concentrating?,Does this person's condition affect their hearing?,Does this person's condition affect their memory?,Does this person's condition affect their mental health?,Does this person's condition affect their mobility?,Does this person's condition affect them socially or behaviourally?,Does this person's condition affect their stamina or breathing or fatigue?,Does this person's condition affect their vision?,Does this person's condition affect them in another way?,How long has the household continuously lived in the local authority area of the new letting?,How long has the household been on the local authority waiting list for the new letting?,What is the tenant's main reason for the household leaving their last settled home?,"If 'Other', what was the main reason for leaving their last settled home?",The soft validation was confirmed,Where was the household immediately before this letting?,Did the household experience homelessness immediately before this letting?,Previous postcode unknown or previous accommodation was temporary,What is the postcode of the household's last settled home?,Was the local authority of the household's last settled home known?,The internal value to indicate if the previous LA was inferred from the postcode,Previous location LA name,Previous location's ONS LA Code,Was the household given reasonable preference by the local authority?,Reasonable preference reason - They were homeless or about to lose their home (within 56 days),"Reasonable preference reason - They were living in insanitary, overcrowded or unisatisfactory housing",Reasonable preference reason - They needed to move on medical and welfare reasons (including disability),Reasonable preference reason - They needed to move to avoid hardship to themselves or others,Reasonable preference reason - Don't Know,Was the letting made under Choice-Based Lettings (CBL)?,Was the letting made under the Common Allocation Policy (CAP)?,Was the letting made under the Common Housing Register (CHR)?,Was the letting made under the Accessible Register?,"The letting was not allocated under CBL, CAP, CHR or Accessible Register.",,What was the source of referral for this letting?,"The following soft validation was confirmed: Are you sure? This is a general needs log, and this referral type is for supported housing.",Do you know the household's combined income after tax?,Was the household income refused?,How often does the household receive income?,How much income does the household have in total?,Populated when someone hits the soft validation and confirmed in the service,Is the tenant likely to be receiving any of these housing-related benefits?,"Does the tenant receive housing-related benefits? Yes if hb = Universal Credit housing element or Housing benefit, No if hb = Don't Know, Neither, Tenant prefers not to say or blank","How much of the household's income is from Universal Credit, state pensions or benefits?",Does the household pay rent or other charges for the accommodation?,Does the household pay rent or other charges for the accommodation? - flag for when household_charge is answered no,How often does the household pay rent and other charges?,What is the basic rent?,Weekly rent,Populated when the soft validation and confirmed in the service,What is the service charge?,Weekly service charge,What is the personal service charge?,Weekly personal service charge,What is the support charge?,Weekly support charge,Total charge to the tenant,Weekly total charge to the tenant,Populated when the soft validation and confirmed in the service,Populated when the soft validation and confirmed in the service,Populated when the soft validation and confirmed in the service,"After the household has received any housing-related benefits, will they still need to pay for rent and charges?",Can you estimate the outstanding amount?,Estimated outstanding amount,Weekly total rent shortfall charge for tenant receiving housing benefit,What scheme does this letting belong to?,"From scheme code, we map to the scheme name",Does the scheme contain confidential information?,"What is this type of scheme? (Direct access hostel), Foyer, Housing for older people or Other supported housing",Is this scheme registered under the Care Standards Act 2000?,Which organisation owns the housing stock for this scheme?,What client group is this scheme intended for?,Does this scheme provide for another client group?,What is the other client group?,What support does this scheme provide?,Intended length of stay,Date scheme was created,Which location is this letting for?,What is the postcode for this location?,What is the name of this location?,How many units are at this location?,What is the most common type of unit at this location?,What are the mobility standards for the majority of the units in this location?,What is the local authority of this postcode?,When did the first property in this location become available under this scheme? id,status,duplicate_set_id,created_by,assigned_to,is_dpo,created_at,updated_by,updated_at,creation_method,collection_start_year,bulk_upload_id,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,declaration,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,uprn,address_line1,address_line2,town_or_city,county,postcode_full,is_la_inferred,la_label,la,uprn_known,uprn_selection,address_search_value_check,address_line1_input,postcode_full_input,address_line1_as_entered,address_line2_as_entered,town_or_city_as_entered,county_as_entered,postcode_full_as_entered,la_as_entered,unittype_gn,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,sheltered,joint,startertenancy,tenancy,tenancyother,tenancylength,hhmemb,pregnancy_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sex1,ethnic_group,ethnic,nationality_all,ecstat1,details_known_2,relat2,partner_under_16_value_check,multiple_partners_value_check,age2,sex2,ecstat2,details_known_3,relat3,age3,sex3,ecstat3,details_known_4,relat4,age4,sex4,ecstat4,details_known_5,relat5,age5,sex5,ecstat5,details_known_6,relat6,age6,sex6,ecstat6,details_known_7,relat7,age7,sex7,ecstat7,details_known_8,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,reasonother_value_check,prevten,homeless,ppcodenk,ppostcode_full,previous_la_known,is_previous_la_inferred,prevloc_label,prevloc,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,accessible_register,letting_allocation_none,referral_type,referral,referral_value_check,net_income_known,incref,incfreq,earnings,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,brent,wrent,rent_value_check,scharge,wscharge,pscharge,wpschrge,supcharg,wsupchrg,tcharge,wtcharge,scharge_value_check,pscharge_value_check,supcharg_value_check,hbrentshortfall,tshortfall_known,tshortfall,wtshortfall,scheme_code,scheme_service_name,scheme_confidential,SCHTYPE,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_local_authority,location_startdate -,in_progress,,s.port@jeemayle.com,s.port@jeemayle.com,false,2025-04-01T00:00:00+01:00,,2025-04-01T00:00:00+01:00,1,2025,,MHCLG,MHCLG,1,7,0,2025-04-01,2,2,,,2,HIJKLMN,ABCDEFG,1,0,2,6,2,,Address line 1,,London,,NW9 5LL,false,Barnet,E09000003,0,,,,,address line 1 as entered,address line 2 as entered,town or city as entered,county as entered,AB1 2CD,la as entered,7,1,3,2025-03-30,1,,1,2025-03-31,,,3,1,4,,2,4,,1,4,0,0,2,35,,F,0,2,36,0,0,P,,,32,M,6,1,R,-9,R,10,0,R,-9,R,10,,,,,,,,,,,,,,,,,,,,,1,4,1,2,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,2,7,4,,,6,1,0,TN23 6LZ,1,false,Ashford,E07000105,1,0,1,0,0,0,0,0,1,0,0,,,,0,0,1,268,,6,1,1,,,2,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,,,,1,0,12.0,6.0,,,,,,,,,,,,,,,,,,,, +,in_progress,,s.port@jeemayle.com,s.port@jeemayle.com,false,2026-04-01T00:00:00+01:00,,2026-04-01T00:00:00+01:00,1,2026,,MHCLG,MHCLG,1,7,0,2026-04-01,2,2,,,2,HIJKLMN,ABCDEFG,1,0,2,6,2,,Address line 1,,London,,NW9 5LL,false,Barnet,E09000003,0,,,,,address line 1 as entered,address line 2 as entered,town or city as entered,county as entered,AB1 2CD,la as entered,7,1,3,2026-03-30,1,,1,2026-03-31,,,3,1,4,,2,4,,1,4,0,0,2,35,,F,0,2,36,0,0,P,,,32,M,6,1,R,-9,R,10,0,R,-9,R,10,,,,,,,,,,,,,,,,,,,,,1,4,1,2,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,2,7,4,,,6,1,0,TN23 6LZ,1,false,Ashford,E07000105,1,0,1,0,0,0,0,0,1,0,0,,,,0,0,1,268,,6,1,1,,,2,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,,,,1,0,12.0,6.0,,,,,,,,,,,,,,,,,,,, diff --git a/spec/fixtures/files/lettings_log_csv_export_labels_26.csv b/spec/fixtures/files/lettings_log_csv_export_labels_26.csv index e2ecf86e6..4d3309bbc 100644 --- a/spec/fixtures/files/lettings_log_csv_export_labels_26.csv +++ b/spec/fixtures/files/lettings_log_csv_export_labels_26.csv @@ -1,3 +1,3 @@ Log ID,Status of log,ID of a set of duplicate logs,User the log is created by,User the log is assigned to,Is the user in the assigned_to column the data protection officer?,Time and date the log was created,User who last updated the log,Time and date the log was last updated,Was the log submitted in-service or via bulk upload?,Year collection period opened,ID of a set of bulk uploaded logs,Which organisation owns this property?,Which organisation manages this letting?,What is the needs type?,What is the letting type?,Is this letting a renewal?,What is the tenancy start date?,"What is the rent type? (grouped into SR, IR or AR)",What is the rent type?,Which type of Intermediate Rent is this letting?,Which 'Other' type of Intermediate Rent is this letting?,Is this a London Affordable Rent letting?,What is the tenant code?,What is the property reference?,Has the tenant seen the MHCLG privacy notice?,Is this the first time the property has been let as social housing?,What rent product was the property most recently let as?,What is the reason for the property being vacant?,Is this property new to the social rented sector?,"If known, property's UPRN",Address line 1,Address line 2,Town or City,County,Postcode,The internal value to indicate if the LA was inferred from the postcode,What is the property's local authority?,Local authority code,Is the UPRN known?,UPRN of the address selected,Was the 'No address found' page seen?,Address line 1 input from address matching feature,Postcode input from address matching feature,Address line 1 entered in bulk upload file,Address line 2 entered in bulk upload file,Town or city entered in bulk upload file,County entered in bulk upload file,Postcode entered in bulk upload file,Local authority entered in bulk upload file,What type of unit is the property?,Is the property built or adapted to wheelchair-user standards?,How many bedrooms does the property have?,What is the void date?,Number of days the property was vacant,The following soft validation was confirmed: You told us that the property has been vacant for more than 2 years. This is higher than we would expect.,Were any major repairs carried out during the void period?,What date were any major repairs completed on?,The following soft validation was confirmed: You told us the property has been vacant for 2 years. This is higher than we would expect.,Is this letting in sheltered accommodation?,Is this a joint tenancy?,Is this a starter tenancy?,What is the type of tenancy?,"If 'Other', what is the type of tenancy?",What is the length of the fixed-term tenancy to the nearest year?,How many people live in the household at this letting?,The following soft validation was confirmed: You told us somebody in the household is pregnant. You also told us there are no female tenants living at the property.,"Where household characteristics have a 'Refused' option for some or all of: AGE1-AGE8, SEX1-SEX8, RELAT2-RELAT8, ECSTAT1-ECSTAT8","Type of household 1 = 1 elder; 2 = 2 adults, including elder(s); 3 = 1 adult; 4 = 2 adults; 5 = 1 adult & 1+ children; 6 = 2+ adults & 1+ children; 9 = Other",Total number of dependent children in the household (Sum of when RELAT2-8 = C),Total number of elders in household (Sum of when AGE1-8 >= 60),Total number of adults in household,What is the lead tenant's age?,The following soft validation was confirmed: You told us this person is aged %{age} years and retired. The minimum expected retirement age for %{gender} in England is %{age}.,Which of these best describes the lead tenant's gender identity?,What is the lead tenant's ethnic group?,Which of these best describes the lead tenant's ethnic background?,What is the lead tenant's nationality?,Which of these best describes the lead tenant's working situation?,Are the details of tenant 2 known?,What is person 2's relationship to the lead tenant?,"The following soft validation was confirmed: You said that [person X]'s relationship to lead tenant is partner, and that their age is [AGEX]. Are you sure this is correct?",The following soft validation was confirmed: You said that more than one person in the household is the partner of the lead tenant. Are you sure this is correct?,What is person 2's age?,Which of these best describes person 2's gender identity?,Which of these best describes person 2's working situation?,Are the details of tenant 3 known?,What is person 3's relationship to the lead tenant?,What is person 3's age?,Which of these best describes person 3's gender identity?,Which of these best describes person 3's working situation?,Are the details of tenant 4 known?,What is person 4's relationship to the lead tenant?,What is person 4's age?,Which of these best describes person 4's gender identity?,Which of these best describes person 4's working situation?,Are the details of tenant 5 known?,What is person 5's relationship to the lead tenant?,What is person 5's age?,Which of these best describes person 5's gender identity?,Which of these best describes person 5's working situation?,Are the details of tenant 6 known?,What is person 6's relationship to the lead tenant?,What is person 6's age?,Which of these best describes person 6's gender identity?,Which of these best describes person 6's working situation?,Are the details of tenant 7 known?,What is person 7's relationship to the lead tenant?,What is person 7's age?,Which of these best describes person 7's gender identity?,Which of these best describes person 7's working situation?,Are the details of tenant 8 known?,What is person 8's relationship to the lead tenant?,What is person 8's age?,Which of these best describes person 8's gender identity?,Which of these best describes person 8's working situation?,Does anybody in the household have links to the UK armed forces?,Is this person still serving in the UK armed forces?,Was this person seriously injured or ill as a result of serving in the UK armed forces?,Is anybody in the household pregnant?,Does anybody in the household have any disabled access needs?,"What access needs do they have? (Fully wheelchair-accessible housing, Level access housing or Wheelchair access to essential rooms)",Disabled access needs a) Fully wheelchair-accessible housing,Disabled access needs b) Wheelchair access to essential rooms,Disabled access needs c) Level access housing,Disabled access needs f) Other disabled access needs,Disabled access needs g) No disabled access needs,Disabled access needs h) Don't know,Do they have any other disabled access needs?,Does anybody in the household have a physical or mental health condition (or other illness) expected to last 12 months or more?,Does this person's condition affect their dexterity?,Does this person's condition affect their learning or understanding or concentrating?,Does this person's condition affect their hearing?,Does this person's condition affect their memory?,Does this person's condition affect their mental health?,Does this person's condition affect their mobility?,Does this person's condition affect them socially or behaviourally?,Does this person's condition affect their stamina or breathing or fatigue?,Does this person's condition affect their vision?,Does this person's condition affect them in another way?,How long has the household continuously lived in the local authority area of the new letting?,How long has the household been on the local authority waiting list for the new letting?,What is the tenant's main reason for the household leaving their last settled home?,"If 'Other', what was the main reason for leaving their last settled home?",The soft validation was confirmed,Where was the household immediately before this letting?,Did the household experience homelessness immediately before this letting?,Previous postcode unknown or previous accommodation was temporary,What is the postcode of the household's last settled home?,Was the local authority of the household's last settled home known?,The internal value to indicate if the previous LA was inferred from the postcode,Previous location LA name,Previous location's ONS LA Code,Was the household given reasonable preference by the local authority?,Reasonable preference reason - They were homeless or about to lose their home (within 56 days),"Reasonable preference reason - They were living in insanitary, overcrowded or unisatisfactory housing",Reasonable preference reason - They needed to move on medical and welfare reasons (including disability),Reasonable preference reason - They needed to move to avoid hardship to themselves or others,Reasonable preference reason - Don't Know,Was the letting made under Choice-Based Lettings (CBL)?,Was the letting made under the Common Allocation Policy (CAP)?,Was the letting made under the Common Housing Register (CHR)?,Was the letting made under the Accessible Register?,"The letting was not allocated under CBL, CAP, CHR or Accessible Register.",,What was the source of referral for this letting?,"The following soft validation was confirmed: Are you sure? This is a general needs log, and this referral type is for supported housing.",Do you know the household's combined income after tax?,Was the household income refused?,How often does the household receive income?,How much income does the household have in total?,Populated when someone hits the soft validation and confirmed in the service,Is the tenant likely to be receiving any of these housing-related benefits?,"Does the tenant receive housing-related benefits? Yes if hb = Universal Credit housing element or Housing benefit, No if hb = Don't Know, Neither, Tenant prefers not to say or blank","How much of the household's income is from Universal Credit, state pensions or benefits?",Does the household pay rent or other charges for the accommodation?,Does the household pay rent or other charges for the accommodation? - flag for when household_charge is answered no,How often does the household pay rent and other charges?,What is the basic rent?,Weekly rent,Populated when the soft validation and confirmed in the service,What is the service charge?,Weekly service charge,What is the personal service charge?,Weekly personal service charge,What is the support charge?,Weekly support charge,Total charge to the tenant,Weekly total charge to the tenant,Populated when the soft validation and confirmed in the service,Populated when the soft validation and confirmed in the service,Populated when the soft validation and confirmed in the service,"After the household has received any housing-related benefits, will they still need to pay for rent and charges?",Can you estimate the outstanding amount?,Estimated outstanding amount,Weekly total rent shortfall charge for tenant receiving housing benefit,What scheme does this letting belong to?,"From scheme code, we map to the scheme name",Does the scheme contain confidential information?,"What is this type of scheme? (Direct access hostel), Foyer, Housing for older people or Other supported housing",Is this scheme registered under the Care Standards Act 2000?,Which organisation owns the housing stock for this scheme?,What client group is this scheme intended for?,Does this scheme provide for another client group?,What is the other client group?,What support does this scheme provide?,Intended length of stay,Date scheme was created,Which location is this letting for?,What is the postcode for this location?,What is the name of this location?,How many units are at this location?,What is the most common type of unit at this location?,What are the mobility standards for the majority of the units in this location?,What is the local authority of this postcode?,When did the first property in this location become available under this scheme? id,status,duplicate_set_id,created_by,assigned_to,is_dpo,created_at,updated_by,updated_at,creation_method,collection_start_year,bulk_upload_id,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,declaration,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,uprn,address_line1,address_line2,town_or_city,county,postcode_full,is_la_inferred,la_label,la,uprn_known,uprn_selection,address_search_value_check,address_line1_input,postcode_full_input,address_line1_as_entered,address_line2_as_entered,town_or_city_as_entered,county_as_entered,postcode_full_as_entered,la_as_entered,unittype_gn,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,sheltered,joint,startertenancy,tenancy,tenancyother,tenancylength,hhmemb,pregnancy_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sex1,ethnic_group,ethnic,nationality_all,ecstat1,details_known_2,relat2,partner_under_16_value_check,multiple_partners_value_check,age2,sex2,ecstat2,details_known_3,relat3,age3,sex3,ecstat3,details_known_4,relat4,age4,sex4,ecstat4,details_known_5,relat5,age5,sex5,ecstat5,details_known_6,relat6,age6,sex6,ecstat6,details_known_7,relat7,age7,sex7,ecstat7,details_known_8,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,reasonother_value_check,prevten,homeless,ppcodenk,ppostcode_full,previous_la_known,is_previous_la_inferred,prevloc_label,prevloc,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,accessible_register,letting_allocation_none,referral_type,referral,referral_value_check,net_income_known,incref,incfreq,earnings,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,brent,wrent,rent_value_check,scharge,wscharge,pscharge,wpschrge,supcharg,wsupchrg,tcharge,wtcharge,scharge_value_check,pscharge_value_check,supcharg_value_check,hbrentshortfall,tshortfall_known,tshortfall,wtshortfall,scheme_code,scheme_service_name,scheme_confidential,SCHTYPE,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_local_authority,location_startdate -,in_progress,,s.port@jeemayle.com,s.port@jeemayle.com,false,2025-04-01T00:00:00+01:00,,2025-04-01T00:00:00+01:00,single log,2025,,MHCLG,MHCLG,General needs,Affordable rent general needs local authority,No,2025-04-01,Affordable Rent,Affordable Rent,,,No,HIJKLMN,ABCDEFG,Yes,No,Affordable rent basis,Tenant abandoned property,No,,Address line 1,,London,,NW9 5LL,No,Barnet,E09000003,No,,,,,address line 1 as entered,address line 2 as entered,town or city as entered,county as entered,AB1 2CD,la as entered,House,Yes,3,2025-03-30,1,,Yes,2025-03-31,,,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,4,,Yes,4,0,0,2,35,,Female,White,Irish,Australia,Other,Yes,Yes,,,32,Male,Not seeking work,No,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Yes,Tenant prefers not to say,Not known,Person prefers not to say,Person prefers not to say,,,,,,,,,,,,,,,,,,,,,Yes – the person is a current or former regular,No – they left up to and including 5 years ago,Yes,No,Yes,Fully wheelchair accessible housing,Yes,No,No,No,No,No,No,Yes,No,No,Yes,No,No,No,No,No,No,No,Less than 1 year,1 year but under 2 years,Loss of tied accommodation,,,Other supported housing,No,Yes,TN23 6LZ,Yes,No,Ashford,E07000105,Yes,,Yes,,,,No,No,Yes,No,No,,,,Yes,No,Weekly,268,,Universal Credit housing element,Yes,All,,,Every 2 weeks,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,,,,Yes,Yes,12.0,6.0,,,,,,,,,,,,,,,,,,,, +,in_progress,,s.port@jeemayle.com,s.port@jeemayle.com,false,2026-04-01T00:00:00+01:00,,2026-04-01T00:00:00+01:00,single log,2026,,MHCLG,MHCLG,General needs,Affordable rent general needs local authority,No,2026-04-01,Affordable Rent,Affordable Rent,,,No,HIJKLMN,ABCDEFG,Yes,No,Affordable rent basis,Tenant abandoned property,No,,Address line 1,,London,,NW9 5LL,No,Barnet,E09000003,No,,,,,address line 1 as entered,address line 2 as entered,town or city as entered,county as entered,AB1 2CD,la as entered,House,Yes,3,2026-03-30,1,,Yes,2026-03-31,,,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,4,,Yes,4,0,0,2,35,,Female,White,Irish,Australia,Other,Yes,Yes,,,32,Male,Not seeking work,No,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Yes,Tenant prefers not to say,Not known,Person prefers not to say,Person prefers not to say,,,,,,,,,,,,,,,,,,,,,Yes – the person is a current or former regular,No – they left up to and including 5 years ago,Yes,No,Yes,Fully wheelchair accessible housing,Yes,No,No,No,No,No,No,Yes,No,No,Yes,No,No,No,No,No,No,No,Less than 1 year,1 year but under 2 years,Loss of tied accommodation,,,Other supported housing,No,Yes,TN23 6LZ,Yes,No,Ashford,E07000105,Yes,,Yes,,,,No,No,Yes,No,No,,,,Yes,No,Weekly,268,,Universal Credit housing element,Yes,All,,,Every 2 weeks,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,,,,Yes,Yes,12.0,6.0,,,,,,,,,,,,,,,,,,,, diff --git a/spec/fixtures/files/lettings_log_csv_export_non_support_codes_26.csv b/spec/fixtures/files/lettings_log_csv_export_non_support_codes_26.csv index 620ef87b7..81a15f603 100644 --- a/spec/fixtures/files/lettings_log_csv_export_non_support_codes_26.csv +++ b/spec/fixtures/files/lettings_log_csv_export_non_support_codes_26.csv @@ -1,3 +1,3 @@ Log ID,Status of log,ID of a set of duplicate logs,User the log is assigned to,Is the user in the assigned_to column the data protection officer?,Time and date the log was created,User who last updated the log,Time and date the log was last updated,Was the log submitted in-service or via bulk upload?,Year collection period opened,ID of a set of bulk uploaded logs,Which organisation owns this property?,Which organisation manages this letting?,What is the needs type?,What is the letting type?,Is this letting a renewal?,What is the tenancy start date?,"What is the rent type? (grouped into SR, IR or AR)",What is the rent type?,Which type of Intermediate Rent is this letting?,Which 'Other' type of Intermediate Rent is this letting?,Is this a London Affordable Rent letting?,What is the tenant code?,What is the property reference?,Has the tenant seen the MHCLG privacy notice?,Is this the first time the property has been let as social housing?,What rent product was the property most recently let as?,What is the reason for the property being vacant?,Is this property new to the social rented sector?,Is the UPRN known?,"If known, property's UPRN",Address line 1,Address line 2,Town or City,County,Postcode,What is the property's local authority?,What type of unit is the property?,Is the property built or adapted to wheelchair-user standards?,How many bedrooms does the property have?,What is the void date?,Number of days the property was vacant,Were any major repairs carried out during the void period?,What date were any major repairs completed on?,Is this letting in sheltered accommodation?,Is this a joint tenancy?,Is this a starter tenancy?,What is the type of tenancy?,"If 'Other', what is the type of tenancy?",What is the length of the fixed-term tenancy to the nearest year?,How many people live in the household at this letting?,"Where household characteristics have a 'Refused' option for some or all of: AGE1-AGE8, SEX1-SEX8, RELAT2-RELAT8, ECSTAT1-ECSTAT8",What is the lead tenant's age?,Which of these best describes the lead tenant's gender identity?,What is the lead tenant's ethnic group?,Which of these best describes the lead tenant's ethnic background?,What is the lead tenant's nationality?,Which of these best describes the lead tenant's working situation?,What is person 2's relationship to the lead tenant?,What is person 2's age?,Which of these best describes person 2's gender identity?,Which of these best describes person 2's working situation?,What is person 3's relationship to the lead tenant?,What is person 3's age?,Which of these best describes person 3's gender identity?,Which of these best describes person 3's working situation?,What is person 4's relationship to the lead tenant?,What is person 4's age?,Which of these best describes person 4's gender identity?,Which of these best describes person 4's working situation?,What is person 5's relationship to the lead tenant?,What is person 5's age?,Which of these best describes person 5's gender identity?,Which of these best describes person 5's working situation?,What is person 6's relationship to the lead tenant?,What is person 6's age?,Which of these best describes person 6's gender identity?,Which of these best describes person 6's working situation?,What is person 7's relationship to the lead tenant?,What is person 7's age?,Which of these best describes person 7's gender identity?,Which of these best describes person 7's working situation?,What is person 8's relationship to the lead tenant?,What is person 8's age?,Which of these best describes person 8's gender identity?,Which of these best describes person 8's working situation?,Does anybody in the household have links to the UK armed forces?,Is this person still serving in the UK armed forces?,Was this person seriously injured or ill as a result of serving in the UK armed forces?,Is anybody in the household pregnant?,Does anybody in the household have any disabled access needs?,"What access needs do they have? (Fully wheelchair-accessible housing, Level access housing or Wheelchair access to essential rooms)",Disabled access needs a) Fully wheelchair-accessible housing,Disabled access needs b) Wheelchair access to essential rooms,Disabled access needs c) Level access housing,Disabled access needs f) Other disabled access needs,Disabled access needs g) No disabled access needs,Disabled access needs h) Don't know,Do they have any other disabled access needs?,Does anybody in the household have a physical or mental health condition (or other illness) expected to last 12 months or more?,Does this person's condition affect their dexterity?,Does this person's condition affect their learning or understanding or concentrating?,Does this person's condition affect their hearing?,Does this person's condition affect their memory?,Does this person's condition affect their mental health?,Does this person's condition affect their mobility?,Does this person's condition affect them socially or behaviourally?,Does this person's condition affect their stamina or breathing or fatigue?,Does this person's condition affect their vision?,Does this person's condition affect them in another way?,How long has the household continuously lived in the local authority area of the new letting?,How long has the household been on the local authority waiting list for the new letting?,What is the tenant's main reason for the household leaving their last settled home?,"If 'Other', what was the main reason for leaving their last settled home?",Where was the household immediately before this letting?,Did the household experience homelessness immediately before this letting?,Previous postcode unknown or previous accommodation was temporary,What is the postcode of the household's last settled home?,Previous location LA name,Was the household given reasonable preference by the local authority?,Reasonable preference reason - They were homeless or about to lose their home (within 56 days),"Reasonable preference reason - They were living in insanitary, overcrowded or unisatisfactory housing",Reasonable preference reason - They needed to move on medical and welfare reasons (including disability),Reasonable preference reason - They needed to move to avoid hardship to themselves or others,Reasonable preference reason - Don't Know,Was the letting made under Choice-Based Lettings (CBL)?,Was the letting made under the Common Allocation Policy (CAP)?,Was the letting made under the Common Housing Register (CHR)?,Was the letting made under the Accessible Register?,"The letting was not allocated under CBL, CAP, CHR or Accessible Register.",,What was the source of referral for this letting?,Was the household income refused?,How often does the household receive income?,How much income does the household have in total?,Is the tenant likely to be receiving any of these housing-related benefits?,"Does the tenant receive housing-related benefits? Yes if hb = Universal Credit housing element or Housing benefit, No if hb = Don't Know, Neither, Tenant prefers not to say or blank","How much of the household's income is from Universal Credit, state pensions or benefits?",Does the household pay rent or other charges for the accommodation?,Does the household pay rent or other charges for the accommodation? - flag for when household_charge is answered no,How often does the household pay rent and other charges?,What is the basic rent?,What is the service charge?,What is the personal service charge?,What is the support charge?,Total charge to the tenant,"After the household has received any housing-related benefits, will they still need to pay for rent and charges?",Estimated outstanding amount,What scheme does this letting belong to?,"From scheme code, we map to the scheme name",Does the scheme contain confidential information?,"What is this type of scheme? (Direct access hostel), Foyer, Housing for older people or Other supported housing",Is this scheme registered under the Care Standards Act 2000?,Which organisation owns the housing stock for this scheme?,What client group is this scheme intended for?,Does this scheme provide for another client group?,What is the other client group?,What support does this scheme provide?,Intended length of stay,Date scheme was created,Which location is this letting for?,What is the postcode for this location?,What is the name of this location?,How many units are at this location?,What is the most common type of unit at this location?,What are the mobility standards for the majority of the units in this location?,What is the local authority of this postcode?,When did the first property in this location become available under this scheme? id,status,duplicate_set_id,assigned_to,is_dpo,created_at,updated_by,updated_at,creation_method,collection_start_year,bulk_upload_id,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,declaration,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,uprn_known,uprn,address_line1,address_line2,town_or_city,county,postcode_full,la_label,unittype_gn,wchair,beds,voiddate,vacdays,majorrepairs,mrcdate,sheltered,joint,startertenancy,tenancy,tenancyother,tenancylength,hhmemb,refused,age1,sex1,ethnic_group,ethnic,nationality_all,ecstat1,relat2,age2,sex2,ecstat2,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,relat7,age7,sex7,ecstat7,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,prevten,homeless,ppcodenk,ppostcode_full,prevloc_label,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,accessible_register,letting_allocation_none,referral_type,referral,incref,incfreq,earnings,hb,has_benefits,benefits,household_charge,nocharge,period,brent,scharge,pscharge,supcharg,tcharge,hbrentshortfall,tshortfall,scheme_code,scheme_service_name,scheme_confidential,SCHTYPE,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_local_authority,location_startdate -,in_progress,,choreographer@owtluk.com,false,2025-04-01T00:00:00+01:00,,2025-04-01T00:00:00+01:00,1,2025,,MHCLG,MHCLG,1,7,0,2025-04-01,2,2,,,2,HIJKLMN,ABCDEFG,1,0,2,6,2,0,,Address line 1,,London,,NW9 5LL,Barnet,7,1,3,2025-03-30,1,1,2025-03-31,,3,1,4,,2,4,1,35,F,0,2,36,0,P,32,M,6,R,-9,R,10,R,-9,R,10,,,,,,,,,,,,,,,,,1,4,1,2,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,2,7,4,,6,1,0,TN23 6LZ,Ashford,1,0,1,0,0,0,0,0,1,0,0,,,0,1,268,6,1,1,,,2,200.0,50.0,40.0,35.0,325.0,1,12.0,,,,,,,,,,,,,,,,,,,, +,in_progress,,choreographer@owtluk.com,false,2026-04-01T00:00:00+01:00,,2026-04-01T00:00:00+01:00,1,2026,,MHCLG,MHCLG,1,7,0,2026-04-01,2,2,,,2,HIJKLMN,ABCDEFG,1,0,2,6,2,0,,Address line 1,,London,,NW9 5LL,Barnet,7,1,3,2026-03-30,1,1,2026-03-31,,3,1,4,,2,4,1,35,F,0,2,36,0,P,32,M,6,R,-9,R,10,R,-9,R,10,,,,,,,,,,,,,,,,,1,4,1,2,1,0,1,0,0,0,0,0,0,1,0,0,1,0,0,0,0,0,0,0,2,7,4,,6,1,0,TN23 6LZ,Ashford,1,0,1,0,0,0,0,0,1,0,0,,,0,1,268,6,1,1,,,2,200.0,50.0,40.0,35.0,325.0,1,12.0,,,,,,,,,,,,,,,,,,,, diff --git a/spec/fixtures/files/lettings_log_csv_export_non_support_labels_26.csv b/spec/fixtures/files/lettings_log_csv_export_non_support_labels_26.csv index 20cbc0ec4..afcb9dac0 100644 --- a/spec/fixtures/files/lettings_log_csv_export_non_support_labels_26.csv +++ b/spec/fixtures/files/lettings_log_csv_export_non_support_labels_26.csv @@ -1,3 +1,3 @@ Log ID,Status of log,ID of a set of duplicate logs,User the log is assigned to,Is the user in the assigned_to column the data protection officer?,Time and date the log was created,User who last updated the log,Time and date the log was last updated,Was the log submitted in-service or via bulk upload?,Year collection period opened,ID of a set of bulk uploaded logs,Which organisation owns this property?,Which organisation manages this letting?,What is the needs type?,What is the letting type?,Is this letting a renewal?,What is the tenancy start date?,"What is the rent type? (grouped into SR, IR or AR)",What is the rent type?,Which type of Intermediate Rent is this letting?,Which 'Other' type of Intermediate Rent is this letting?,Is this a London Affordable Rent letting?,What is the tenant code?,What is the property reference?,Has the tenant seen the MHCLG privacy notice?,Is this the first time the property has been let as social housing?,What rent product was the property most recently let as?,What is the reason for the property being vacant?,Is this property new to the social rented sector?,Is the UPRN known?,"If known, property's UPRN",Address line 1,Address line 2,Town or City,County,Postcode,What is the property's local authority?,What type of unit is the property?,Is the property built or adapted to wheelchair-user standards?,How many bedrooms does the property have?,What is the void date?,Number of days the property was vacant,Were any major repairs carried out during the void period?,What date were any major repairs completed on?,Is this letting in sheltered accommodation?,Is this a joint tenancy?,Is this a starter tenancy?,What is the type of tenancy?,"If 'Other', what is the type of tenancy?",What is the length of the fixed-term tenancy to the nearest year?,How many people live in the household at this letting?,"Where household characteristics have a 'Refused' option for some or all of: AGE1-AGE8, SEX1-SEX8, RELAT2-RELAT8, ECSTAT1-ECSTAT8",What is the lead tenant's age?,Which of these best describes the lead tenant's gender identity?,What is the lead tenant's ethnic group?,Which of these best describes the lead tenant's ethnic background?,What is the lead tenant's nationality?,Which of these best describes the lead tenant's working situation?,What is person 2's relationship to the lead tenant?,What is person 2's age?,Which of these best describes person 2's gender identity?,Which of these best describes person 2's working situation?,What is person 3's relationship to the lead tenant?,What is person 3's age?,Which of these best describes person 3's gender identity?,Which of these best describes person 3's working situation?,What is person 4's relationship to the lead tenant?,What is person 4's age?,Which of these best describes person 4's gender identity?,Which of these best describes person 4's working situation?,What is person 5's relationship to the lead tenant?,What is person 5's age?,Which of these best describes person 5's gender identity?,Which of these best describes person 5's working situation?,What is person 6's relationship to the lead tenant?,What is person 6's age?,Which of these best describes person 6's gender identity?,Which of these best describes person 6's working situation?,What is person 7's relationship to the lead tenant?,What is person 7's age?,Which of these best describes person 7's gender identity?,Which of these best describes person 7's working situation?,What is person 8's relationship to the lead tenant?,What is person 8's age?,Which of these best describes person 8's gender identity?,Which of these best describes person 8's working situation?,Does anybody in the household have links to the UK armed forces?,Is this person still serving in the UK armed forces?,Was this person seriously injured or ill as a result of serving in the UK armed forces?,Is anybody in the household pregnant?,Does anybody in the household have any disabled access needs?,"What access needs do they have? (Fully wheelchair-accessible housing, Level access housing or Wheelchair access to essential rooms)",Disabled access needs a) Fully wheelchair-accessible housing,Disabled access needs b) Wheelchair access to essential rooms,Disabled access needs c) Level access housing,Disabled access needs f) Other disabled access needs,Disabled access needs g) No disabled access needs,Disabled access needs h) Don't know,Do they have any other disabled access needs?,Does anybody in the household have a physical or mental health condition (or other illness) expected to last 12 months or more?,Does this person's condition affect their dexterity?,Does this person's condition affect their learning or understanding or concentrating?,Does this person's condition affect their hearing?,Does this person's condition affect their memory?,Does this person's condition affect their mental health?,Does this person's condition affect their mobility?,Does this person's condition affect them socially or behaviourally?,Does this person's condition affect their stamina or breathing or fatigue?,Does this person's condition affect their vision?,Does this person's condition affect them in another way?,How long has the household continuously lived in the local authority area of the new letting?,How long has the household been on the local authority waiting list for the new letting?,What is the tenant's main reason for the household leaving their last settled home?,"If 'Other', what was the main reason for leaving their last settled home?",Where was the household immediately before this letting?,Did the household experience homelessness immediately before this letting?,Previous postcode unknown or previous accommodation was temporary,What is the postcode of the household's last settled home?,Previous location LA name,Was the household given reasonable preference by the local authority?,Reasonable preference reason - They were homeless or about to lose their home (within 56 days),"Reasonable preference reason - They were living in insanitary, overcrowded or unisatisfactory housing",Reasonable preference reason - They needed to move on medical and welfare reasons (including disability),Reasonable preference reason - They needed to move to avoid hardship to themselves or others,Reasonable preference reason - Don't Know,Was the letting made under Choice-Based Lettings (CBL)?,Was the letting made under the Common Allocation Policy (CAP)?,Was the letting made under the Common Housing Register (CHR)?,Was the letting made under the Accessible Register?,"The letting was not allocated under CBL, CAP, CHR or Accessible Register.",,What was the source of referral for this letting?,Was the household income refused?,How often does the household receive income?,How much income does the household have in total?,Is the tenant likely to be receiving any of these housing-related benefits?,"Does the tenant receive housing-related benefits? Yes if hb = Universal Credit housing element or Housing benefit, No if hb = Don't Know, Neither, Tenant prefers not to say or blank","How much of the household's income is from Universal Credit, state pensions or benefits?",Does the household pay rent or other charges for the accommodation?,Does the household pay rent or other charges for the accommodation? - flag for when household_charge is answered no,How often does the household pay rent and other charges?,What is the basic rent?,What is the service charge?,What is the personal service charge?,What is the support charge?,Total charge to the tenant,"After the household has received any housing-related benefits, will they still need to pay for rent and charges?",Estimated outstanding amount,What scheme does this letting belong to?,"From scheme code, we map to the scheme name",Does the scheme contain confidential information?,"What is this type of scheme? (Direct access hostel), Foyer, Housing for older people or Other supported housing",Is this scheme registered under the Care Standards Act 2000?,Which organisation owns the housing stock for this scheme?,What client group is this scheme intended for?,Does this scheme provide for another client group?,What is the other client group?,What support does this scheme provide?,Intended length of stay,Date scheme was created,Which location is this letting for?,What is the postcode for this location?,What is the name of this location?,How many units are at this location?,What is the most common type of unit at this location?,What are the mobility standards for the majority of the units in this location?,What is the local authority of this postcode?,When did the first property in this location become available under this scheme? id,status,duplicate_set_id,assigned_to,is_dpo,created_at,updated_by,updated_at,creation_method,collection_start_year,bulk_upload_id,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,declaration,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,uprn_known,uprn,address_line1,address_line2,town_or_city,county,postcode_full,la_label,unittype_gn,wchair,beds,voiddate,vacdays,majorrepairs,mrcdate,sheltered,joint,startertenancy,tenancy,tenancyother,tenancylength,hhmemb,refused,age1,sex1,ethnic_group,ethnic,nationality_all,ecstat1,relat2,age2,sex2,ecstat2,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,relat7,age7,sex7,ecstat7,relat8,age8,sex8,ecstat8,armedforces,leftreg,reservist,preg_occ,housingneeds,housingneeds_type,housingneeds_a,housingneeds_b,housingneeds_c,housingneeds_f,housingneeds_g,housingneeds_h,housingneeds_other,illness,illness_type_4,illness_type_5,illness_type_2,illness_type_6,illness_type_7,illness_type_3,illness_type_9,illness_type_8,illness_type_1,illness_type_10,layear,waityear,reason,reasonother,prevten,homeless,ppcodenk,ppostcode_full,prevloc_label,reasonpref,rp_homeless,rp_insan_unsat,rp_medwel,rp_hardship,rp_dontknow,cbl,cap,chr,accessible_register,letting_allocation_none,referral_type,referral,incref,incfreq,earnings,hb,has_benefits,benefits,household_charge,nocharge,period,brent,scharge,pscharge,supcharg,tcharge,hbrentshortfall,tshortfall,scheme_code,scheme_service_name,scheme_confidential,SCHTYPE,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,location_code,location_postcode,location_name,location_units,location_type_of_unit,location_mobility_type,location_local_authority,location_startdate -,in_progress,,choreographer@owtluk.com,false,2025-04-01T00:00:00+01:00,,2025-04-01T00:00:00+01:00,single log,2025,,MHCLG,MHCLG,General needs,Affordable rent general needs local authority,No,2025-04-01,Affordable Rent,Affordable Rent,,,No,HIJKLMN,ABCDEFG,Yes,No,Affordable rent basis,Tenant abandoned property,No,No,,Address line 1,,London,,NW9 5LL,Barnet,House,Yes,3,2025-03-30,1,Yes,2025-03-31,,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,4,Yes,35,Female,White,Irish,Australia,Other,Yes,32,Male,Not seeking work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Tenant prefers not to say,Not known,Person prefers not to say,Person prefers not to say,,,,,,,,,,,,,,,,,Yes – the person is a current or former regular,No – they left up to and including 5 years ago,Yes,No,Yes,Fully wheelchair accessible housing,Yes,No,No,No,No,No,No,Yes,No,No,Yes,No,No,No,No,No,No,No,Less than 1 year,1 year but under 2 years,Loss of tied accommodation,,Other supported housing,No,Yes,TN23 6LZ,Ashford,Yes,,Yes,,,,No,No,Yes,No,No,,,No,Weekly,268,Universal Credit housing element,Yes,All,,,Every 2 weeks,200.0,50.0,40.0,35.0,325.0,Yes,12.0,,,,,,,,,,,,,,,,,,,, +,in_progress,,choreographer@owtluk.com,false,2026-04-01T00:00:00+01:00,,2026-04-01T00:00:00+01:00,single log,2026,,MHCLG,MHCLG,General needs,Affordable rent general needs local authority,No,2026-04-01,Affordable Rent,Affordable Rent,,,No,HIJKLMN,ABCDEFG,Yes,No,Affordable rent basis,Tenant abandoned property,No,No,,Address line 1,,London,,NW9 5LL,Barnet,House,Yes,3,2026-03-30,1,Yes,2026-03-31,,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,4,Yes,35,Female,White,Irish,Australia,Other,Yes,32,Male,Not seeking work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Tenant prefers not to say,Not known,Person prefers not to say,Person prefers not to say,,,,,,,,,,,,,,,,,Yes – the person is a current or former regular,No – they left up to and including 5 years ago,Yes,No,Yes,Fully wheelchair accessible housing,Yes,No,No,No,No,No,No,Yes,No,No,Yes,No,No,No,No,No,No,No,Less than 1 year,1 year but under 2 years,Loss of tied accommodation,,Other supported housing,No,Yes,TN23 6LZ,Ashford,Yes,,Yes,,,,No,No,Yes,No,No,,,No,Weekly,268,Universal Credit housing element,Yes,All,,,Every 2 weeks,200.0,50.0,40.0,35.0,325.0,Yes,12.0,,,,,,,,,,,,,,,,,,,, diff --git a/spec/services/csv/lettings_log_csv_service_spec.rb b/spec/services/csv/lettings_log_csv_service_spec.rb index a46fe6fc1..1579fb499 100644 --- a/spec/services/csv/lettings_log_csv_service_spec.rb +++ b/spec/services/csv/lettings_log_csv_service_spec.rb @@ -231,9 +231,9 @@ RSpec.describe Csv::LettingsLogCsvService do unittype_gn: 7, wchair: 1, beds: 3, - voiddate: Time.zone.local(2025, 3, 30), + voiddate: Time.zone.local(2026, 3, 30), majorrepairs: 1, - mrcdate: Time.zone.local(2025, 3, 31), + mrcdate: Time.zone.local(2026, 3, 31), joint: 3, startertenancy: 1, tenancy: 4, @@ -424,9 +424,9 @@ RSpec.describe Csv::LettingsLogCsvService do builtype: 1, wchair: 1, beds: 3, - voiddate: Time.zone.local(2026, 3, 30), + voiddate: Time.zone.local(2025, 3, 30), majorrepairs: 1, - mrcdate: Time.zone.local(2026, 3, 31), + mrcdate: Time.zone.local(2025, 3, 31), joint: 3, startertenancy: 1, tenancy: 4, From 0fdcd85d31bc240a36eb1bca1d78a35942a50890 Mon Sep 17 00:00:00 2001 From: Samuel Young Date: Tue, 13 Jan 2026 09:54:25 +0000 Subject: [PATCH 13/14] fixup! CLDC-4136: Hide question on UI flow update tests to account --- .../subsections/property_information_spec.rb | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/spec/models/form/lettings/subsections/property_information_spec.rb b/spec/models/form/lettings/subsections/property_information_spec.rb index ed0add494..568e4b028 100644 --- a/spec/models/form/lettings/subsections/property_information_spec.rb +++ b/spec/models/form/lettings/subsections/property_information_spec.rb @@ -15,22 +15,23 @@ RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model do before do allow(form).to receive(:start_year_2024_or_later?).and_return(true) - allow(form).to receive(:start_year_2025_or_later?).and_return(false) + allow(form).to receive(:start_year_2025_or_later?).and_return(true) + allow(form).to receive(:start_year_2026_or_later?).and_return(true) end - context "when 2023" do - let(:start_date) { Time.utc(2023, 2, 8) } + context "when 2024" do + let(:start_date) { Time.utc(2024, 4, 8) } before do - allow(form).to receive(:start_year_2024_or_later?).and_return(false) + allow(form).to receive(:start_year_2024_or_later?).and_return(true) allow(form).to receive(:start_year_2025_or_later?).and_return(false) + allow(form).to receive(:start_year_2026_or_later?).and_return(false) end it "has correct pages" do expect(property_information.pages.map(&:id)).to eq( %w[ - uprn - uprn_confirmation + address_search address property_local_authority local_authority_rent_value_check @@ -38,7 +39,6 @@ RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model do property_let_type property_vacancy_reason_not_first_let property_vacancy_reason_first_let - property_number_of_times_relet property_unit_type property_building_type property_wheelchair_accessible @@ -51,27 +51,36 @@ RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model do ], ) end + + context "when it is supported housing and a renewal" do + let(:log) { FactoryBot.build(:lettings_log, needstype: 2, renewal: 1) } + + it "is not displayed in tasklist" do + expect(property_information.displayed_in_tasklist?(log)).to eq(false) + end + end end - context "when 2024" do - let(:start_date) { Time.utc(2024, 2, 8) } + context "when 2025" do + let(:start_date) { Time.utc(2025, 4, 8) } before do allow(form).to receive(:start_year_2024_or_later?).and_return(true) - allow(form).to receive(:start_year_2025_or_later?).and_return(false) + allow(form).to receive(:start_year_2025_or_later?).and_return(true) + allow(form).to receive(:start_year_2026_or_later?).and_return(false) end it "has correct pages" do expect(property_information.pages.map(&:id)).to eq( %w[ - address_search - address - property_local_authority - local_authority_rent_value_check first_time_property_let_as_social_housing property_let_type property_vacancy_reason_not_first_let property_vacancy_reason_first_let + address_search + address + property_local_authority + local_authority_rent_value_check property_unit_type property_building_type property_wheelchair_accessible @@ -81,6 +90,7 @@ RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model do void_date_value_check property_major_repairs property_major_repairs_value_check + sheltered_accommodation ], ) end @@ -88,23 +98,24 @@ RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model do context "when it is supported housing and a renewal" do let(:log) { FactoryBot.build(:lettings_log, needstype: 2, renewal: 1) } - it "is not displayed in tasklist" do - expect(property_information.displayed_in_tasklist?(log)).to eq(false) + it "is displayed in tasklist" do + expect(property_information.displayed_in_tasklist?(log)).to eq(true) end end end - context "when 2025" do - let(:start_date) { Time.utc(2025, 2, 8) } + context "when 2026" do + let(:start_date) { Time.utc(2026, 4, 8) } before do allow(form).to receive(:start_year_2024_or_later?).and_return(true) allow(form).to receive(:start_year_2025_or_later?).and_return(true) + allow(form).to receive(:start_year_2026_or_later?).and_return(true) end it "has correct pages" do expect(property_information.pages.map(&:id)).to eq( - %w[ + %w[ first_time_property_let_as_social_housing property_let_type property_vacancy_reason_not_first_let @@ -114,7 +125,6 @@ RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model do property_local_authority local_authority_rent_value_check property_unit_type - property_building_type property_wheelchair_accessible property_number_of_bedrooms beds_rent_value_check @@ -124,15 +134,7 @@ RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model do property_major_repairs_value_check sheltered_accommodation ], - ) - end - - context "when it is supported housing and a renewal" do - let(:log) { FactoryBot.build(:lettings_log, needstype: 2, renewal: 1) } - - it "is displayed in tasklist" do - expect(property_information.displayed_in_tasklist?(log)).to eq(true) - end + ) end end end From a4ec6d951bdb9dd27e338bffec06588679ae9ab2 Mon Sep 17 00:00:00 2001 From: Samuel Young Date: Tue, 13 Jan 2026 15:20:09 +0000 Subject: [PATCH 14/14] fixup! CLDC-4136: Hide question on UI flow lint test --- .../form/lettings/subsections/property_information_spec.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/spec/models/form/lettings/subsections/property_information_spec.rb b/spec/models/form/lettings/subsections/property_information_spec.rb index 568e4b028..245106036 100644 --- a/spec/models/form/lettings/subsections/property_information_spec.rb +++ b/spec/models/form/lettings/subsections/property_information_spec.rb @@ -115,7 +115,7 @@ RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model do it "has correct pages" do expect(property_information.pages.map(&:id)).to eq( - %w[ + %w[ first_time_property_let_as_social_housing property_let_type property_vacancy_reason_not_first_let @@ -134,7 +134,7 @@ RSpec.describe Form::Lettings::Subsections::PropertyInformation, type: :model do property_major_repairs_value_check sheltered_accommodation ], - ) + ) end end end