From 8d7d12116f91cd36fd4d95e33a49017da4e246c0 Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Thu, 9 Apr 2026 09:44:10 +0100
Subject: [PATCH 01/34] CLDC-4304: Update person known page copy for 2026
(#3278)
to account for this question now being total person count
---
app/views/form/headers/_person_2_known_page.erb | 6 +++++-
app/views/form/headers/_person_3_known_page.erb | 6 +++++-
app/views/form/headers/_person_4_known_page.erb | 6 +++++-
app/views/form/headers/_person_5_known_page.erb | 6 +++++-
app/views/form/headers/_person_6_known_page.erb | 6 +++++-
5 files changed, 25 insertions(+), 5 deletions(-)
diff --git a/app/views/form/headers/_person_2_known_page.erb b/app/views/form/headers/_person_2_known_page.erb
index b179fcdb8..734a5383f 100644
--- a/app/views/form/headers/_person_2_known_page.erb
+++ b/app/views/form/headers/_person_2_known_page.erb
@@ -1 +1,5 @@
-You have given us the details for 0 of the <%= log.hholdcount %> other people in the household
+<% if log.form.start_year_2026_or_later? %>
+ You have given us the details for 1 of the <%= log.hholdcount %> people in the household
+<% else %>
+ You have given us the details for 0 of the <%= log.hholdcount %> other people in the household
+<% end %>
diff --git a/app/views/form/headers/_person_3_known_page.erb b/app/views/form/headers/_person_3_known_page.erb
index 678db7c27..3efe7f926 100644
--- a/app/views/form/headers/_person_3_known_page.erb
+++ b/app/views/form/headers/_person_3_known_page.erb
@@ -1 +1,5 @@
-You have given us the details for <%= log.joint_purchase? ? 0 : 1 %> of the <%= log.hholdcount %> other people in the household
+<% if log.form.start_year_2026_or_later? %>
+ You have given us the details for 2 of the <%= log.hholdcount %> people in the household
+<% else %>
+ You have given us the details for <%= log.joint_purchase? ? 0 : 1 %> of the <%= log.hholdcount %> other people in the household
+<% end %>
diff --git a/app/views/form/headers/_person_4_known_page.erb b/app/views/form/headers/_person_4_known_page.erb
index 5b82c4776..1ef9ba254 100644
--- a/app/views/form/headers/_person_4_known_page.erb
+++ b/app/views/form/headers/_person_4_known_page.erb
@@ -1 +1,5 @@
-You have given us the details for <%= log.joint_purchase? ? 1 : 2 %> of the <%= log.hholdcount %> other people in the household
+<% if log.form.start_year_2026_or_later? %>
+ You have given us the details for 3 of the <%= log.hholdcount %> people in the household
+<% else %>
+ You have given us the details for <%= log.joint_purchase? ? 1 : 2 %> of the <%= log.hholdcount %> other people in the household
+<% end %>
diff --git a/app/views/form/headers/_person_5_known_page.erb b/app/views/form/headers/_person_5_known_page.erb
index 5d53e86be..52e05ea27 100644
--- a/app/views/form/headers/_person_5_known_page.erb
+++ b/app/views/form/headers/_person_5_known_page.erb
@@ -1 +1,5 @@
-You have given us the details for <%= log.joint_purchase? ? 2 : 3 %> of the <%= log.hholdcount %> other people in the household
+<% if log.form.start_year_2026_or_later? %>
+ You have given us the details for 4 of the <%= log.hholdcount %> people in the household
+<% else %>
+ You have given us the details for <%= log.joint_purchase? ? 2 : 3 %> of the <%= log.hholdcount %> other people in the household
+<% end %>
diff --git a/app/views/form/headers/_person_6_known_page.erb b/app/views/form/headers/_person_6_known_page.erb
index 96cc94fd3..c07727f3d 100644
--- a/app/views/form/headers/_person_6_known_page.erb
+++ b/app/views/form/headers/_person_6_known_page.erb
@@ -1 +1,5 @@
-You have given us the details for <%= log.joint_purchase? ? 3 : 4 %> of the <%= log.hholdcount %> other people in the household
+<% if log.form.start_year_2026_or_later? %>
+ You have given us the details for 5 of the <%= log.hholdcount %> people in the household
+<% else %>
+ You have given us the details for <%= log.joint_purchase? ? 3 : 4 %> of the <%= log.hholdcount %> other people in the household
+<% end %>
From b8915c499f8f73db47442e9015fbbe8a5279f5cf Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Thu, 9 Apr 2026 09:44:49 +0100
Subject: [PATCH 02/34] CLDC-4356: Add hyphen to builtype Purpose-built (#3284)
* CLDC-4356: Add hyphen to builtype Purpose-built in lettings
* CLDC-4356: Add hyphen to building type Purpose-built in sales
* CLDC-4356: Update CSV export tests
* CLDC-4356: Update model tests
---
app/models/form/lettings/questions/builtype.rb | 2 +-
app/models/form/sales/questions/property_building_type.rb | 2 +-
spec/fixtures/files/lettings_log_csv_export_labels_23.csv | 2 +-
spec/fixtures/files/lettings_log_csv_export_labels_24.csv | 2 +-
spec/fixtures/files/lettings_log_csv_export_labels_25.csv | 2 +-
.../files/lettings_log_csv_export_non_support_labels_23.csv | 2 +-
.../files/lettings_log_csv_export_non_support_labels_24.csv | 2 +-
.../files/lettings_log_csv_export_non_support_labels_25.csv | 2 +-
spec/fixtures/files/sales_logs_csv_export_labels_24.csv | 2 +-
spec/fixtures/files/sales_logs_csv_export_labels_25.csv | 2 +-
spec/fixtures/files/sales_logs_csv_export_labels_26.csv | 2 +-
.../files/sales_logs_csv_export_non_support_labels_24.csv | 2 +-
.../files/sales_logs_csv_export_non_support_labels_25.csv | 2 +-
.../files/sales_logs_csv_export_non_support_labels_26.csv | 2 +-
spec/models/form/sales/questions/property_building_type_spec.rb | 2 +-
15 files changed, 15 insertions(+), 15 deletions(-)
diff --git a/app/models/form/lettings/questions/builtype.rb b/app/models/form/lettings/questions/builtype.rb
index 55f76536c..205970cec 100644
--- a/app/models/form/lettings/questions/builtype.rb
+++ b/app/models/form/lettings/questions/builtype.rb
@@ -9,7 +9,7 @@ class Form::Lettings::Questions::Builtype < ::Form::Question
ANSWER_OPTIONS = {
"2" => { "value" => "Converted from previous residential or non-residential property" },
- "1" => { "value" => "Purpose built" },
+ "1" => { "value" => "Purpose-built" },
}.freeze
QUESTION_NUMBER_FROM_YEAR = { 2023 => 20, 2024 => 20, 2025 => 20 }.freeze
diff --git a/app/models/form/sales/questions/property_building_type.rb b/app/models/form/sales/questions/property_building_type.rb
index a1bc3a7d8..25e07bfa7 100644
--- a/app/models/form/sales/questions/property_building_type.rb
+++ b/app/models/form/sales/questions/property_building_type.rb
@@ -9,7 +9,7 @@ class Form::Sales::Questions::PropertyBuildingType < ::Form::Question
end
ANSWER_OPTIONS = {
- "1" => { "value" => "Purpose built" },
+ "1" => { "value" => "Purpose-built" },
"2" => { "value" => "Converted from previous residential or non-residential property" },
}.freeze
diff --git a/spec/fixtures/files/lettings_log_csv_export_labels_23.csv b/spec/fixtures/files/lettings_log_csv_export_labels_23.csv
index 62dc32c91..40247f067 100644
--- a/spec/fixtures/files/lettings_log_csv_export_labels_23.csv
+++ b/spec/fixtures/files/lettings_log_csv_export_labels_23.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?,The (internal) ID on the old service,The ID the users saw on the old service,Year collection period opened,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?,Is the UPRN known?,"If known, property's UPRN",We found an address that might be this property. Is this the property address?,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 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?,How many times was the property offered between becoming vacant and this letting?,What type of unit is the property?,Which type of building 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 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?,Is this letting in sheltered accommodation?,Has the tenant seen the MHCLG privacy notice?,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?,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?",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)?,"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?,Is this accommodation a care home?,"If this is a care home, how much does the household pay every [time period]?",Weekly care home charge,Populated when the soft validation and confirmed in the service,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,old_id,old_form_id,collection_start_year,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,uprn_known,uprn,uprn_confirmed,address_line1,address_line2,town_or_city,county,postcode_full,is_la_inferred,la_label,la,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,offered,unittype_gn,builtype,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,declaration,hhmemb,pregnancy_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sex1,ethnic_group,ethnic,national,ecstat1,details_known_2,relat2,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,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,letting_allocation_none,referral,referral_value_check,net_income_known,incref,incfreq,earnings,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,is_carehome,chcharge,wchchrg,carehome_charges_value_check,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
-,completed,,s.port@jeemayle.com,s.port@jeemayle.com,false,2023-11-26T00:00:00+00:00,,2023-11-26T00:00:00+00:00,single log,,,2023,MHCLG,MHCLG,General needs,Affordable rent general needs local authority,No,2023-11-26,Affordable Rent,Affordable Rent,,,No,HIJKLMN,ABCDEFG,No,,,Address line 1,,London,,NW9 5LL,No,Barnet,E09000003,No,Affordable rent basis,Tenant abandoned property,No,2,House,Purpose built,Yes,3,2023-11-24,1,,Yes,2023-11-25,,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,,Yes,4,,Yes,4,0,0,2,35,,Female,White,Irish,Tenant prefers not to say,Other,Yes,Partner,32,Male,Not seeking work,No,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Yes,Person 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,Tenant applied directly (no referral or nomination),,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,,,,,,,,,,,,,,,,,,,,
+,completed,,s.port@jeemayle.com,s.port@jeemayle.com,false,2023-11-26T00:00:00+00:00,,2023-11-26T00:00:00+00:00,single log,,,2023,MHCLG,MHCLG,General needs,Affordable rent general needs local authority,No,2023-11-26,Affordable Rent,Affordable Rent,,,No,HIJKLMN,ABCDEFG,No,,,Address line 1,,London,,NW9 5LL,No,Barnet,E09000003,No,Affordable rent basis,Tenant abandoned property,No,2,House,Purpose-built,Yes,3,2023-11-24,1,,Yes,2023-11-25,,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,,Yes,4,,Yes,4,0,0,2,35,,Female,White,Irish,Tenant prefers not to say,Other,Yes,Partner,32,Male,Not seeking work,No,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Yes,Person 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,Tenant applied directly (no referral or nomination),,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_labels_24.csv b/spec/fixtures/files/lettings_log_csv_export_labels_24.csv
index 8a538b0d8..0291915d3 100644
--- a/spec/fixtures/files/lettings_log_csv_export_labels_24.csv
+++ b/spec/fixtures/files/lettings_log_csv_export_labels_24.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?,"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,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?,What type of unit is the property?,Which type of building 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 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?,Is this letting in sheltered accommodation?,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?,Is this accommodation a care home?,"If this is a care home, how much does the household pay every [time period]?",Weekly care home charge,Populated when the soft validation and confirmed in the service,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,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,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,unittype_gn,builtype,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,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,referral_value_check,net_income_known,incref,incfreq,earnings,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,is_carehome,chcharge,wchchrg,carehome_charges_value_check,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,2024-04-01T00:00:00+01:00,,2024-04-01T00:00:00+01:00,single log,2024,,MHCLG,MHCLG,General needs,Affordable rent general needs local authority,No,2024-04-01,Affordable Rent,Affordable Rent,,,No,HIJKLMN,ABCDEFG,Yes,,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,No,Affordable rent basis,Tenant abandoned property,No,House,Purpose built,Yes,3,2024-03-30,1,,Yes,2024-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,Partner,,,32,Male,Not seeking work,No,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Yes,Person 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,Tenant applied directly (no referral or nomination),,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,2024-04-01T00:00:00+01:00,,2024-04-01T00:00:00+01:00,single log,2024,,MHCLG,MHCLG,General needs,Affordable rent general needs local authority,No,2024-04-01,Affordable Rent,Affordable Rent,,,No,HIJKLMN,ABCDEFG,Yes,,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,No,Affordable rent basis,Tenant abandoned property,No,House,Purpose-built,Yes,3,2024-03-30,1,,Yes,2024-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,Partner,,,32,Male,Not seeking work,No,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Yes,Person 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,Tenant applied directly (no referral or nomination),,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_labels_25.csv b/spec/fixtures/files/lettings_log_csv_export_labels_25.csv
index 92ed08f82..d06f25efe 100644
--- a/spec/fixtures/files/lettings_log_csv_export_labels_25.csv
+++ b/spec/fixtures/files/lettings_log_csv_export_labels_25.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?,Which type of building 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,builtype,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,Purpose built,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,Under 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,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,Purpose-built,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,Under 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_labels_23.csv b/spec/fixtures/files/lettings_log_csv_export_non_support_labels_23.csv
index 296073a12..7280ac2ce 100644
--- a/spec/fixtures/files/lettings_log_csv_export_non_support_labels_23.csv
+++ b/spec/fixtures/files/lettings_log_csv_export_non_support_labels_23.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,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?,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?,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?,How many times was the property offered between becoming vacant and this letting?,What type of unit is the property?,Which type of building 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 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?,Is this letting in sheltered accommodation?,Has the tenant seen the MHCLG privacy notice?,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)?,"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?,Is this accommodation a care home?,"If this is a care home, how much does the household pay every [time period]?",Weekly care home charge,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,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,uprn_known,uprn,address_line1,address_line2,town_or_city,county,postcode_full,la_label,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,offered,unittype_gn,builtype,wchair,beds,voiddate,vacdays,majorrepairs,mrcdate,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,declaration,hhmemb,refused,age1,sex1,ethnic_group,ethnic,national,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,letting_allocation_none,referral,incref,incfreq,earnings,hb,has_benefits,benefits,household_charge,nocharge,period,is_carehome,chcharge,wchchrg,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
-,completed,,choreographer@owtluk.com,false,2023-11-26T00:00:00+00:00,,2023-11-26T00:00:00+00:00,single log,2023,MHCLG,MHCLG,General needs,Affordable rent general needs local authority,No,2023-11-26,Affordable Rent,Affordable Rent,,,No,HIJKLMN,ABCDEFG,No,,Address line 1,,London,,NW9 5LL,Barnet,No,Affordable rent basis,Tenant abandoned property,No,2,House,Purpose built,Yes,3,2023-11-24,1,Yes,2023-11-25,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,,Yes,4,Yes,35,Female,White,Irish,Tenant prefers not to say,Other,Partner,32,Male,Not seeking work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Person 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,Tenant applied directly (no referral or nomination),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,,,,,,,,,,,,,,,,,,,,
+,completed,,choreographer@owtluk.com,false,2023-11-26T00:00:00+00:00,,2023-11-26T00:00:00+00:00,single log,2023,MHCLG,MHCLG,General needs,Affordable rent general needs local authority,No,2023-11-26,Affordable Rent,Affordable Rent,,,No,HIJKLMN,ABCDEFG,No,,Address line 1,,London,,NW9 5LL,Barnet,No,Affordable rent basis,Tenant abandoned property,No,2,House,Purpose-built,Yes,3,2023-11-24,1,Yes,2023-11-25,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,,Yes,4,Yes,35,Female,White,Irish,Tenant prefers not to say,Other,Partner,32,Male,Not seeking work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Person 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,Tenant applied directly (no referral or nomination),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/fixtures/files/lettings_log_csv_export_non_support_labels_24.csv b/spec/fixtures/files/lettings_log_csv_export_non_support_labels_24.csv
index 4184b90c7..c4c9a17a3 100644
--- a/spec/fixtures/files/lettings_log_csv_export_non_support_labels_24.csv
+++ b/spec/fixtures/files/lettings_log_csv_export_non_support_labels_24.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 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?,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?,What type of unit is the property?,Which type of building 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 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?,Is this letting in sheltered accommodation?,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?,Is this accommodation a care home?,"If this is a care home, how much does the household pay every [time period]?",Weekly care home charge,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,uprn_known,uprn,address_line1,address_line2,town_or_city,county,postcode_full,la_label,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,unittype_gn,builtype,wchair,beds,voiddate,vacdays,majorrepairs,mrcdate,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,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,incref,incfreq,earnings,hb,has_benefits,benefits,household_charge,nocharge,period,is_carehome,chcharge,wchchrg,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,2024-04-01T00:00:00+01:00,,2024-04-01T00:00:00+01:00,single log,2024,,MHCLG,MHCLG,General needs,Affordable rent general needs local authority,No,2024-04-01,Affordable Rent,Affordable Rent,,,No,HIJKLMN,ABCDEFG,Yes,No,,Address line 1,,London,,NW9 5LL,Barnet,No,Affordable rent basis,Tenant abandoned property,No,House,Purpose built,Yes,3,2024-03-30,1,Yes,2024-03-31,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,,4,Yes,35,Female,White,Irish,Australia,Other,Partner,32,Male,Not seeking work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Person 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,Tenant applied directly (no referral or nomination),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,2024-04-01T00:00:00+01:00,,2024-04-01T00:00:00+01:00,single log,2024,,MHCLG,MHCLG,General needs,Affordable rent general needs local authority,No,2024-04-01,Affordable Rent,Affordable Rent,,,No,HIJKLMN,ABCDEFG,Yes,No,,Address line 1,,London,,NW9 5LL,Barnet,No,Affordable rent basis,Tenant abandoned property,No,House,Purpose-built,Yes,3,2024-03-30,1,Yes,2024-03-31,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,,4,Yes,35,Female,White,Irish,Australia,Other,Partner,32,Male,Not seeking work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,Person 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,Tenant applied directly (no referral or nomination),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/fixtures/files/lettings_log_csv_export_non_support_labels_25.csv b/spec/fixtures/files/lettings_log_csv_export_non_support_labels_25.csv
index 9873aa207..59a96669f 100644
--- a/spec/fixtures/files/lettings_log_csv_export_non_support_labels_25.csv
+++ b/spec/fixtures/files/lettings_log_csv_export_non_support_labels_25.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?,Which type of building 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,builtype,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,Purpose built,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,Under 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,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,Purpose-built,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,Under 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/fixtures/files/sales_logs_csv_export_labels_24.csv b/spec/fixtures/files/sales_logs_csv_export_labels_24.csv
index 7b2c0f183..c02f1313e 100644
--- a/spec/fixtures/files/sales_logs_csv_export_labels_24.csv
+++ b/spec/fixtures/files/sales_logs_csv_export_labels_24.csv
@@ -1,3 +1,3 @@
Log ID,Status of log,ID of a set of duplicate logs,Time and date the log was created,Time and date the log was last updated,Year collection period opened,Was the log submitted in-service or via bulk upload?,ID of a set of bulk uploaded logs,Is the user in the created_by column the data protection officer?,Day of sale completion date,Month of sale completion date,Year of sale completion date,Which organisation owned this property before the sale?,Which organisation reported the sale?,User that created the log,User the log is assigned to,What is the purchaser code?,Was this purchase made through an ownership scheme?,What is the type of shared ownership/discounted ownership/outright sale?,"If type = 'Other', what is the type of outright sale?",Is the buyer a company?,Will the buyer(s) live in the property?,Is this a joint purchase?,Are there more than 2 joint buyers of this property?,Did you interview the buyer to answer these questions?,Has the buyer seen the MHCLG privacy notice?,"What is the UPRN of the property?",Address line 1,Address line 2,Town/City,County,Postcode,The internal value to indicate if the LA was inferred from the postcode,LA name,LA code,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,How many bedrooms does the property have?,What type of unit is the property?,Which type of building is the property?,Is the property built or adapted to wheelchair-user standards?,What is buyer 1's age?,Which of these best describes buyer 1's gender identity?,What is buyer 1's ethnic group?,Which of the following best describes buyer 1's ethnic background?,What is buyer 1's nationality?,Which of these best describes buyer 1's working situation?,Will buyer 1 live in the property?,What is buyer 2 or person 2's relationship to buyer 1?,What is buyer 2 or person 2's age?,Which of these best describes buyer 2 or person 2's gender identity?,What is buyer 2's ethnic group?,Which of the following best describes buyer 2's ethnic background?,What is buyer 2's nationality?,What is buyer 2 or person 2's working situation?,Will buyer 2 live in the property?,"Besides the buyer(s), how many other people live or will live in the property?",What is person 3's relationship to buyer 1?,What is person 3's age?,What is person 3's gender identity?,What is person 3's working situation?,What is person 4's relationship to buyer 1?,What is person 4's age?,What is person 4's gender identity?,What is person 4's working situation?,What is person 5's relationship to buyer 1?,What is person 5's age?,What is person 5's gender identity?,What is person 5's working situation?,What is person 6's relationship to buyer 1?,What is person 6's age?,What is person 6's gender identity?,What is person 6's working situation?,What was buyer 1's previous tenure?,Do you know the postcode of buyer 1's last settled accommodation?,Part 1 of postcode of buyer 1's last settled accommodation,Part 2 of postcode of buyer 1's last settled accommodation,Do you know the local authority of buyer 1's last settled accommodation?,The local authority code of buyer 1's last settled accommodation,The local authority name of buyer 1's last settled accommodation,Was the buyer registered with their PRP (HA)?,Was the buyer registered with another PRP (HA)?,Was the buyer registered with the local authority?,Was the buyer registered with a Help to Buy agent?,"Populated if pregyrha, pregother, pregla and pregghb are blank","At the time of purchase, was buyer 2 living at the same address as buyer 1?",What was buyer 2's previous tenure?,Have any of the buyers ever served as a regular in the UK armed forces?,Is the buyer still serving in the UK armed forces?,Are any of the buyers a spouse or civil partner of a UK armed forces regular who died in service within the last 2 years?,Does anyone in the household consider themselves to have a disability?,Does anyone in the household use a wheelchair?,Is buyer 1's annual income known?,What is buyer 1's annual income?,Was buyer 1's income used for a mortgage application?,Is buyer 1's annual income known?,What is buyer 2's annual income?,Was buyer 2's income used for a mortgage application?,Were the buyers receiving any of these housing-related benefits immediately before buying this property?,Is the the total amount the buyers had in savings known?,What is the total amount the buyers had in savings before they paid any deposit for the property?,Have any of the buyers previously owned a property?,Was the previous property under shared ownership?,How long did the buyer(s) live in the property before purchasing it?,Is this a staircasing transaction?,What percentage of the property has been bought in this staircasing transaction?,What percentage of the property do the buyers now own in total?,Was this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?,Is this a resale?,Day of the exchange of contracts,Month of the exchange of contracts,Year of the exchange of contracts,Day of the practical completion or handover date,Month of the practical completion or handover date,Year of the practical completion or handover date,Was the household rehoused under a local authority nominations agreement?,"Was the buyer a private registered provider, housing association or local authority tenant immediately before this sale?",How many bedrooms did the buyer's previous property have?,What was the previous property type?,What was the rent type of buyer's previous tenure?,What is the full purchase price?,Populated if a soft validation is confirmed.,What was the initial percentage equity stake purchased?,Was a mortgage used to buy this property?,What is the mortgage amount?,What is the name of the mortgage lender?,"If mortgagelender = 'Other', what is the name of the mortgage lender?",What is the length of the mortgage in years?,Does this include any extra borrowing?,How much was the cash deposit paid on the property?,How much cash discount was given through Social Homebuy?,What is the basic monthly rent?,Does the property have any monthly leasehold charges?,What are the total monthly leasehold charges for the property?,Populated if a soft validation is confirmed.,What was the percentage discount?,"What was the amount of any loan, grant, discount or subsidy given?"
ID,STATUS,DUPLICATESET,CREATEDDATE,UPLOADDATE,COLLECTIONYEAR,CREATIONMETHOD,BULKUPLOADID,DATAPROTECT,DAY,MONTH,YEAR,OWNINGORGNAME,MANINGORGNAME,CREATEDBY,USERNAME,PURCHID,OWNERSHIP,TYPE,OTHTYPE,COMPANY,LIVEINBUYER,JOINT,JOINTMORE,NOINT,PRIVACYNOTICE,UPRN,ADDRESS1,ADDRESS2,TOWNCITY,COUNTY,POSTCODE,ISLAINFERRED,LANAME,LA,UPRNSELECTED,ADDRESS_SEARCH_VALUE_CHECK,ADDRESS1INPUT,POSTCODEINPUT,BULKADDRESS1,BULKADDRESS2,BULKTOWNCITY,BULKCOUNTY,BULKPOSTCODE,BULKLA,BEDS,PROPTYPE,BUILTYPE,WCHAIR,AGE1,SEX1,ETHNICGROUP1,ETHNIC,NATIONALITYALL1,ECSTAT1,LIVEINBUYER1,RELAT2,AGE2,SEX2,ETHNICGROUP2,ETHNIC2,NATIONALITYALL2,ECSTAT2,LIVEINBUYER2,HHTYPE,RELAT3,AGE3,SEX3,ECSTAT3,RELAT4,AGE4,SEX4,ECSTAT4,RELAT5,AGE5,SEX5,ECSTAT5,RELAT6,AGE6,SEX6,ECSTAT6,PREVTEN,PPCODENK,PPOSTC1,PPOSTC2,PREVIOUSLAKNOWN,PREVLOC,PREVLOCNAME,PREGYRHA,PREGOTHER,PREGLA,PREGGHB,PREGBLANK,BUY2LIVING,PREVTEN2,HHREGRES,HHREGRESSTILL,ARMEDFORCESSPOUSE,DISABLED,WHEEL,INC1NK,INCOME1,INC1MORT,INC2NK,INCOME2,INC2MORT,HB,SAVINGSNK,SAVINGS,PREVOWN,PREVSHARED,PROPLEN,STAIRCASE,STAIRBOUGHT,STAIROWNED,STAIRCASETOSALE,RESALE,EXDAY,EXMONTH,EXYEAR,HODAY,HOMONTH,HOYEAR,LANOMAGR,SOCTEN,FROMBEDS,FROMPROP,SOCPREVTEN,VALUE,VALUE_VALUE_CHECK,EQUITY,MORTGAGEUSED,MORTGAGE,MORTGAGELENDER,MORTGAGELENDEROTHER,MORTLEN1,EXTRABOR,DEPOSIT,CASHDIS,MRENT,HASMSCHARGE,MSCHARGE,MSCHARGE_VALUE_CHECK,DISCOUNT,GRANT
-,completed,,2024-04-01T00:00:00+01:00,2024-04-01T00:00:00+01:00,2024,single log,,false,1,4,2024,MHCLG,MHCLG,billyboy@eyeklaud.com,billyboy@eyeklaud.com,,Yes - a discounted ownership scheme,Right to Acquire (RTA),,,,Yes,Yes,Yes,1,1,"1, Test Street",,Test Town,,AA1 1AA,Yes,Westminster,E09000033,1,,,,address line 1 as entered,address line 2 as entered,town or city as entered,county as entered,AB1 2CD,la as entered,2,Flat or maisonette,Purpose built,Yes,30,Non-binary,Buyer prefers not to say,17,United Kingdom,Full-time - 30 hours or more,Yes,Partner,35,Non-binary,Buyer prefers not to say,,United Kingdom,Full-time - 30 hours or more,Yes,3,Child,14,Non-binary,Child under 16,Other,Not known,Non-binary,In government training into work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,,,,,Local authority tenant,Yes,SW1A,1AA,Yes,E09000033,Westminster,1,1,1,1,,Don’t know,,Yes,Yes,No,Yes,Yes,Yes,13400,Yes,Yes,13400,Yes,Don’t know ,No,,Yes,No,10,,,,,,,,,,,,,,,,,110000.0,,,Yes,20000.0,Cambridge Building Society,,10,Yes,80000.0,,,Yes,100.0,,,10000.0
+,completed,,2024-04-01T00:00:00+01:00,2024-04-01T00:00:00+01:00,2024,single log,,false,1,4,2024,MHCLG,MHCLG,billyboy@eyeklaud.com,billyboy@eyeklaud.com,,Yes - a discounted ownership scheme,Right to Acquire (RTA),,,,Yes,Yes,Yes,1,1,"1, Test Street",,Test Town,,AA1 1AA,Yes,Westminster,E09000033,1,,,,address line 1 as entered,address line 2 as entered,town or city as entered,county as entered,AB1 2CD,la as entered,2,Flat or maisonette,Purpose-built,Yes,30,Non-binary,Buyer prefers not to say,17,United Kingdom,Full-time - 30 hours or more,Yes,Partner,35,Non-binary,Buyer prefers not to say,,United Kingdom,Full-time - 30 hours or more,Yes,3,Child,14,Non-binary,Child under 16,Other,Not known,Non-binary,In government training into work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,,,,,Local authority tenant,Yes,SW1A,1AA,Yes,E09000033,Westminster,1,1,1,1,,Don’t know,,Yes,Yes,No,Yes,Yes,Yes,13400,Yes,Yes,13400,Yes,Don’t know ,No,,Yes,No,10,,,,,,,,,,,,,,,,,110000.0,,,Yes,20000.0,Cambridge Building Society,,10,Yes,80000.0,,,Yes,100.0,,,10000.0
diff --git a/spec/fixtures/files/sales_logs_csv_export_labels_25.csv b/spec/fixtures/files/sales_logs_csv_export_labels_25.csv
index bd43a851f..245ee6ab2 100644
--- a/spec/fixtures/files/sales_logs_csv_export_labels_25.csv
+++ b/spec/fixtures/files/sales_logs_csv_export_labels_25.csv
@@ -1,3 +1,3 @@
Log ID,Status of log,ID of a set of duplicate logs,Which organisation owned this property before the sale?,Which organisation owned this property before the sale? (ID),Which organisation reported the sale?,Which organisation reported the sale? (ID),Time and date the log was created,User that created the log (email),User that created the log (ID),User the log is assigned to (email),User the log is assigned to (ID),Time and date the log was last updated,User that last amended the log (email),User that last amended the log (ID),Was the log submitted in-service or via bulk upload?,ID of a set of bulk uploaded logs,Year collection period opened,Day of sale completion date,Month of sale completion date,Year of sale completion date,What is the purchaser code?,Shared or discounted ownership,Type of ownership,Is this a staircasing transaction?,Is this a joint purchase?,Are there more than 2 joint buyers of this property?,Did you interview the buyer to answer these questions?,Has the buyer seen the MHCLG privacy notice?,What is the UPRN of the property?,Address line 1,Address line 2,Town/City,County,Postcode,The internal value to indicate if the LA was inferred from the postcode,LA name,LA code,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?,How many bedrooms does the property have?,Which type of building is the property?,Is the property built or adapted to wheelchair-user standards?,What is buyer 1's age?,Which of these best describes buyer 1's gender identity?,What is buyer 1's ethnic group?,Which of the following best describes buyer 1's ethnic background?,What is buyer 1's nationality?,Which of these best describes buyer 1's working situation?,Will buyer 1 live in the property?,Is buyer 2 or person 2 the partner of buyer 1?,What is buyer 2 or person 2's age?,Which of these best describes buyer 2 or person 2's gender identity?,What is buyer 2's ethnic group?,Which of the following best describes buyer 2's ethnic background?,What is buyer 2's nationality?,What is buyer 2 or person 2's working situation?,Will buyer 2 live in the property?,"Besides the buyer(s), how many other people live or will live in the property?",Is person 3 the partner of buyer 1?,What is person 3's age?,What is person 3's gender identity?,What is person 3's working situation?,Is person 4 the partner of buyer 1?,What is person 4's age?,What is person 4's gender identity?,What is person 4's working situation?,Is person 5 the partner of buyer 1?,What is person 5's age?,What is person 5's gender identity?,What is person 5's working situation?,Is person 6 the partner of buyer 1?,What is person 6's age?,What is person 6's gender identity?,What is person 6's working situation?,Household type,What was buyer 1's previous tenure?,Do you know the postcode of buyer 1's last settled accommodation?,Part 1 of postcode of buyer 1's last settled accommodation,Part 2 of postcode of buyer 1's last settled accommodation,Do you know the local authority of buyer 1's last settled accommodation?,The local authority code of buyer 1's last settled accommodation,The local authority name of buyer 1's last settled accommodation,"At the time of purchase, was buyer 2 living at the same address as buyer 1?",What was buyer 2's previous tenure?,Have any of the buyers ever served as a regular in the UK armed forces?,Is the buyer still serving in the UK armed forces?,Are any of the buyers a spouse or civil partner of a UK armed forces regular who died in service within the last 2 years?,Does anyone in the household consider themselves to have a disability?,Does anyone in the household use a wheelchair?,Is buyer 1's annual income known?,What is buyer 1's annual income?,Was buyer 1's income used for a mortgage application?,Is buyer 1's annual income known?,What is buyer 2's annual income?,Was buyer 2's income used for a mortgage application?,Were the buyers receiving any of these housing-related benefits immediately before buying this property?,Is the the total amount the buyers had in savings known?,What is the total amount the buyers had in savings before they paid any deposit for the property?,Have any of the buyers previously owned a property?,Was the previous property under shared ownership?,Is this a resale?,How long did the buyer(s) live in the property before purchasing it?,Day of the practical completion or handover date,Month of the practical completion or handover date,Year of the practical completion or handover date,How many bedrooms did the buyer's previous property have?,What was the previous property type?,What was the rent type of buyer's previous tenure?,What is the full purchase price?,Populated if a soft validation is confirmed.,What was the initial percentage equity stake purchased?,Was a mortgage used to buy this property?,What is the mortgage amount?,What is the length of the mortgage in years?,How much was the cash deposit paid on the property?,How much cash discount was given through Social Homebuy?,What is the basic monthly rent?,Does the property have any service charges?,Monthly service charges amount,Does the property have an estate management fee?,Monthly estate management fee amount,What percentage of the property has been bought in this staircasing transaction?,What percentage of the property do the buyers now own in total?,Was this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?,Is this the first time the shared owner has engaged in staircasing in the home?,"Including this time, how many times has the shared owner engaged in staircasing in the home?",Day of last staircasing transaction,Month of last staircasing transaction,Year of last staircasing transaction,Day of initial staircasing transaction,Month of initial staircasing transaction,Year of initial staircasing transaction,What was the basic monthly rent prior to staircasing?,"What was the amount of any loan, grant, discount or subsidy given?",What was the percentage discount?,Does this include any extra borrowing?,Does the property have any monthly leasehold charges?,What are the total monthly leasehold charges for the property?,Populated if a soft validation is confirmed
ID,STATUS,DUPLICATESET,OWNINGORGNAME,OWNINGORGID,MANINGORGNAME,MANINGORGID,CREATEDDATE,CREATEDBY,CREATEDBYID,USERNAME,USERNAMEID,UPLOADDATE,AMENDEDBY,AMENDEDBYID,CREATIONMETHOD,BULKUPLOADID,COLLECTIONYEAR,DAY,MONTH,YEAR,PURCHID,OWNERSHIP,TYPE,STAIRCASE,JOINT,JOINTMORE,NOINT,PRIVACYNOTICE,UPRN,ADDRESS1,ADDRESS2,TOWNCITY,COUNTY,POSTCODE,ISLAINFERRED,LANAME,LA,UPRNSELECTED,ADDRESS_SEARCH_VALUE_CHECK,ADDRESS1INPUT,POSTCODEINPUT,BULKADDRESS1,BULKADDRESS2,BULKTOWNCITY,BULKCOUNTY,BULKPOSTCODE,BULKLA,PROPTYPE,BEDS,BUILTYPE,WCHAIR,AGE1,SEX1,ETHNICGROUP1,ETHNIC,NATIONALITYALL1,ECSTAT1,LIVEINBUYER1,RELAT2,AGE2,SEX2,ETHNICGROUP2,ETHNIC2,NATIONALITYALL2,ECSTAT2,LIVEINBUYER2,HHOLDCOUNT,RELAT3,AGE3,SEX3,ECSTAT3,RELAT4,AGE4,SEX4,ECSTAT4,RELAT5,AGE5,SEX5,ECSTAT5,RELAT6,AGE6,SEX6,ECSTAT6,HHTYPE,PREVTEN,PPCODENK,PPOSTC1,PPOSTC2,PREVIOUSLAKNOWN,PREVLOC,PREVLOCNAME,BUY2LIVING,PREVTEN2,HHREGRES,HHREGRESSTILL,ARMEDFORCESSPOUSE,DISABLED,WHEEL,INC1NK,INCOME1,INC1MORT,INC2NK,INCOME2,INC2MORT,HB,SAVINGSNK,SAVINGS,PREVOWN,PREVSHARED,RESALE,PROPLEN,HODAY,HOMONTH,HOYEAR,FROMBEDS,FROMPROP,SOCPREVTEN,VALUE,VALUE_VALUE_CHECK,EQUITY,MORTGAGEUSED,MORTGAGE,MORTLEN1,DEPOSIT,CASHDIS,MRENT,HASSERVICECHARGES,SERVICECHARGES,HASESTATEFEE,ESTATEFEE,STAIRBOUGHT,STAIROWNED,STAIRCASETOSALE,FIRSTSTAIR,NUMSTAIR,STAIRLASTDAY,STAIRLASTMONTH,STAIRLASTYEAR,STAIRINITIALDAY,STAIRINITIALMONTH,STAIRINITIALYEAR,MRENTPRESTAIRCASING,GRANT,DISCOUNT,EXTRABOR,HASMSCHARGE,MSCHARGE,MSCHARGE_VALUE_CHECK
-,completed,,MHCLG,,MHCLG,,2025-04-01T00:00:00+01:00,billyboy@eyeklaud.com,,billyboy@eyeklaud.com,,2025-04-01T00:00:00+01:00,,,single log,,2025,1,4,2025,,Discounted Ownership,Right to Acquire (RTA),,Yes,Yes,Yes,1,1,"1, Test Street",,Test Town,,AA1 1AA,Yes,Westminster,E09000033,1,,,,address line 1 as entered,address line 2 as entered,town or city as entered,county as entered,AB1 2CD,la as entered,Flat or maisonette,2,Purpose built,Yes,30,Non-binary,Buyer prefers not to say,17,United Kingdom,Full-time – 30 hours or more per week,Yes,Yes,35,Non-binary,Buyer prefers not to say,,United Kingdom,Full-time – 30 hours or more per week,Yes,3,No,14,Non-binary,Child under 16,No,Not known,Non-binary,In government training into work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,,,,,6,Local authority tenant,Yes,SW1A,1AA,Yes,E09000033,Westminster,Don’t know,,Yes,Yes,No,Yes,Yes,Yes,13400,Yes,Yes,13400,Yes,Don’t know ,No,,Yes,No,,10,,,,,,,110000.0,,,Yes,20000.0,10,80000.0,,,,,,,,,,,,,,,,,,,10000.0,,Yes,Yes,100.0,
+,completed,,MHCLG,,MHCLG,,2025-04-01T00:00:00+01:00,billyboy@eyeklaud.com,,billyboy@eyeklaud.com,,2025-04-01T00:00:00+01:00,,,single log,,2025,1,4,2025,,Discounted Ownership,Right to Acquire (RTA),,Yes,Yes,Yes,1,1,"1, Test Street",,Test Town,,AA1 1AA,Yes,Westminster,E09000033,1,,,,address line 1 as entered,address line 2 as entered,town or city as entered,county as entered,AB1 2CD,la as entered,Flat or maisonette,2,Purpose-built,Yes,30,Non-binary,Buyer prefers not to say,17,United Kingdom,Full-time – 30 hours or more per week,Yes,Yes,35,Non-binary,Buyer prefers not to say,,United Kingdom,Full-time – 30 hours or more per week,Yes,3,No,14,Non-binary,Child under 16,No,Not known,Non-binary,In government training into work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,,,,,6,Local authority tenant,Yes,SW1A,1AA,Yes,E09000033,Westminster,Don’t know,,Yes,Yes,No,Yes,Yes,Yes,13400,Yes,Yes,13400,Yes,Don’t know ,No,,Yes,No,,10,,,,,,,110000.0,,,Yes,20000.0,10,80000.0,,,,,,,,,,,,,,,,,,,10000.0,,Yes,Yes,100.0,
diff --git a/spec/fixtures/files/sales_logs_csv_export_labels_26.csv b/spec/fixtures/files/sales_logs_csv_export_labels_26.csv
index 2cf82726d..be98441fb 100644
--- a/spec/fixtures/files/sales_logs_csv_export_labels_26.csv
+++ b/spec/fixtures/files/sales_logs_csv_export_labels_26.csv
@@ -1,3 +1,3 @@
Log ID,Status of log,ID of a set of duplicate logs,Which organisation owned this property before the sale?,,Which organisation reported the sale?,,Time and date the log was created,User that created the log,,User the log is assigned to,,Time and date the log was last updated,,,Was the log submitted in-service or via bulk upload?,ID of a set of bulk uploaded logs,Year collection period opened,Day of sale completion date,Month of sale completion date,Year of sale completion date,What is the purchaser code?,Was this purchase made through an ownership scheme?,What is the type of shared ownership/discounted ownership/outright sale?,Is this a staircasing transaction?,Is this a joint purchase?,Are there more than 2 joint buyers of this property?,Did you interview the buyer(s) to answer these questions?,Has the buyer seen the MHCLG privacy notice?,What is the UPRN of the property?,Address line 1,Address line 2,Town/City,County,Postcode,The internal value to indicate if the LA was inferred from the postcode,LA name,LA code,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?,What is the building height classification?,How many bedrooms does the property have?,Which type of building is the property?,Is the property built or adapted to wheelchair-user standards?,What is buyer 1's age?,What was buyer 1's sex at birth?,Is the gender buyer 1 identifies with the same as their sex registered at birth?,"If 'No', enter buyer 1's gender identity",What is buyer 1's ethnic group?,Which of the following best describes buyer 1's ethnic background?,What is buyer 1's nationality?,Which of these best describes buyer 1's working situation?,Will buyer 1 live in the property?,What is buyer 2 or person 2's relationship to buyer 1?,What is buyer 2 or person 2's age?,What was buyer/person 2's sex at birth?,Is the gender buyer/person 2 identifies with the same as their sex registered at birth?,"If 'No', enter buyer/person 2's gender identity",What is buyer 2's ethnic group?,Which of the following best describes buyer 2's ethnic background?,What is buyer 2's nationality?,What is buyer 2 or person 2's working situation?,Will buyer 2 live in the property?,"In total, how many people live in the property?",What is person 3's relationship to buyer 1?,What is person 3's age?,What was person 3's sex at birth?,Is the gender person 3 identifies with the same as their sex registered at birth?,"If 'No', enter person 3's gender identity",What is person 3's working situation?,What is person 4's relationship to buyer 1?,What is person 4's age?,What was person 4's sex at birth?,Is the gender person 4 identifies with the same as their sex registered at birth?,"If 'No', enter person 4's gender identity",What is person 4's working situation?,What is person 5's relationship to buyer 1?,What is person 5's age?,What was person 5's sex at birth?,Is the gender person 5 identifies with the same as their sex registered at birth?,"If 'No', enter person 5's gender identity",What is person 5's working situation?,What is person 6's relationship to buyer 1?,What is person 6's age?,What was person 6's sex at birth?,Is the gender person 6 identifies with the same as their sex registered at birth?,"If 'No', enter person 6's gender identity",What is person 6's working situation?,Household type,What was buyer 1's previous tenure?,Do you know the postcode of buyer 1's last settled accommodation?,Part 1 of postcode of buyer 1's last settled accommodation,Part 2 of postcode of buyer 1's last settled accommodation,Do you know the local authority of buyer 1's last settled accommodation?,The local authority code of buyer 1's last settled accommodation,The local authority name of buyer 1's last settled accommodation,"At the time of purchase, was buyer 2 living at the same address as buyer 1?",What was buyer 2's previous tenure?,Have any of the buyers ever served as a regular in the UK armed forces?,Is the buyer still serving in the UK armed forces?,Are any of the buyers a spouse or civil partner of a UK armed forces regular who died in service within the last 2 years?,Does anyone in the household consider themselves to have a disability?,Does anyone in the household use a wheelchair?,Is buyer 1's annual income known?,What is buyer 1's annual income?,Was buyer 1's income used for a mortgage application?,Is buyer 1's annual income known?,What is buyer 2's annual income?,Was buyer 2's income used for a mortgage application?,Were the buyers receiving any of these housing-related benefits immediately before buying this property?,Is the the total amount the buyers had in savings known?,What is the total amount the buyers had in savings before they paid any deposit for the property?,Have any of the buyers previously owned a property?,Was the previous property under shared ownership?,Is this a resale?,How long did the buyer(s) live in the property before purchasing it?,Day of the practical completion or handover date,Month of the practical completion or handover date,Year of the practical completion or handover date,How many bedrooms did the buyer's previous property have?,What was the previous property type?,What was the rent type of buyer's previous tenure?,What is the full purchase price?,Populated if a soft validation is confirmed.,What was the initial percentage equity stake purchased?,Was a mortgage used to buy this property?,What is the mortgage amount?,What is the length of the mortgage in years?,How much was the cash deposit paid on the property?,How much cash discount was given through Social Homebuy?,What is the basic monthly rent?,,,,,What percentage of the property has been bought in this staircasing transaction?,What percentage of the property do the buyers now own in total?,Was this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?,,,,,,,,,,"What was the amount of any loan, grant, discount or subsidy given?",What was the percentage discount?,Does this include any extra borrowing?,Does the property have any monthly leasehold charges?,What are the total monthly leasehold charges for the property?,Populated if a soft validation is confirmed.,Will the service charge change after this staircasing transaction takes place?,What are the new total monthly service charges for the property?
ID,STATUS,DUPLICATESET,OWNINGORGNAME,OWNINGORGID,MANINGORGNAME,MANINGORGID,CREATEDDATE,CREATEDBY,CREATEDBYID,USERNAME,USERNAMEID,UPLOADDATE,AMENDEDBY,AMENDEDBYID,CREATIONMETHOD,BULKUPLOADID,COLLECTIONYEAR,DAY,MONTH,YEAR,PURCHID,OWNERSHIP,TYPE,STAIRCASE,JOINT,JOINTMORE,NOINT,PRIVACYNOTICE,UPRN,ADDRESS1,ADDRESS2,TOWNCITY,COUNTY,POSTCODE,ISLAINFERRED,LANAME,LA,UPRNSELECTED,ADDRESS_SEARCH_VALUE_CHECK,ADDRESS1INPUT,POSTCODEINPUT,BULKADDRESS1,BULKADDRESS2,BULKTOWNCITY,BULKCOUNTY,BULKPOSTCODE,BULKLA,PROPTYPE,BUILDHEIGHTCLASS,BEDS,BUILTYPE,WCHAIR,AGE1,SEXRAB1,GENDER_SAME_AS_SEX1,GENDER_DESCRIPTION1,ETHNICGROUP1,ETHNIC,NATIONALITYALL1,ECSTAT1,LIVEINBUYER1,RELAT2,AGE2,SEXRAB2,GENDER_SAME_AS_SEX2,GENDER_DESCRIPTION2,ETHNICGROUP2,ETHNIC2,NATIONALITYALL2,ECSTAT2,LIVEINBUYER2,HHOLDCOUNT,RELAT3,AGE3,SEXRAB3,GENDER_SAME_AS_SEX3,GENDER_DESCRIPTION3,ECSTAT3,RELAT4,AGE4,SEXRAB4,GENDER_SAME_AS_SEX4,GENDER_DESCRIPTION4,ECSTAT4,RELAT5,AGE5,SEXRAB5,GENDER_SAME_AS_SEX5,GENDER_DESCRIPTION5,ECSTAT5,RELAT6,AGE6,SEXRAB6,GENDER_SAME_AS_SEX6,GENDER_DESCRIPTION6,ECSTAT6,HHTYPE,PREVTEN,PPCODENK,PPOSTC1,PPOSTC2,PREVIOUSLAKNOWN,PREVLOC,PREVLOCNAME,BUY2LIVING,PREVTEN2,HHREGRES,HHREGRESSTILL,ARMEDFORCESSPOUSE,DISABLED,WHEEL,INC1NK,INCOME1,INC1MORT,INC2NK,INCOME2,INC2MORT,HB,SAVINGSNK,SAVINGS,PREVOWN,PREVSHARED,RESALE,PROPLEN,HODAY,HOMONTH,HOYEAR,FROMBEDS,FROMPROP,SOCPREVTEN,VALUE,VALUE_VALUE_CHECK,EQUITY,MORTGAGEUSED,MORTGAGE,MORTLEN1,DEPOSIT,CASHDIS,MRENT,HASSERVICECHARGES,SERVICECHARGES,HASESTATEFEE,ESTATEFEE,STAIRBOUGHT,STAIROWNED,STAIRCASETOSALE,FIRSTSTAIR,NUMSTAIR,STAIRLASTDAY,STAIRLASTMONTH,STAIRLASTYEAR,STAIRINITIALDAY,STAIRINITIALMONTH,STAIRINITIALYEAR,MRENTPRESTAIRCASING,GRANT,DISCOUNT,EXTRABOR,HASMSCHARGE,MSCHARGE,MSCHARGE_VALUE_CHECK,HASSERVICECHARGESCHANGED,NEWSERVICECHARGES
-,completed,,MHCLG,,MHCLG,,2026-04-01T00:00:00+01:00,billyboy@eyeklaud.com,,billyboy@eyeklaud.com,,2026-04-01T00:00:00+01:00,,,single log,,2026,1,4,2026,,Discounted Ownership,Right to Acquire (RTA),,Yes,Yes,Yes,1,1,"1, Test Street",,Test Town,,AA1 1AA,Yes,Westminster,E09000033,1,,,,address line 1 as entered,address line 2 as entered,town or city as entered,county as entered,AB1 2CD,la as entered,Flat or maisonette,Low-rise,2,Purpose built,Yes,30,Female,Yes,,Buyer prefers not to say,17,United Kingdom,Full-time – 30 hours or more per week,Yes,Yes,35,Male,"No, enter gender identity",Nonbinary,Buyer prefers not to say,,United Kingdom,Full-time – 30 hours or more per week,Yes,5,No,14,Female,Yes,,Child under 16,No,Not known,Prefers not to say,"No, enter gender identity",Genderfluid,In government training into work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,,Prefers not to say,,,,,,,6,Local authority tenant,Yes,SW1A,1AA,Yes,E09000033,Westminster,Don’t know,,Yes,Yes,No,Yes,Yes,Yes,13400,Yes,Yes,13400,Yes,Don’t know ,No,,Yes,No,,10,,,,,,,110000.0,,,Yes,20000.0,10,80000.0,,,,,,,,,,,,,,,,,,,10000.0,,Yes,Yes,100.0,,,
+,completed,,MHCLG,,MHCLG,,2026-04-01T00:00:00+01:00,billyboy@eyeklaud.com,,billyboy@eyeklaud.com,,2026-04-01T00:00:00+01:00,,,single log,,2026,1,4,2026,,Discounted Ownership,Right to Acquire (RTA),,Yes,Yes,Yes,1,1,"1, Test Street",,Test Town,,AA1 1AA,Yes,Westminster,E09000033,1,,,,address line 1 as entered,address line 2 as entered,town or city as entered,county as entered,AB1 2CD,la as entered,Flat or maisonette,Low-rise,2,Purpose-built,Yes,30,Female,Yes,,Buyer prefers not to say,17,United Kingdom,Full-time – 30 hours or more per week,Yes,Yes,35,Male,"No, enter gender identity",Nonbinary,Buyer prefers not to say,,United Kingdom,Full-time – 30 hours or more per week,Yes,5,No,14,Female,Yes,,Child under 16,No,Not known,Prefers not to say,"No, enter gender identity",Genderfluid,In government training into work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,,Prefers not to say,,,,,,,6,Local authority tenant,Yes,SW1A,1AA,Yes,E09000033,Westminster,Don’t know,,Yes,Yes,No,Yes,Yes,Yes,13400,Yes,Yes,13400,Yes,Don’t know ,No,,Yes,No,,10,,,,,,,110000.0,,,Yes,20000.0,10,80000.0,,,,,,,,,,,,,,,,,,,10000.0,,Yes,Yes,100.0,,,
diff --git a/spec/fixtures/files/sales_logs_csv_export_non_support_labels_24.csv b/spec/fixtures/files/sales_logs_csv_export_non_support_labels_24.csv
index a1390a940..b745b7089 100644
--- a/spec/fixtures/files/sales_logs_csv_export_non_support_labels_24.csv
+++ b/spec/fixtures/files/sales_logs_csv_export_non_support_labels_24.csv
@@ -1,3 +1,3 @@
Log ID,Status of log,ID of a set of duplicate logs,Time and date the log was created,Time and date the log was last updated,Year collection period opened,Was the log submitted in-service or via bulk upload?,,Is the user in the assigned_to column the data protection officer?,Day of sale completion date,Month of sale completion date,Year of sale completion date,Which organisation owned this property before the sale?,Which organisation reported the sale?,User the log is assigned to,What is the purchaser code?,Was this purchase made through an ownership scheme?,What is the type of shared ownership/discounted ownership/outright sale?,"If type = 'Other', what is the type of outright sale?",Is the buyer a company?,Will the buyer(s) live in the property?,Is this a joint purchase?,Are there more than 2 joint buyers of this property?,Did you interview the buyer to answer these questions?,Has the buyer seen the MHCLG privacy notice?,What is the UPRN of the property?,We found an address that might be this property. Is this the property address?,Address line 1 input from address matching feature,Postcode input from address matching feature,UPRN of the address selected,Address line 1,Address line 2,Town/City,County,Part 1 of the property's postcode,Part 2 of the property's postcode,LA code,LA name,How many bedrooms does the property have?,What type of unit is the property?,Which type of building is the property?,Is the property built or adapted to wheelchair-user standards?,What is buyer 1's age?,Which of these best describes buyer 1's gender identity?,What is buyer 1's ethnic group?,Which of the following best describes buyer 1's ethnic background?,What is buyer 1's nationality?,Which of these best describes buyer 1's working situation?,Will buyer 1 live in the property?,What is buyer 2 or person 2's relationship to buyer 1?,What is buyer 2 or person 2's age?,Which of these best describes buyer 2 or person 2's gender identity?,What is buyer 2's ethnic group?,Which of the following best describes buyer 2's ethnic background?,What is buyer 2's nationality?,What is buyer 2 or person 2's working situation?,Will buyer 2 live in the property?,"Besides the buyer(s), how many other people live or will live in the property?",What is person 3's relationship to buyer 1?,What is person 3's age?,What is person 3's gender identity?,What is person 3's working situation?,What is person 4's relationship to buyer 1?,What is person 4's age?,What is person 4's gender identity?,What is person 4's working situation?,What is person 5's relationship to buyer 1?,What is person 5's age?,What is person 5's gender identity?,What is person 5's working situation?,What is person 6's relationship to buyer 1?,What is person 6's age?,What is person 6's gender identity?,What is person 6's working situation?,What was buyer 1's previous tenure?,Do you know the postcode of buyer 1's last settled accommodation?,Part 1 of postcode of buyer 1's last settled accommodation,Part 2 of postcode of buyer 1's last settled accommodation,Do you know the local authority of buyer 1's last settled accommodation?,The local authority code of buyer 1's last settled accommodation,The local authority name of buyer 1's last settled accommodation,Was the buyer registered with their PRP (HA)?,Was the buyer registered with another PRP (HA)?,Was the buyer registered with the local authority?,Was the buyer registered with a Help to Buy agent?,"Populated if pregyrha, pregother, pregla and pregghb are blank","At the time of purchase, was buyer 2 living at the same address as buyer 1?",What was buyer 2's previous tenure?,Have any of the buyers ever served as a regular in the UK armed forces?,Is the buyer still serving in the UK armed forces?,Are any of the buyers a spouse or civil partner of a UK armed forces regular who died in service within the last 2 years?,Does anyone in the household consider themselves to have a disability?,Does anyone in the household use a wheelchair?,Is buyer 1's annual income known?,What is buyer 1's annual income?,Was buyer 1's income used for a mortgage application?,Is buyer 2's annual income known?,What is buyer 2's annual income?,Was buyer 2's income used for a mortgage application?,Were the buyers receiving any of these housing-related benefits immediately before buying this property?,Is the the total amount the buyers had in savings known?,What is the total amount the buyers had in savings before they paid any deposit for the property?,Have any of the buyers previously owned a property?,Was the previous property under shared ownership?,How long did the buyer(s) live in the property before purchasing it?,Is this a staircasing transaction?,What percentage of the property has been bought in this staircasing transaction?,What percentage of the property do the buyers now own in total?,Was this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?,Is this a resale?,Day of the exchange of contracts,Month of the exchange of contracts,Year of the exchange of contracts,Day of the practical completion or handover date,Month of the practical completion or handover date,Year of the practical completion or handover date,Was the household rehoused under a local authority nominations agreement?,"Was the buyer a private registered provider, housing association or local authority tenant immediately before this sale?",How many bedrooms did the buyer's previous property have?,What was the previous property type?,What was the rent type of buyer's previous tenure?,What is the full purchase price?,What was the initial percentage equity stake purchased?,Was a mortgage used to buy this property?,What is the mortgage amount?,What is the name of the mortgage lender?,"If mortgagelender = 'Other', what is the name of the mortgage lender?",What is the length of the mortgage in years?,Does this include any extra borrowing?,How much was the cash deposit paid on the property?,How much cash discount was given through Social Homebuy?,What is the basic monthly rent?,Does the property have any monthly leasehold charges?,What are the total monthly leasehold charges for the property?,What was the percentage discount?,"What was the amount of any loan, grant, discount or subsidy given?"
id,status,duplicate_set_id,created_at,updated_at,collection_start_year,creation_method,bulk_upload_id,is_dpo,day,month,year,owning_organisation_name,managing_organisation_name,assigned_to,purchid,ownershipsch,type,othtype,companybuy,buylivein,jointpur,jointmore,noint,privacynotice,uprn,uprn_confirmed,address_line1_input,postcode_full_input,uprn_selection,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la,la_label,beds,proptype,builtype,wchair,age1,sex1,ethnic_group,ethnic,nationality_all,ecstat1,buy1livein,relat2,age2,sex2,ethnic_group2,ethnicbuy2,nationality_all_buyer2,ecstat2,buy2livein,hholdcount,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,pregyrha,pregother,pregla,pregghb,pregblank,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,proplen,staircase,stairbought,stairowned,staircasesale,resale,exday,exmonth,exyear,hoday,homonth,hoyear,lanomagr,soctenant,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortgagelender,mortgagelenderother,mortlen,extrabor,deposit,cashdis,mrent,has_mscharge,mscharge,discount,grant
-,completed,,2024-04-01T00:00:00+01:00,2024-04-01T00:00:00+01:00,2024,single log,,false,1,4,2024,MHCLG,MHCLG,billyboy@eyeklaud.com,,Yes - a discounted ownership scheme,Right to Acquire (RTA),,,,Yes,Yes,Yes,1,1,Yes,,,1,"1, Test Street",,Test Town,,SW1A,1AA,E09000033,Westminster,2,Flat or maisonette,Purpose built,Yes,30,Non-binary,Buyer prefers not to say,17,United Kingdom,Full-time - 30 hours or more,Yes,Partner,35,Non-binary,Buyer prefers not to say,,United Kingdom,Full-time - 30 hours or more,Yes,3,Child,14,Non-binary,Child under 16,Other,Not known,Non-binary,In government training into work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,,,,,Local authority tenant,Yes,SW1A,1AA,Yes,E09000033,Westminster,1,1,1,1,,Don’t know,,Yes,Yes,No,Yes,Yes,Yes,13400,Yes,Yes,13400,Yes,Don’t know ,No,,Yes,No,10,,,,,,,,,,,,,,,,,110000.0,,Yes,20000.0,Cambridge Building Society,,10,Yes,80000.0,,,Yes,100.0,,10000.0
+,completed,,2024-04-01T00:00:00+01:00,2024-04-01T00:00:00+01:00,2024,single log,,false,1,4,2024,MHCLG,MHCLG,billyboy@eyeklaud.com,,Yes - a discounted ownership scheme,Right to Acquire (RTA),,,,Yes,Yes,Yes,1,1,Yes,,,1,"1, Test Street",,Test Town,,SW1A,1AA,E09000033,Westminster,2,Flat or maisonette,Purpose-built,Yes,30,Non-binary,Buyer prefers not to say,17,United Kingdom,Full-time - 30 hours or more,Yes,Partner,35,Non-binary,Buyer prefers not to say,,United Kingdom,Full-time - 30 hours or more,Yes,3,Child,14,Non-binary,Child under 16,Other,Not known,Non-binary,In government training into work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,,,,,Local authority tenant,Yes,SW1A,1AA,Yes,E09000033,Westminster,1,1,1,1,,Don’t know,,Yes,Yes,No,Yes,Yes,Yes,13400,Yes,Yes,13400,Yes,Don’t know ,No,,Yes,No,10,,,,,,,,,,,,,,,,,110000.0,,Yes,20000.0,Cambridge Building Society,,10,Yes,80000.0,,,Yes,100.0,,10000.0
diff --git a/spec/fixtures/files/sales_logs_csv_export_non_support_labels_25.csv b/spec/fixtures/files/sales_logs_csv_export_non_support_labels_25.csv
index b0d461902..880c5ba40 100644
--- a/spec/fixtures/files/sales_logs_csv_export_non_support_labels_25.csv
+++ b/spec/fixtures/files/sales_logs_csv_export_non_support_labels_25.csv
@@ -1,3 +1,3 @@
Log ID,Status of log,ID of a set of duplicate logs,Which organisation owned this property before the sale?,Which organisation owned this property before the sale? (ID),Which organisation reported the sale?,Which organisation reported the sale? (ID),Time and date the log was created,User the log is assigned to (email),User the log is assigned to (ID),Time and date the log was last updated,User that last amended the log (email),User that last amended the log (ID),Was the log submitted in-service or via bulk upload?,ID of a set of bulk uploaded logs,Year collection period opened,Day of sale completion date,Month of sale completion date,Year of sale completion date,What is the purchaser code?,Shared or discounted ownership,Type of ownership,Is this a staircasing transaction?,Is this a joint purchase?,Are there more than 2 joint buyers of this property?,Did you interview the buyer to answer these questions?,Has the buyer seen the MHCLG privacy notice?,What is the UPRN of the property?,We found an address that might be this property. Is this the property address?,Address line 1 input from address matching feature,Postcode input from address matching feature,UPRN of the address selected,Address line 1,Address line 2,Town/City,County,Part 1 of the property's postcode,Part 2 of the property's postcode,LA code,LA name,What type of unit is the property?,How many bedrooms does the property have?,Which type of building is the property?,Is the property built or adapted to wheelchair-user standards?,What is buyer 1's age?,Which of these best describes buyer 1's gender identity?,What is buyer 1's ethnic group?,Which of the following best describes buyer 1's ethnic background?,What is buyer 1's nationality?,Which of these best describes buyer 1's working situation?,Will buyer 1 live in the property?,Is buyer 2 or person 2 the partner of buyer 1?,What is buyer 2 or person 2's age?,Which of these best describes buyer 2 or person 2's gender identity?,What is buyer 2's ethnic group?,Which of the following best describes buyer 2's ethnic background?,What is buyer 2's nationality?,What is buyer 2 or person 2's working situation?,Will buyer 2 live in the property?,"Besides the buyer(s), how many other people live or will live in the property?",Is person 3 the partner of buyer 1?,What is person 3's age?,What is person 3's gender identity?,What is person 3's working situation?,Is person 4 the partner of buyer 1?,What is person 4's age?,What is person 4's gender identity?,What is person 4's working situation?,Is person 5 the partner of buyer 1?,What is person 5's age?,What is person 5's gender identity?,What is person 5's working situation?,Is person 6 the partner of buyer 1?,What is person 6's age?,What is person 6's gender identity?,What is person 6's working situation?,Household type,What was buyer 1's previous tenure?,Do you know the postcode of buyer 1's last settled accommodation?,Part 1 of postcode of buyer 1's last settled accommodation,Part 2 of postcode of buyer 1's last settled accommodation,Do you know the local authority of buyer 1's last settled accommodation?,The local authority code of buyer 1's last settled accommodation,The local authority name of buyer 1's last settled accommodation,"At the time of purchase, was buyer 2 living at the same address as buyer 1?",What was buyer 2's previous tenure?,Have any of the buyers ever served as a regular in the UK armed forces?,Is the buyer still serving in the UK armed forces?,Are any of the buyers a spouse or civil partner of a UK armed forces regular who died in service within the last 2 years?,Does anyone in the household consider themselves to have a disability?,Does anyone in the household use a wheelchair?,Is buyer 1's annual income known?,What is buyer 1's annual income?,Was buyer 1's income used for a mortgage application?,Is buyer 1's annual income known?,What is buyer 2's annual income?,Was buyer 2's income used for a mortgage application?,Were the buyers receiving any of these housing-related benefits immediately before buying this property?,Is the the total amount the buyers had in savings known?,What is the total amount the buyers had in savings before they paid any deposit for the property?,Have any of the buyers previously owned a property?,Was the previous property under shared ownership?,Is this a resale?,How long did the buyer(s) live in the property before purchasing it?,Day of the practical completion or handover date,Month of the practical completion or handover date,Year of the practical completion or handover date,How many bedrooms did the buyer's previous property have?,What was the previous property type?,What was the rent type of buyer's previous tenure?,What is the full purchase price?,What was the initial percentage equity stake purchased?,Was a mortgage used to buy this property?,What is the mortgage amount?,What is the length of the mortgage in years?,How much was the cash deposit paid on the property?,How much cash discount was given through Social Homebuy?,What is the basic monthly rent?,Does the property have any service charges?,Monthly service charges amount,Does the property have an estate management fee?,Monthly estate management fee amount,What percentage of the property has been bought in this staircasing transaction?,What percentage of the property do the buyers now own in total?,Was this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?,Is this the first time the shared owner has engaged in staircasing in the home?,"Including this time, how many times has the shared owner engaged in staircasing in the home?",Day of last staircasing transaction,Month of last staircasing transaction,Year of last staircasing transaction,Day of initial staircasing transaction,Month of initial staircasing transaction,Year of initial staircasing transaction,What was the basic monthly rent prior to staircasing?,"What was the amount of any loan, grant, discount or subsidy given?",What was the percentage discount?,Does this include any extra borrowing?,Does the property have any monthly leasehold charges?,What are the total monthly leasehold charges for the property?
id,status,duplicate_set_id,owning_organisation_name,owning_organisation_id,managing_organisation_name,managing_organisation_id,created_at,assigned_to,assigned_to_id,updated_at,updated_by,updated_by_id,creation_method,bulk_upload_id,collection_start_year,day,month,year,purchid,ownershipsch,type,staircase,jointpur,jointmore,noint,privacynotice,uprn,uprn_confirmed,address_line1_input,postcode_full_input,uprn_selection,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la,la_label,proptype,beds,builtype,wchair,age1,sex1,ethnic_group,ethnic,nationality_all,ecstat1,buy1livein,relat2,age2,sex2,ethnic_group2,ethnicbuy2,nationality_all_buyer2,ecstat2,buy2livein,hholdcount,relat3,age3,sex3,ecstat3,relat4,age4,sex4,ecstat4,relat5,age5,sex5,ecstat5,relat6,age6,sex6,ecstat6,hhtype,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,resale,proplen,hoday,homonth,hoyear,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortlen,deposit,cashdis,mrent,has_servicecharges,servicecharges,has_management_fee,management_fee,stairbought,stairowned,staircasesale,firststair,numstair,stairlastday,stairlastmonth,stairlastyear,stairinitialday,stairinitialmonth,stairinitialyear,mrentprestaircasing,grant,discount,extrabor,has_mscharge,mscharge
-,completed,,MHCLG,,MHCLG,,2025-04-01T00:00:00+01:00,billyboy@eyeklaud.com,,2025-04-01T00:00:00+01:00,,,single log,,2025,1,4,2025,,Discounted Ownership,Right to Acquire (RTA),,Yes,Yes,Yes,1,1,Yes,,,1,"1, Test Street",,Test Town,,SW1A,1AA,E09000033,Westminster,Flat or maisonette,2,Purpose built,Yes,30,Non-binary,Buyer prefers not to say,17,United Kingdom,Full-time – 30 hours or more per week,Yes,Yes,35,Non-binary,Buyer prefers not to say,,United Kingdom,Full-time – 30 hours or more per week,Yes,3,No,14,Non-binary,Child under 16,No,Not known,Non-binary,In government training into work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,,,,,6,Local authority tenant,Yes,SW1A,1AA,Yes,E09000033,Westminster,Don’t know,,Yes,Yes,No,Yes,Yes,Yes,13400,Yes,Yes,13400,Yes,Don’t know ,No,,Yes,No,,10,,,,,,,110000.0,,Yes,20000.0,10,80000.0,,,,,,,,,,,,,,,,,,,10000.0,,Yes,Yes,100.0
+,completed,,MHCLG,,MHCLG,,2025-04-01T00:00:00+01:00,billyboy@eyeklaud.com,,2025-04-01T00:00:00+01:00,,,single log,,2025,1,4,2025,,Discounted Ownership,Right to Acquire (RTA),,Yes,Yes,Yes,1,1,Yes,,,1,"1, Test Street",,Test Town,,SW1A,1AA,E09000033,Westminster,Flat or maisonette,2,Purpose-built,Yes,30,Non-binary,Buyer prefers not to say,17,United Kingdom,Full-time – 30 hours or more per week,Yes,Yes,35,Non-binary,Buyer prefers not to say,,United Kingdom,Full-time – 30 hours or more per week,Yes,3,No,14,Non-binary,Child under 16,No,Not known,Non-binary,In government training into work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,,,,,6,Local authority tenant,Yes,SW1A,1AA,Yes,E09000033,Westminster,Don’t know,,Yes,Yes,No,Yes,Yes,Yes,13400,Yes,Yes,13400,Yes,Don’t know ,No,,Yes,No,,10,,,,,,,110000.0,,Yes,20000.0,10,80000.0,,,,,,,,,,,,,,,,,,,10000.0,,Yes,Yes,100.0
diff --git a/spec/fixtures/files/sales_logs_csv_export_non_support_labels_26.csv b/spec/fixtures/files/sales_logs_csv_export_non_support_labels_26.csv
index dd8a657fb..9167c2627 100644
--- a/spec/fixtures/files/sales_logs_csv_export_non_support_labels_26.csv
+++ b/spec/fixtures/files/sales_logs_csv_export_non_support_labels_26.csv
@@ -1,3 +1,3 @@
Log ID,Status of log,ID of a set of duplicate logs,Which organisation owned this property before the sale?,Which organisation owned this property before the sale? (ID),Which organisation reported the sale?,Which organisation reported the sale? (ID),Time and date the log was created,User the log is assigned to (email),User the log is assigned to (ID),Time and date the log was last updated,User that last amended the log (email),User that last amended the log (ID),Was the log submitted in-service or via bulk upload?,ID of a set of bulk uploaded logs,Year collection period opened,Day of sale completion date,Month of sale completion date,Year of sale completion date,What is the purchaser code?,Shared or discounted ownership,Type of ownership,Is this a staircasing transaction?,Is this a joint purchase?,Are there more than 2 joint buyers of this property?,Did you interview the buyer(s) to answer these questions?,Has the buyer seen the MHCLG privacy notice?,What is the UPRN of the property?,We found an address that might be this property. Is this the property address?,Address line 1 input from address matching feature,Postcode input from address matching feature,UPRN of the address selected,Address line 1,Address line 2,Town/City,County,Part 1 of the property's postcode,Part 2 of the property's postcode,LA code,LA name,What type of unit is the property?,What is the building height classification?,How many bedrooms does the property have?,Which type of building is the property?,Is the property built or adapted to wheelchair-user standards?,What is buyer 1's age?,What is buyer 1's sex registered at birth?,Is the gender buyer 1 identifies with the same as their sex registered at birth?,"If 'No', enter buyer 1's gender identity",What is buyer 1's ethnic group?,Which of the following best describes buyer 1's ethnic background?,What is buyer 1's nationality?,Which of these best describes buyer 1's working situation?,Will buyer 1 live in the property?,Is buyer 2 or person 2 the partner of buyer 1?,What is buyer 2 or person 2's age?,What is buyer 2 or person 2's sex registered at birth?,Is the gender buyer/person 2 identifies with the same as their sex registered at birth?,"If 'No', enter buyer/person 2's gender identity",What is buyer 2's ethnic group?,Which of the following best describes buyer 2's ethnic background?,What is buyer 2's nationality?,What is buyer 2 or person 2's working situation?,Will buyer 2 live in the property?,"In total, how many people live in the property?",Is person 3 the partner of buyer 1?,What is person 3's age?,What is person 3's sex registered at birth?,Is the gender person 3 identifies with the same as their sex registered at birth?,"If 'No', enter person 3's gender identity",What is person 3's working situation?,Is person 4 the partner of buyer 1?,What is person 4's age?,What is person 4's sex registered at birth?,Is the gender person 4 identifies with the same as their sex registered at birth?,"If 'No', enter person 4's gender identity",What is person 4's working situation?,Is person 5 the partner of buyer 1?,What is person 5's age?,What is person 5's sex registered at birth?,Is the gender person 5 identifies with the same as their sex registered at birth?,"If 'No', enter person 5's gender identity",What is person 5's working situation?,Is person 6 the partner of buyer 1?,What is person 6's age?,What is person 6's sex registered at birth?,Is the gender person 6 identifies with the same as their sex registered at birth?,"If 'No', enter person 6's gender identity",What is person 6's working situation?,Household type,What was buyer 1's previous tenure?,Do you know the postcode of buyer 1's last settled accommodation?,Part 1 of postcode of buyer 1's last settled accommodation,Part 2 of postcode of buyer 1's last settled accommodation,Do you know the local authority of buyer 1's last settled accommodation?,The local authority code of buyer 1's last settled accommodation,The local authority name of buyer 1's last settled accommodation,"At the time of purchase, was buyer 2 living at the same address as buyer 1?",What was buyer 2's previous tenure?,Have any of the buyers ever served as a regular in the UK armed forces?,Is the buyer still serving in the UK armed forces?,Are any of the buyers a spouse or civil partner of a UK armed forces regular who died in service within the last 2 years?,Does anyone in the household consider themselves to have a disability?,Does anyone in the household use a wheelchair?,Is buyer 1's annual income known?,What is buyer 1's annual income?,Was buyer 1's income used for a mortgage application?,Is buyer 1's annual income known?,What is buyer 2's annual income?,Was buyer 2's income used for a mortgage application?,Were the buyers receiving any of these housing-related benefits immediately before buying this property?,Is the the total amount the buyers had in savings known?,What is the total amount the buyers had in savings before they paid any deposit for the property?,Have any of the buyers previously owned a property?,Was the previous property under shared ownership?,Is this a resale?,How long did the buyer(s) live in the property before purchasing it?,Day of the practical completion or handover date,Month of the practical completion or handover date,Year of the practical completion or handover date,How many bedrooms did the buyer's previous property have?,What was the previous property type?,What was the rent type of buyer's previous tenure?,What is the full purchase price?,What was the initial percentage equity stake purchased?,Was a mortgage used to buy this property?,What is the mortgage amount?,What is the length of the mortgage in years?,How much was the cash deposit paid on the property?,How much cash discount was given through Social Homebuy?,What is the basic monthly rent?,Does the property have any service charges?,Monthly service charges amount,Does the property have an estate management fee?,Monthly estate management fee amount,What percentage of the property has been bought in this staircasing transaction?,What percentage of the property do the buyers now own in total?,Was this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?,Is this the first time the shared owner has engaged in staircasing in the home?,"Including this time, how many times has the shared owner engaged in staircasing in the home?",Day of last staircasing transaction,Month of last staircasing transaction,Year of last staircasing transaction,Day of initial staircasing transaction,Month of initial staircasing transaction,Year of initial staircasing transaction,What was the basic monthly rent prior to staircasing?,"What was the amount of any loan, grant, discount or subsidy given?",What was the percentage discount?,Does this include any extra borrowing?,Does the property have any monthly leasehold charges?,What are the total monthly leasehold charges for the property?,Will the service charge change after this staircasing transaction takes place?,What are the new total monthly service charges for the property?
id,status,duplicate_set_id,owning_organisation_name,owning_organisation_id,managing_organisation_name,managing_organisation_id,created_at,assigned_to,assigned_to_id,updated_at,updated_by,updated_by_id,creation_method,bulk_upload_id,collection_start_year,day,month,year,purchid,ownershipsch,type,staircase,jointpur,jointmore,noint,privacynotice,uprn,uprn_confirmed,address_line1_input,postcode_full_input,uprn_selection,address_line1,address_line2,town_or_city,county,pcode1,pcode2,la,la_label,proptype,buildheightclass,beds,builtype,wchair,age1,sexrab1,gender_same_as_sex1,gender_description1,ethnic_group,ethnic,nationality_all,ecstat1,buy1livein,relat2,age2,sexrab2,gender_same_as_sex2,gender_description2,ethnic_group2,ethnicbuy2,nationality_all_buyer2,ecstat2,buy2livein,hholdcount,relat3,age3,sexrab3,gender_same_as_sex3,gender_description3,ecstat3,relat4,age4,sexrab4,gender_same_as_sex4,gender_description4,ecstat4,relat5,age5,sexrab5,gender_same_as_sex5,gender_description5,ecstat5,relat6,age6,sexrab6,gender_same_as_sex6,gender_description6,ecstat6,hhtype,prevten,ppcodenk,ppostc1,ppostc2,previous_la_known,prevloc,prevloc_label,buy2living,prevtenbuy2,hhregres,hhregresstill,armedforcesspouse,disabled,wheel,income1nk,income1,inc1mort,income2nk,income2,inc2mort,hb,savingsnk,savings,prevown,prevshared,resale,proplen,hoday,homonth,hoyear,frombeds,fromprop,socprevten,value,equity,mortgageused,mortgage,mortlen,deposit,cashdis,mrent,has_servicecharges,servicecharges,has_management_fee,management_fee,stairbought,stairowned,staircasesale,firststair,numstair,stairlastday,stairlastmonth,stairlastyear,stairinitialday,stairinitialmonth,stairinitialyear,mrentprestaircasing,grant,discount,extrabor,has_mscharge,mscharge,hasservicechargeschanged,newservicecharges
-,completed,,MHCLG,,MHCLG,,2026-04-01T00:00:00+01:00,billyboy@eyeklaud.com,,2026-04-01T00:00:00+01:00,,,single log,,2026,1,4,2026,,Discounted Ownership,Right to Acquire (RTA),,Yes,Yes,Yes,1,1,Yes,,,1,"1, Test Street",,Test Town,,SW1A,1AA,E09000033,Westminster,Flat or maisonette,Low-rise,2,Purpose built,Yes,30,Female,Yes,,Buyer prefers not to say,17,United Kingdom,Full-time – 30 hours or more per week,Yes,Yes,35,Male,"No, enter gender identity",Nonbinary,Buyer prefers not to say,,United Kingdom,Full-time – 30 hours or more per week,Yes,5,No,14,Female,Yes,,Child under 16,No,Not known,Prefers not to say,"No, enter gender identity",Genderfluid,In government training into work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,,Prefers not to say,,,,,,,6,Local authority tenant,Yes,SW1A,1AA,Yes,E09000033,Westminster,Don’t know,,Yes,Yes,No,Yes,Yes,Yes,13400,Yes,Yes,13400,Yes,Don’t know ,No,,Yes,No,,10,,,,,,,110000.0,,Yes,20000.0,10,80000.0,,,,,,,,,,,,,,,,,,,10000.0,,Yes,Yes,100.0,,
+,completed,,MHCLG,,MHCLG,,2026-04-01T00:00:00+01:00,billyboy@eyeklaud.com,,2026-04-01T00:00:00+01:00,,,single log,,2026,1,4,2026,,Discounted Ownership,Right to Acquire (RTA),,Yes,Yes,Yes,1,1,Yes,,,1,"1, Test Street",,Test Town,,SW1A,1AA,E09000033,Westminster,Flat or maisonette,Low-rise,2,Purpose-built,Yes,30,Female,Yes,,Buyer prefers not to say,17,United Kingdom,Full-time – 30 hours or more per week,Yes,Yes,35,Male,"No, enter gender identity",Nonbinary,Buyer prefers not to say,,United Kingdom,Full-time – 30 hours or more per week,Yes,5,No,14,Female,Yes,,Child under 16,No,Not known,Prefers not to say,"No, enter gender identity",Genderfluid,In government training into work,Prefers not to say,Not known,Prefers not to say,Prefers not to say,,Prefers not to say,,,,,,,6,Local authority tenant,Yes,SW1A,1AA,Yes,E09000033,Westminster,Don’t know,,Yes,Yes,No,Yes,Yes,Yes,13400,Yes,Yes,13400,Yes,Don’t know ,No,,Yes,No,,10,,,,,,,110000.0,,Yes,20000.0,10,80000.0,,,,,,,,,,,,,,,,,,,10000.0,,Yes,Yes,100.0,,
diff --git a/spec/models/form/sales/questions/property_building_type_spec.rb b/spec/models/form/sales/questions/property_building_type_spec.rb
index c8a0aecf0..2097f42cb 100644
--- a/spec/models/form/sales/questions/property_building_type_spec.rb
+++ b/spec/models/form/sales/questions/property_building_type_spec.rb
@@ -25,7 +25,7 @@ RSpec.describe Form::Sales::Questions::PropertyBuildingType, type: :model do
it "has the correct answer_options" do
expect(question.answer_options).to eq({
- "1" => { "value" => "Purpose built" },
+ "1" => { "value" => "Purpose-built" },
"2" => { "value" => "Converted from previous residential or non-residential property" },
})
end
From 441a01990a8eb77043ada45999ac47fc45cc73eb Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Fri, 10 Apr 2026 09:40:04 +0100
Subject: [PATCH 03/34] CLDC-4289: Ensure numbers can be parsed to floats
before totaling (#3292)
---
app/frontend/controllers/numeric_question_controller.js | 2 +-
spec/features/form/progressive_total_field_spec.rb | 9 +++++++++
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/app/frontend/controllers/numeric_question_controller.js b/app/frontend/controllers/numeric_question_controller.js
index 56c76f636..83f8e2fef 100644
--- a/app/frontend/controllers/numeric_question_controller.js
+++ b/app/frontend/controllers/numeric_question_controller.js
@@ -11,7 +11,7 @@ export default class extends Controller {
calculateFields () {
const affectedField = this.element.dataset.target
const fieldsToAdd = JSON.parse(this.element.dataset.calculated).map(x => `lettings-log-${x.replaceAll('_', '-')}-field`)
- const valuesToAdd = fieldsToAdd.map(x => getFieldValue(x)).filter(x => x)
+ const valuesToAdd = fieldsToAdd.map(x => getFieldValue(x)).filter(x => x && !isNaN(parseFloat(x)))
const newValue = valuesToAdd.map(x => parseFloat(x)).reduce((a, b) => a + b, 0).toFixed(2)
const elementToUpdate = document.getElementById(affectedField)
elementToUpdate.value = newValue
diff --git a/spec/features/form/progressive_total_field_spec.rb b/spec/features/form/progressive_total_field_spec.rb
index 1f90a4483..814eefb1d 100644
--- a/spec/features/form/progressive_total_field_spec.rb
+++ b/spec/features/form/progressive_total_field_spec.rb
@@ -58,4 +58,13 @@ RSpec.describe "Accessible Autocomplete" do
fill_in("lettings-log-supcharg-field-error", with: 50)
expect(find("#lettings-log-tcharge-field").value).to eq("550.00")
end
+
+ it "does not show 'NaN' if one of the inputs is not a number", :js do
+ visit("/lettings-logs/#{lettings_log.id}/rent")
+ expect(page).to have_selector("#tcharge_div")
+ fill_in("lettings-log-brent-field", with: 5)
+ expect(find("#lettings-log-tcharge-field").value).to eq("5.00")
+ fill_in("lettings-log-pscharge-field", with: "something else")
+ expect(find("#lettings-log-tcharge-field").value).to eq("5.00")
+ end
end
From 5806eb8d72a43a8b1802d41bd3420b9142549fa1 Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Mon, 13 Apr 2026 17:33:48 +0100
Subject: [PATCH 04/34] CLDC-4298: Ensure value must be a whole number (#3297)
* CLDC-4298: Update purchase price step for 2026
* CLDC-4298: Add a rake task to round value values
* fixup! CLDC-4298: Add a rake task to round value values
remove redundant query
update desc
remove unneeded comment
---
app/models/form/sales/questions/purchase_price.rb | 2 +-
lib/tasks/round_value_for_2026_sales_logs.rake | 11 +++++++++++
2 files changed, 12 insertions(+), 1 deletion(-)
create mode 100644 lib/tasks/round_value_for_2026_sales_logs.rake
diff --git a/app/models/form/sales/questions/purchase_price.rb b/app/models/form/sales/questions/purchase_price.rb
index 24aecd7ec..8a919b55f 100644
--- a/app/models/form/sales/questions/purchase_price.rb
+++ b/app/models/form/sales/questions/purchase_price.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::PurchasePrice < ::Form::Question
@id = "value"
@type = "numeric"
@min = form.start_year_2026_or_later? ? 15_000 : 0
- @step = 0.01
+ @step = form.start_year_2026_or_later? ? 1 : 0.01 # 0.01 was a mistake that was fixed in 2026
@width = 5
@prefix = "£"
@ownership_sch = ownershipsch
diff --git a/lib/tasks/round_value_for_2026_sales_logs.rake b/lib/tasks/round_value_for_2026_sales_logs.rake
new file mode 100644
index 000000000..c0f584799
--- /dev/null
+++ b/lib/tasks/round_value_for_2026_sales_logs.rake
@@ -0,0 +1,11 @@
+desc "Rounds purchase price (the 'value' field) for sales logs in the database if not a whole number"
+task round_value_for_2026_sales_logs: :environment do
+ logs = SalesLog.filter_by_year(2026).where("value % 1 != 0")
+ puts "Correcting #{logs.count} sales logs, #{logs.map(&:id)}"
+
+ logs.find_each do |log|
+ log.update(value: log.value.round)
+ end
+
+ puts "Done"
+end
From 31e707495a30ac259e12f1fbf8f25741902e239e Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Tue, 14 Apr 2026 11:16:00 +0100
Subject: [PATCH 05/34] CLDC-4406: Add a script to delete logs in batches
(#3306)
---
lib/tasks/delete_logs_before_year.rake | 34 ++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
create mode 100644 lib/tasks/delete_logs_before_year.rake
diff --git a/lib/tasks/delete_logs_before_year.rake b/lib/tasks/delete_logs_before_year.rake
new file mode 100644
index 000000000..1343ed4ae
--- /dev/null
+++ b/lib/tasks/delete_logs_before_year.rake
@@ -0,0 +1,34 @@
+desc "Deletes all logs in a given collection year and earlier. Note that this operation is PERMANENT and this will bypass callbacks/paper trail. Use only as instructed in a yearly cleanup task."
+task :delete_logs_before_year, %i[year] => :environment do |_task, args|
+ year = args[:year].to_i
+
+ if year < 2020
+ raise ArgumentError, "Year must be above 2020. Make sure you've written out the entire year"
+ end
+
+ if year > Time.zone.now.year - 3
+ raise ArgumentError, "Year cannot be the last 3 years, as these may contain visible logs"
+ end
+
+ puts "Deleting Logs before #{year}"
+
+ puts "Deleting Sales Logs in batches of 10000"
+ logs = SalesLog.filter_by_year_or_earlier(year)
+
+ logs.in_batches(of: 10_000).each_with_index do |logs, i|
+ puts "Deleting batch #{i + 1}"
+ logs.delete_all
+ end
+ puts "Done deleting Sales Logs"
+
+ puts "Deleting Lettings Logs in batches of 10000"
+ logs = LettingsLog.filter_by_year_or_earlier(year)
+
+ logs.in_batches(of: 10_000).each_with_index do |logs, i|
+ puts "Deleting batch #{i + 1}"
+ logs.delete_all
+ end
+ puts "Done deleting Lettings Logs"
+
+ puts "Done deleting Logs before #{year}"
+end
From b44fcb8fd953a2154831eb2c6c3bbd8b7216580f Mon Sep 17 00:00:00 2001
From: Nat Dean-Lewis <94526761+natdeanlewissoftwire@users.noreply.github.com>
Date: Tue, 14 Apr 2026 16:03:41 +0100
Subject: [PATCH 06/34] CLDC-4430: make dev containers mac compatible (#3309)
---
aws-devcontainer/.devcontainer/Dockerfile | 8 +++++++-
1 file changed, 7 insertions(+), 1 deletion(-)
diff --git a/aws-devcontainer/.devcontainer/Dockerfile b/aws-devcontainer/.devcontainer/Dockerfile
index 3fd23c4d4..82f969b4d 100644
--- a/aws-devcontainer/.devcontainer/Dockerfile
+++ b/aws-devcontainer/.devcontainer/Dockerfile
@@ -1,7 +1,13 @@
FROM homebrew/brew
RUN brew install aws-vault && brew install awscli
-RUN curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/ubuntu_64bit/session-manager-plugin.deb" -o "session-manager-plugin.deb" && sudo dpkg -i session-manager-plugin.deb
+RUN if [ "$(dpkg --print-architecture)" = "arm64" ]; then \
+ ARCH="ubuntu_arm64"; \
+ else \
+ ARCH="ubuntu_64bit"; \
+ fi && \
+ curl "https://s3.amazonaws.com/session-manager-downloads/plugin/latest/${ARCH}/session-manager-plugin.deb" -o "session-manager-plugin.deb" && \
+ sudo dpkg -i session-manager-plugin.deb
ENV AWS_VAULT_BACKEND=file
ENV AWS_VAULT_FILE_DIR=./vault
From 5d45e04d0d2012f68574e45a31c5e220c97ebc68 Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Tue, 14 Apr 2026 16:13:43 +0100
Subject: [PATCH 07/34] CLDC-4406: Update rake name to delete old logs (#3311)
considering this is a very dangerous script best not to leave the name slightly ambiguous (since it deletes from the given year and before)
---
...ear.rake => delete_logs_in_collection_year_and_earlier.rake} | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
rename lib/tasks/{delete_logs_before_year.rake => delete_logs_in_collection_year_and_earlier.rake} (92%)
diff --git a/lib/tasks/delete_logs_before_year.rake b/lib/tasks/delete_logs_in_collection_year_and_earlier.rake
similarity index 92%
rename from lib/tasks/delete_logs_before_year.rake
rename to lib/tasks/delete_logs_in_collection_year_and_earlier.rake
index 1343ed4ae..b5ed4573b 100644
--- a/lib/tasks/delete_logs_before_year.rake
+++ b/lib/tasks/delete_logs_in_collection_year_and_earlier.rake
@@ -1,5 +1,5 @@
desc "Deletes all logs in a given collection year and earlier. Note that this operation is PERMANENT and this will bypass callbacks/paper trail. Use only as instructed in a yearly cleanup task."
-task :delete_logs_before_year, %i[year] => :environment do |_task, args|
+task :delete_logs_in_collection_year_and_earlier, %i[year] => :environment do |_task, args|
year = args[:year].to_i
if year < 2020
From f9f3edd11a754bcce7b026293ca52a8636167721 Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Wed, 15 Apr 2026 17:46:09 +0100
Subject: [PATCH 08/34] CLDC-4373: Fix pregnancy check appearing twice (#3308)
* CLDC-4373: Add a person_index to lead age pregnancy check
* CLDC-4373: Ensure pregnancy validation is not shown for people without details
---
...o_household_member_likely_to_be_pregnant_check.rb | 12 ++++++++++--
.../subsections/household_characteristics.rb | 2 +-
2 files changed, 11 insertions(+), 3 deletions(-)
diff --git a/app/models/form/lettings/pages/no_household_member_likely_to_be_pregnant_check.rb b/app/models/form/lettings/pages/no_household_member_likely_to_be_pregnant_check.rb
index cefb98ceb..da0fdbb9f 100644
--- a/app/models/form/lettings/pages/no_household_member_likely_to_be_pregnant_check.rb
+++ b/app/models/form/lettings/pages/no_household_member_likely_to_be_pregnant_check.rb
@@ -2,7 +2,8 @@ class Form::Lettings::Pages::NoHouseholdMemberLikelyToBePregnantCheck < ::Form::
def initialize(id, hsh, subsection, person_index: 0)
super(id, hsh, subsection)
@copy_key = "lettings.soft_validations.pregnancy_value_check.no_household_member_likely_to_be_pregnant_check"
- @depends_on = [{ "no_household_member_likely_to_be_pregnant?" => true }]
+ @person_index = person_index
+ @depends_on = depends_on
@title_text = {
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.title_text",
"arguments" => [],
@@ -11,7 +12,14 @@ class Form::Lettings::Pages::NoHouseholdMemberLikelyToBePregnantCheck < ::Form::
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.informative_text",
"arguments" => [],
}
- @person_index = person_index
+ end
+
+ def depends_on
+ if @person_index >= 2
+ [{ "no_household_member_likely_to_be_pregnant?" => true, "details_known_#{@person_index}" => 0 }]
+ else
+ [{ "no_household_member_likely_to_be_pregnant?" => true }]
+ end
end
def questions
diff --git a/app/models/form/lettings/subsections/household_characteristics.rb b/app/models/form/lettings/subsections/household_characteristics.rb
index 50e2cfa61..5ac573df3 100644
--- a/app/models/form/lettings/subsections/household_characteristics.rb
+++ b/app/models/form/lettings/subsections/household_characteristics.rb
@@ -16,7 +16,7 @@ class Form::Lettings::Subsections::HouseholdCharacteristics < ::Form::Subsection
Form::Lettings::Pages::LeadTenantAge.new(nil, nil, self),
(Form::Lettings::Pages::NoFemalesPregnantHouseholdLeadAgeValueCheck.new(nil, nil, self) unless form.start_year_2026_or_later?),
(Form::Lettings::Pages::FemalesInSoftAgeRangeInPregnantHouseholdLeadAgeValueCheck.new(nil, nil, self) unless form.start_year_2026_or_later?),
- (Form::Lettings::Pages::NoHouseholdMemberLikelyToBePregnantCheck.new("no_household_member_likely_to_be_pregnant_lead_age_check", nil, self) if form.start_year_2026_or_later?),
+ (Form::Lettings::Pages::NoHouseholdMemberLikelyToBePregnantCheck.new("no_household_member_likely_to_be_pregnant_lead_age_check", nil, self, person_index: 1) if form.start_year_2026_or_later?),
Form::Lettings::Pages::LeadTenantUnderRetirementValueCheck.new("age_lead_tenant_under_retirement_value_check", nil, self),
Form::Lettings::Pages::LeadTenantOverRetirementValueCheck.new("age_lead_tenant_over_retirement_value_check", nil, self),
(Form::Lettings::Pages::LeadTenantSexRegisteredAtBirth.new(nil, nil, self) if form.start_year_2026_or_later?),
From 8020b2fbfb16718977dd800c60b1691d888b438b Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Wed, 15 Apr 2026 17:54:30 +0100
Subject: [PATCH 09/34] Bump addressable from 2.8.1 to 2.9.0 in /docs (#3304)
Bumps [addressable](https://github.com/sporkmonger/addressable) from 2.8.1 to 2.9.0.
- [Changelog](https://github.com/sporkmonger/addressable/blob/main/CHANGELOG.md)
- [Commits](https://github.com/sporkmonger/addressable/compare/addressable-2.8.1...addressable-2.9.0)
---
updated-dependencies:
- dependency-name: addressable
dependency-version: 2.9.0
dependency-type: indirect
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
docs/Gemfile.lock | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/docs/Gemfile.lock b/docs/Gemfile.lock
index cd65dd5a6..ada074c92 100644
--- a/docs/Gemfile.lock
+++ b/docs/Gemfile.lock
@@ -13,8 +13,8 @@ GEM
minitest (>= 5.1, < 6)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
- addressable (2.8.1)
- public_suffix (>= 2.0.2, < 6.0)
+ addressable (2.9.0)
+ public_suffix (>= 2.0.2, < 8.0)
base64 (0.3.0)
benchmark (0.5.0)
bigdecimal (4.0.1)
From aa22e8dc151bba225cd0431106382582ac8b3b90 Mon Sep 17 00:00:00 2001
From: Nat Dean-Lewis <94526761+natdeanlewissoftwire@users.noreply.github.com>
Date: Fri, 17 Apr 2026 11:15:06 +0100
Subject: [PATCH 10/34] CLDC-4400: Buyer still serving answer remapping (#3310)
* CLDC-4400: update 2025 options and hide 10 from ui
* CLDC-4400: add rake task to remap values
* CLDC-4400: tweak desc and rename
* CLDC-4400: update spec
* CLDC-4400: rename task file
* CLDC-4400: rename task file
* CLDC-4400: rename task file
* CLDC-4400: refactor usage error
* CLDC-4400: use datetime not date in case logs are made between release and rake task completion
* CLDC-4400: before_date -> before_datetime
* CLDC-4400: print log ids and use update!
---
.../sales/questions/buyer_still_serving.rb | 11 +++++---
.../remap_2025_hhregresstill_values.rake | 24 +++++++++++++++++
.../questions/buyer_still_serving_spec.rb | 27 ++++++++++++++++---
3 files changed, 56 insertions(+), 6 deletions(-)
create mode 100644 lib/tasks/remap_2025_hhregresstill_values.rake
diff --git a/app/models/form/sales/questions/buyer_still_serving.rb b/app/models/form/sales/questions/buyer_still_serving.rb
index fc7b9fcb2..6ef135f40 100644
--- a/app/models/form/sales/questions/buyer_still_serving.rb
+++ b/app/models/form/sales/questions/buyer_still_serving.rb
@@ -19,13 +19,18 @@ class Form::Sales::Questions::BuyerStillServing < ::Form::Question
else
{
"4" => { "value" => "Yes" },
- "5" => { "value" => "No" },
- "6" => { "value" => "Buyer prefers not to say" },
+ "5" => { "value" => "No - they left up to and including 2 years ago" },
+ "6" => { "value" => "No - they left more than 2 years ago" },
"divider" => { "value" => true },
- "7" => { "value" => "Don’t know" },
+ "9" => { "value" => "Don’t know" },
+ "10" => { "value" => "No" },
}.freeze
end
end
+ def displayed_answer_options(_log, _user = nil)
+ answer_options.reject { |key, _v| key == "10" }
+ end
+
QUESTION_NUMBER_FROM_YEAR = { 2023 => 63, 2024 => 65, 2025 => 62, 2026 => 70 }.freeze
end
diff --git a/lib/tasks/remap_2025_hhregresstill_values.rake b/lib/tasks/remap_2025_hhregresstill_values.rake
new file mode 100644
index 000000000..30ec38e10
--- /dev/null
+++ b/lib/tasks/remap_2025_hhregresstill_values.rake
@@ -0,0 +1,24 @@
+desc "Remaps hhregresstill values for manually created 2025/26 sales logs"
+task :remap_2025_hhregresstill_values, %i[before_datetime] => :environment do |_task, args|
+ usage_message = "Usage: rake remap_2025_hhregresstill_values['before_datetime']. before_datetime must be in format YYYY-MM-DDTHH:MM:SS"
+ raise usage_message if args[:before_datetime].blank?
+
+ before_datetime = Time.zone.parse(args[:before_datetime])
+ raise usage_message if before_datetime.nil?
+
+ logs = SalesLog.filter_by_year(2025).where(bulk_upload_id: nil).where(hhregresstill: [5, 6, 7]).where("created_at < ?", before_datetime)
+ puts "Updating #{logs.count} sales logs"
+
+ updated_ids = []
+ logs.find_each do |log|
+ new_value = case log.hhregresstill
+ when 5 then 10
+ when 6, 7 then 9
+ end
+ log.update!(hhregresstill: new_value)
+ updated_ids << log.id
+ end
+
+ puts "Updated log IDs: #{updated_ids.join(', ')}"
+ puts "Done"
+end
diff --git a/spec/models/form/sales/questions/buyer_still_serving_spec.rb b/spec/models/form/sales/questions/buyer_still_serving_spec.rb
index 4b89879f6..d9222fae2 100644
--- a/spec/models/form/sales/questions/buyer_still_serving_spec.rb
+++ b/spec/models/form/sales/questions/buyer_still_serving_spec.rb
@@ -32,10 +32,21 @@ RSpec.describe Form::Sales::Questions::BuyerStillServing, type: :model do
it "has the correct answer_options" do
expect(question.answer_options).to eq({
"4" => { "value" => "Yes" },
- "5" => { "value" => "No" },
- "6" => { "value" => "Buyer prefers not to say" },
+ "5" => { "value" => "No - they left up to and including 2 years ago" },
+ "6" => { "value" => "No - they left more than 2 years ago" },
"divider" => { "value" => true },
- "7" => { "value" => "Don’t know" },
+ "9" => { "value" => "Don’t know" },
+ "10" => { "value" => "No" },
+ })
+ end
+
+ it "has the correct displayed_answer_options" do
+ expect(question.displayed_answer_options(nil)).to eq({
+ "4" => { "value" => "Yes" },
+ "5" => { "value" => "No - they left up to and including 2 years ago" },
+ "6" => { "value" => "No - they left more than 2 years ago" },
+ "divider" => { "value" => true },
+ "9" => { "value" => "Don’t know" },
})
end
end
@@ -52,5 +63,15 @@ RSpec.describe Form::Sales::Questions::BuyerStillServing, type: :model do
"9" => { "value" => "Don’t know" },
})
end
+
+ it "has the correct displayed_answer_options" do
+ expect(question.displayed_answer_options(nil)).to eq({
+ "4" => { "value" => "Yes" },
+ "5" => { "value" => "No - they left up to and including 2 years ago" },
+ "6" => { "value" => "No - they left more than 2 years ago" },
+ "divider" => { "value" => true },
+ "9" => { "value" => "Don’t know" },
+ })
+ end
end
end
From 6bccc2676e25595e6346e4ae2f29390dc4a61739 Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Fri, 17 Apr 2026 16:08:45 +0100
Subject: [PATCH 11/34] CLDC-4435: Always show LA question if it can't be
derived (#3314)
* CLDC-4435: Always show LA question if it can't be derived
* CLDC-4435: Update tests
* fixup! CLDC-4435: Update tests
clean up sales prop la spec
---
.../pages/property_local_authority.rb | 4 +-
.../sales/pages/property_local_authority.rb | 4 +-
.../pages/property_local_authority_spec.rb | 72 +++++--------------
.../pages/property_local_authority_spec.rb | 61 +++-------------
spec/requests/check_errors_controller_spec.rb | 2 +-
5 files changed, 32 insertions(+), 111 deletions(-)
diff --git a/app/models/form/lettings/pages/property_local_authority.rb b/app/models/form/lettings/pages/property_local_authority.rb
index 339ccb4d8..5656ec2d9 100644
--- a/app/models/form/lettings/pages/property_local_authority.rb
+++ b/app/models/form/lettings/pages/property_local_authority.rb
@@ -3,8 +3,8 @@ class Form::Lettings::Pages::PropertyLocalAuthority < ::Form::Page
super
@id = "property_local_authority"
@depends_on = [
- { "is_la_inferred" => false, "is_general_needs?" => true, "form.start_year_2024_or_later?" => false },
- { "is_la_inferred" => false, "is_general_needs?" => true, "form.start_year_2024_or_later?" => true, "address_search_given?" => true },
+ { "is_la_inferred" => false, "is_general_needs?" => true, "form.start_year_2025_or_later?" => false, "address_search_given?" => true },
+ { "is_la_inferred" => false, "is_general_needs?" => true, "form.start_year_2025_or_later?" => true },
]
end
diff --git a/app/models/form/sales/pages/property_local_authority.rb b/app/models/form/sales/pages/property_local_authority.rb
index fe9ad1bc0..cd1d898e2 100644
--- a/app/models/form/sales/pages/property_local_authority.rb
+++ b/app/models/form/sales/pages/property_local_authority.rb
@@ -3,8 +3,8 @@ class Form::Sales::Pages::PropertyLocalAuthority < ::Form::Page
super
@id = "property_local_authority"
@depends_on = [
- { "is_la_inferred" => false, "form.start_year_2024_or_later?" => false },
- { "is_la_inferred" => false, "form.start_year_2024_or_later?" => true, "address_search_given?" => true },
+ { "is_la_inferred" => false, "form.start_year_2025_or_later?" => false, "address_search_given?" => true },
+ { "is_la_inferred" => false, "form.start_year_2025_or_later?" => true },
]
end
diff --git a/spec/models/form/lettings/pages/property_local_authority_spec.rb b/spec/models/form/lettings/pages/property_local_authority_spec.rb
index 75d680ddd..5e29424e3 100644
--- a/spec/models/form/lettings/pages/property_local_authority_spec.rb
+++ b/spec/models/form/lettings/pages/property_local_authority_spec.rb
@@ -35,66 +35,26 @@ RSpec.describe Form::Lettings::Pages::PropertyLocalAuthority, type: :model do
context "when routing to the page" do
let(:log) { build(:lettings_log) }
- context "with form before 2024" do
- before do
- allow(form).to receive(:start_year_2024_or_later?).and_return(false)
- end
-
- it "is routed to when la is not inferred and it is general needs log" do
- log.needstype = 1
- log.is_la_inferred = false
- expect(page).to be_routed_to(log, nil)
- end
-
- it "is not routed to when la is inferred" do
- log.needstype = 1
- log.is_la_inferred = true
- expect(page).not_to be_routed_to(log, nil)
- end
-
- it "is not routed to when it's a supported housing log" do
- log.needstype = 2
- log.is_la_inferred = false
- expect(page).not_to be_routed_to(log, nil)
- end
+ before do
+ allow(form).to receive(:start_year_2025_or_later?).and_return(true)
end
- context "with form after 2024" do
- before do
- allow(form).to receive(:start_year_2024_or_later?).and_return(true)
- end
-
- it "is routed to when la is not inferred, it is general needs log and address search has been given" do
- log.needstype = 1
- log.is_la_inferred = false
- log.address_line1_input = "1"
- log.postcode_full_input = "A11AA"
- expect(page).to be_routed_to(log, nil)
- end
-
- it "is not routed to when la is inferred" do
- log.needstype = 1
- log.is_la_inferred = true
- log.address_line1_input = "1"
- log.postcode_full_input = "A11AA"
- expect(page).not_to be_routed_to(log, nil)
- end
+ it "is routed to when la is not inferred and it is general needs log" do
+ log.needstype = 1
+ log.is_la_inferred = false
+ expect(page).to be_routed_to(log, nil)
+ end
- it "is not routed to when it's a supported housing log" do
- log.needstype = 2
- log.is_la_inferred = false
- log.address_line1_input = "1"
- log.postcode_full_input = "A11AA"
- expect(page).not_to be_routed_to(log, nil)
- end
+ it "is not routed to when la is inferred" do
+ log.needstype = 1
+ log.is_la_inferred = true
+ expect(page).not_to be_routed_to(log, nil)
+ end
- it "is not routed to when address search is not given" do
- log.needstype = 1
- log.is_la_inferred = false
- log.address_line1_input = nil
- log.postcode_full_input = "A11AA"
- expect(page).not_to be_routed_to(log, nil)
- end
+ it "is not routed to when it's a supported housing log" do
+ log.needstype = 2
+ log.is_la_inferred = false
+ expect(page).not_to be_routed_to(log, nil)
end
end
end
diff --git a/spec/models/form/sales/pages/property_local_authority_spec.rb b/spec/models/form/sales/pages/property_local_authority_spec.rb
index 88d049bce..579b3d48a 100644
--- a/spec/models/form/sales/pages/property_local_authority_spec.rb
+++ b/spec/models/form/sales/pages/property_local_authority_spec.rb
@@ -17,18 +17,8 @@ RSpec.describe Form::Sales::Pages::PropertyLocalAuthority, type: :model do
expect(page.subsection).to eq(subsection)
end
- describe "has correct questions" do
- context "when 2023" do
- let(:start_date) { Time.utc(2023, 2, 8) }
-
- it "has correct questions" do
- expect(page.questions.map(&:id)).to eq(
- %w[
- la
- ],
- )
- end
- end
+ it "has correct questions" do
+ expect(page.questions.map(&:id)).to eq(%w[la])
end
it "has the correct id" do
@@ -42,47 +32,18 @@ RSpec.describe Form::Sales::Pages::PropertyLocalAuthority, type: :model do
context "when routing to the page" do
let(:log) { build(:sales_log) }
- context "with form before 2024" do
- before do
- allow(form).to receive(:start_year_2024_or_later?).and_return(false)
- end
-
- it "is routed to when la is not inferred" do
- log.is_la_inferred = false
- expect(page).to be_routed_to(log, nil)
- end
-
- it "is not routed to when la is inferred" do
- log.is_la_inferred = true
- expect(page).not_to be_routed_to(log, nil)
- end
+ before do
+ allow(form).to receive(:start_year_2025_or_later?).and_return(true)
end
- context "with form after 2024" do
- before do
- allow(form).to receive(:start_year_2024_or_later?).and_return(true)
- end
-
- it "is routed to when la is not inferred and address search has been given" do
- log.is_la_inferred = false
- log.address_line1_input = "1"
- log.postcode_full_input = "A11AA"
- expect(page).to be_routed_to(log, nil)
- end
-
- it "is not routed to when la is inferred" do
- log.is_la_inferred = true
- log.address_line1_input = "1"
- log.postcode_full_input = "A11AA"
- expect(page).not_to be_routed_to(log, nil)
- end
+ it "is routed to when la is not inferred" do
+ log.is_la_inferred = false
+ expect(page).to be_routed_to(log, nil)
+ end
- it "is not routed to when address search is not given" do
- log.is_la_inferred = false
- log.address_line1_input = nil
- log.postcode_full_input = "A11AA"
- expect(page).not_to be_routed_to(log, nil)
- end
+ it "is not routed to when la is inferred" do
+ log.is_la_inferred = true
+ expect(page).not_to be_routed_to(log, nil)
end
end
end
diff --git a/spec/requests/check_errors_controller_spec.rb b/spec/requests/check_errors_controller_spec.rb
index 017879d89..168931d71 100644
--- a/spec/requests/check_errors_controller_spec.rb
+++ b/spec/requests/check_errors_controller_spec.rb
@@ -84,7 +84,7 @@ RSpec.describe CheckErrorsController, type: :request do
end
it "displays correct clear and change links" do
- expect(page.all(:button, value: "Clear").count).to eq(1)
+ expect(page.all(:button, value: "Clear").count).to eq(2)
expect(page).to have_link("Change", count: 1)
expect(page).to have_button("Clear all")
end
From 02c3d00bf688b6f752b21c583e8ca2820ec1fac9 Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Mon, 20 Apr 2026 16:09:27 +0100
Subject: [PATCH 12/34] CLDC-4436: Add a script to recalculate LA of logs in a
year (#3315)
* CLDC-4436: Add a script to recalculate LA of logs in a year
* fixup! CLDC-4436: Add a script to recalculate LA of logs in a year
dont filter by BU, if this is nil we ought to try to correct it
only set back completed logs
* fixup! CLDC-4436: Add a script to recalculate LA of logs in a year
report count both before and after processing
* fixup! CLDC-4436: Add a script to recalculate LA of logs in a year
fix SalesLog reference
* CLDC-4436: Upgrade log LA fix script
for every log it changes to in progress after setting LA, print this to the console
this output can be copied and written to a file local. the two subsequent tasks will convert these to CSV files that can be shared with LAs
combines them into a single namespace
* CLDC-4436: Put final files into a folder for easy access
* CLDC-4436: Print relation IDs as well
* fixup! CLDC-4436: Upgrade log LA fix script
* CLDC-4436: Add separate cols for la ecode and la name
* CLDC-4436: Allow 30 logs in an org
* fixup! CLDC-4436: Upgrade log LA fix script
fix rows for sales too
Co-authored-by: Oscar Richardson <116292912+oscar-richardson-softwire@users.noreply.github.com>
---------
Co-authored-by: Oscar Richardson <116292912+oscar-richardson-softwire@users.noreply.github.com>
---
lib/tasks/log_la_fix.rake | 129 ++++++++++++++++++++++++++++++++++++++
1 file changed, 129 insertions(+)
create mode 100644 lib/tasks/log_la_fix.rake
diff --git a/lib/tasks/log_la_fix.rake b/lib/tasks/log_la_fix.rake
new file mode 100644
index 000000000..1a13602be
--- /dev/null
+++ b/lib/tasks/log_la_fix.rake
@@ -0,0 +1,129 @@
+namespace :log_la_fix do
+ desc "For all logs missing an LA that could have one, call the postcode changed method to request a new one from postcodes API. For logs where an LA still cannot be found, this will set them back to in progress."
+ task :search_for_la_on_logs_with_nil_la, [:year] => :environment do |_task, args|
+ include CollectionTimeHelper
+
+ year = args[:year]&.to_i || current_collection_start_year
+
+ lettings_logs = LettingsLog.filter_by_year(year).where(la: nil, needstype: 1, status: "completed")
+ sales_logs = SalesLog.filter_by_year(year).where(la: nil, status: "completed")
+ lettings_logs_count = lettings_logs.count
+ sales_logs_count = sales_logs.count
+
+ puts "Checking LA on #{lettings_logs_count} lettings logs in #{year}"
+
+ i = 0
+ lettings_logs.find_each do |log|
+ next unless log.valid?
+
+ log.process_postcode_changes!
+ unless log.save
+ puts "Failed to save lettings log #{log.id}"
+ puts "Errors: #{log.errors.full_messages}"
+ end
+
+ if log.la.nil? && log.status == "in_progress"
+ puts "#lettings##{log.id},\"#{log.tenancycode}\",\"#{log.propcode}\",#{log.owning_organisation_id},\"#{log.owning_organisation&.name}\",#{log.managing_organisation_id},\"#{log.managing_organisation&.name}\",#{log.assigned_to_id},\"#{log.assigned_to&.name}\",#{log.startdate},\"#{log.address_line1}\",\"#{log.address_line2}\",\"#{log.town_or_city}\",\"#{log.county}\",\"#{log.postcode_full}\",\"\",\"\""
+ end
+
+ i += 1
+ if (i % 100).zero?
+ puts "Processed #{i} lettings logs"
+ end
+ end
+
+ puts "Done #{lettings_logs_count} lettings logs"
+
+ puts "Checking LA on #{sales_logs_count} sales logs in #{year}"
+
+ i = 0
+ sales_logs.find_each do |log|
+ next unless log.valid?
+
+ log.process_postcode_changes!
+ unless log.save
+ puts "Failed to save sales log #{log.id}"
+ puts "Errors: #{log.errors.full_messages}"
+ end
+
+ if log.la.nil? && log.status == "in_progress"
+ puts "#sales##{log.id},\"#{log.purchid}\",#{log.owning_organisation_id},\"#{log.owning_organisation&.name}\",#{log.managing_organisation_id},\"#{log.managing_organisation&.name}\",#{log.assigned_to_id},\"#{log.assigned_to&.name}\",#{log.saledate},\"#{log.address_line1}\",\"#{log.address_line2}\",\"#{log.town_or_city}\",\"#{log.county}\",\"#{log.postcode_full}\",\"\",\"\""
+ end
+
+ i += 1
+ if (i % 100).zero?
+ puts "Processed #{i} sales logs"
+ end
+ end
+
+ puts "Done #{sales_logs_count} sales logs"
+
+ puts "Done"
+ end
+
+ desc "Parse the output of search_for_la_on_logs_with_nil_la into separate lettings and sales CSV files"
+ task parse_logs_moved_to_incomplete_with_no_la: :environment do
+ require "csv"
+
+ file = "output.txt"
+
+ lettings_headers = %w[id tenancycode propcode owning_organisation_id owning_organisation managing_organisation_id managing_organisation assigned_to_id assigned_to startdate address_line1 address_line2 town_or_city county postcode_full la_ecode la_name]
+ sales_headers = %w[id purchid owning_organisation_id owning_organisation managing_organisation_id managing_organisation assigned_to_id assigned_to saledate address_line1 address_line2 town_or_city county postcode_full la_ecode la_name]
+
+ lettings_csv = CSV.open("lettings_logs_moved_to_incomplete_with_no_la.csv", "w")
+ sales_csv = CSV.open("sales_logs_moved_to_incomplete_with_no_la.csv", "w")
+
+ lettings_csv << lettings_headers
+ sales_csv << sales_headers
+
+ File.readlines(file).each do |line|
+ line = line.strip
+ if line.start_with?("#lettings#")
+ row = CSV.parse_line(line.delete_prefix("#lettings#"))
+ lettings_csv << row
+ elsif line.start_with?("#sales#")
+ row = CSV.parse_line(line.delete_prefix("#sales#"))
+ sales_csv << row
+ end
+ end
+
+ lettings_csv.close
+ sales_csv.close
+
+ puts "Written lettings_logs_moved_to_incomplete_with_no_la.csv"
+ puts "Written sales_logs_moved_to_incomplete_with_no_la.csv"
+ end
+
+ desc "Split lettings and sales CSVs by managing organisation into separate files per org"
+ task split_logs_by_managing_org: :environment do
+ require "csv"
+
+ %w[lettings sales].each do |log_type|
+ input_file = "#{log_type}_logs_moved_to_incomplete_with_no_la.csv"
+
+ rows_by_org = Hash.new { |h, k| h[k] = [] }
+ table = CSV.read(input_file, headers: true)
+
+ table.each do |row|
+ org_name = row["managing_organisation"]
+ rows_by_org[org_name] << row
+ end
+
+ rows_by_org.each do |org_name, rows|
+ if rows.size < 30
+ puts "Skipping #{org_name} (#{rows.size} rows)"
+ next
+ end
+
+ FileUtils.mkdir_p("log_output")
+ sanitised_name = org_name.parameterize(separator: "_")
+ output_file = "log_output/#{sanitised_name}_#{log_type}_logs_moved_to_incomplete_with_no_la.csv"
+ CSV.open(output_file, "w") do |csv|
+ csv << table.headers
+ rows.each { |row| csv << row }
+ end
+ puts "Written #{output_file} (#{rows.size} rows)"
+ end
+ end
+ end
+end
From 51a684e5ca0fd414a121ea7856586d02b0651e92 Mon Sep 17 00:00:00 2001
From: Nat Dean-Lewis <94526761+natdeanlewissoftwire@users.noreply.github.com>
Date: Tue, 21 Apr 2026 09:39:32 +0100
Subject: [PATCH 13/34] CLDC-4436: use liberal parsing for sales log with
purchid in quotes (105099) (#3323)
---
lib/tasks/log_la_fix.rake | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/lib/tasks/log_la_fix.rake b/lib/tasks/log_la_fix.rake
index 1a13602be..61de339c2 100644
--- a/lib/tasks/log_la_fix.rake
+++ b/lib/tasks/log_la_fix.rake
@@ -79,10 +79,10 @@ namespace :log_la_fix do
File.readlines(file).each do |line|
line = line.strip
if line.start_with?("#lettings#")
- row = CSV.parse_line(line.delete_prefix("#lettings#"))
+ row = CSV.parse_line(line.delete_prefix("#lettings#"), liberal_parsing: true)
lettings_csv << row
elsif line.start_with?("#sales#")
- row = CSV.parse_line(line.delete_prefix("#sales#"))
+ row = CSV.parse_line(line.delete_prefix("#sales#"), liberal_parsing: true)
sales_csv << row
end
end
From 2fae205cf17060936562b21e136cb49ee234b53d Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Tue, 21 Apr 2026 11:26:47 +0100
Subject: [PATCH 14/34] CLDC-4250: New universal credit validation (#3299)
* CLDC-4250: Add a new validation for universal credit and household income sources
* CLDC-4250: Add verifying tests
* CLDC-4250: Add a post release script
* fixup! CLDC-4250: Add verifying tests
remove unneeded setup
* fixup! CLDC-4250: Add verifying tests
fix test name
* CLDC-4250: make benefits also invalid
as requested on ticket
update rake
---
app/models/lettings_log.rb | 21 ++--
.../validations/financial_validations.rb | 9 ++
.../validations/lettings/financial.en.yml | 3 +
...te_logs_with_invalid_hb_benefits_2026.rake | 10 ++
.../validations/financial_validations_spec.rb | 101 +++++++++++++++++-
5 files changed, 125 insertions(+), 19 deletions(-)
create mode 100644 lib/tasks/update_logs_with_invalid_hb_benefits_2026.rake
diff --git a/app/models/lettings_log.rb b/app/models/lettings_log.rb
index 0ac9f728d..2e6b800eb 100644
--- a/app/models/lettings_log.rb
+++ b/app/models/lettings_log.rb
@@ -542,7 +542,7 @@ class LettingsLog < Log
reason == 1
end
- def receives_housing_benefit_only?
+ def receives_housing_benefit?
# 1: Housing benefit
hb == 1
end
@@ -551,13 +551,7 @@ class LettingsLog < Log
hb == 3
end
- # Option 8 has been removed starting from 22/23
- def receives_housing_benefit_and_universal_credit?
- # 8: Housing benefit and Universal Credit (without housing element)
- hb == 8
- end
-
- def receives_uc_with_housing_element_excl_housing_benefit?
+ def receives_universal_credit
# 6: Universal Credit with housing element (excluding housing benefit)
hb == 6
end
@@ -572,12 +566,11 @@ class LettingsLog < Log
end
def receives_housing_related_benefits?
- if collection_start_year <= 2021
- receives_housing_benefit_only? || receives_uc_with_housing_element_excl_housing_benefit? ||
- receives_housing_benefit_and_universal_credit?
- else
- receives_housing_benefit_only? || receives_uc_with_housing_element_excl_housing_benefit?
- end
+ receives_housing_benefit? || receives_universal_credit
+ end
+
+ def no_household_income_comes_from_benefits?
+ benefits == 3
end
def local_housing_referral?
diff --git a/app/models/validations/financial_validations.rb b/app/models/validations/financial_validations.rb
index 3dd6890be..a5794a5e3 100644
--- a/app/models/validations/financial_validations.rb
+++ b/app/models/validations/financial_validations.rb
@@ -175,6 +175,15 @@ module Validations::FinancialValidations
end
end
+ def validate_housing_benefits_matches_income_proportion(record)
+ return unless record.hb && record.benefits && record.form.start_year_2026_or_later?
+
+ if (record.receives_universal_credit || record.receives_housing_benefit?) && record.no_household_income_comes_from_benefits?
+ record.errors.add :hb, I18n.t("validations.lettings.financial.hb.housing_benefits_not_match_income_source")
+ record.errors.add :benefits, I18n.t("validations.lettings.financial.benefits.housing_benefits_not_match_income_source")
+ end
+ end
+
private
def validate_charges(record)
diff --git a/config/locales/validations/lettings/financial.en.yml b/config/locales/validations/lettings/financial.en.yml
index d91610602..6f83e85aa 100644
--- a/config/locales/validations/lettings/financial.en.yml
+++ b/config/locales/validations/lettings/financial.en.yml
@@ -12,6 +12,7 @@ en:
outstanding_amount_not_expected: "Answer must be ‘yes’ as you have answered the outstanding amount question."
benefits:
part_or_full_time: "Answer cannot be ‘all’ for income from Universal Credit, state pensions or benefits if the tenant or their partner works part-time or full-time."
+ housing_benefits_not_match_income_source: "You answered that none of the household’s income is from Universal Credit, state pensions or benefits, but also that the tenant is likely to be receiving Universal Credit or housing benefit."
earnings:
over_hard_max: "The household’s income cannot be greater than %{hard_max} per week given the household’s working situation."
under_hard_min: "The household’s income cannot be less than %{hard_min} per week given the household’s working situation."
@@ -87,3 +88,5 @@ en:
needstype:
rent_below_hard_min: "Rent is below the absolute minimum expected for a property of this type based on this lettings type."
rent_above_hard_max: "Rent is higher than the absolute maximum expected for a property of this type based on this lettings type."
+ hb:
+ housing_benefits_not_match_income_source: "You answered that none of the household’s income is from Universal Credit, state pensions or benefits, but also that the tenant is likely to be receiving Universal Credit or housing benefit."
diff --git a/lib/tasks/update_logs_with_invalid_hb_benefits_2026.rake b/lib/tasks/update_logs_with_invalid_hb_benefits_2026.rake
new file mode 100644
index 000000000..638d7d899
--- /dev/null
+++ b/lib/tasks/update_logs_with_invalid_hb_benefits_2026.rake
@@ -0,0 +1,10 @@
+desc "For logs that fail the validate_housing_universal_credit_matches_income_proportion check created before we released it, clear the answer to the question"
+task update_logs_with_invalid_hb_benefits_2026: :environment do
+ impacted_logs = LettingsLog.filter_by_year(2026).where(hb: [1, 6], benefits: 3)
+
+ puts "#{impacted_logs.count} logs will be updated #{impacted_logs.map(&:id)}"
+
+ impacted_logs.update!(benefits: nil, hb: nil)
+
+ puts "Done"
+end
diff --git a/spec/models/validations/financial_validations_spec.rb b/spec/models/validations/financial_validations_spec.rb
index 14e2dfd0c..e4bdb2e82 100644
--- a/spec/models/validations/financial_validations_spec.rb
+++ b/spec/models/validations/financial_validations_spec.rb
@@ -5,11 +5,6 @@ RSpec.describe Validations::FinancialValidations do
let(:validator_class) { Class.new { include Validations::FinancialValidations } }
let(:record) { FactoryBot.create(:lettings_log) }
- let(:fake_2021_2022_form) { Form.new("spec/fixtures/forms/2021_2022.json") }
-
- before do
- allow(FormHandler.instance).to receive(:current_lettings_form).and_return(fake_2021_2022_form)
- end
describe "earnings and income frequency" do
it "when earnings are provided it validates that income frequency must be provided" do
@@ -1234,4 +1229,100 @@ RSpec.describe Validations::FinancialValidations do
end
end
end
+
+ describe "universal credit and income sources validations" do
+ before do
+ record.hb = hb
+ record.benefits = benefits
+ end
+
+ context "with a 2025 form", metadata: { year: 25 } do
+ before do
+ allow(record.form).to receive(:start_year_2026_or_later?).and_return(false)
+ end
+
+ context "when tenant receives universal credit and no household income comes from benefits" do
+ let(:hb) { 6 }
+ let(:benefits) { 3 }
+
+ it "does not add errors" do
+ financial_validator.validate_housing_benefits_matches_income_proportion(record)
+ expect(record.errors["hb"]).to be_empty
+ expect(record.errors["benefits"]).to be_empty
+ end
+ end
+ end
+
+ context "with a 2026 form", metadata: { year: 26 } do
+ before do
+ allow(record.form).to receive(:start_year_2026_or_later?).and_return(true)
+ end
+
+ context "when tenant receives universal credit and no household income comes from benefits" do
+ let(:hb) { 6 }
+ let(:benefits) { 3 }
+
+ it "adds errors to hb and benefits" do
+ financial_validator.validate_housing_benefits_matches_income_proportion(record)
+ expect(record.errors["hb"]).to include(match I18n.t("validations.lettings.financial.hb.housing_benefits_not_match_income_source"))
+ expect(record.errors["benefits"]).to include(match I18n.t("validations.lettings.financial.benefits.housing_benefits_not_match_income_source"))
+ end
+ end
+
+ context "when tenant receives universal credit and some household income comes from benefits" do
+ let(:hb) { 6 }
+ let(:benefits) { 2 }
+
+ it "does not add errors" do
+ financial_validator.validate_housing_benefits_matches_income_proportion(record)
+ expect(record.errors["hb"]).to be_empty
+ expect(record.errors["benefits"]).to be_empty
+ end
+ end
+
+ context "when tenant receives housing benefit and no household income comes from benefits" do
+ let(:hb) { 1 }
+ let(:benefits) { 3 }
+
+ it "adds errors to hb and benefits" do
+ financial_validator.validate_housing_benefits_matches_income_proportion(record)
+ expect(record.errors["hb"]).to include(match I18n.t("validations.lettings.financial.hb.housing_benefits_not_match_income_source"))
+ expect(record.errors["benefits"]).to include(match I18n.t("validations.lettings.financial.benefits.housing_benefits_not_match_income_source"))
+ end
+ end
+
+ context "when tenant receives housing benefit and some household income comes from benefits" do
+ let(:hb) { 1 }
+ let(:benefits) { 2 }
+
+ it "does not add errors" do
+ financial_validator.validate_housing_benefits_matches_income_proportion(record)
+ expect(record.errors["hb"]).to be_empty
+ expect(record.errors["benefits"]).to be_empty
+ end
+ end
+
+ context "when hb is not set" do
+ let(:hb) { nil }
+ let(:benefits) { 3 }
+
+ it "does not add errors" do
+ financial_validator.validate_housing_benefits_matches_income_proportion(record)
+ expect(record.errors["hb"]).to be_empty
+ expect(record.errors["benefits"]).to be_empty
+ end
+ end
+
+ context "when benefits is not set" do
+ let(:hb) { 6 }
+ let(:benefits) { nil }
+
+ it "does not add errors" do
+ financial_validator.validate_housing_benefits_matches_income_proportion(record)
+ expect(record.errors["hb"]).to be_empty
+ expect(record.errors["benefits"]).to be_empty
+ end
+ end
+ end
+ end
end
From 4f53210b6ada26dfd146f44d9123be74ddd9dc11 Mon Sep 17 00:00:00 2001
From: Nat Dean-Lewis <94526761+natdeanlewissoftwire@users.noreply.github.com>
Date: Tue, 21 Apr 2026 15:10:36 +0100
Subject: [PATCH 15/34] CLDC-4429 and CLDC-4242: dependency updates (#3312)
* CLDC-4429: push fix commented to test failure on review app
* CLDC-4429: remove redundant fix
* CLDC-4229: update alpine to 3.22 in dockerfile
* CLDC-4229: update alpine to 3.21 to avoid upgrading node
* CLDC-4229: allow node 22
* CLDC-4229: excplitlyupgrade for security patches
* CLDC-4229: allow both node versions temporarily
* CLDC-4229: upgrade ruby and node at the same tiem
* CLDC-4229: upgrade gemfile
* CLDC-4229: bump to node 24
* CLDC-4229: update docs
* CLDC-4229: limit node to within 24
* CLDC-4229: upgrade at start of file
* CLDC-4229: upgrade at start of file
* CLDC-4229: remove stale ruby version references
* CLDC-4429: respond to wiz comments
* CLDC-4429: use same firefox
---
.github/workflows/run_tests.yml | 20 +++++++-------------
.nvmrc | 2 +-
.ruby-version | 2 +-
Dockerfile | 15 +++++++++------
Gemfile | 2 +-
Gemfile.lock | 2 +-
docs/setup.md | 10 ++++------
package.json | 2 +-
8 files changed, 25 insertions(+), 30 deletions(-)
diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml
index fde032a69..b4d4f697d 100644
--- a/.github/workflows/run_tests.yml
+++ b/.github/workflows/run_tests.yml
@@ -38,7 +38,6 @@ jobs:
env:
RAILS_ENV: test
- GEMFILE_RUBY_VERSION: 3.1.1
DB_HOST: localhost
DB_DATABASE: data_collector
DB_USERNAME: postgres
@@ -59,7 +58,7 @@ jobs:
uses: actions/setup-node@v4
with:
cache: yarn
- node-version: 20
+ node-version: 24
# This is temporary to fix flaky parallel tests due to `secret_key_base` being read before it's set
- name: Create local secret
@@ -102,7 +101,6 @@ jobs:
env:
RAILS_ENV: test
- GEMFILE_RUBY_VERSION: 3.1.1
DB_HOST: localhost
DB_DATABASE: data_collector
DB_USERNAME: postgres
@@ -122,7 +120,7 @@ jobs:
uses: actions/setup-node@v4
with:
cache: yarn
- node-version: 20
+ node-version: 24
- name: Create database
run: |
@@ -160,7 +158,6 @@ jobs:
env:
RAILS_ENV: test
- GEMFILE_RUBY_VERSION: 3.1.1
DB_HOST: localhost
DB_DATABASE: data_collector
DB_USERNAME: postgres
@@ -180,7 +177,7 @@ jobs:
uses: actions/setup-node@v4
with:
cache: yarn
- node-version: 20
+ node-version: 24
- name: Create database
run: |
@@ -218,7 +215,6 @@ jobs:
env:
RAILS_ENV: test
- GEMFILE_RUBY_VERSION: 3.1.1
DB_HOST: localhost
DB_DATABASE: data_collector
DB_USERNAME: postgres
@@ -239,7 +235,7 @@ jobs:
uses: actions/setup-node@v4
with:
cache: yarn
- node-version: 20
+ node-version: 24
- name: Create local secret
run: |
@@ -281,7 +277,6 @@ jobs:
env:
RAILS_ENV: test
- GEMFILE_RUBY_VERSION: 3.1.1
DB_HOST: localhost
DB_DATABASE: data_collector
DB_USERNAME: postgres
@@ -302,7 +297,7 @@ jobs:
uses: actions/setup-node@v4
with:
cache: yarn
- node-version: 20
+ node-version: 24
- name: Create local secret
run: |
@@ -344,7 +339,6 @@ jobs:
env:
RAILS_ENV: test
- GEMFILE_RUBY_VERSION: 3.1.1
DB_HOST: localhost
DB_DATABASE: data_collector
DB_USERNAME: postgres
@@ -365,7 +359,7 @@ jobs:
uses: actions/setup-node@v4
with:
cache: yarn
- node-version: 20
+ node-version: 24
- name: Create database
run: |
@@ -396,7 +390,7 @@ jobs:
uses: actions/setup-node@v4
with:
cache: yarn
- node-version: 20
+ node-version: 24
- name: Install packages and symlink local dependencies
run: |
diff --git a/.nvmrc b/.nvmrc
index 209e3ef4b..a45fd52cc 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-20
+24
diff --git a/.ruby-version b/.ruby-version
index f9892605c..7bcbb3808 100644
--- a/.ruby-version
+++ b/.ruby-version
@@ -1 +1 @@
-3.4.4
+3.4.9
diff --git a/Dockerfile b/Dockerfile
index 88a7e6a79..ce24943c2 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,7 +1,10 @@
-FROM ruby:3.4.4-alpine3.20 as base
+FROM ruby:3.4.9-alpine3.23 as base
WORKDIR /app
+# Upgrade base packages to pick up latest security patches
+RUN apk upgrade --no-cache
+
# Add the timezone as it's not configured by default in Alpine
RUN apk add --update --no-cache tzdata && \
cp /usr/share/zoneinfo/Europe/London /etc/localtime && \
@@ -10,7 +13,7 @@ RUN apk add --update --no-cache tzdata && \
# build-base: compilation tools for bundle
# yarn: node package manager
# postgresql-dev: postgres driver and libraries
-RUN apk add --no-cache build-base=0.5-r3 busybox=1.36.1-r29 nodejs=20.15.1-r0 yarn=1.22.22-r0 bash=5.2.26-r0 libpq-dev yaml-dev linux-headers
+RUN apk add --no-cache build-base busybox nodejs yarn bash libpq-dev yaml-dev linux-headers
# Bundler version should be the same version as what the Gemfile.lock was bundled with
RUN gem install bundler:2.6.4 --no-document
@@ -40,14 +43,14 @@ RUN bundle config set without ""
RUN bundle install --jobs=4 --no-binstubs --no-cache
# Install gecko driver for Capybara tests
-RUN apk add firefox
+RUN apk add firefox=145.0-r0
RUN wget https://github.com/mozilla/geckodriver/releases/download/v0.31.0/geckodriver-v0.31.0-linux64.tar.gz \
&& tar -xvzf geckodriver-v0.31.0-linux64.tar.gz \
&& rm geckodriver-v0.31.0-linux64.tar.gz \
&& chmod +x geckodriver \
&& mv geckodriver /usr/local/bin/
-CMD bundle exec rake parallel:setup && bundle exec rake parallel:spec
+CMD ["sh", "-c", "bundle exec rake parallel:setup && bundle exec rake parallel:spec"]
FROM base as development
@@ -61,7 +64,7 @@ RUN bundle install --jobs=4 --no-binstubs --no-cache
USER nonroot
-CMD bundle exec rails s -e ${RAILS_ENV} -p ${PORT} --binding=0.0.0.0
+CMD ["sh", "-c", "bundle exec rails s -e ${RAILS_ENV} -p ${PORT} --binding=0.0.0.0"]
FROM base as production
@@ -75,4 +78,4 @@ RUN chown -R nonroot performance_test
USER nonroot
-CMD bundle exec rails s -e ${RAILS_ENV} -p ${PORT} --binding=0.0.0.0
+CMD ["sh", "-c", "bundle exec rails s -e ${RAILS_ENV} -p ${PORT} --binding=0.0.0.0"]
diff --git a/Gemfile b/Gemfile
index 91ed6c8a8..c76a48bec 100644
--- a/Gemfile
+++ b/Gemfile
@@ -3,7 +3,7 @@
source "https://rubygems.org"
git_source(:github) { |repo| "https://github.com/#{repo}.git" }
-ruby "3.4.4"
+ruby "3.4.9"
# Bundle edge Rails instead: gem 'rails', github: 'rails/rails', branch: 'main'
gem "rails", "~> 7.2.2"
diff --git a/Gemfile.lock b/Gemfile.lock
index 85aa27b6d..c83c95414 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -648,7 +648,7 @@ DEPENDENCIES
webmock
RUBY VERSION
- ruby 3.4.4p0
+ ruby 3.4.9p82
BUNDLED WITH
2.6.4
diff --git a/docs/setup.md b/docs/setup.md
index 8bf9c635f..9f66e234c 100644
--- a/docs/setup.md
+++ b/docs/setup.md
@@ -70,21 +70,19 @@ We recommend using [nvm](https://github.com/nvm-sh/nvm) to manage NodeJS version
4. Install Ruby and Bundler
```bash
- rbenv install 3.4.4
- rbenv global 3.4.4
+ rbenv install 3.4.9
+ rbenv global 3.4.9
source ~/.bashrc
gem install bundler
```
5. Install JavaScript dependencies
- Note that we currently use node v16, which is no longer the latest LTS version so you will need to specify the version number when installing
-
macOS (using nvm):
```bash
- nvm install 20
- nvm use 20
+ nvm install 24
+ nvm use 24
brew install yarn
```
diff --git a/package.json b/package.json
index c2efb5da1..837240f58 100644
--- a/package.json
+++ b/package.json
@@ -2,7 +2,7 @@
"name": "data-collector",
"private": true,
"engines": {
- "node": "^20.0.0"
+ "node": "^24.0.0"
},
"dependencies": {
"@babel/core": "^7.17.7",
From cd6973c557dedff58811bf2a1a51d8271f5615f9 Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Thu, 23 Apr 2026 14:45:25 +0100
Subject: [PATCH 16/34] CLDC-3205: Income soft validation not always being
shown (#3302)
* CLDC-3205: Add net income value check where missing
hhmemb
ecstat1..8
age2..8 (twice as the age question moved)
* CLDC-3205: Group household_characteristics better
* CLDC-3205: Update tests
* CLDC-3205: Update csv export specs
* fixup! CLDC-3205: Update tests
---
.../lettings/pages/net_income_value_check.rb | 25 ++++++++--
.../subsections/household_characteristics.rb | 10 ++++
.../subsections/income_and_benefits.rb | 2 +-
.../lettings_log_csv_export_codes_24.csv | 6 +--
.../lettings_log_csv_export_codes_25.csv | 6 +--
.../lettings_log_csv_export_codes_26.csv | 6 +--
.../lettings_log_csv_export_labels_25.csv | 6 +--
.../lettings_log_csv_export_labels_26.csv | 6 +--
.../pages/net_income_value_check_spec.rb | 4 --
.../household_characteristics_spec.rb | 48 +++++++++++++++++++
.../subsections/income_and_benefits_spec.rb | 4 +-
11 files changed, 97 insertions(+), 26 deletions(-)
diff --git a/app/models/form/lettings/pages/net_income_value_check.rb b/app/models/form/lettings/pages/net_income_value_check.rb
index 9bdce131d..5eb850725 100644
--- a/app/models/form/lettings/pages/net_income_value_check.rb
+++ b/app/models/form/lettings/pages/net_income_value_check.rb
@@ -1,9 +1,9 @@
class Form::Lettings::Pages::NetIncomeValueCheck < ::Form::Page
- def initialize(id, hsh, subsection)
- super
- @id = "net_income_value_check"
+ def initialize(id, hsh, subsection, person_index: nil)
+ super(id, hsh, subsection)
@copy_key = "lettings.soft_validations.net_income_value_check"
- @depends_on = [{ "net_income_soft_validation_triggered?" => true }]
+ @person_index = person_index
+ @depends_on = depends_on
@title_text = {
"translation" => "forms.#{form.start_date.year}.#{@copy_key}.title_text",
"arguments" => [
@@ -32,6 +32,23 @@ class Form::Lettings::Pages::NetIncomeValueCheck < ::Form::Page
}
end
+ def depends_on
+ if @person_index.present?
+ [
+ {
+ "net_income_soft_validation_triggered?" => true,
+ "details_known_#{@person_index}" => 0,
+ },
+ ]
+ else
+ [
+ {
+ "net_income_soft_validation_triggered?" => true,
+ },
+ ]
+ end
+ end
+
def questions
@questions ||= [Form::Lettings::Questions::NetIncomeValueCheck.new(nil, nil, self)]
end
diff --git a/app/models/form/lettings/subsections/household_characteristics.rb b/app/models/form/lettings/subsections/household_characteristics.rb
index 5ac573df3..104d72a0b 100644
--- a/app/models/form/lettings/subsections/household_characteristics.rb
+++ b/app/models/form/lettings/subsections/household_characteristics.rb
@@ -13,6 +13,7 @@ class Form::Lettings::Subsections::HouseholdCharacteristics < ::Form::Subsection
(Form::Lettings::Pages::NoFemalesPregnantHouseholdLeadHhmembValueCheck.new(nil, nil, self) unless form.start_year_2026_or_later?),
(Form::Lettings::Pages::FemalesInSoftAgeRangeInPregnantHouseholdLeadHhmembValueCheck.new(nil, nil, self) unless form.start_year_2026_or_later?),
(Form::Lettings::Pages::NoHouseholdMemberLikelyToBePregnantCheck.new("no_household_member_likely_to_be_pregnant_hhmemb_check", nil, self) if form.start_year_2026_or_later?),
+ Form::Lettings::Pages::NetIncomeValueCheck.new("hhmemb_net_income_value_check", nil, self),
Form::Lettings::Pages::LeadTenantAge.new(nil, nil, self),
(Form::Lettings::Pages::NoFemalesPregnantHouseholdLeadAgeValueCheck.new(nil, nil, self) unless form.start_year_2026_or_later?),
(Form::Lettings::Pages::FemalesInSoftAgeRangeInPregnantHouseholdLeadAgeValueCheck.new(nil, nil, self) unless form.start_year_2026_or_later?),
@@ -37,6 +38,7 @@ class Form::Lettings::Subsections::HouseholdCharacteristics < ::Form::Subsection
Form::Lettings::Pages::LeadTenantUnderRetirementValueCheck.new("working_situation_lead_tenant_under_retirement_value_check", nil, self),
Form::Lettings::Pages::LeadTenantOverRetirementValueCheck.new("working_situation_lead_tenant_over_retirement_value_check", nil, self),
(Form::Lettings::Pages::WorkingSituationIllnessCheckLead.new("working_situation_lead_tenant_long_term_illness_check", nil, self) if form.start_year_2026_or_later?),
+ Form::Lettings::Pages::NetIncomeValueCheck.new("working_situation_lead_tenant_net_income_value_check", nil, self),
*person_questions(person_index: 2),
*person_questions(person_index: 3),
*person_questions(person_index: 4),
@@ -50,10 +52,14 @@ class Form::Lettings::Subsections::HouseholdCharacteristics < ::Form::Subsection
def person_questions(person_index:)
[
Form::Lettings::Pages::PersonKnown.new(nil, nil, self, person_index:),
+
(Form::Lettings::Pages::PersonAge.new(nil, nil, self, person_index:) if form.start_year_2026_or_later?),
+ (Form::Lettings::Pages::NetIncomeValueCheck.new("age_#{person_index}_net_income_value_check", nil, self, person_index:) if form.start_year_2026_or_later?),
+
relationship_question(person_index:),
(Form::Lettings::Pages::PartnerUnder16ValueCheck.new("relationship_#{person_index}_partner_under_16_value_check", nil, self, person_index:) unless form.start_year_2026_or_later?),
(Form::Lettings::Pages::MultiplePartnersValueCheck.new("relationship_#{person_index}_multiple_partners_value_check", nil, self, person_index:) unless form.start_year_2026_or_later?),
+
(Form::Lettings::Pages::PersonAge.new(nil, nil, self, person_index:) unless form.start_year_2026_or_later?),
(Form::Lettings::Pages::NoFemalesPregnantHouseholdPersonAgeValueCheck.new(nil, nil, self, person_index:) unless form.start_year_2026_or_later?),
(Form::Lettings::Pages::FemalesInSoftAgeRangeInPregnantHouseholdPersonAgeValueCheck.new(nil, nil, self, person_index:) unless form.start_year_2026_or_later?),
@@ -61,6 +67,8 @@ class Form::Lettings::Subsections::HouseholdCharacteristics < ::Form::Subsection
Form::Lettings::Pages::PersonUnderRetirementValueCheck.new("age_#{person_index}_under_retirement_value_check", nil, self, person_index:),
Form::Lettings::Pages::PersonOverRetirementValueCheck.new("age_#{person_index}_over_retirement_value_check", nil, self, person_index:),
(Form::Lettings::Pages::PartnerUnder16ValueCheck.new("age_#{person_index}_partner_under_16_value_check", nil, self, person_index:) unless form.start_year_2026_or_later?),
+ (Form::Lettings::Pages::NetIncomeValueCheck.new("age_#{person_index}_net_income_value_check", nil, self, person_index:) unless form.start_year_2026_or_later?),
+
(Form::Lettings::Pages::PersonSexRegisteredAtBirth.new(nil, nil, self, person_index:) if form.start_year_2026_or_later?),
(Form::Lettings::Pages::PersonGenderSameAsSex.new(nil, nil, self, person_index:) if form.start_year_2026_or_later?),
(Form::Lettings::Pages::PersonGenderIdentity.new(nil, nil, self, person_index:) unless form.start_year_2026_or_later?),
@@ -68,10 +76,12 @@ class Form::Lettings::Subsections::HouseholdCharacteristics < ::Form::Subsection
(Form::Lettings::Pages::FemalesInSoftAgeRangeInPregnantHouseholdPersonValueCheck.new(nil, nil, self, person_index:) unless form.start_year_2026_or_later?),
(Form::Lettings::Pages::NoHouseholdMemberLikelyToBePregnantCheck.new("no_household_member_likely_to_be_pregnant_person_#{person_index}_check", nil, self, person_index:) if form.start_year_2026_or_later?),
Form::Lettings::Pages::PersonOverRetirementValueCheck.new("gender_#{person_index}_over_retirement_value_check", nil, self, person_index:),
+
Form::Lettings::Pages::PersonWorkingSituation.new(nil, nil, self, person_index:),
Form::Lettings::Pages::PersonUnderRetirementValueCheck.new("working_situation_#{person_index}_under_retirement_value_check", nil, self, person_index:),
Form::Lettings::Pages::PersonOverRetirementValueCheck.new("working_situation_#{person_index}_over_retirement_value_check", nil, self, person_index:),
(Form::Lettings::Pages::WorkingSituationIllnessCheckPerson.new("working_situation_#{person_index}_long_term_illness_check", nil, self, person_index:) if form.start_year_2026_or_later?),
+ Form::Lettings::Pages::NetIncomeValueCheck.new("working_situation_#{person_index}_net_income_value_check", nil, self, person_index:),
]
end
diff --git a/app/models/form/lettings/subsections/income_and_benefits.rb b/app/models/form/lettings/subsections/income_and_benefits.rb
index e037dfc2a..36a36766d 100644
--- a/app/models/form/lettings/subsections/income_and_benefits.rb
+++ b/app/models/form/lettings/subsections/income_and_benefits.rb
@@ -10,7 +10,7 @@ class Form::Lettings::Subsections::IncomeAndBenefits < ::Form::Subsection
@pages ||= [
Form::Lettings::Pages::IncomeKnown.new(nil, nil, self),
Form::Lettings::Pages::IncomeAmount.new(nil, nil, self),
- Form::Lettings::Pages::NetIncomeValueCheck.new(nil, nil, self),
+ Form::Lettings::Pages::NetIncomeValueCheck.new("income_amount_net_income_value_check", nil, self),
Form::Lettings::Pages::HousingBenefit.new("housing_benefit", nil, self),
Form::Lettings::Pages::BenefitsProportion.new("benefits_proportion", nil, self),
Form::Lettings::Pages::RentOrOtherCharges.new(nil, nil, self),
diff --git a/spec/fixtures/files/lettings_log_csv_export_codes_24.csv b/spec/fixtures/files/lettings_log_csv_export_codes_24.csv
index 084318abe..192d6389f 100644
--- a/spec/fixtures/files/lettings_log_csv_export_codes_24.csv
+++ b/spec/fixtures/files/lettings_log_csv_export_codes_24.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?,"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,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?,What type of unit is the property?,Which type of building 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 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?,Is this letting in sheltered accommodation?,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?,Is this accommodation a care home?,"If this is a care home, how much does the household pay every [time period]?",Weekly care home charge,Populated when the soft validation and confirmed in the service,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,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,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,unittype_gn,builtype,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,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,referral_value_check,net_income_known,incref,incfreq,earnings,net_income_value_check,hb,has_benefits,benefits,household_charge,nocharge,period,is_carehome,chcharge,wchchrg,carehome_charges_value_check,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,2024-04-01T00:00:00+01:00,,2024-04-01T00:00:00+01:00,1,2024,,MHCLG,MHCLG,1,7,0,2024-04-01,2,2,,,2,HIJKLMN,ABCDEFG,1,,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,0,2,6,2,7,1,1,3,2024-03-30,1,,1,2024-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,2,,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,,,,,,,,,,,,,,,,,,,,
+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?,"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,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?,What type of unit is the property?,Which type of building 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 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?,Is this letting in sheltered accommodation?,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.,Populated when someone hits the soft validation and confirmed in the service,"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?,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?,Is this accommodation a care home?,"If this is a care home, how much does the household pay every [time period]?",Weekly care home charge,Populated when the soft validation and confirmed in the service,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,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,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,unittype_gn,builtype,wchair,beds,voiddate,vacdays,void_date_value_check,majorrepairs,mrcdate,major_repairs_date_value_check,joint,startertenancy,tenancy,tenancyother,tenancylength,sheltered,hhmemb,pregnancy_value_check,net_income_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,referral_value_check,net_income_known,incref,incfreq,earnings,hb,has_benefits,benefits,household_charge,nocharge,period,is_carehome,chcharge,wchchrg,carehome_charges_value_check,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,2024-04-01T00:00:00+01:00,,2024-04-01T00:00:00+01:00,1,2024,,MHCLG,MHCLG,1,7,0,2024-04-01,2,2,,,2,HIJKLMN,ABCDEFG,1,,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,0,2,6,2,7,1,1,3,2024-03-30,1,,1,2024-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,2,,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_codes_25.csv b/spec/fixtures/files/lettings_log_csv_export_codes_25.csv
index 001b342eb..b51f5831f 100644
--- a/spec/fixtures/files/lettings_log_csv_export_codes_25.csv
+++ b/spec/fixtures/files/lettings_log_csv_export_codes_25.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?,Which type of building 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,builtype,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,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,,,,,,,,,,,,,,,,,,,,
+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?,Which type of building 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.,Populated when someone hits the soft validation and confirmed in the service,"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?,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,builtype,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,net_income_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,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,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_codes_26.csv b/spec/fixtures/files/lettings_log_csv_export_codes_26.csv
index 15e33638a..6e43119e6 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}.,What was the lead tenant's sex at birth?,Is the gender the lead tenant identifies with the same as their sex registered at birth?,"If 'No', enter 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?,The following soft validation was confirmed: You have said that at least one person's situation is 'Unable to work because of long-term sickness or disability'.,Are the details of tenant 2 known?,What is person 2's age?,What is person 2's relationship to the lead tenant?,What was person 2's sex at birth?,Is the gender person 2 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 3's relationship to the lead tenant?,What was person 3's sex at birth?,Is the gender person 3 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 4's relationship to the lead tenant?,What was person 4's sex at birth?,Is the gender person 4 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 5's relationship to the lead tenant?,What was person 5's sex at birth?,Is the gender person 5 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 6's relationship to the lead tenant?,What was person 6's sex at birth?,Is the gender person 6 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 7's relationship to the lead tenant?,What was person 7's sex at birth?,Is the gender person 7 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 8's relationship to the lead tenant?,What was person 8's sex at birth?,Is the gender person 8 identifies with the same as their sex registered at birth?,"If 'No', enter 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?,What was the source of referral for this letting?,What was the source of referral for this letting?,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,tenancyother_value_check,tenancylength,hhmemb,pregnancy_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sexrab1,gender_same_as_sex1,gender_description1,ethnic_group,ethnic,nationality_all,ecstat1,working_situation_illness_check,details_known_2,age2,relat2,sexrab2,gender_same_as_sex2,gender_description2,ecstat2,details_known_3,age3,relat3,sexrab3,gender_same_as_sex3,gender_description3,ecstat3,details_known_4,age4,relat4,sexrab4,gender_same_as_sex4,gender_description4,ecstat4,details_known_5,age5,relat5,sexrab5,gender_same_as_sex5,gender_description5,ecstat5,details_known_6,age6,relat6,sexrab6,gender_same_as_sex6,gender_description6,ecstat6,details_known_7,age7,relat7,sexrab7,gender_same_as_sex7,gender_description7,ecstat7,details_known_8,age8,relat8,sexrab8,gender_same_as_sex8,gender_description8,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_register,referral_noms,referral_org,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,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,1,,0,2,36,0,,0,32,P,M,2,Non-binary,6,1,-9,R,R,3,,10,0,-9,R,R,3,,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,1,,,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,,,,,,,,,,,,,,,,,,,,
+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.,Populated when someone hits the soft validation and confirmed in the service,"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}.,What was the lead tenant's sex at birth?,Is the gender the lead tenant identifies with the same as their sex registered at birth?,"If 'No', enter 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?,The following soft validation was confirmed: You have said that at least one person's situation is 'Unable to work because of long-term sickness or disability'.,Are the details of tenant 2 known?,What is person 2's age?,What is person 2's relationship to the lead tenant?,What was person 2's sex at birth?,Is the gender person 2 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 3's relationship to the lead tenant?,What was person 3's sex at birth?,Is the gender person 3 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 4's relationship to the lead tenant?,What was person 4's sex at birth?,Is the gender person 4 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 5's relationship to the lead tenant?,What was person 5's sex at birth?,Is the gender person 5 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 6's relationship to the lead tenant?,What was person 6's sex at birth?,Is the gender person 6 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 7's relationship to the lead tenant?,What was person 7's sex at birth?,Is the gender person 7 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 8's relationship to the lead tenant?,What was person 8's sex at birth?,Is the gender person 8 identifies with the same as their sex registered at birth?,"If 'No', enter 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?,What was the source of referral for this letting?,What was the source of referral for this letting?,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?,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,tenancyother_value_check,tenancylength,hhmemb,pregnancy_value_check,net_income_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sexrab1,gender_same_as_sex1,gender_description1,ethnic_group,ethnic,nationality_all,ecstat1,working_situation_illness_check,details_known_2,age2,relat2,sexrab2,gender_same_as_sex2,gender_description2,ecstat2,details_known_3,age3,relat3,sexrab3,gender_same_as_sex3,gender_description3,ecstat3,details_known_4,age4,relat4,sexrab4,gender_same_as_sex4,gender_description4,ecstat4,details_known_5,age5,relat5,sexrab5,gender_same_as_sex5,gender_description5,ecstat5,details_known_6,age6,relat6,sexrab6,gender_same_as_sex6,gender_description6,ecstat6,details_known_7,age7,relat7,sexrab7,gender_same_as_sex7,gender_description7,ecstat7,details_known_8,age8,relat8,sexrab8,gender_same_as_sex8,gender_description8,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_register,referral_noms,referral_org,net_income_known,incref,incfreq,earnings,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,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,1,,0,2,36,0,,0,32,P,M,2,Non-binary,6,1,-9,R,R,3,,10,0,-9,R,R,3,,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,1,,,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_25.csv b/spec/fixtures/files/lettings_log_csv_export_labels_25.csv
index d06f25efe..445a5dda8 100644
--- a/spec/fixtures/files/lettings_log_csv_export_labels_25.csv
+++ b/spec/fixtures/files/lettings_log_csv_export_labels_25.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?,Which type of building 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,builtype,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,Purpose-built,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,Under 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,,,,,,,,,,,,,,,,,,,,
+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?,Which type of building 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.,Populated when someone hits the soft validation and confirmed in the service,"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?,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,builtype,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,net_income_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,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,Purpose-built,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,Under 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_labels_26.csv b/spec/fixtures/files/lettings_log_csv_export_labels_26.csv
index cc2117437..a8a2494ed 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}.,What was the lead tenant's sex at birth?,Is the gender the lead tenant identifies with the same as their sex registered at birth?,"If 'No', enter 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?,The following soft validation was confirmed: You have said that at least one person's situation is 'Unable to work because of long-term sickness or disability'.,Are the details of tenant 2 known?,What is person 2's age?,What is person 2's relationship to the lead tenant?,What was person 2's sex at birth?,Is the gender person 2 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 3's relationship to the lead tenant?,What was person 3's sex at birth?,Is the gender person 3 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 4's relationship to the lead tenant?,What was person 4's sex at birth?,Is the gender person 4 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 5's relationship to the lead tenant?,What was person 5's sex at birth?,Is the gender person 5 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 6's relationship to the lead tenant?,What was person 6's sex at birth?,Is the gender person 6 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 7's relationship to the lead tenant?,What was person 7's sex at birth?,Is the gender person 7 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 8's relationship to the lead tenant?,What was person 8's sex at birth?,Is the gender person 8 identifies with the same as their sex registered at birth?,"If 'No', enter 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?,What was the source of referral for this letting?,What was the source of referral for this letting?,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,tenancyother_value_check,tenancylength,hhmemb,pregnancy_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sexrab1,gender_same_as_sex1,gender_description1,ethnic_group,ethnic,nationality_all,ecstat1,working_situation_illness_check,details_known_2,age2,relat2,sexrab2,gender_same_as_sex2,gender_description2,ecstat2,details_known_3,age3,relat3,sexrab3,gender_same_as_sex3,gender_description3,ecstat3,details_known_4,age4,relat4,sexrab4,gender_same_as_sex4,gender_description4,ecstat4,details_known_5,age5,relat5,sexrab5,gender_same_as_sex5,gender_description5,ecstat5,details_known_6,age6,relat6,sexrab6,gender_same_as_sex6,gender_description6,ecstat6,details_known_7,age7,relat7,sexrab7,gender_same_as_sex7,gender_description7,ecstat7,details_known_8,age8,relat8,sexrab8,gender_same_as_sex8,gender_description8,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_register,referral_noms,referral_org,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,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,Yes,,White,Irish,Australia,Other,,Yes,32,Yes,Male,"No, enter gender identity",Non-binary,Not seeking work,No,Not known,Prefers not to say,Prefers not to say,Prefers not to say,,Prefers not to say,Yes,Not known,Tenant prefers not to say,Prefers not to say,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,Under 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,Renewal to the same tenant in the same property,,,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,,,,,,,,,,,,,,,,,,,,
+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.,Populated when someone hits the soft validation and confirmed in the service,"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}.,What was the lead tenant's sex at birth?,Is the gender the lead tenant identifies with the same as their sex registered at birth?,"If 'No', enter 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?,The following soft validation was confirmed: You have said that at least one person's situation is 'Unable to work because of long-term sickness or disability'.,Are the details of tenant 2 known?,What is person 2's age?,What is person 2's relationship to the lead tenant?,What was person 2's sex at birth?,Is the gender person 2 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 3's relationship to the lead tenant?,What was person 3's sex at birth?,Is the gender person 3 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 4's relationship to the lead tenant?,What was person 4's sex at birth?,Is the gender person 4 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 5's relationship to the lead tenant?,What was person 5's sex at birth?,Is the gender person 5 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 6's relationship to the lead tenant?,What was person 6's sex at birth?,Is the gender person 6 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 7's relationship to the lead tenant?,What was person 7's sex at birth?,Is the gender person 7 identifies with the same as their sex registered at birth?,"If 'No', enter 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 age?,What is person 8's relationship to the lead tenant?,What was person 8's sex at birth?,Is the gender person 8 identifies with the same as their sex registered at birth?,"If 'No', enter 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?,What was the source of referral for this letting?,What was the source of referral for this letting?,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?,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,tenancyother_value_check,tenancylength,hhmemb,pregnancy_value_check,net_income_value_check,refused,hhtype,totchild,totelder,totadult,age1,retirement_value_check,sexrab1,gender_same_as_sex1,gender_description1,ethnic_group,ethnic,nationality_all,ecstat1,working_situation_illness_check,details_known_2,age2,relat2,sexrab2,gender_same_as_sex2,gender_description2,ecstat2,details_known_3,age3,relat3,sexrab3,gender_same_as_sex3,gender_description3,ecstat3,details_known_4,age4,relat4,sexrab4,gender_same_as_sex4,gender_description4,ecstat4,details_known_5,age5,relat5,sexrab5,gender_same_as_sex5,gender_description5,ecstat5,details_known_6,age6,relat6,sexrab6,gender_same_as_sex6,gender_description6,ecstat6,details_known_7,age7,relat7,sexrab7,gender_same_as_sex7,gender_description7,ecstat7,details_known_8,age8,relat8,sexrab8,gender_same_as_sex8,gender_description8,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_register,referral_noms,referral_org,net_income_known,incref,incfreq,earnings,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,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,Yes,,White,Irish,Australia,Other,,Yes,32,Yes,Male,"No, enter gender identity",Non-binary,Not seeking work,No,Not known,Prefers not to say,Prefers not to say,Prefers not to say,,Prefers not to say,Yes,Not known,Tenant prefers not to say,Prefers not to say,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,Under 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,Renewal to the same tenant in the same property,,,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/models/form/lettings/pages/net_income_value_check_spec.rb b/spec/models/form/lettings/pages/net_income_value_check_spec.rb
index fe98919ae..ca7b36534 100644
--- a/spec/models/form/lettings/pages/net_income_value_check_spec.rb
+++ b/spec/models/form/lettings/pages/net_income_value_check_spec.rb
@@ -15,10 +15,6 @@ RSpec.describe Form::Lettings::Pages::NetIncomeValueCheck, type: :model do
expect(page.questions.map(&:id)).to eq(%w[net_income_value_check])
end
- it "has the correct id" do
- expect(page.id).to eq("net_income_value_check")
- end
-
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "net_income_soft_validation_triggered?" => true }])
end
diff --git a/spec/models/form/lettings/subsections/household_characteristics_spec.rb b/spec/models/form/lettings/subsections/household_characteristics_spec.rb
index b54d1c980..7a3c9a2f4 100644
--- a/spec/models/form/lettings/subsections/household_characteristics_spec.rb
+++ b/spec/models/form/lettings/subsections/household_characteristics_spec.rb
@@ -28,6 +28,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
household_members
no_females_pregnant_household_lead_hhmemb_value_check
females_in_soft_age_range_in_pregnant_household_lead_hhmemb_value_check
+ hhmemb_net_income_value_check
lead_tenant_age
no_females_pregnant_household_lead_age_value_check
females_in_soft_age_range_in_pregnant_household_lead_age_value_check
@@ -47,6 +48,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
lead_tenant_working_situation
working_situation_lead_tenant_under_retirement_value_check
working_situation_lead_tenant_over_retirement_value_check
+ working_situation_lead_tenant_net_income_value_check
person_2_known
person_2_relationship_to_lead
relationship_2_partner_under_16_value_check
@@ -57,6 +59,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
age_2_under_retirement_value_check
age_2_over_retirement_value_check
age_2_partner_under_16_value_check
+ age_2_net_income_value_check
person_2_gender_identity
no_females_pregnant_household_person_2_value_check
females_in_soft_age_range_in_pregnant_household_person_2_value_check
@@ -64,6 +67,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_2_working_situation
working_situation_2_under_retirement_value_check
working_situation_2_over_retirement_value_check
+ working_situation_2_net_income_value_check
person_3_known
person_3_relationship_to_lead
relationship_3_partner_under_16_value_check
@@ -74,6 +78,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
age_3_under_retirement_value_check
age_3_over_retirement_value_check
age_3_partner_under_16_value_check
+ age_3_net_income_value_check
person_3_gender_identity
no_females_pregnant_household_person_3_value_check
females_in_soft_age_range_in_pregnant_household_person_3_value_check
@@ -81,6 +86,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_3_working_situation
working_situation_3_under_retirement_value_check
working_situation_3_over_retirement_value_check
+ working_situation_3_net_income_value_check
person_4_known
person_4_relationship_to_lead
relationship_4_partner_under_16_value_check
@@ -91,6 +97,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
age_4_under_retirement_value_check
age_4_over_retirement_value_check
age_4_partner_under_16_value_check
+ age_4_net_income_value_check
person_4_gender_identity
no_females_pregnant_household_person_4_value_check
females_in_soft_age_range_in_pregnant_household_person_4_value_check
@@ -98,6 +105,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_4_working_situation
working_situation_4_under_retirement_value_check
working_situation_4_over_retirement_value_check
+ working_situation_4_net_income_value_check
person_5_known
person_5_relationship_to_lead
relationship_5_partner_under_16_value_check
@@ -108,6 +116,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
age_5_under_retirement_value_check
age_5_over_retirement_value_check
age_5_partner_under_16_value_check
+ age_5_net_income_value_check
person_5_gender_identity
no_females_pregnant_household_person_5_value_check
females_in_soft_age_range_in_pregnant_household_person_5_value_check
@@ -115,6 +124,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_5_working_situation
working_situation_5_under_retirement_value_check
working_situation_5_over_retirement_value_check
+ working_situation_5_net_income_value_check
person_6_known
person_6_relationship_to_lead
relationship_6_partner_under_16_value_check
@@ -125,6 +135,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
age_6_under_retirement_value_check
age_6_over_retirement_value_check
age_6_partner_under_16_value_check
+ age_6_net_income_value_check
person_6_gender_identity
no_females_pregnant_household_person_6_value_check
females_in_soft_age_range_in_pregnant_household_person_6_value_check
@@ -132,6 +143,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_6_working_situation
working_situation_6_under_retirement_value_check
working_situation_6_over_retirement_value_check
+ working_situation_6_net_income_value_check
person_7_known
person_7_relationship_to_lead
relationship_7_partner_under_16_value_check
@@ -142,6 +154,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
age_7_under_retirement_value_check
age_7_over_retirement_value_check
age_7_partner_under_16_value_check
+ age_7_net_income_value_check
person_7_gender_identity
no_females_pregnant_household_person_7_value_check
females_in_soft_age_range_in_pregnant_household_person_7_value_check
@@ -149,6 +162,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_7_working_situation
working_situation_7_under_retirement_value_check
working_situation_7_over_retirement_value_check
+ working_situation_7_net_income_value_check
person_8_known
person_8_relationship_to_lead
relationship_8_partner_under_16_value_check
@@ -159,6 +173,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
age_8_under_retirement_value_check
age_8_over_retirement_value_check
age_8_partner_under_16_value_check
+ age_8_net_income_value_check
person_8_gender_identity
no_females_pregnant_household_person_8_value_check
females_in_soft_age_range_in_pregnant_household_person_8_value_check
@@ -166,6 +181,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_8_working_situation
working_situation_8_under_retirement_value_check
working_situation_8_over_retirement_value_check
+ working_situation_8_net_income_value_check
],
)
end
@@ -182,6 +198,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
household_members
no_females_pregnant_household_lead_hhmemb_value_check
females_in_soft_age_range_in_pregnant_household_lead_hhmemb_value_check
+ hhmemb_net_income_value_check
lead_tenant_age
no_females_pregnant_household_lead_age_value_check
females_in_soft_age_range_in_pregnant_household_lead_age_value_check
@@ -201,6 +218,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
lead_tenant_working_situation
working_situation_lead_tenant_under_retirement_value_check
working_situation_lead_tenant_over_retirement_value_check
+ working_situation_lead_tenant_net_income_value_check
person_2_known
person_2_lead_partner
relationship_2_partner_under_16_value_check
@@ -211,6 +229,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
age_2_under_retirement_value_check
age_2_over_retirement_value_check
age_2_partner_under_16_value_check
+ age_2_net_income_value_check
person_2_gender_identity
no_females_pregnant_household_person_2_value_check
females_in_soft_age_range_in_pregnant_household_person_2_value_check
@@ -218,6 +237,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_2_working_situation
working_situation_2_under_retirement_value_check
working_situation_2_over_retirement_value_check
+ working_situation_2_net_income_value_check
person_3_known
person_3_lead_partner
relationship_3_partner_under_16_value_check
@@ -228,6 +248,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
age_3_under_retirement_value_check
age_3_over_retirement_value_check
age_3_partner_under_16_value_check
+ age_3_net_income_value_check
person_3_gender_identity
no_females_pregnant_household_person_3_value_check
females_in_soft_age_range_in_pregnant_household_person_3_value_check
@@ -235,6 +256,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_3_working_situation
working_situation_3_under_retirement_value_check
working_situation_3_over_retirement_value_check
+ working_situation_3_net_income_value_check
person_4_known
person_4_lead_partner
relationship_4_partner_under_16_value_check
@@ -245,6 +267,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
age_4_under_retirement_value_check
age_4_over_retirement_value_check
age_4_partner_under_16_value_check
+ age_4_net_income_value_check
person_4_gender_identity
no_females_pregnant_household_person_4_value_check
females_in_soft_age_range_in_pregnant_household_person_4_value_check
@@ -252,6 +275,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_4_working_situation
working_situation_4_under_retirement_value_check
working_situation_4_over_retirement_value_check
+ working_situation_4_net_income_value_check
person_5_known
person_5_lead_partner
relationship_5_partner_under_16_value_check
@@ -262,6 +286,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
age_5_under_retirement_value_check
age_5_over_retirement_value_check
age_5_partner_under_16_value_check
+ age_5_net_income_value_check
person_5_gender_identity
no_females_pregnant_household_person_5_value_check
females_in_soft_age_range_in_pregnant_household_person_5_value_check
@@ -269,6 +294,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_5_working_situation
working_situation_5_under_retirement_value_check
working_situation_5_over_retirement_value_check
+ working_situation_5_net_income_value_check
person_6_known
person_6_lead_partner
relationship_6_partner_under_16_value_check
@@ -279,6 +305,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
age_6_under_retirement_value_check
age_6_over_retirement_value_check
age_6_partner_under_16_value_check
+ age_6_net_income_value_check
person_6_gender_identity
no_females_pregnant_household_person_6_value_check
females_in_soft_age_range_in_pregnant_household_person_6_value_check
@@ -286,6 +313,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_6_working_situation
working_situation_6_under_retirement_value_check
working_situation_6_over_retirement_value_check
+ working_situation_6_net_income_value_check
person_7_known
person_7_lead_partner
relationship_7_partner_under_16_value_check
@@ -296,6 +324,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
age_7_under_retirement_value_check
age_7_over_retirement_value_check
age_7_partner_under_16_value_check
+ age_7_net_income_value_check
person_7_gender_identity
no_females_pregnant_household_person_7_value_check
females_in_soft_age_range_in_pregnant_household_person_7_value_check
@@ -303,6 +332,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_7_working_situation
working_situation_7_under_retirement_value_check
working_situation_7_over_retirement_value_check
+ working_situation_7_net_income_value_check
person_8_known
person_8_lead_partner
relationship_8_partner_under_16_value_check
@@ -313,6 +343,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
age_8_under_retirement_value_check
age_8_over_retirement_value_check
age_8_partner_under_16_value_check
+ age_8_net_income_value_check
person_8_gender_identity
no_females_pregnant_household_person_8_value_check
females_in_soft_age_range_in_pregnant_household_person_8_value_check
@@ -320,6 +351,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_8_working_situation
working_situation_8_under_retirement_value_check
working_situation_8_over_retirement_value_check
+ working_situation_8_net_income_value_check
],
)
end
@@ -335,6 +367,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
%w[
household_members
no_household_member_likely_to_be_pregnant_hhmemb_check
+ hhmemb_net_income_value_check
lead_tenant_age
no_household_member_likely_to_be_pregnant_lead_age_check
age_lead_tenant_under_retirement_value_check
@@ -354,8 +387,10 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
working_situation_lead_tenant_under_retirement_value_check
working_situation_lead_tenant_over_retirement_value_check
working_situation_lead_tenant_long_term_illness_check
+ working_situation_lead_tenant_net_income_value_check
person_2_known
person_2_age
+ age_2_net_income_value_check
person_2_lead_partner
no_household_member_likely_to_be_pregnant_person_age_2_check
age_2_under_retirement_value_check
@@ -368,8 +403,10 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
working_situation_2_under_retirement_value_check
working_situation_2_over_retirement_value_check
working_situation_2_long_term_illness_check
+ working_situation_2_net_income_value_check
person_3_known
person_3_age
+ age_3_net_income_value_check
person_3_lead_partner
no_household_member_likely_to_be_pregnant_person_age_3_check
age_3_under_retirement_value_check
@@ -382,8 +419,10 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
working_situation_3_under_retirement_value_check
working_situation_3_over_retirement_value_check
working_situation_3_long_term_illness_check
+ working_situation_3_net_income_value_check
person_4_known
person_4_age
+ age_4_net_income_value_check
person_4_lead_partner
no_household_member_likely_to_be_pregnant_person_age_4_check
age_4_under_retirement_value_check
@@ -396,8 +435,10 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
working_situation_4_under_retirement_value_check
working_situation_4_over_retirement_value_check
working_situation_4_long_term_illness_check
+ working_situation_4_net_income_value_check
person_5_known
person_5_age
+ age_5_net_income_value_check
person_5_lead_partner
no_household_member_likely_to_be_pregnant_person_age_5_check
age_5_under_retirement_value_check
@@ -410,8 +451,10 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
working_situation_5_under_retirement_value_check
working_situation_5_over_retirement_value_check
working_situation_5_long_term_illness_check
+ working_situation_5_net_income_value_check
person_6_known
person_6_age
+ age_6_net_income_value_check
person_6_lead_partner
no_household_member_likely_to_be_pregnant_person_age_6_check
age_6_under_retirement_value_check
@@ -424,8 +467,10 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
working_situation_6_under_retirement_value_check
working_situation_6_over_retirement_value_check
working_situation_6_long_term_illness_check
+ working_situation_6_net_income_value_check
person_7_known
person_7_age
+ age_7_net_income_value_check
person_7_lead_partner
no_household_member_likely_to_be_pregnant_person_age_7_check
age_7_under_retirement_value_check
@@ -438,8 +483,10 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
working_situation_7_under_retirement_value_check
working_situation_7_over_retirement_value_check
working_situation_7_long_term_illness_check
+ working_situation_7_net_income_value_check
person_8_known
person_8_age
+ age_8_net_income_value_check
person_8_lead_partner
no_household_member_likely_to_be_pregnant_person_age_8_check
age_8_under_retirement_value_check
@@ -452,6 +499,7 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
working_situation_8_under_retirement_value_check
working_situation_8_over_retirement_value_check
working_situation_8_long_term_illness_check
+ working_situation_8_net_income_value_check
],
)
end
diff --git a/spec/models/form/lettings/subsections/income_and_benefits_spec.rb b/spec/models/form/lettings/subsections/income_and_benefits_spec.rb
index 9d78b3216..9cdefd297 100644
--- a/spec/models/form/lettings/subsections/income_and_benefits_spec.rb
+++ b/spec/models/form/lettings/subsections/income_and_benefits_spec.rb
@@ -24,7 +24,7 @@ RSpec.describe Form::Lettings::Subsections::IncomeAndBenefits, type: :model do
%w[
income_known
income_amount
- net_income_value_check
+ income_amount_net_income_value_check
housing_benefit
benefits_proportion
rent_or_other_charges
@@ -58,7 +58,7 @@ RSpec.describe Form::Lettings::Subsections::IncomeAndBenefits, type: :model do
%w[
income_known
income_amount
- net_income_value_check
+ income_amount_net_income_value_check
housing_benefit
benefits_proportion
rent_or_other_charges
From 85d53dd95a23d92489baeaba23ebbd34e07951ec Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Thu, 23 Apr 2026 14:46:48 +0100
Subject: [PATCH 17/34] CLDC-4329: Add support role description (#3316)
---
app/views/users/new.html.erb | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/app/views/users/new.html.erb b/app/views/users/new.html.erb
index f9f9b1e48..2ed9f8186 100644
--- a/app/views/users/new.html.erb
+++ b/app/views/users/new.html.erb
@@ -54,7 +54,7 @@
options: { disabled: [""], selected: @organisation_id ? answer_options.first : "" } %>
<% end %>
- <% hints_for_roles = { data_provider: ["Can view and submit logs for this organisation"], data_coordinator: ["Can view and submit logs for this organisation and any of its managing agents", "Can manage details for this organisation", "Can manage users for this organisation"], support: nil } %>
+ <% hints_for_roles = { data_provider: ["Can view and submit logs for this organisation"], data_coordinator: ["Can view and submit logs for this organisation and any of its managing agents", "Can manage details for this organisation", "Can manage users for this organisation"], support: ["Can only be created for the MHCLG organisation in the CORE service, to be used by MHCLG and its contractor staff", "Has access to all organisations' data across the CORE service", "Cannot be created for users in housing organisations as this would be a data protection breach"] } %>
<% roles_with_hints = current_user.assignable_roles.map { |key, _| OpenStruct.new(id: key, name: key.to_s.humanize, description: hints_for_roles[key.to_sym]) } %>
From 1dbcd70bb810bc0fa7ad937fd6a081b46cd968d7 Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Mon, 27 Apr 2026 12:24:46 +0100
Subject: [PATCH 18/34] CLDC-4432: Skip invalid field errors if the question is
not routed to (#3322)
* CLDC-4432: Skip invalid field errors if the question is not routed to
* CLDC-4432: Add tests
* CLDC-4432: Lint
* fixup! CLDC-4432: Add tests
comment test dependencies
---
.../lettings/year2025/row_parser.rb | 8 ++++++++
.../lettings/year2026/row_parser.rb | 8 ++++++++
.../bulk_upload/sales/year2025/row_parser.rb | 8 ++++++++
.../bulk_upload/sales/year2026/row_parser.rb | 8 ++++++++
.../lettings/year2025/row_parser_spec.rb | 17 +++++++++++++++--
.../lettings/year2026/row_parser_spec.rb | 17 +++++++++++++++--
.../sales/year2025/row_parser_spec.rb | 18 ++++++++++++++++--
.../sales/year2026/row_parser_spec.rb | 18 ++++++++++++++++--
8 files changed, 94 insertions(+), 8 deletions(-)
diff --git a/app/services/bulk_upload/lettings/year2025/row_parser.rb b/app/services/bulk_upload/lettings/year2025/row_parser.rb
index f3b6e7edd..e407e9fe6 100644
--- a/app/services/bulk_upload/lettings/year2025/row_parser.rb
+++ b/app/services/bulk_upload/lettings/year2025/row_parser.rb
@@ -1035,6 +1035,14 @@ private
def add_errors_for_invalid_fields
invalid_fields.each do |field|
+ # ensure questions not routed to are not included in error report
+ error_questions_ids = field_mapping_for_errors
+ .select { |_k, fields| fields.map(&:to_s).include?(field.to_s) }
+ .keys
+ .map(&:to_s)
+ error_questions = questions.select { |question| error_questions_ids.include?(question.id) }
+ next if error_questions.none? { |question| question.page.routed_to?(log, nil) }
+
errors.delete(field) # take precedence over any other errors as this is a BU format issue
errors.add(field, I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: QUESTIONS[field.to_sym]))
end
diff --git a/app/services/bulk_upload/lettings/year2026/row_parser.rb b/app/services/bulk_upload/lettings/year2026/row_parser.rb
index 98a38d6e7..ac366dc57 100644
--- a/app/services/bulk_upload/lettings/year2026/row_parser.rb
+++ b/app/services/bulk_upload/lettings/year2026/row_parser.rb
@@ -1113,6 +1113,14 @@ private
def add_errors_for_invalid_fields
invalid_fields.each do |field|
+ # ensure questions not routed to are not included in error report
+ error_questions_ids = field_mapping_for_errors
+ .select { |_k, fields| fields.map(&:to_s).include?(field.to_s) }
+ .keys
+ .map(&:to_s)
+ error_questions = questions.select { |question| error_questions_ids.include?(question.id) }
+ next if error_questions.none? { |question| question.page.routed_to?(log, nil) }
+
errors.delete(field) # take precedence over any other errors as this is a BU format issue
errors.add(field, I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: QUESTIONS[field.to_sym]))
end
diff --git a/app/services/bulk_upload/sales/year2025/row_parser.rb b/app/services/bulk_upload/sales/year2025/row_parser.rb
index fac377138..2962205c4 100644
--- a/app/services/bulk_upload/sales/year2025/row_parser.rb
+++ b/app/services/bulk_upload/sales/year2025/row_parser.rb
@@ -689,6 +689,14 @@ private
def add_errors_for_invalid_fields
invalid_fields.each do |field|
+ # ensure questions not routed to are not included in error report
+ error_questions_ids = field_mapping_for_errors
+ .select { |_k, fields| fields.map(&:to_s).include?(field.to_s) }
+ .keys
+ .map(&:to_s)
+ error_questions = questions.select { |question| error_questions_ids.include?(question.id) }
+ next if error_questions.none? { |question| question.page.routed_to?(log, nil) }
+
errors.delete(field) # take precedence over any other errors as this is a BU format issue
errors.add(field, I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: QUESTIONS[field.to_sym]))
end
diff --git a/app/services/bulk_upload/sales/year2026/row_parser.rb b/app/services/bulk_upload/sales/year2026/row_parser.rb
index 08668d278..bd0b12c92 100644
--- a/app/services/bulk_upload/sales/year2026/row_parser.rb
+++ b/app/services/bulk_upload/sales/year2026/row_parser.rb
@@ -750,6 +750,14 @@ private
def add_errors_for_invalid_fields
invalid_fields.each do |field|
+ # ensure questions not routed to are not included in error report
+ error_questions_ids = field_mapping_for_errors
+ .select { |_k, fields| fields.map(&:to_s).include?(field.to_s) }
+ .keys
+ .map(&:to_s)
+ error_questions = questions.select { |question| error_questions_ids.include?(question.id) }
+ next if error_questions.none? { |question| question.page.routed_to?(log, nil) }
+
errors.delete(field) # take precedence over any other errors as this is a BU format issue
errors.add(field, I18n.t("#{ERROR_BASE_KEY}.invalid_option", question: QUESTIONS[field.to_sym]))
end
diff --git a/spec/services/bulk_upload/lettings/year2025/row_parser_spec.rb b/spec/services/bulk_upload/lettings/year2025/row_parser_spec.rb
index a62685970..113490c78 100644
--- a/spec/services/bulk_upload/lettings/year2025/row_parser_spec.rb
+++ b/spec/services/bulk_upload/lettings/year2025/row_parser_spec.rb
@@ -646,9 +646,9 @@ RSpec.describe BulkUpload::Lettings::Year2025::RowParser do
end
describe "invalid fields" do
- let(:attributes) { setup_section_params.merge({ field_45: 0 }) }
-
context "when a field has been marked as invalid" do
+ let(:attributes) { setup_section_params.merge({ field_45: 0 }) }
+
before do
parser.add_invalid_field("field_45")
end
@@ -659,6 +659,19 @@ RSpec.describe BulkUpload::Lettings::Year2025::RowParser do
expect(parser.errors[:field_45]).to include(I18n.t("validations.lettings.2025.bulk_upload.invalid_option", question: "What is the lead tenant’s nationality?"))
end
end
+
+ context "when a field has been marked as invalid but it is not routed to" do
+ let(:attributes) { setup_section_params.merge({ field_117: 2 }) }
+
+ before do
+ parser.add_invalid_field("field_118")
+ end
+
+ it "does not set an error on that field" do
+ parser.valid?
+ expect(parser.errors[:field_118].size).to eq(0)
+ end
+ end
end
end
end
diff --git a/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb b/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb
index b312f0b5e..665e3d683 100644
--- a/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb
+++ b/spec/services/bulk_upload/lettings/year2026/row_parser_spec.rb
@@ -538,9 +538,9 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do
end
describe "invalid fields" do
- let(:attributes) { setup_section_params.merge({ field_46: 0 }) }
-
context "when a field has been marked as invalid" do
+ let(:attributes) { setup_section_params.merge({ field_46: 0 }) }
+
before do
parser.add_invalid_field("field_46")
end
@@ -551,6 +551,19 @@ RSpec.describe BulkUpload::Lettings::Year2026::RowParser do
expect(parser.errors[:field_46]).to include(match(I18n.t("validations.lettings.2026.bulk_upload.invalid_option", question: "What is the lead tenant’s nationality?")))
end
end
+
+ context "when a field has been marked as invalid but it is not routed to" do
+ let(:attributes) { setup_section_params.merge({ field_135: 2 }) }
+
+ before do
+ parser.add_invalid_field("field_136")
+ end
+
+ it "does not set an error on that field" do
+ parser.valid?
+ expect(parser.errors[:field_136].size).to eq(0)
+ end
+ end
end
end
diff --git a/spec/services/bulk_upload/sales/year2025/row_parser_spec.rb b/spec/services/bulk_upload/sales/year2025/row_parser_spec.rb
index 67f5c6116..99f0774fc 100644
--- a/spec/services/bulk_upload/sales/year2025/row_parser_spec.rb
+++ b/spec/services/bulk_upload/sales/year2025/row_parser_spec.rb
@@ -338,9 +338,10 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end
describe "invalid fields" do
- let(:attributes) { setup_section_params.merge({ field_31: 0 }) }
-
context "when a field has been marked as invalid" do
+ # field_34 nationality is only shown if field_10 staircasing is no
+ let(:attributes) { setup_section_params.merge({ field_10: 2, field_31: 0 }) }
+
before do
parser.add_invalid_field("field_31")
end
@@ -351,6 +352,19 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
expect(parser.errors[:field_31]).to include(match(I18n.t("validations.sales.2025.bulk_upload.invalid_option", question: "What is buyer 1’s nationality?")))
end
end
+
+ context "when a field has been marked as invalid but it is not routed to" do
+ let(:attributes) { setup_section_params.merge({ field_10: 1, field_31: 0 }) }
+
+ before do
+ parser.add_invalid_field("field_31")
+ end
+
+ it "does not set an error on that field" do
+ parser.valid?
+ expect(parser.errors[:field_31].size).to eq(0)
+ end
+ end
end
end
end
diff --git a/spec/services/bulk_upload/sales/year2026/row_parser_spec.rb b/spec/services/bulk_upload/sales/year2026/row_parser_spec.rb
index 91edf5c5e..f38ed5580 100644
--- a/spec/services/bulk_upload/sales/year2026/row_parser_spec.rb
+++ b/spec/services/bulk_upload/sales/year2026/row_parser_spec.rb
@@ -344,9 +344,10 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
end
describe "invalid fields" do
- let(:attributes) { setup_section_params.merge({ field_34: 0 }) }
-
context "when a field has been marked as invalid" do
+ # field_34 nationality is only shown if field_10 staircasing is no
+ let(:attributes) { setup_section_params.merge({ field_10: 2, field_34: 0 }) }
+
before do
parser.add_invalid_field("field_34")
end
@@ -357,6 +358,19 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
expect(parser.errors[:field_34]).to include(match(I18n.t("validations.sales.2026.bulk_upload.invalid_option", question: "What is buyer 1's nationality?")))
end
end
+
+ context "when a field has been marked as invalid but it is not routed to" do
+ let(:attributes) { setup_section_params.merge({ field_10: 1, field_34: 0 }) }
+
+ before do
+ parser.add_invalid_field("field_34")
+ end
+
+ it "does not set an error on that field" do
+ parser.valid?
+ expect(parser.errors[:field_34].size).to eq(0)
+ end
+ end
end
end
end
From cf551d652c3b7af77a8c9f15f611417c4f0d7f8a Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Mon, 27 Apr 2026 21:48:32 +0100
Subject: [PATCH 19/34] CLDC-4330: Stop login count resetting on deactivation
(#3321)
* CLDC-4330: Add reset password on confirmation flag
to be used instead of resetting sign in count to 0
* CLDC-4330: Use this new flag to determine when to show password reset
* CLDC-4330: Update confirmation comment
* fixup! CLDC-4330: Update confirmation comment
* CLDC-4330: Rename col to force_reset_password_on_confirmation
* CLDC-4330: Remove unneeded if
---
app/controllers/auth/confirmations_controller.rb | 6 +++++-
app/controllers/auth/passwords_controller.rb | 1 +
app/models/user.rb | 2 +-
...627_add_force_reset_password_on_confirmation_to_users.rb | 5 +++++
db/schema.rb | 3 ++-
5 files changed, 14 insertions(+), 3 deletions(-)
create mode 100644 db/migrate/20260420151627_add_force_reset_password_on_confirmation_to_users.rb
diff --git a/app/controllers/auth/confirmations_controller.rb b/app/controllers/auth/confirmations_controller.rb
index d3f617822..cd09d7bb6 100644
--- a/app/controllers/auth/confirmations_controller.rb
+++ b/app/controllers/auth/confirmations_controller.rb
@@ -5,7 +5,11 @@ class Auth::ConfirmationsController < Devise::ConfirmationsController
yield resource if block_given?
if resource.errors.empty?
- if resource.sign_in_count.zero?
+ # previously we reset sign_in_count on deactivation and had only the .zero? check here.
+ # this would force a password reset both if it was your very first log in, and on your first login after reactivation.
+ # now we have a specific flag for the latter case as resetting sign_in_count was difficult for auditing.
+ # note that some deactivated users will have a sign_in_count of 0 and not have this flag set if they were deactivated before we made this change.
+ if resource.force_reset_password_on_confirmation || resource.sign_in_count.zero?
token = resource.send(:set_reset_password_token)
redirect_to "#{edit_user_password_url}?reset_password_token=#{token}&confirmation=true"
else
diff --git a/app/controllers/auth/passwords_controller.rb b/app/controllers/auth/passwords_controller.rb
index e4a21675b..702e99f1f 100644
--- a/app/controllers/auth/passwords_controller.rb
+++ b/app/controllers/auth/passwords_controller.rb
@@ -37,6 +37,7 @@ class Auth::PasswordsController < Devise::PasswordsController
if resource.errors.empty?
resource.unlock_access! if resource.respond_to?(:unlock_access!)
+ resource.force_reset_password_on_confirmation = false
if Devise.sign_in_after_reset_password
set_flash_message!(:notice, password_update_flash_message)
resource.after_database_authentication
diff --git a/app/models/user.rb b/app/models/user.rb
index ea8289e53..92fd37dc8 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -179,7 +179,7 @@ class User < ApplicationRecord
update!(
active: false,
confirmed_at: nil,
- sign_in_count: 0,
+ force_reset_password_on_confirmation: true,
initial_confirmation_sent: false,
reactivate_with_organisation:,
unconfirmed_email: nil,
diff --git a/db/migrate/20260420151627_add_force_reset_password_on_confirmation_to_users.rb b/db/migrate/20260420151627_add_force_reset_password_on_confirmation_to_users.rb
new file mode 100644
index 000000000..ad8a18980
--- /dev/null
+++ b/db/migrate/20260420151627_add_force_reset_password_on_confirmation_to_users.rb
@@ -0,0 +1,5 @@
+class AddForceResetPasswordOnConfirmationToUsers < ActiveRecord::Migration[7.2]
+ def change
+ add_column :users, :force_reset_password_on_confirmation, :boolean, default: false
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index 37e5c764e..4af47a53f 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -10,7 +10,7 @@
#
# It's strongly recommended that you check this file into your version control system.
-ActiveRecord::Schema[7.2].define(version: 2026_03_05_095832) do
+ActiveRecord::Schema[7.2].define(version: 2026_04_20_151627) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -924,6 +924,7 @@ ActiveRecord::Schema[7.2].define(version: 2026_03_05_095832) do
t.datetime "discarded_at"
t.string "phone_extension"
t.datetime "values_updated_at"
+ t.boolean "force_reset_password_on_confirmation", default: false
t.index ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true
t.index ["email"], name: "index_users_on_email", unique: true
t.index ["encrypted_otp_secret_key"], name: "index_users_on_encrypted_otp_secret_key", unique: true
From 9a2daa511945b86177ac7f0f8fa728c724df9f91 Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Mon, 27 Apr 2026 21:48:54 +0100
Subject: [PATCH 20/34] CLDC-4395: Fix staircasing sale wording (#3334)
---
config/locales/forms/2024/sales/sale_information.en.yml | 2 +-
config/locales/forms/2025/sales/sale_information.en.yml | 2 +-
config/locales/forms/2026/sales/sale_information.en.yml | 2 +-
3 files changed, 3 insertions(+), 3 deletions(-)
diff --git a/config/locales/forms/2024/sales/sale_information.en.yml b/config/locales/forms/2024/sales/sale_information.en.yml
index e8f898e3a..de12f919e 100644
--- a/config/locales/forms/2024/sales/sale_information.en.yml
+++ b/config/locales/forms/2024/sales/sale_information.en.yml
@@ -57,7 +57,7 @@ en:
check_answer_label: "Part of a back-to-back staircasing transaction"
check_answer_prompt: "Tell us if this is part of a back-to-back staircasing transaction"
hint_text: ""
- question_text: "Is this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?"
+ question_text: "Was this part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?"
resale:
page_header: ""
diff --git a/config/locales/forms/2025/sales/sale_information.en.yml b/config/locales/forms/2025/sales/sale_information.en.yml
index e81e82940..5d0d5b1fb 100644
--- a/config/locales/forms/2025/sales/sale_information.en.yml
+++ b/config/locales/forms/2025/sales/sale_information.en.yml
@@ -53,7 +53,7 @@ en:
check_answer_label: "Part of a back-to-back staircasing transaction"
check_answer_prompt: "Tell us if this is part of a back-to-back staircasing transaction"
hint_text: "Back-to-back staircasing transactions are used as a way for shared owners who own less than 100% of their property to sell on the open market. It involves the shared owner purchasing the remaining share from their landlord and immediately selling 100% of the property to a buyer on the open market. The landlord is then reimbursed for the staircasing transaction through the proceeds of sale to the buyer."
- question_text: "Is this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?"
+ question_text: "Was this part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?"
firststair:
page_header: ""
diff --git a/config/locales/forms/2026/sales/sale_information.en.yml b/config/locales/forms/2026/sales/sale_information.en.yml
index f7edff900..fe64a51ff 100644
--- a/config/locales/forms/2026/sales/sale_information.en.yml
+++ b/config/locales/forms/2026/sales/sale_information.en.yml
@@ -53,7 +53,7 @@ en:
check_answer_label: "Part of a back-to-back staircasing transaction"
check_answer_prompt: "Tell us if this is part of a back-to-back staircasing transaction"
hint_text: "Back-to-back staircasing transactions are used as a way for shared owners who own less than 100% of their property to sell on the open market. It involves the shared owner purchasing the remaining share from their landlord and immediately selling 100% of the property to a buyer on the open market. The landlord is then reimbursed for the staircasing transaction through the proceeds of sale to the buyer."
- question_text: "Is this transaction part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?"
+ question_text: "Was this part of a back-to-back staircasing transaction to facilitate sale of the home on the open market?"
firststair:
page_header: ""
From ef7aa6af255db3aecc785313d4fd3d7efd862933 Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Mon, 27 Apr 2026 21:50:04 +0100
Subject: [PATCH 21/34] CLDC-4313: Add maximum bounds to value and mortgage
questions (#3295)
* CLDC-4313: Add maximum bounds to value and mortgage questions for 2026
* CLDC-4313: Add a rake task to correct logs
* CLDC-4313: New max from 2025 or later
* CLDC-4313: Remove redundant queries from rake
* CLDC-4313: Fix page specs
* fixup! CLDC-4313: Fix page specs
missed one
* CLDC-4313: Update rake name
2025 or later
* CLDC-4313: Include other fields missing max
mrentprestaircasing
management_fee
---
.../form/sales/questions/management_fee.rb | 1 +
.../questions/monthly_rent_before_staircasing.rb | 1 +
.../form/sales/questions/mortgage_amount.rb | 1 +
.../form/sales/questions/purchase_price.rb | 1 +
app/models/form/sales/questions/value.rb | 1 +
...missing_max_for_2025_or_later_sales_logs.rake | 16 ++++++++++++++++
.../pages/monthly_rent_staircasing_owned_spec.rb | 4 +++-
.../sales/pages/monthly_rent_staircasing_spec.rb | 4 +++-
.../form/sales/pages/mortgage_amount_spec.rb | 2 +-
.../purchase_price_outright_ownership_spec.rb | 2 +-
.../form/sales/pages/purchase_price_spec.rb | 2 +-
.../sales/pages/value_shared_ownership_spec.rb | 2 +-
.../monthly_rent_before_staircasing_spec.rb | 9 ++++++++-
.../form/sales/questions/mortgage_amount_spec.rb | 6 +++++-
.../form/sales/questions/purchase_price_spec.rb | 10 +++++++++-
spec/models/form/sales/questions/value_spec.rb | 14 +++++++++-----
16 files changed, 62 insertions(+), 14 deletions(-)
create mode 100644 lib/tasks/correct_values_missing_max_for_2025_or_later_sales_logs.rake
diff --git a/app/models/form/sales/questions/management_fee.rb b/app/models/form/sales/questions/management_fee.rb
index af7ff574f..6ca114981 100644
--- a/app/models/form/sales/questions/management_fee.rb
+++ b/app/models/form/sales/questions/management_fee.rb
@@ -5,6 +5,7 @@ class Form::Sales::Questions::ManagementFee < ::Form::Question
@copy_key = "sales.sale_information.management_fee.management_fee"
@type = "numeric"
@min = 1
+ @max = form.start_year_2025_or_later? ? 9_999 : nil
@step = 0.01
@width = 5
@prefix = "£"
diff --git a/app/models/form/sales/questions/monthly_rent_before_staircasing.rb b/app/models/form/sales/questions/monthly_rent_before_staircasing.rb
index 042e2be32..bf101e993 100644
--- a/app/models/form/sales/questions/monthly_rent_before_staircasing.rb
+++ b/app/models/form/sales/questions/monthly_rent_before_staircasing.rb
@@ -5,6 +5,7 @@ class Form::Sales::Questions::MonthlyRentBeforeStaircasing < ::Form::Question
@copy_key = "sales.sale_information.mrent_staircasing.prestaircasing"
@type = "numeric"
@min = 0
+ @max = form.start_year_2025_or_later? ? 9_999 : nil
@step = 0.01
@width = 5
@prefix = "£"
diff --git a/app/models/form/sales/questions/mortgage_amount.rb b/app/models/form/sales/questions/mortgage_amount.rb
index 81549c011..2a11b882d 100644
--- a/app/models/form/sales/questions/mortgage_amount.rb
+++ b/app/models/form/sales/questions/mortgage_amount.rb
@@ -4,6 +4,7 @@ class Form::Sales::Questions::MortgageAmount < ::Form::Question
@id = "mortgage"
@type = "numeric"
@min = 1
+ @max = form.start_year_2025_or_later? ? 999_999 : nil
@step = 1
@width = 5
@prefix = "£"
diff --git a/app/models/form/sales/questions/purchase_price.rb b/app/models/form/sales/questions/purchase_price.rb
index 8a919b55f..010dfa99a 100644
--- a/app/models/form/sales/questions/purchase_price.rb
+++ b/app/models/form/sales/questions/purchase_price.rb
@@ -4,6 +4,7 @@ class Form::Sales::Questions::PurchasePrice < ::Form::Question
@id = "value"
@type = "numeric"
@min = form.start_year_2026_or_later? ? 15_000 : 0
+ @max = form.start_year_2025_or_later? ? 999_999 : nil
@step = form.start_year_2026_or_later? ? 1 : 0.01 # 0.01 was a mistake that was fixed in 2026
@width = 5
@prefix = "£"
diff --git a/app/models/form/sales/questions/value.rb b/app/models/form/sales/questions/value.rb
index 0884a3fb6..0521c3705 100644
--- a/app/models/form/sales/questions/value.rb
+++ b/app/models/form/sales/questions/value.rb
@@ -5,6 +5,7 @@ class Form::Sales::Questions::Value < ::Form::Question
@copy_key = form.start_year_2025_or_later? ? "sales.sale_information.value.#{page.id}" : "sales.sale_information.value"
@type = "numeric"
@min = form.start_year_2026_or_later? ? 15_000 : 0
+ @max = form.start_year_2025_or_later? ? 999_999 : nil
@step = 1
@width = 10
@prefix = "£"
diff --git a/lib/tasks/correct_values_missing_max_for_2025_or_later_sales_logs.rake b/lib/tasks/correct_values_missing_max_for_2025_or_later_sales_logs.rake
new file mode 100644
index 000000000..87d683c97
--- /dev/null
+++ b/lib/tasks/correct_values_missing_max_for_2025_or_later_sales_logs.rake
@@ -0,0 +1,16 @@
+desc "Clears mortgage, purchase price (the 'value' field), monthly rent before staircasing and management fee values for sales logs in the database if they are over their new max"
+task correct_values_missing_max_for_2025_or_later_sales_logs: :environment do
+ mortgage_incorrect_logs = SalesLog.filter_by_year_or_later(2025).where("mortgage > 999999")
+ value_incorrect_logs = SalesLog.filter_by_year_or_later(2025).where("value > 999999")
+ mrentprestaircasing_incorrect_logs = SalesLog.filter_by_year_or_later(2025).where("mrentprestaircasing > 9999")
+ management_fee_incorrect_logs = SalesLog.filter_by_year_or_later(2025).where("management_fee > 9999")
+ all_incorrect_logs = (mortgage_incorrect_logs + value_incorrect_logs + mrentprestaircasing_incorrect_logs + management_fee_incorrect_logs).uniq
+ puts "Correcting #{all_incorrect_logs.count} sales logs, #{all_incorrect_logs.map(&:id)}"
+
+ mortgage_incorrect_logs.update!(mortgage: nil)
+ value_incorrect_logs.update!(value: nil)
+ mrentprestaircasing_incorrect_logs.update!(mrentprestaircasing: nil)
+ management_fee_incorrect_logs.update!(management_fee: nil)
+
+ puts "Done"
+end
diff --git a/spec/models/form/sales/pages/monthly_rent_staircasing_owned_spec.rb b/spec/models/form/sales/pages/monthly_rent_staircasing_owned_spec.rb
index 21f0e0ee6..2761e5f76 100644
--- a/spec/models/form/sales/pages/monthly_rent_staircasing_owned_spec.rb
+++ b/spec/models/form/sales/pages/monthly_rent_staircasing_owned_spec.rb
@@ -1,11 +1,13 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::MonthlyRentStaircasingOwned, type: :model do
+ include CollectionTimeHelper
+
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2025, 4, 1))) }
+ let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: current_collection_start_date, start_year_2025_or_later?: true)) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
diff --git a/spec/models/form/sales/pages/monthly_rent_staircasing_spec.rb b/spec/models/form/sales/pages/monthly_rent_staircasing_spec.rb
index 347e105fd..21e68ea64 100644
--- a/spec/models/form/sales/pages/monthly_rent_staircasing_spec.rb
+++ b/spec/models/form/sales/pages/monthly_rent_staircasing_spec.rb
@@ -1,11 +1,13 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::MonthlyRentStaircasing, type: :model do
+ include CollectionTimeHelper
+
subject(:page) { described_class.new(page_id, page_definition, subsection) }
let(:page_id) { nil }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2025, 4, 1))) }
+ let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: current_collection_start_year, start_year_2025_or_later?: true)) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
diff --git a/spec/models/form/sales/pages/mortgage_amount_spec.rb b/spec/models/form/sales/pages/mortgage_amount_spec.rb
index 8127dfb2d..045d8b1dc 100644
--- a/spec/models/form/sales/pages/mortgage_amount_spec.rb
+++ b/spec/models/form/sales/pages/mortgage_amount_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Pages::MortgageAmount, type: :model do
let(:page_id) { nil }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, id: "shared_ownership_initial_purchase", form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2026_or_later?: false)) }
+ let(:subsection) { instance_double(Form::Subsection, id: "shared_ownership_initial_purchase", form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2025_or_later?: true, start_year_2026_or_later?: true)) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
diff --git a/spec/models/form/sales/pages/purchase_price_outright_ownership_spec.rb b/spec/models/form/sales/pages/purchase_price_outright_ownership_spec.rb
index e26221554..00f7d1f4e 100644
--- a/spec/models/form/sales/pages/purchase_price_outright_ownership_spec.rb
+++ b/spec/models/form/sales/pages/purchase_price_outright_ownership_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Pages::PurchasePriceOutrightOwnership, type: :model
let(:page_id) { "purchase_price" }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, id: "discounted_ownership_scheme", form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2026_or_later?: false)) }
+ let(:subsection) { instance_double(Form::Subsection, id: "discounted_ownership_scheme", form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2025_or_later?: true, start_year_2026_or_later?: false)) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
diff --git a/spec/models/form/sales/pages/purchase_price_spec.rb b/spec/models/form/sales/pages/purchase_price_spec.rb
index 8ceb58f4a..4b74bbd4c 100644
--- a/spec/models/form/sales/pages/purchase_price_spec.rb
+++ b/spec/models/form/sales/pages/purchase_price_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Form::Sales::Pages::PurchasePrice, type: :model do
let(:subsection) { instance_double(Form::Subsection) }
before do
- allow(subsection).to receive_messages(form: instance_double(Form, start_year_2024_or_later?: false, start_date: Time.zone.local(2023, 4, 1), start_year_2026_or_later?: false), id: "discounted_ownership_scheme")
+ allow(subsection).to receive_messages(form: instance_double(Form, start_year_2024_or_later?: true, start_date: Time.zone.local(2023, 4, 1), start_year_2025_or_later?: true, start_year_2026_or_later?: false), id: "discounted_ownership_scheme")
end
it "has correct subsection" do
diff --git a/spec/models/form/sales/pages/value_shared_ownership_spec.rb b/spec/models/form/sales/pages/value_shared_ownership_spec.rb
index e7e709d28..a8a1db327 100644
--- a/spec/models/form/sales/pages/value_shared_ownership_spec.rb
+++ b/spec/models/form/sales/pages/value_shared_ownership_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Pages::ValueSharedOwnership, type: :model do
let(:page_id) { "value_shared_ownership" }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2026_or_later?: false), id: "shared_ownership") }
+ let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2025_or_later?: true, start_year_2026_or_later?: false), id: "shared_ownership") }
before do
allow(page.subsection.form).to receive(:start_year_2025_or_later?).and_return(false)
diff --git a/spec/models/form/sales/questions/monthly_rent_before_staircasing_spec.rb b/spec/models/form/sales/questions/monthly_rent_before_staircasing_spec.rb
index 8d7d864a8..8ec7b1824 100644
--- a/spec/models/form/sales/questions/monthly_rent_before_staircasing_spec.rb
+++ b/spec/models/form/sales/questions/monthly_rent_before_staircasing_spec.rb
@@ -1,11 +1,14 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::MonthlyRentBeforeStaircasing, type: :model do
+ include CollectionTimeHelper
+
subject(:question) { described_class.new(question_id, question_definition, page) }
let(:question_id) { nil }
let(:question_definition) { nil }
- let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1)))) }
+ let(:start_year_2025_or_later?) { true }
+ let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: current_collection_start_date, start_year_2025_or_later?: start_year_2025_or_later?))) }
it "has correct page" do
expect(question.page).to eq(page)
@@ -34,4 +37,8 @@ RSpec.describe Form::Sales::Questions::MonthlyRentBeforeStaircasing, type: :mode
it "has correct min" do
expect(question.min).to eq(0)
end
+
+ it "has correct max" do
+ expect(question.max).to eq(9_999)
+ end
end
diff --git a/spec/models/form/sales/questions/mortgage_amount_spec.rb b/spec/models/form/sales/questions/mortgage_amount_spec.rb
index 12da4bc1f..064dead90 100644
--- a/spec/models/form/sales/questions/mortgage_amount_spec.rb
+++ b/spec/models/form/sales/questions/mortgage_amount_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Questions::MortgageAmount, type: :model do
let(:question_id) { nil }
let(:question_definition) { nil }
- let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, id: "shared_ownership_initial_purchase", form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2026_or_later?: false))) }
+ let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, id: "shared_ownership_initial_purchase", form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2025_or_later?: true, start_year_2026_or_later?: true))) }
it "has correct page" do
expect(question.page).to be(page)
@@ -35,6 +35,10 @@ RSpec.describe Form::Sales::Questions::MortgageAmount, type: :model do
expect(question.min).to be(1)
end
+ it "has correct max" do
+ expect(question.max).to eq(999_999)
+ end
+
context "when the mortgage is not used" do
let(:log) { build(:sales_log, :completed, mortgageused: 2, deposit: nil) }
diff --git a/spec/models/form/sales/questions/purchase_price_spec.rb b/spec/models/form/sales/questions/purchase_price_spec.rb
index 47081edb4..083baf4da 100644
--- a/spec/models/form/sales/questions/purchase_price_spec.rb
+++ b/spec/models/form/sales/questions/purchase_price_spec.rb
@@ -9,7 +9,7 @@ RSpec.describe Form::Sales::Questions::PurchasePrice, type: :model do
let(:question_definition) { nil }
let(:start_year) { current_collection_start_year }
let(:start_year_2026_or_later?) { false }
- let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, id: "shared_ownership_initial_purchase", form: instance_double(Form, start_date: collection_start_date_for_year(start_year), start_year_2026_or_later?: start_year_2026_or_later?))) }
+ let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, id: "shared_ownership_initial_purchase", form: instance_double(Form, start_date: collection_start_date_for_year(start_year), start_year_2026_or_later?: start_year_2026_or_later?, start_year_2025_or_later?: true))) }
it "has correct page" do
expect(question.page).to eq(page)
@@ -65,6 +65,10 @@ RSpec.describe Form::Sales::Questions::PurchasePrice, type: :model do
it "has correct min" do
expect(question.min).to eq(0)
end
+
+ it "has correct max" do
+ expect(question.max).to eq(999_999)
+ end
end
context "with year 2026", metadata: { year: 26 } do
@@ -74,5 +78,9 @@ RSpec.describe Form::Sales::Questions::PurchasePrice, type: :model do
it "has correct min" do
expect(question.min).to eq(15_000)
end
+
+ it "has correct max" do
+ expect(question.max).to eq(999_999)
+ end
end
end
diff --git a/spec/models/form/sales/questions/value_spec.rb b/spec/models/form/sales/questions/value_spec.rb
index 952b02e7c..ca63f89f5 100644
--- a/spec/models/form/sales/questions/value_spec.rb
+++ b/spec/models/form/sales/questions/value_spec.rb
@@ -9,11 +9,7 @@ RSpec.describe Form::Sales::Questions::Value, type: :model do
let(:question_definition) { nil }
let(:start_year) { current_collection_start_year }
let(:start_year_2026_or_later?) { false }
- let(:page) { instance_double(Form::Page, id: "value_shared_ownership", subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: collection_start_date_for_year(start_year), start_year_2026_or_later?: start_year_2026_or_later?), id: "shared_ownership")) }
-
- before do
- allow(page.subsection.form).to receive(:start_year_2025_or_later?).and_return(false)
- end
+ let(:page) { instance_double(Form::Page, id: "value_shared_ownership", subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: collection_start_date_for_year(start_year), start_year_2026_or_later?: start_year_2026_or_later?, start_year_2025_or_later?: true), id: "shared_ownership")) }
it "has correct page" do
expect(question.page).to eq(page)
@@ -45,6 +41,10 @@ RSpec.describe Form::Sales::Questions::Value, type: :model do
it "has correct min" do
expect(question.min).to eq(0)
end
+
+ it "has correct max" do
+ expect(question.max).to eq(999_999)
+ end
end
context "with year 2026", metadata: { year: 26 } do
@@ -54,5 +54,9 @@ RSpec.describe Form::Sales::Questions::Value, type: :model do
it "has correct min" do
expect(question.min).to eq(15_000)
end
+
+ it "has correct max" do
+ expect(question.max).to eq(999_999)
+ end
end
end
From a592cb8a66fb19dded9646a54c7fca35889ce44a Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Wed, 29 Apr 2026 09:53:34 +0100
Subject: [PATCH 22/34] CLDC-4234: Allow 'R' as an input for prevten (#3326)
---
.../bulk_upload/sales/year2025/row_parser.rb | 16 +++++++++++++---
.../bulk_upload/sales/year2026/row_parser.rb | 16 +++++++++++++---
.../sales/year2025/row_parser_spec.rb | 10 +++++++++-
.../sales/year2026/row_parser_spec.rb | 10 +++++++++-
4 files changed, 44 insertions(+), 8 deletions(-)
diff --git a/app/services/bulk_upload/sales/year2025/row_parser.rb b/app/services/bulk_upload/sales/year2025/row_parser.rb
index 2962205c4..39ca46c8f 100644
--- a/app/services/bulk_upload/sales/year2025/row_parser.rb
+++ b/app/services/bulk_upload/sales/year2025/row_parser.rb
@@ -154,6 +154,7 @@ class BulkUpload::Sales::Year2025::RowParser
:field_52, # Gender identity of person 5
:field_56, # Gender identity of person 6
+ :field_58, # What was buyer 1’s previous tenure?
:field_64, # What was buyer 2’s previous tenure?
:field_75, # What is the total amount the buyers had in savings before they paid any deposit for the property?
@@ -227,7 +228,7 @@ class BulkUpload::Sales::Year2025::RowParser
attribute :field_56, :string
attribute :field_57, :integer
- attribute :field_58, :integer
+ attribute :field_58, :string
attribute :field_59, :integer
attribute :field_60, :string
attribute :field_61, :string
@@ -564,6 +565,15 @@ private
end
end
+ def prevten
+ case field_58
+ when "R"
+ 0
+ else
+ field_58
+ end
+ end
+
def prevtenbuy2
case field_64
when "R"
@@ -910,7 +920,7 @@ private
attributes["savings"] = field_75.to_i if attributes["savingsnk"]&.zero? && field_75&.match(/\A\d+\z/)
attributes["prevown"] = field_76
- attributes["prevten"] = field_58
+ attributes["prevten"] = prevten
attributes["prevloc"] = field_62
attributes["previous_la_known"] = previous_la_known
attributes["ppcodenk"] = previous_postcode_known
@@ -1291,7 +1301,7 @@ private
def infer_soctenant_from_prevten_and_prevtenbuy2
return unless shared_ownership?
- if [1, 2].include?(field_58) || [1, 2].include?(field_64.to_i)
+ if [1, 2].include?(field_58.to_i) || [1, 2].include?(field_64.to_i)
1
else
2
diff --git a/app/services/bulk_upload/sales/year2026/row_parser.rb b/app/services/bulk_upload/sales/year2026/row_parser.rb
index bd0b12c92..d9989fb9f 100644
--- a/app/services/bulk_upload/sales/year2026/row_parser.rb
+++ b/app/services/bulk_upload/sales/year2026/row_parser.rb
@@ -169,6 +169,7 @@ class BulkUpload::Sales::Year2026::RowParser
:field_61, # Person 5's sex, as registered at birth
:field_67, # Person 6's sex, as registered at birth
+ :field_71, # What was buyer 1’s previous tenure?
:field_77, # What was buyer 2’s previous tenure?
:field_88, # What is the total amount the buyers had in savings before they paid any deposit for the property?
@@ -263,7 +264,7 @@ class BulkUpload::Sales::Year2026::RowParser
attribute :field_69, :string
attribute :field_70, :integer
- attribute :field_71, :integer
+ attribute :field_71, :string
attribute :field_72, :integer
attribute :field_73, :string
attribute :field_74, :string
@@ -621,6 +622,15 @@ private
end
end
+ def prevten
+ case field_71
+ when "R"
+ 0
+ else
+ field_71
+ end
+ end
+
def prevtenbuy2
case field_77
when "R"
@@ -1003,7 +1013,7 @@ private
attributes["savings"] = field_88.to_i if attributes["savingsnk"]&.zero? && field_88&.match(/\A\d+\z/)
attributes["prevown"] = field_89
- attributes["prevten"] = field_71
+ attributes["prevten"] = prevten
attributes["prevloc"] = field_75
attributes["previous_la_known"] = previous_la_known
attributes["ppcodenk"] = previous_postcode_known
@@ -1424,7 +1434,7 @@ private
def infer_soctenant_from_prevten_and_prevtenbuy2
return unless shared_ownership?
- if [1, 2].include?(field_71) || [1, 2].include?(field_77.to_i)
+ if [1, 2].include?(field_71.to_i) || [1, 2].include?(field_77.to_i)
1
else
2
diff --git a/spec/services/bulk_upload/sales/year2025/row_parser_spec.rb b/spec/services/bulk_upload/sales/year2025/row_parser_spec.rb
index 99f0774fc..beb8ece77 100644
--- a/spec/services/bulk_upload/sales/year2025/row_parser_spec.rb
+++ b/spec/services/bulk_upload/sales/year2025/row_parser_spec.rb
@@ -295,7 +295,7 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
context "and case insensitive fields are set to lowercase" do
let(:case_insensitive_fields) { %w[field_29 field_36 field_44 field_48 field_52 field_56] }
- let(:case_insensitive_integer_fields_with_r_option) { %w[field_28 field_35 field_43 field_47 field_51 field_55 field_64 field_75 field_70 field_72] }
+ let(:case_insensitive_integer_fields_with_r_option) { %w[field_28 field_35 field_43 field_47 field_51 field_55 field_58 field_64 field_75 field_70 field_72] }
let(:attributes) do
valid_attributes
.merge(case_insensitive_fields.each_with_object({}) { |field, h| h[field.to_sym] = valid_attributes[field.to_sym]&.downcase })
@@ -1778,6 +1778,14 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
end
end
+ describe "#prevten" do
+ let(:attributes) { setup_section_params.merge({ field_58: "R" }) }
+
+ it "is correctly set" do
+ expect(parser.log.prevten).to be(0)
+ end
+ end
+
describe "#prevtenbuy2" do
let(:attributes) { setup_section_params.merge({ field_64: "R" }) }
diff --git a/spec/services/bulk_upload/sales/year2026/row_parser_spec.rb b/spec/services/bulk_upload/sales/year2026/row_parser_spec.rb
index f38ed5580..b2baf8343 100644
--- a/spec/services/bulk_upload/sales/year2026/row_parser_spec.rb
+++ b/spec/services/bulk_upload/sales/year2026/row_parser_spec.rb
@@ -301,7 +301,7 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
context "and case insensitive fields are set to lowercase" do
let(:case_insensitive_fields) { %w[field_30 field_39 field_49 field_55 field_61 field_67] }
- let(:case_insensitive_integer_fields_with_r_option) { %w[field_29 field_38 field_48 field_54 field_60 field_66 field_77 field_88 field_83 field_85 field_103 field_107 field_125 field_126 field_133 field_136] }
+ let(:case_insensitive_integer_fields_with_r_option) { %w[field_29 field_38 field_48 field_54 field_60 field_66 field_71 field_77 field_88 field_83 field_85 field_103 field_107 field_125 field_126 field_133 field_136] }
let(:attributes) do
valid_attributes
.merge(case_insensitive_fields.each_with_object({}) { |field, h| h[field.to_sym] = valid_attributes[field.to_sym]&.downcase })
@@ -1840,6 +1840,14 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
end
end
+ describe "#prevten" do
+ let(:attributes) { setup_section_params.merge({ field_71: "R" }) }
+
+ it "is correctly set" do
+ expect(parser.log.prevten).to be(0)
+ end
+ end
+
describe "#prevtenbuy2" do
let(:attributes) { setup_section_params.merge({ field_77: "R" }) }
From 1e1773605c29e681981d9a8609b058306f5e5ce6 Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Wed, 29 Apr 2026 09:56:07 +0100
Subject: [PATCH 23/34] CLDC-4300: Update sale date staircasing date validation
(#3307)
* CLDC-4300: Stricten validation on initialpurchase
* CLDC-4300: Add a correction script
* CLDC-4300: Update tests
* CLDC-4300: Ensure lasttransaction cannot equal saledate or initialtransaction
* CLDC-4300: Update date correcting rake to also account for lasttransaction = initialpurchase
* CLDC-4300: Revert updates to copy
* CLDC-4300: Apply these changes from 2026 only
* fixup! CLDC-4300: Apply these changes from 2026 only
in rake too
* CLDC-4300: Compare lasttransaction to saledate
due to the it <= lt <= sd relationship, there's no need to comparse it to sd. if it == sd then it == lt and lt == sd
* fixup! CLDC-4300: Compare lasttransaction to saledate
update rake desc
Co-authored-by: Oscar Richardson <116292912+oscar-richardson-softwire@users.noreply.github.com>
---------
Co-authored-by: Oscar Richardson <116292912+oscar-richardson-softwire@users.noreply.github.com>
---
.../sales/sale_information_validations.rb | 6 +-
...valid_initialpurchase_lasttransaction.rake | 13 ++++
.../sale_information_validations_spec.rb | 69 +++++++++++++++----
3 files changed, 73 insertions(+), 15 deletions(-)
create mode 100644 lib/tasks/fix_sales_logs_with_invalid_initialpurchase_lasttransaction.rake
diff --git a/app/models/validations/sales/sale_information_validations.rb b/app/models/validations/sales/sale_information_validations.rb
index 32bf2a716..7cd24183c 100644
--- a/app/models/validations/sales/sale_information_validations.rb
+++ b/app/models/validations/sales/sale_information_validations.rb
@@ -42,7 +42,7 @@ module Validations::Sales::SaleInformationValidations
record.errors.add :initialpurchase, I18n.t("validations.sales.sale_information.initialpurchase.must_be_after_1980")
end
- if record.saledate.present? && record.initialpurchase > record.saledate
+ if record.saledate.present? && ((record.initialpurchase > record.saledate) || (record.initialpurchase == record.saledate && record.form.start_year_2026_or_later?))
record.errors.add :initialpurchase, I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_saledate")
record.errors.add :saledate, :skip_bu_error, message: I18n.t("validations.sales.sale_information.saledate.must_be_after_initial_purchase_date")
end
@@ -55,11 +55,11 @@ module Validations::Sales::SaleInformationValidations
record.errors.add :lasttransaction, I18n.t("validations.sales.sale_information.lasttransaction.must_be_after_1980")
end
- if record.saledate.present? && record.lasttransaction > record.saledate
+ if record.saledate.present? && ((record.lasttransaction > record.saledate) || (record.lasttransaction == record.saledate && record.form.start_year_2026_or_later?))
record.errors.add :lasttransaction, I18n.t("validations.sales.sale_information.lasttransaction.must_be_before_saledate")
record.errors.add :saledate, :skip_bu_error, message: I18n.t("validations.sales.sale_information.saledate.must_be_after_last_transaction_date")
end
- if record.initialpurchase.present? && record.lasttransaction < record.initialpurchase
+ if record.initialpurchase.present? && ((record.lasttransaction < record.initialpurchase) || (record.lasttransaction == record.initialpurchase && record.form.start_year_2026_or_later?))
record.errors.add :initialpurchase, I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_last_transaction")
record.errors.add :lasttransaction, I18n.t("validations.sales.sale_information.lasttransaction.must_be_after_initial_purchase")
end
diff --git a/lib/tasks/fix_sales_logs_with_invalid_initialpurchase_lasttransaction.rake b/lib/tasks/fix_sales_logs_with_invalid_initialpurchase_lasttransaction.rake
new file mode 100644
index 000000000..44475a46f
--- /dev/null
+++ b/lib/tasks/fix_sales_logs_with_invalid_initialpurchase_lasttransaction.rake
@@ -0,0 +1,13 @@
+desc "We tightened the validation in 2026 between initial purchase date, last transaction date and sale date so that no two can be equal and initial purchase date < last transaction date < sale date. To avoid invalid logs we clear lasttransaction if it equals saledate and if initialpurchase = lasttransaction we clear both"
+task fix_sales_logs_with_invalid_initialpurchase_lasttransaction: :environment do
+ lasttransaction_equal_saledate_logs = SalesLog.filter_by_year_or_later(2026).where("lasttransaction = saledate")
+ initial_purchase_equal_lasttransaction_logs = SalesLog.filter_by_year_or_later(2026).where("initialpurchase = lasttransaction")
+
+ puts "Updating #{lasttransaction_equal_saledate_logs.count} logs where lasttransaction = saledate, #{lasttransaction_equal_saledate_logs.map(&:id)}"
+ lasttransaction_equal_saledate_logs.update!(lasttransaction: nil)
+
+ puts "Updating #{initial_purchase_equal_lasttransaction_logs.count} logs where initialpurchase = lasttransaction, #{initial_purchase_equal_lasttransaction_logs.map(&:id)}"
+ initial_purchase_equal_lasttransaction_logs.update!(initialpurchase: nil, lasttransaction: nil)
+
+ puts "Done"
+end
diff --git a/spec/models/validations/sales/sale_information_validations_spec.rb b/spec/models/validations/sales/sale_information_validations_spec.rb
index 8d4eb4cea..04f71b198 100644
--- a/spec/models/validations/sales/sale_information_validations_spec.rb
+++ b/spec/models/validations/sales/sale_information_validations_spec.rb
@@ -252,12 +252,27 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end
context "when initial purchase date == saledate" do
- let(:record) { build(:sales_log, initialpurchase: current_collection_start_date, saledate: current_collection_start_date) }
+ let(:record) { build(:sales_log, initialpurchase: collection_start_date_for_year(start_year), saledate: collection_start_date_for_year(start_year)) }
- it "does not add an error" do
- sale_information_validator.validate_staircasing_initial_purchase_date(record)
+ context "and 2025", metadata: { year: 25 } do
+ let(:start_year) { 2025 }
- expect(record.errors[:initialpurchase]).not_to be_present
+ it "does not add an error" do
+ sale_information_validator.validate_staircasing_initial_purchase_date(record)
+
+ expect(record.errors[:lasttransaction]).not_to be_present
+ end
+ end
+
+ context "and 2026", metadata: { year: 26 } do
+ let(:start_year) { 2026 }
+
+ it "adds error" do
+ sale_information_validator.validate_staircasing_initial_purchase_date(record)
+
+ expect(record.errors[:initialpurchase]).to eq([I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_saledate")])
+ expect(record.errors[:saledate]).to eq([I18n.t("validations.sales.sale_information.saledate.must_be_after_initial_purchase_date")])
+ end
end
end
end
@@ -315,12 +330,27 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end
context "when last transaction date == saledate" do
- let(:record) { build(:sales_log, lasttransaction: current_collection_start_date, saledate: current_collection_start_date) }
+ let(:record) { build(:sales_log, lasttransaction: collection_start_date_for_year(start_year), saledate: collection_start_date_for_year(start_year)) }
- it "does not add an error" do
- sale_information_validator.validate_staircasing_last_transaction_date(record)
+ context "and 2025", metadata: { year: 25 } do
+ let(:start_year) { 2025 }
- expect(record.errors[:lasttransaction]).not_to be_present
+ it "does not add an error" do
+ sale_information_validator.validate_staircasing_last_transaction_date(record)
+
+ expect(record.errors[:lasttransaction]).not_to be_present
+ end
+ end
+
+ context "and 2026", metadata: { year: 26 } do
+ let(:start_year) { 2026 }
+
+ it "adds error" do
+ sale_information_validator.validate_staircasing_last_transaction_date(record)
+
+ expect(record.errors[:lasttransaction]).to eq([I18n.t("validations.sales.sale_information.lasttransaction.must_be_before_saledate")])
+ expect(record.errors[:saledate]).to eq([I18n.t("validations.sales.sale_information.saledate.must_be_after_last_transaction_date")])
+ end
end
end
@@ -346,12 +376,27 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end
context "when last transaction date == initial purchase date" do
- let(:record) { build(:sales_log, lasttransaction: current_collection_start_date, initialpurchase: current_collection_start_date) }
+ let(:record) { build(:sales_log, lasttransaction: collection_start_date_for_year(start_year), initialpurchase: collection_start_date_for_year(start_year), saledate: collection_start_date_for_year(start_year) + 1.day) }
- it "does not add an error" do
- sale_information_validator.validate_staircasing_last_transaction_date(record)
+ context "and 2025", metadata: { year: 25 } do
+ let(:start_year) { 2025 }
- expect(record.errors[:lasttransaction]).not_to be_present
+ it "does not add an error" do
+ sale_information_validator.validate_staircasing_last_transaction_date(record)
+
+ expect(record.errors[:lasttransaction]).not_to be_present
+ end
+ end
+
+ context "and 2026", metadata: { year: 26 } do
+ let(:start_year) { 2026 }
+
+ it "adds error" do
+ sale_information_validator.validate_staircasing_last_transaction_date(record)
+
+ expect(record.errors[:lasttransaction]).to eq([I18n.t("validations.sales.sale_information.lasttransaction.must_be_after_initial_purchase")])
+ expect(record.errors[:initialpurchase]).to eq([I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_last_transaction")])
+ end
end
end
end
From 4367e80545eb27b0d6722241f4a6313c99b75d27 Mon Sep 17 00:00:00 2001
From: Nat Dean-Lewis <94526761+natdeanlewissoftwire@users.noreply.github.com>
Date: Wed, 29 Apr 2026 12:14:03 +0100
Subject: [PATCH 24/34] CLDC-4352: Update building height class hint text as
dropdown (#3335)
* CLDC-4352: update hint text as dropdown
* CLDC-4352: update spec
* CLDC-4352: refactoring
---
app/models/form/sales/questions/building_height_class.rb | 1 +
app/views/form/guidance/_building_height_class.html.erb | 5 +++++
config/locales/forms/2026/sales/guidance.en.yml | 9 +++++++++
.../locales/forms/2026/sales/property_information.en.yml | 4 ++--
.../form/sales/questions/building_height_class_spec.rb | 4 ++++
5 files changed, 21 insertions(+), 2 deletions(-)
create mode 100644 app/views/form/guidance/_building_height_class.html.erb
diff --git a/app/models/form/sales/questions/building_height_class.rb b/app/models/form/sales/questions/building_height_class.rb
index 51e2c3623..c84470c60 100644
--- a/app/models/form/sales/questions/building_height_class.rb
+++ b/app/models/form/sales/questions/building_height_class.rb
@@ -3,6 +3,7 @@ class Form::Sales::Questions::BuildingHeightClass < ::Form::Question
super
@id = "buildheightclass"
@type = "radio"
+ @top_guidance_partial = "building_height_class"
@answer_options = ANSWER_OPTIONS
@question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
diff --git a/app/views/form/guidance/_building_height_class.html.erb b/app/views/form/guidance/_building_height_class.html.erb
new file mode 100644
index 000000000..f538ae151
--- /dev/null
+++ b/app/views/form/guidance/_building_height_class.html.erb
@@ -0,0 +1,5 @@
+
+ <%= govuk_details(summary_text: I18n.t("forms.#{@log.form.start_date.year}.sales.guidance.building_height_class.title")) do %>
+ <%= I18n.t("forms.#{@log.form.start_date.year}.sales.guidance.building_height_class.content").html_safe %>
+ <% end %>
+
diff --git a/config/locales/forms/2026/sales/guidance.en.yml b/config/locales/forms/2026/sales/guidance.en.yml
index bc40e2a7b..f5863b3af 100644
--- a/config/locales/forms/2026/sales/guidance.en.yml
+++ b/config/locales/forms/2026/sales/guidance.en.yml
@@ -55,3 +55,12 @@ en:
title: "What is a UPRN?"
content: "The Unique Property Reference Number (UPRN) is a unique number system created by Ordnance Survey and used by housing providers and various industries across the UK. An example is 0010457355.
The UPRN may not be the same as the property reference assigned by your organisation.
"
+
+ building_height_class:
+ title: "What do these classifications mean?"
+ content: "High-rise residential buildings are those containing 2 or more residential units and either:
+
+ - have 7 or more stories
+ - are at least 18 metres in height
+
+ If unsure, answer based on the number of storeys.
"
diff --git a/config/locales/forms/2026/sales/property_information.en.yml b/config/locales/forms/2026/sales/property_information.en.yml
index b63ea755c..16f9625c8 100644
--- a/config/locales/forms/2026/sales/property_information.en.yml
+++ b/config/locales/forms/2026/sales/property_information.en.yml
@@ -60,10 +60,10 @@ en:
question_text: "What type of unit is the property?"
buildheightclass:
- page_header: ""
+ page_header: "Building height classification"
check_answer_label: "Building height classification"
check_answer_prompt: ""
- hint_text: "High-rise residential buildings are those containing 2 or more residential units and either have 7 or more storeys or are at least 18 metres in height. If unsure, answer based on the number of storeys."
+ hint_text: ""
question_text: "What is the building height classification?"
builtype:
diff --git a/spec/models/form/sales/questions/building_height_class_spec.rb b/spec/models/form/sales/questions/building_height_class_spec.rb
index e7ab032d4..704739d37 100644
--- a/spec/models/form/sales/questions/building_height_class_spec.rb
+++ b/spec/models/form/sales/questions/building_height_class_spec.rb
@@ -36,4 +36,8 @@ RSpec.describe Form::Sales::Questions::BuildingHeightClass, type: :model do
it "has the correct question_number" do
expect(question.question_number).to eq(17)
end
+
+ it "has correct guidance partial" do
+ expect(question.top_guidance_partial).to eq("building_height_class")
+ end
end
From aa79c1fdfe83b3d9bbdc25db96c1a26b70c37a43 Mon Sep 17 00:00:00 2001
From: Nat Dean-Lewis <94526761+natdeanlewissoftwire@users.noreply.github.com>
Date: Wed, 29 Apr 2026 12:14:11 +0100
Subject: [PATCH 25/34] CLDC-4370: Update reason for leaving renewal hint text
(#3336)
* CLDC-4370: update hint_text
* CLDC-4370: align hint text in 2025
---
config/locales/forms/2025/lettings/household_situation.en.yml | 2 +-
config/locales/forms/2026/lettings/household_situation.en.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/config/locales/forms/2025/lettings/household_situation.en.yml b/config/locales/forms/2025/lettings/household_situation.en.yml
index 549f28810..5102c4832 100644
--- a/config/locales/forms/2025/lettings/household_situation.en.yml
+++ b/config/locales/forms/2025/lettings/household_situation.en.yml
@@ -23,7 +23,7 @@ en:
reason:
check_answer_label: "Reason for leaving last settled home"
check_answer_prompt: ""
- hint_text: "You told us this letting is a renewal. We have removed some options because of this."
+ hint_text: "The tenant’s ‘last settled home’ is their last long-standing home. For tenants who were in temporary accommodation, sleeping rough or otherwise homeless, their last settled home is where they were living previously.
You told us this letting is a renewal. We have removed some options because of this."
question_text: "What is the tenant’s main reason for the household leaving their last settled home?"
reasonother:
check_answer_label: ""
diff --git a/config/locales/forms/2026/lettings/household_situation.en.yml b/config/locales/forms/2026/lettings/household_situation.en.yml
index 133bcf6c3..57facd061 100644
--- a/config/locales/forms/2026/lettings/household_situation.en.yml
+++ b/config/locales/forms/2026/lettings/household_situation.en.yml
@@ -23,7 +23,7 @@ en:
reason:
check_answer_label: "Reason for leaving last settled home"
check_answer_prompt: ""
- hint_text: "You told us this letting is a renewal. We have removed some options because of this."
+ hint_text: "The tenant’s ‘last settled home’ is their last long-standing home. For tenants who were in temporary accommodation, sleeping rough or otherwise homeless, their last settled home is where they were living immediately before that period.
You told us this letting is a renewal. We have removed some options because of this."
question_text: "What is the tenant’s main reason for the household leaving their last settled home?"
reasonother:
check_answer_label: ""
From 8d6cd8354970e3c79330853614f64d4d5b63dc1d Mon Sep 17 00:00:00 2001
From: Nat Dean-Lewis <94526761+natdeanlewissoftwire@users.noreply.github.com>
Date: Wed, 29 Apr 2026 12:26:44 +0100
Subject: [PATCH 26/34] CLDC-4269: Raise max hhmemb (#3332)
* CLDC-4269: update hhmemb question
* CLDC-4269: update counts in vars and validations
* CLDC-4269: update depends_on for person_known and update tests
* CLDC-4269: reformat
* CLDC-4269: update spec
* CLDC-4269: update spec
* CLDC-4269: cleanup
* CLDC-4269: cleanup
* CLDC-4352: refactoring
* CLDC-4269: move depends_on after person_index for safety
* CLDC-4269: comment for not fully implemented const
---
.../lettings_log_variables.rb | 2 +-
.../form/lettings/pages/person_known.rb | 9 ++++-
app/models/form/lettings/questions/hhmemb.rb | 2 +-
app/models/lettings_log.rb | 3 +-
app/models/log.rb | 8 +++++
app/models/sales_log.rb | 1 +
.../validations/financial_validations.rb | 4 +--
app/models/validations/soft_validations.rb | 35 ++++++-------------
.../lettings/household_characteristics.en.yml | 2 +-
.../lettings/household_characteristics.en.yml | 2 +-
.../form/lettings/pages/person_known_spec.rb | 29 +++++++--------
.../validations/household_validations_spec.rb | 12 +++----
12 files changed, 53 insertions(+), 56 deletions(-)
diff --git a/app/models/derived_variables/lettings_log_variables.rb b/app/models/derived_variables/lettings_log_variables.rb
index abce99667..f0f4ff279 100644
--- a/app/models/derived_variables/lettings_log_variables.rb
+++ b/app/models/derived_variables/lettings_log_variables.rb
@@ -339,7 +339,7 @@ private
def infer_only_partner!(partner_number)
return unless hhmemb
- (2..hhmemb).each do |i|
+ (2..people_with_details).each do |i|
next if i == partner_number
if ["P", nil].include?(public_send("relat#{i}"))
diff --git a/app/models/form/lettings/pages/person_known.rb b/app/models/form/lettings/pages/person_known.rb
index 6e699926d..db22da32e 100644
--- a/app/models/form/lettings/pages/person_known.rb
+++ b/app/models/form/lettings/pages/person_known.rb
@@ -2,11 +2,18 @@ class Form::Lettings::Pages::PersonKnown < ::Form::Page
def initialize(id, hsh, subsection, person_index:)
super(id, hsh, subsection)
@id = "person_#{person_index}_known"
- @depends_on = (person_index..8).map { |index| { "hhmemb" => index } }
@person_index = person_index
+ @depends_on = depends_on
end
def questions
@questions ||= [Form::Lettings::Questions::DetailsKnown.new(nil, nil, self, person_index: @person_index)]
end
+
+ def depends_on
+ [{ "hhmemb" => {
+ "operator" => ">=",
+ "operand" => @person_index,
+ } }]
+ end
end
diff --git a/app/models/form/lettings/questions/hhmemb.rb b/app/models/form/lettings/questions/hhmemb.rb
index 614b2b27e..8aa071788 100644
--- a/app/models/form/lettings/questions/hhmemb.rb
+++ b/app/models/form/lettings/questions/hhmemb.rb
@@ -5,7 +5,7 @@ class Form::Lettings::Questions::Hhmemb < ::Form::Question
@type = "numeric"
@width = 2
@check_answers_card_number = 0
- @max = 8
+ @max = 15
@min = 1
@step = 1
@question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
diff --git a/app/models/lettings_log.rb b/app/models/lettings_log.rb
index 2e6b800eb..5a11da38a 100644
--- a/app/models/lettings_log.rb
+++ b/app/models/lettings_log.rb
@@ -191,6 +191,7 @@ class LettingsLog < Log
NUM_OF_WEEKS_FROM_PERIOD = { 2 => 26, 3 => 13, 4 => 12, 5 => 50, 6 => 49, 7 => 48, 8 => 47, 9 => 46, 11 => 51, 1 => 52, 10 => 53 }.freeze
SUFFIX_FROM_PERIOD = { 2 => "every 2 weeks", 3 => "every 4 weeks", 4 => "every month" }.freeze
DUPLICATE_LOG_ATTRIBUTES = %w[owning_organisation_id tenancycode startdate age1_known age1 sex1 sexrab1 ecstat1 tcharge household_charge chcharge].freeze
+ MAX_PEOPLE_WITH_DETAILS = 8 # This is not yet used in all lettings validations etc. so check for other occurrences of this concept if updating this
RENT_TYPE = {
social_rent: 0,
affordable_rent: 1,
@@ -284,7 +285,7 @@ class LettingsLog < Log
range = ALLOWED_INCOME_RANGES[ecstat1].clone
if hhmemb > 1
- (2..hhmemb).each do |person_index|
+ (2..people_with_details).each do |person_index|
ecstat = self["ecstat#{person_index}"]
if ecstat.nil?
diff --git a/app/models/log.rb b/app/models/log.rb
index 5500991b6..abb652474 100644
--- a/app/models/log.rb
+++ b/app/models/log.rb
@@ -204,6 +204,14 @@ class Log < ApplicationRecord
false
end
+ def people_with_details
+ [hhmemb || max_people_with_details, max_people_with_details].min
+ end
+
+ def max_people_with_details
+ self.class::MAX_PEOPLE_WITH_DETAILS
+ end
+
def ethnic_refused?
ethnic_group == 17
end
diff --git a/app/models/sales_log.rb b/app/models/sales_log.rb
index 4d6e152a2..06f1c201b 100644
--- a/app/models/sales_log.rb
+++ b/app/models/sales_log.rb
@@ -104,6 +104,7 @@ class SalesLog < Log
OPTIONAL_FIELDS = %w[purchid othtype buyers_organisations].freeze
DUPLICATE_LOG_ATTRIBUTES = %w[owning_organisation_id purchid saledate age1_known age1 sex1 sexrab1 ecstat1 postcode_full uprn address_line1].freeze
+ MAX_PEOPLE_WITH_DETAILS = 6 # This is not yet used in all sales validations etc. so check for other occurrences of this concept if updating this
def lettings?
false
diff --git a/app/models/validations/financial_validations.rb b/app/models/validations/financial_validations.rb
index a5794a5e3..dd8029ebb 100644
--- a/app/models/validations/financial_validations.rb
+++ b/app/models/validations/financial_validations.rb
@@ -41,7 +41,7 @@ module Validations::FinancialValidations
:over_hard_max,
message: I18n.t("validations.lettings.financial.hhmemb.earnings_over_hard_max", earnings: format_as_currency(record.earnings), frequency:),
)
- (1..record.hhmemb).each do |n|
+ (1..record.people_with_details).each do |n|
record.errors.add(
"ecstat#{n}",
:over_hard_max,
@@ -70,7 +70,7 @@ module Validations::FinancialValidations
:under_hard_min,
message: I18n.t("validations.lettings.financial.hhmemb.earnings_under_hard_min", earnings: format_as_currency(record.earnings), frequency:),
)
- (1..record.hhmemb).each do |n|
+ (1..record.people_with_details).each do |n|
record.errors.add(
"ecstat#{n}",
:under_hard_min,
diff --git a/app/models/validations/soft_validations.rb b/app/models/validations/soft_validations.rb
index 0ff08afb1..71ef99a4f 100644
--- a/app/models/validations/soft_validations.rb
+++ b/app/models/validations/soft_validations.rb
@@ -208,8 +208,7 @@ module Validations::SoftValidations
def multiple_partners?
return unless hhmemb
- max_person_with_details = sales? ? [hhmemb, 6].min : [hhmemb, 8].min
- (2..max_person_with_details).many? { |n| public_send("relat#{n}") == "P" }
+ (2..people_with_details).many? { |n| public_send("relat#{n}") == "P" }
end
def at_least_one_working_situation_is_sickness_and_household_sickness_is_no?
@@ -219,22 +218,18 @@ module Validations::SoftValidations
private
def all_tenants_age_and_gender_information_completed?
- return false if hhmemb.present? && hhmemb > 8
+ return false if hhmemb.present? && hhmemb > max_people_with_details
return false unless all_tenants_gender_information_completed?
- person_count = hhmemb || 8
-
- (1..person_count).all? do |n|
+ (1..people_with_details).all? do |n|
public_send("age#{n}").present? && public_send("age#{n}_known").present? && public_send("age#{n}_known").zero?
end
end
def all_tenants_gender_information_completed?
- return false if hhmemb.present? && hhmemb > 8
-
- person_count = hhmemb || 8
+ return false if hhmemb.present? && hhmemb > max_people_with_details
- (1..person_count).all? do |n|
+ (1..people_with_details).all? do |n|
tenant_gender_information_completed?(n)
end
end
@@ -258,27 +253,21 @@ private
end
def any_non_male_in_expected_pregnancy_age_range(min, max)
- person_count = hhmemb || 8
-
- (1..person_count).any? do |n|
+ (1..people_with_details).any? do |n|
person_in_expected_pregnancy_age_range(n, min, max) && person_is_non_male(n)
end
end
def non_males_in_the_household?
- person_count = hhmemb || 8
-
- (1..person_count).any? do |n|
+ (1..people_with_details).any? do |n|
person_is_non_male(n)
end
end
def all_male_tenants_in_the_household?
- return false if hhmemb.present? && hhmemb > 8
+ return false if hhmemb.present? && hhmemb > max_people_with_details
- person_count = hhmemb || 8
-
- (1..person_count).all? do |n|
+ (1..people_with_details).all? do |n|
person_is_male(n)
end
end
@@ -344,11 +333,7 @@ private
end
def at_least_one_person_working_situation_is_illness?
- return if hhmemb.present? && hhmemb > 8
-
- person_count = hhmemb || 8
-
- (1..person_count).any? { |n| public_send("ecstat#{n}") == 8 }
+ (1..people_with_details).any? { |n| public_send("ecstat#{n}") == 8 }
end
def no_one_in_household_with_illness?
diff --git a/config/locales/forms/2025/lettings/household_characteristics.en.yml b/config/locales/forms/2025/lettings/household_characteristics.en.yml
index 432b0d08f..3ed45dcea 100644
--- a/config/locales/forms/2025/lettings/household_characteristics.en.yml
+++ b/config/locales/forms/2025/lettings/household_characteristics.en.yml
@@ -7,7 +7,7 @@ en:
page_header: ""
check_answer_label: "Number of household members"
check_answer_prompt: "Enter total number of household members"
- hint_text: "You can provide details for a maximum of 8 people."
+ hint_text: "You can answer up to 15 people. You will be asked to add details for a maximum of 8 people in the next questions."
question_text: "How many people live in the household for this letting?"
age1:
diff --git a/config/locales/forms/2026/lettings/household_characteristics.en.yml b/config/locales/forms/2026/lettings/household_characteristics.en.yml
index 84d7c5f33..bff084a3c 100644
--- a/config/locales/forms/2026/lettings/household_characteristics.en.yml
+++ b/config/locales/forms/2026/lettings/household_characteristics.en.yml
@@ -7,7 +7,7 @@ en:
page_header: ""
check_answer_label: "Number of household members"
check_answer_prompt: "Enter total number of household members"
- hint_text: "You can provide details for a maximum of 8 people."
+ hint_text: "You can answer up to 15 people. You will be asked to add details for a maximum of 8 people in the next questions."
question_text: "How many people live in the household for this letting?"
age1:
diff --git a/spec/models/form/lettings/pages/person_known_spec.rb b/spec/models/form/lettings/pages/person_known_spec.rb
index 7b77c5c0f..01616e5e0 100644
--- a/spec/models/form/lettings/pages/person_known_spec.rb
+++ b/spec/models/form/lettings/pages/person_known_spec.rb
@@ -26,15 +26,12 @@ RSpec.describe Form::Lettings::Pages::PersonKnown, type: :model do
it "has correct depends_on" do
expect(page.depends_on).to eq(
- [
- { "hhmemb" => 2 },
- { "hhmemb" => 3 },
- { "hhmemb" => 4 },
- { "hhmemb" => 5 },
- { "hhmemb" => 6 },
- { "hhmemb" => 7 },
- { "hhmemb" => 8 },
- ],
+ [{
+ "hhmemb" => {
+ "operator" => ">=",
+ "operand" => 2,
+ },
+ }],
)
end
end
@@ -52,14 +49,12 @@ RSpec.describe Form::Lettings::Pages::PersonKnown, type: :model do
it "has correct depends_on" do
expect(page.depends_on).to eq(
- [
- { "hhmemb" => 3 },
- { "hhmemb" => 4 },
- { "hhmemb" => 5 },
- { "hhmemb" => 6 },
- { "hhmemb" => 7 },
- { "hhmemb" => 8 },
- ],
+ [{
+ "hhmemb" => {
+ "operator" => ">=",
+ "operand" => 3,
+ },
+ }],
)
end
end
diff --git a/spec/models/validations/household_validations_spec.rb b/spec/models/validations/household_validations_spec.rb
index 9848afd67..0f874dcc5 100644
--- a/spec/models/validations/household_validations_spec.rb
+++ b/spec/models/validations/household_validations_spec.rb
@@ -252,18 +252,18 @@ RSpec.describe Validations::HouseholdValidations do
record.hhmemb = 0
household_validator.validate_numeric_min_max(record)
expect(record.errors["hhmemb"])
- .to include(match I18n.t("validations.shared.numeric.within_range", field: "Number of household members", min: 1, max: 8))
+ .to include(match I18n.t("validations.shared.numeric.within_range", field: "Number of household members", min: 1, max: 15))
end
- it "validates that the number of household members cannot be more than 8" do
- record.hhmemb = 9
+ it "validates that the number of household members cannot be more than 15" do
+ record.hhmemb = 16
household_validator.validate_numeric_min_max(record)
expect(record.errors["hhmemb"])
- .to include(match I18n.t("validations.shared.numeric.within_range", field: "Number of household members", min: 1, max: 8))
+ .to include(match I18n.t("validations.shared.numeric.within_range", field: "Number of household members", min: 1, max: 15))
end
- it "expects that the number of other household members is between the min and max" do
- record.hhmemb = 5
+ it "expects that the number of household members is between the min and max" do
+ record.hhmemb = 11
household_validator.validate_numeric_min_max(record)
expect(record.errors["hhmemb"]).to be_empty
end
From e72707b77e2ff2749d0df52d661dc7b36cad8826 Mon Sep 17 00:00:00 2001
From: Nat Dean-Lewis <94526761+natdeanlewissoftwire@users.noreply.github.com>
Date: Wed, 29 Apr 2026 12:28:15 +0100
Subject: [PATCH 27/34] CLDC-4389: BU validation prioritisation (#3317)
---
app/services/bulk_upload/lettings/year2025/row_parser.rb | 3 ++-
app/services/bulk_upload/lettings/year2026/row_parser.rb | 3 ++-
app/services/bulk_upload/sales/year2025/row_parser.rb | 6 +++---
app/services/bulk_upload/sales/year2026/row_parser.rb | 5 +++--
4 files changed, 10 insertions(+), 7 deletions(-)
diff --git a/app/services/bulk_upload/lettings/year2025/row_parser.rb b/app/services/bulk_upload/lettings/year2025/row_parser.rb
index e407e9fe6..fdf76d1cb 100644
--- a/app/services/bulk_upload/lettings/year2025/row_parser.rb
+++ b/app/services/bulk_upload/lettings/year2025/row_parser.rb
@@ -461,7 +461,6 @@ class BulkUpload::Lettings::Year2025::RowParser
validate :validate_uprn_exists_if_any_key_address_fields_are_blank, on: :after_log, unless: -> { supported_housing? }
validate :validate_address_fields, on: :after_log, unless: -> { supported_housing? }
- validate :validate_incomplete_soft_validations, on: :after_log
validate :validate_nationality, on: :after_log
validate :validate_reasonpref_reason_values, on: :after_log
validate :validate_prevten_value_when_renewal, on: :after_log
@@ -506,6 +505,8 @@ class BulkUpload::Lettings::Year2025::RowParser
end
end
+ validate_incomplete_soft_validations
+
add_errors_for_invalid_fields
@valid = errors.blank?
diff --git a/app/services/bulk_upload/lettings/year2026/row_parser.rb b/app/services/bulk_upload/lettings/year2026/row_parser.rb
index ac366dc57..13baad405 100644
--- a/app/services/bulk_upload/lettings/year2026/row_parser.rb
+++ b/app/services/bulk_upload/lettings/year2026/row_parser.rb
@@ -496,7 +496,6 @@ class BulkUpload::Lettings::Year2026::RowParser
validate :validate_uprn_exists_if_any_key_address_fields_are_blank, on: :after_log
validate :validate_address_fields, on: :after_log
- validate :validate_incomplete_soft_validations, on: :after_log
validate :validate_nationality, on: :after_log
validate :validate_reasonpref_reason_values, on: :after_log
validate :validate_prevten_value_when_renewal, on: :after_log
@@ -541,6 +540,8 @@ class BulkUpload::Lettings::Year2026::RowParser
end
end
+ validate_incomplete_soft_validations
+
add_errors_for_invalid_fields
@valid = errors.blank?
diff --git a/app/services/bulk_upload/sales/year2025/row_parser.rb b/app/services/bulk_upload/sales/year2025/row_parser.rb
index 39ca46c8f..849f37a21 100644
--- a/app/services/bulk_upload/sales/year2025/row_parser.rb
+++ b/app/services/bulk_upload/sales/year2025/row_parser.rb
@@ -439,8 +439,6 @@ class BulkUpload::Sales::Year2025::RowParser
validate :validate_assigned_to_when_support, on: :after_log
validate :validate_managing_org_related, on: :after_log
validate :validate_relevant_collection_window, on: :after_log
- validate :validate_incomplete_soft_validations, on: :after_log
-
validate :validate_uprn_exists_if_any_key_address_fields_are_blank, on: :after_log
validate :validate_address_fields, on: :after_log
validate :validate_if_log_already_exists, on: :after_log, if: -> { FeatureToggle.bulk_upload_duplicate_log_check_enabled? }
@@ -504,6 +502,8 @@ class BulkUpload::Sales::Year2025::RowParser
end
end
+ validate_incomplete_soft_validations
+
add_errors_for_invalid_fields
errors.blank?
@@ -1519,7 +1519,7 @@ private
next if log.form.questions.none? { |q| q.id == interruption_screen_question_id && q.page.routed_to?(log, nil) }
field_mapping_for_errors[interruption_screen_question_id.to_sym]&.each do |field|
- if errors.none? { |e| e.options[:category] == :soft_validation && field_mapping_for_errors[interruption_screen_question_id.to_sym].include?(e.attribute) }
+ if errors.none? { |e| field_mapping_for_errors[interruption_screen_question_id.to_sym].include?(e.attribute) }
error_message = [display_title_text(question.page.title_text, log), display_informative_text(question.page.informative_text, log)].reject(&:empty?).join(" ")
errors.add(field, message: error_message, category: :soft_validation)
end
diff --git a/app/services/bulk_upload/sales/year2026/row_parser.rb b/app/services/bulk_upload/sales/year2026/row_parser.rb
index d9989fb9f..f9a3d5242 100644
--- a/app/services/bulk_upload/sales/year2026/row_parser.rb
+++ b/app/services/bulk_upload/sales/year2026/row_parser.rb
@@ -493,7 +493,6 @@ class BulkUpload::Sales::Year2026::RowParser
validate :validate_assigned_to_when_support, on: :after_log
validate :validate_managing_org_related, on: :after_log
validate :validate_relevant_collection_window, on: :after_log
- validate :validate_incomplete_soft_validations, on: :after_log
validate :validate_uprn_exists_if_any_key_address_fields_are_blank, on: :after_log
validate :validate_address_fields, on: :after_log
@@ -561,6 +560,8 @@ class BulkUpload::Sales::Year2026::RowParser
end
end
+ validate_incomplete_soft_validations
+
add_errors_for_invalid_fields
errors.blank?
@@ -1672,7 +1673,7 @@ private
next if log.form.questions.none? { |q| q.id == interruption_screen_question_id && q.page.routed_to?(log, nil) }
field_mapping_for_errors[interruption_screen_question_id.to_sym]&.each do |field|
- if errors.none? { |e| e.options[:category] == :soft_validation && field_mapping_for_errors[interruption_screen_question_id.to_sym].include?(e.attribute) }
+ if errors.none? { |e| field_mapping_for_errors[interruption_screen_question_id.to_sym].include?(e.attribute) }
error_message = [display_title_text(question.page.title_text, log), display_informative_text(question.page.informative_text, log)].reject(&:empty?).join(" ")
errors.add(field, message: error_message, category: :soft_validation)
end
From 99ea75f9e8e796e9596a99b26825fc25fb6a82d4 Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Wed, 29 Apr 2026 15:51:29 +0100
Subject: [PATCH 28/34] Revert "CLDC-4300: Update sale date staircasing date
validation (#3307)" (#3339)
This reverts commit 1e1773605c29e681981d9a8609b058306f5e5ce6.
---
.../sales/sale_information_validations.rb | 6 +-
...valid_initialpurchase_lasttransaction.rake | 13 ----
.../sale_information_validations_spec.rb | 69 ++++---------------
3 files changed, 15 insertions(+), 73 deletions(-)
delete mode 100644 lib/tasks/fix_sales_logs_with_invalid_initialpurchase_lasttransaction.rake
diff --git a/app/models/validations/sales/sale_information_validations.rb b/app/models/validations/sales/sale_information_validations.rb
index 7cd24183c..32bf2a716 100644
--- a/app/models/validations/sales/sale_information_validations.rb
+++ b/app/models/validations/sales/sale_information_validations.rb
@@ -42,7 +42,7 @@ module Validations::Sales::SaleInformationValidations
record.errors.add :initialpurchase, I18n.t("validations.sales.sale_information.initialpurchase.must_be_after_1980")
end
- if record.saledate.present? && ((record.initialpurchase > record.saledate) || (record.initialpurchase == record.saledate && record.form.start_year_2026_or_later?))
+ if record.saledate.present? && record.initialpurchase > record.saledate
record.errors.add :initialpurchase, I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_saledate")
record.errors.add :saledate, :skip_bu_error, message: I18n.t("validations.sales.sale_information.saledate.must_be_after_initial_purchase_date")
end
@@ -55,11 +55,11 @@ module Validations::Sales::SaleInformationValidations
record.errors.add :lasttransaction, I18n.t("validations.sales.sale_information.lasttransaction.must_be_after_1980")
end
- if record.saledate.present? && ((record.lasttransaction > record.saledate) || (record.lasttransaction == record.saledate && record.form.start_year_2026_or_later?))
+ if record.saledate.present? && record.lasttransaction > record.saledate
record.errors.add :lasttransaction, I18n.t("validations.sales.sale_information.lasttransaction.must_be_before_saledate")
record.errors.add :saledate, :skip_bu_error, message: I18n.t("validations.sales.sale_information.saledate.must_be_after_last_transaction_date")
end
- if record.initialpurchase.present? && ((record.lasttransaction < record.initialpurchase) || (record.lasttransaction == record.initialpurchase && record.form.start_year_2026_or_later?))
+ if record.initialpurchase.present? && record.lasttransaction < record.initialpurchase
record.errors.add :initialpurchase, I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_last_transaction")
record.errors.add :lasttransaction, I18n.t("validations.sales.sale_information.lasttransaction.must_be_after_initial_purchase")
end
diff --git a/lib/tasks/fix_sales_logs_with_invalid_initialpurchase_lasttransaction.rake b/lib/tasks/fix_sales_logs_with_invalid_initialpurchase_lasttransaction.rake
deleted file mode 100644
index 44475a46f..000000000
--- a/lib/tasks/fix_sales_logs_with_invalid_initialpurchase_lasttransaction.rake
+++ /dev/null
@@ -1,13 +0,0 @@
-desc "We tightened the validation in 2026 between initial purchase date, last transaction date and sale date so that no two can be equal and initial purchase date < last transaction date < sale date. To avoid invalid logs we clear lasttransaction if it equals saledate and if initialpurchase = lasttransaction we clear both"
-task fix_sales_logs_with_invalid_initialpurchase_lasttransaction: :environment do
- lasttransaction_equal_saledate_logs = SalesLog.filter_by_year_or_later(2026).where("lasttransaction = saledate")
- initial_purchase_equal_lasttransaction_logs = SalesLog.filter_by_year_or_later(2026).where("initialpurchase = lasttransaction")
-
- puts "Updating #{lasttransaction_equal_saledate_logs.count} logs where lasttransaction = saledate, #{lasttransaction_equal_saledate_logs.map(&:id)}"
- lasttransaction_equal_saledate_logs.update!(lasttransaction: nil)
-
- puts "Updating #{initial_purchase_equal_lasttransaction_logs.count} logs where initialpurchase = lasttransaction, #{initial_purchase_equal_lasttransaction_logs.map(&:id)}"
- initial_purchase_equal_lasttransaction_logs.update!(initialpurchase: nil, lasttransaction: nil)
-
- puts "Done"
-end
diff --git a/spec/models/validations/sales/sale_information_validations_spec.rb b/spec/models/validations/sales/sale_information_validations_spec.rb
index 04f71b198..8d4eb4cea 100644
--- a/spec/models/validations/sales/sale_information_validations_spec.rb
+++ b/spec/models/validations/sales/sale_information_validations_spec.rb
@@ -252,27 +252,12 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end
context "when initial purchase date == saledate" do
- let(:record) { build(:sales_log, initialpurchase: collection_start_date_for_year(start_year), saledate: collection_start_date_for_year(start_year)) }
+ let(:record) { build(:sales_log, initialpurchase: current_collection_start_date, saledate: current_collection_start_date) }
- context "and 2025", metadata: { year: 25 } do
- let(:start_year) { 2025 }
-
- it "does not add an error" do
- sale_information_validator.validate_staircasing_initial_purchase_date(record)
-
- expect(record.errors[:lasttransaction]).not_to be_present
- end
- end
-
- context "and 2026", metadata: { year: 26 } do
- let(:start_year) { 2026 }
-
- it "adds error" do
- sale_information_validator.validate_staircasing_initial_purchase_date(record)
+ it "does not add an error" do
+ sale_information_validator.validate_staircasing_initial_purchase_date(record)
- expect(record.errors[:initialpurchase]).to eq([I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_saledate")])
- expect(record.errors[:saledate]).to eq([I18n.t("validations.sales.sale_information.saledate.must_be_after_initial_purchase_date")])
- end
+ expect(record.errors[:initialpurchase]).not_to be_present
end
end
end
@@ -330,27 +315,12 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end
context "when last transaction date == saledate" do
- let(:record) { build(:sales_log, lasttransaction: collection_start_date_for_year(start_year), saledate: collection_start_date_for_year(start_year)) }
-
- context "and 2025", metadata: { year: 25 } do
- let(:start_year) { 2025 }
-
- it "does not add an error" do
- sale_information_validator.validate_staircasing_last_transaction_date(record)
-
- expect(record.errors[:lasttransaction]).not_to be_present
- end
- end
+ let(:record) { build(:sales_log, lasttransaction: current_collection_start_date, saledate: current_collection_start_date) }
- context "and 2026", metadata: { year: 26 } do
- let(:start_year) { 2026 }
-
- it "adds error" do
- sale_information_validator.validate_staircasing_last_transaction_date(record)
+ it "does not add an error" do
+ sale_information_validator.validate_staircasing_last_transaction_date(record)
- expect(record.errors[:lasttransaction]).to eq([I18n.t("validations.sales.sale_information.lasttransaction.must_be_before_saledate")])
- expect(record.errors[:saledate]).to eq([I18n.t("validations.sales.sale_information.saledate.must_be_after_last_transaction_date")])
- end
+ expect(record.errors[:lasttransaction]).not_to be_present
end
end
@@ -376,27 +346,12 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end
context "when last transaction date == initial purchase date" do
- let(:record) { build(:sales_log, lasttransaction: collection_start_date_for_year(start_year), initialpurchase: collection_start_date_for_year(start_year), saledate: collection_start_date_for_year(start_year) + 1.day) }
-
- context "and 2025", metadata: { year: 25 } do
- let(:start_year) { 2025 }
-
- it "does not add an error" do
- sale_information_validator.validate_staircasing_last_transaction_date(record)
+ let(:record) { build(:sales_log, lasttransaction: current_collection_start_date, initialpurchase: current_collection_start_date) }
- expect(record.errors[:lasttransaction]).not_to be_present
- end
- end
-
- context "and 2026", metadata: { year: 26 } do
- let(:start_year) { 2026 }
-
- it "adds error" do
- sale_information_validator.validate_staircasing_last_transaction_date(record)
+ it "does not add an error" do
+ sale_information_validator.validate_staircasing_last_transaction_date(record)
- expect(record.errors[:lasttransaction]).to eq([I18n.t("validations.sales.sale_information.lasttransaction.must_be_after_initial_purchase")])
- expect(record.errors[:initialpurchase]).to eq([I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_last_transaction")])
- end
+ expect(record.errors[:lasttransaction]).not_to be_present
end
end
end
From e079455f65372dcdef152c74d59a29c853acdf30 Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Wed, 29 Apr 2026 16:16:43 +0100
Subject: [PATCH 29/34] CLDC-4332: Check that a support user can only be in
certain orgs (#3305)
* CLDC-4332: Check that a support user can only be in certain orgs
* CLDC-4332: Add tests
* CLDC-4332: Lint
* CLDC-4332: Only show the check for wrong org on edit
* CLDC-4332: Add the error to role if role is wrong
* fixup! CLDC-4332: Only show the check for wrong org on edit
lint
* CLDC-4332: TEMP: Add MHCLG filter for review apps
* Revert "CLDC-4332: TEMP: Add MHCLG filter for review apps"
This reverts commit b65c630edea1f06403b4f837ec79d2541b7fb46b.
---
app/controllers/users_controller.rb | 10 ++++--
app/models/user.rb | 17 +++++++++++
app/services/feature_toggle.rb | 6 ++++
config/locales/en.yml | 4 +++
spec/models/user_spec.rb | 47 +++++++++++++++++++++++++++++
5 files changed, 82 insertions(+), 2 deletions(-)
diff --git a/app/controllers/users_controller.rb b/app/controllers/users_controller.rb
index 57036cabe..677925679 100644
--- a/app/controllers/users_controller.rb
+++ b/app/controllers/users_controller.rb
@@ -221,8 +221,14 @@ private
@user.errors.add :phone
end
- if user_params.key?(:organisation_id) && user_params[:organisation_id].blank?
- @user.errors.add :organisation_id, :blank
+ if user_params.key?(:organisation_id)
+ if user_params[:organisation_id].blank?
+ @user.errors.add :organisation_id, :blank
+ elsif !@user.role_is_allowed_to_be_in_organisation?(override_organisation_id: user_params[:organisation_id].to_i) && @user.id.present?
+ # this will also be flagged by the validation in user.rb.
+ # for convenience we show the error early before they go through the change org flow (involves reassigning logs).
+ @user.errors.add :organisation_id, I18n.t("validations.user.support_user_in_wrong_organisation.change_organisation")
+ end
end
end
diff --git a/app/models/user.rb b/app/models/user.rb
index 92fd37dc8..b2ab58c11 100644
--- a/app/models/user.rb
+++ b/app/models/user.rb
@@ -25,6 +25,7 @@ class User < ApplicationRecord
validates :organisation_id, presence: true
validate :organisation_not_merged
+ validate :support_user_is_in_correct_organisation
has_paper_trail ignore: %w[last_sign_in_at
current_sign_in_at
@@ -390,6 +391,12 @@ class User < ApplicationRecord
end
end
+ def role_is_allowed_to_be_in_organisation?(override_organisation_id: nil)
+ return true unless support? && FeatureToggle.support_organisation_allow_list.present?
+
+ FeatureToggle.support_organisation_allow_list.include?(override_organisation_id || organisation_id)
+ end
+
protected
# Checks whether a password is needed or not. For validations only.
@@ -407,6 +414,16 @@ private
end
end
+ def support_user_is_in_correct_organisation
+ return if role_is_allowed_to_be_in_organisation?
+
+ if role_changed?
+ errors.add :role, I18n.t("validations.user.support_user_in_wrong_organisation.change_role")
+ else
+ errors.add :organisation_id, I18n.t("validations.user.support_user_in_wrong_organisation.change_organisation")
+ end
+ end
+
def send_data_protection_confirmation_reminder
return unless persisted?
return unless is_dpo?
diff --git a/app/services/feature_toggle.rb b/app/services/feature_toggle.rb
index 2f301294c..7404309f2 100644
--- a/app/services/feature_toggle.rb
+++ b/app/services/feature_toggle.rb
@@ -34,4 +34,10 @@ class FeatureToggle
def self.sales_export_enabled?
Time.zone.now >= Time.zone.local(2025, 4, 1) || (Rails.env.review? || Rails.env.staging?)
end
+
+ # IDs of organisations a user must be in to be allowed the support role
+ # if nil this feature will be disabled
+ def self.support_organisation_allow_list
+ [1] if Rails.env.production?
+ end
end
diff --git a/config/locales/en.yml b/config/locales/en.yml
index 26a834e5d..843d1da8b 100644
--- a/config/locales/en.yml
+++ b/config/locales/en.yml
@@ -260,6 +260,10 @@ en:
blank: "Enter an email address."
role:
invalid: "Role must be data accessor, data provider or data coordinator."
+ user:
+ support_user_in_wrong_organisation:
+ change_role: "You cannot create a support account type for a user in this organisation. Support accounts should only be created for MHCLG and contractor staff as they are administrator level accounts with access to all organisations' data. Any support accounts for housing organisations would be a data protection breach."
+ change_organisation: "You cannot move a user with a support account to a non-MHCLG organisation. If you need to move the user, change their role type to data coordinator or data provider."
setup:
saledate:
diff --git a/spec/models/user_spec.rb b/spec/models/user_spec.rb
index 495d5ba13..b461b60e5 100644
--- a/spec/models/user_spec.rb
+++ b/spec/models/user_spec.rb
@@ -540,6 +540,53 @@ RSpec.describe User, type: :model do
.to raise_error(ActiveRecord::RecordInvalid, error_message)
end
end
+
+ describe "#support_user_is_in_correct_organisation" do
+ let(:organisation) { create(:organisation) }
+
+ context "when the user is not a support user" do
+ let(:user) { build(:user, :data_coordinator, organisation:) }
+
+ it "is valid regardless of the allow list" do
+ allow(FeatureToggle).to receive(:support_organisation_allow_list).and_return([999])
+ expect(user).to be_valid
+ end
+ end
+
+ context "when the user is a support user" do
+ let(:user) { build(:user, :support, organisation:) }
+
+ context "and the allow list is nil" do
+ before do
+ allow(FeatureToggle).to receive(:support_organisation_allow_list).and_return(nil)
+ end
+
+ it "is valid" do
+ expect(user).to be_valid
+ end
+ end
+
+ context "and the organisation is in the allow list" do
+ before do
+ allow(FeatureToggle).to receive(:support_organisation_allow_list).and_return([organisation.id])
+ end
+
+ it "is valid" do
+ expect(user).to be_valid
+ end
+ end
+
+ context "and the organisation is not in the allow list" do
+ before do
+ allow(FeatureToggle).to receive(:support_organisation_allow_list).and_return([organisation.id + 1])
+ end
+
+ it "is not valid" do
+ expect(user).not_to be_valid
+ end
+ end
+ end
+ end
end
describe "delete" do
From 13b2fc61c1b047d7e5494b07f543a86826de1556 Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Thu, 30 Apr 2026 15:16:27 +0100
Subject: [PATCH 30/34] CLDC-3280: Remove error report upload again when
viewing before decision (#3303)
* CLDC-3280: Add back link to error summary page
* CLDC-3280: Hide upload button if navigating from a view url
* CLDC-3280: Update tests
* CLDC-3280: Make read only error report opt-in
this means we can be happy only the touched pages will have a change in behaviour
* CLDC-3280: Rename fix errors in tests to reupload file
Co-authored-by: Oscar Richardson <116292912+oscar-richardson-softwire@users.noreply.github.com>
---------
Co-authored-by: Oscar Richardson <116292912+oscar-richardson-softwire@users.noreply.github.com>
---
.../forms/bulk_upload_resume/confirm.rb | 6 ++--
.../forms/bulk_upload_resume/fix_choice.rb | 6 ++--
.../show.html.erb | 4 ++-
.../summary.html.erb | 8 ++++-
.../confirm.html.erb | 2 +-
.../fix_choice.html.erb | 2 +-
.../bulk_upload_sales_results/show.html.erb | 4 ++-
.../summary.html.erb | 8 ++++-
.../bulk_upload_sales_resume/confirm.html.erb | 2 +-
.../fix_choice.html.erb | 2 +-
...upload_lettings_results_controller_spec.rb | 36 +++++++++++++++++++
...lk_upload_sales_results_controller_spec.rb | 36 +++++++++++++++++++
12 files changed, 102 insertions(+), 14 deletions(-)
diff --git a/app/models/forms/bulk_upload_resume/confirm.rb b/app/models/forms/bulk_upload_resume/confirm.rb
index 96a1fe1bc..596018d50 100644
--- a/app/models/forms/bulk_upload_resume/confirm.rb
+++ b/app/models/forms/bulk_upload_resume/confirm.rb
@@ -20,11 +20,11 @@ module Forms
send("resume_bulk_upload_#{log_type}_result_path", bulk_upload)
end
- def error_report_path
+ def error_report_path(read_only: false)
if BulkUploadErrorSummaryTableComponent.new(bulk_upload:).errors?
- send("summary_bulk_upload_#{log_type}_result_path", bulk_upload)
+ send("summary_bulk_upload_#{log_type}_result_path", bulk_upload, hide_upload_button: read_only ? "true" : nil)
else
- send("bulk_upload_#{log_type}_result_path", bulk_upload)
+ send("bulk_upload_#{log_type}_result_path", bulk_upload, hide_upload_button: read_only ? "true" : nil)
end
end
diff --git a/app/models/forms/bulk_upload_resume/fix_choice.rb b/app/models/forms/bulk_upload_resume/fix_choice.rb
index c731dbf93..b14970643 100644
--- a/app/models/forms/bulk_upload_resume/fix_choice.rb
+++ b/app/models/forms/bulk_upload_resume/fix_choice.rb
@@ -34,11 +34,11 @@ module Forms
end
end
- def error_report_path
+ def error_report_path(read_only: false)
if BulkUploadErrorSummaryTableComponent.new(bulk_upload:).errors?
- send("summary_bulk_upload_#{log_type}_result_path", bulk_upload)
+ send("summary_bulk_upload_#{log_type}_result_path", bulk_upload, hide_upload_button: read_only ? "true" : nil)
else
- send("bulk_upload_#{log_type}_result_path", bulk_upload)
+ send("bulk_upload_#{log_type}_result_path", bulk_upload, hide_upload_button: read_only ? "true" : nil)
end
end
diff --git a/app/views/bulk_upload_lettings_results/show.html.erb b/app/views/bulk_upload_lettings_results/show.html.erb
index 5eedefe49..cf8c62eeb 100644
--- a/app/views/bulk_upload_lettings_results/show.html.erb
+++ b/app/views/bulk_upload_lettings_results/show.html.erb
@@ -33,4 +33,6 @@
-<%= govuk_button_link_to "Upload your file again", start_bulk_upload_lettings_logs_path(organisation_id: @bulk_upload.organisation_id) %>
+<% if params[:hide_upload_button] != "true" %>
+ <%= govuk_button_link_to "Upload your file again", start_bulk_upload_lettings_logs_path(organisation_id: @bulk_upload.organisation_id) %>
+<% end %>
diff --git a/app/views/bulk_upload_lettings_results/summary.html.erb b/app/views/bulk_upload_lettings_results/summary.html.erb
index ab60212e9..1a31eb0a9 100644
--- a/app/views/bulk_upload_lettings_results/summary.html.erb
+++ b/app/views/bulk_upload_lettings_results/summary.html.erb
@@ -1,3 +1,7 @@
+<% content_for :before_content do %>
+ <%= govuk_back_link(href: :back) %>
+<% end %>
+
<%= render partial: "bulk_upload_shared/moved_user_banner" %>
@@ -34,4 +38,6 @@
<% end %>
-<%= govuk_button_link_to "Upload your file again", start_bulk_upload_lettings_logs_path(organisation_id: @bulk_upload.organisation_id) %>
+<% if params[:hide_upload_button] != "true" %>
+ <%= govuk_button_link_to "Upload your file again", start_bulk_upload_lettings_logs_path(organisation_id: @bulk_upload.organisation_id) %>
+<% end %>
diff --git a/app/views/bulk_upload_lettings_resume/confirm.html.erb b/app/views/bulk_upload_lettings_resume/confirm.html.erb
index bb15c7101..c72cab57b 100644
--- a/app/views/bulk_upload_lettings_resume/confirm.html.erb
+++ b/app/views/bulk_upload_lettings_resume/confirm.html.erb
@@ -9,7 +9,7 @@
<%= logs_and_errors_warning(@bulk_upload) %>
- <%= govuk_link_to "View the error report", @form.error_report_path %>
+ <%= govuk_link_to "View the error report", @form.error_report_path(read_only: true) %>
<% if unique_answers_to_be_cleared(@bulk_upload).present? %>
diff --git a/app/views/bulk_upload_lettings_resume/fix_choice.html.erb b/app/views/bulk_upload_lettings_resume/fix_choice.html.erb
index 225fb07bf..3bb326d02 100644
--- a/app/views/bulk_upload_lettings_resume/fix_choice.html.erb
+++ b/app/views/bulk_upload_lettings_resume/fix_choice.html.erb
@@ -19,7 +19,7 @@
- <%= govuk_link_to "View the error report", @form.error_report_path %>
+ <%= govuk_link_to "View the error report", @form.error_report_path(read_only: true) %>
<%= govuk_details(summary_text: "How to choose between fixing errors on the CORE site or in the CSV") do %>
diff --git a/app/views/bulk_upload_sales_results/show.html.erb b/app/views/bulk_upload_sales_results/show.html.erb
index 2276285fe..68aaf7311 100644
--- a/app/views/bulk_upload_sales_results/show.html.erb
+++ b/app/views/bulk_upload_sales_results/show.html.erb
@@ -33,4 +33,6 @@
-<%= govuk_button_link_to "Upload your file again", start_bulk_upload_sales_logs_path(organisation_id: @bulk_upload.organisation_id) %>
+<% if params[:hide_upload_button] != "true" %>
+ <%= govuk_button_link_to "Upload your file again", start_bulk_upload_sales_logs_path(organisation_id: @bulk_upload.organisation_id) %>
+<% end %>
diff --git a/app/views/bulk_upload_sales_results/summary.html.erb b/app/views/bulk_upload_sales_results/summary.html.erb
index ed2ec14b3..fc9f39d82 100644
--- a/app/views/bulk_upload_sales_results/summary.html.erb
+++ b/app/views/bulk_upload_sales_results/summary.html.erb
@@ -1,3 +1,7 @@
+<% content_for :before_content do %>
+ <%= govuk_back_link(href: :back) %>
+<% end %>
+
<%= render partial: "bulk_upload_shared/moved_user_banner" %>
@@ -34,4 +38,6 @@
<% end %>
-<%= govuk_button_link_to "Upload your file again", start_bulk_upload_sales_logs_path(organisation_id: @bulk_upload.organisation_id) %>
+<% if params[:hide_upload_button] != "true" %>
+ <%= govuk_button_link_to "Upload your file again", start_bulk_upload_sales_logs_path(organisation_id: @bulk_upload.organisation_id) %>
+<% end %>
diff --git a/app/views/bulk_upload_sales_resume/confirm.html.erb b/app/views/bulk_upload_sales_resume/confirm.html.erb
index b47619053..1259d8bf9 100644
--- a/app/views/bulk_upload_sales_resume/confirm.html.erb
+++ b/app/views/bulk_upload_sales_resume/confirm.html.erb
@@ -9,7 +9,7 @@
<%= logs_and_errors_warning(@bulk_upload) %>
- <%= govuk_link_to "View the error report", @form.error_report_path %>
+ <%= govuk_link_to "View the error report", @form.error_report_path(read_only: true) %>
<% if unique_answers_to_be_cleared(@bulk_upload).present? %>
diff --git a/app/views/bulk_upload_sales_resume/fix_choice.html.erb b/app/views/bulk_upload_sales_resume/fix_choice.html.erb
index b376ee62d..8a2887678 100644
--- a/app/views/bulk_upload_sales_resume/fix_choice.html.erb
+++ b/app/views/bulk_upload_sales_resume/fix_choice.html.erb
@@ -19,7 +19,7 @@
- <%= govuk_link_to "View the error report", @form.error_report_path %>
+ <%= govuk_link_to "View the error report", @form.error_report_path(read_only: true) %>
<%= govuk_details(summary_text: "How to choose between fixing errors on the CORE site or in the CSV") do %>
diff --git a/spec/requests/bulk_upload_lettings_results_controller_spec.rb b/spec/requests/bulk_upload_lettings_results_controller_spec.rb
index 3416b6da9..e3ec4b4c1 100644
--- a/spec/requests/bulk_upload_lettings_results_controller_spec.rb
+++ b/spec/requests/bulk_upload_lettings_results_controller_spec.rb
@@ -82,6 +82,24 @@ RSpec.describe BulkUploadLettingsResultsController, type: :request do
expect(response.body).to include("You moved to a different organisation since this file was uploaded. Upload the file again to get an accurate error report.")
end
end
+
+ context "and user has upload button shown" do
+ it "displays a link to reupload file" do
+ get "/lettings-logs/bulk-upload-results/#{bulk_upload.id}/summary"
+
+ expect(response.body).to include("Upload your file again")
+ expect(response.body).to include("/lettings-logs/bulk-upload-logs/start")
+ end
+ end
+
+ context "and user has upload button hidden" do
+ it "does not display a link to reupload file" do
+ get "/lettings-logs/bulk-upload-results/#{bulk_upload.id}/summary?hide_upload_button=true"
+
+ expect(response.body).not_to include("Upload your file again")
+ expect(response.body).not_to include("/lettings-logs/bulk-upload-logs/start")
+ end
+ end
end
end
@@ -152,5 +170,23 @@ RSpec.describe BulkUploadLettingsResultsController, type: :request do
expect(response.body).to include("You moved to a different organisation since this file was uploaded. Upload the file again to get an accurate error report.")
end
end
+
+ context "and user has upload button shown" do
+ it "displays a link to reupload file" do
+ get "/lettings-logs/bulk-upload-results/#{bulk_upload.id}"
+
+ expect(response.body).to include("Upload your file again")
+ expect(response.body).to include("/lettings-logs/bulk-upload-logs/start")
+ end
+ end
+
+ context "and user has upload button hidden" do
+ it "does not display a link to reupload file" do
+ get "/lettings-logs/bulk-upload-results/#{bulk_upload.id}?hide_upload_button=true"
+
+ expect(response.body).not_to include("Upload your file again")
+ expect(response.body).not_to include("/lettings-logs/bulk-upload-logs/start")
+ end
+ end
end
end
diff --git a/spec/requests/bulk_upload_sales_results_controller_spec.rb b/spec/requests/bulk_upload_sales_results_controller_spec.rb
index 2236475fa..c6d31b0f4 100644
--- a/spec/requests/bulk_upload_sales_results_controller_spec.rb
+++ b/spec/requests/bulk_upload_sales_results_controller_spec.rb
@@ -44,6 +44,24 @@ RSpec.describe BulkUploadSalesResultsController, type: :request do
expect(response.body).to include("You moved to a different organisation since this file was uploaded. Upload the file again to get an accurate error report.")
end
end
+
+ context "and user has upload button shown" do
+ it "displays a link to reupload file" do
+ get "/sales-logs/bulk-upload-results/#{bulk_upload.id}/summary"
+
+ expect(response.body).to include("Upload your file again")
+ expect(response.body).to include("/sales-logs/bulk-upload-logs/start")
+ end
+ end
+
+ context "and user has upload button hidden" do
+ it "does not display a link to reupload file" do
+ get "/sales-logs/bulk-upload-results/#{bulk_upload.id}/summary?hide_upload_button=true"
+
+ expect(response.body).not_to include("Upload your file again")
+ expect(response.body).not_to include("/sales-logs/bulk-upload-logs/start")
+ end
+ end
end
end
@@ -127,5 +145,23 @@ RSpec.describe BulkUploadSalesResultsController, type: :request do
expect(response.body).to include("You moved to a different organisation since this file was uploaded. Upload the file again to get an accurate error report.")
end
end
+
+ context "and user has upload button shown" do
+ it "displays a link to reupload file" do
+ get "/sales-logs/bulk-upload-results/#{bulk_upload.id}"
+
+ expect(response.body).to include("Upload your file again")
+ expect(response.body).to include("/sales-logs/bulk-upload-logs/start")
+ end
+ end
+
+ context "and user has upload button hidden" do
+ it "does not display a link to reupload file" do
+ get "/sales-logs/bulk-upload-results/#{bulk_upload.id}?hide_upload_button=true"
+
+ expect(response.body).not_to include("Upload your file again")
+ expect(response.body).not_to include("/sales-logs/bulk-upload-logs/start")
+ end
+ end
end
end
From 614fd111e5b11469fb3f9087bf6b0249b261b7f5 Mon Sep 17 00:00:00 2001
From: Samuel Young
Date: Thu, 30 Apr 2026 17:04:20 +0100
Subject: [PATCH 31/34] CLDC-4300: Update sale date staircasing date validation
(#3341)
* CLDC-4300: Stricten validation on initialpurchase
* CLDC-4300: Add a correction script
* CLDC-4300: Update tests
* CLDC-4300: Ensure lasttransaction cannot equal saledate or initialtransaction
* CLDC-4300: Update date correcting rake to also account for lasttransaction = initialpurchase
* CLDC-4300: Revert updates to copy
* CLDC-4300: Apply these changes from 2026 only
* CLDC-4300: Compare lasttransaction to saledate
due to the it <= lt <= sd relationship, there's no need to comparse it to sd. if it == sd then it == lt and lt == sd
* CLDC-4300: Fix script in cases where all 3 dates are equal
---
.../sales/sale_information_validations.rb | 6 +-
...valid_initialpurchase_lasttransaction.rake | 15 ++++
.../sale_information_validations_spec.rb | 69 +++++++++++++++----
3 files changed, 75 insertions(+), 15 deletions(-)
create mode 100644 lib/tasks/fix_sales_logs_with_invalid_initialpurchase_lasttransaction.rake
diff --git a/app/models/validations/sales/sale_information_validations.rb b/app/models/validations/sales/sale_information_validations.rb
index 32bf2a716..7cd24183c 100644
--- a/app/models/validations/sales/sale_information_validations.rb
+++ b/app/models/validations/sales/sale_information_validations.rb
@@ -42,7 +42,7 @@ module Validations::Sales::SaleInformationValidations
record.errors.add :initialpurchase, I18n.t("validations.sales.sale_information.initialpurchase.must_be_after_1980")
end
- if record.saledate.present? && record.initialpurchase > record.saledate
+ if record.saledate.present? && ((record.initialpurchase > record.saledate) || (record.initialpurchase == record.saledate && record.form.start_year_2026_or_later?))
record.errors.add :initialpurchase, I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_saledate")
record.errors.add :saledate, :skip_bu_error, message: I18n.t("validations.sales.sale_information.saledate.must_be_after_initial_purchase_date")
end
@@ -55,11 +55,11 @@ module Validations::Sales::SaleInformationValidations
record.errors.add :lasttransaction, I18n.t("validations.sales.sale_information.lasttransaction.must_be_after_1980")
end
- if record.saledate.present? && record.lasttransaction > record.saledate
+ if record.saledate.present? && ((record.lasttransaction > record.saledate) || (record.lasttransaction == record.saledate && record.form.start_year_2026_or_later?))
record.errors.add :lasttransaction, I18n.t("validations.sales.sale_information.lasttransaction.must_be_before_saledate")
record.errors.add :saledate, :skip_bu_error, message: I18n.t("validations.sales.sale_information.saledate.must_be_after_last_transaction_date")
end
- if record.initialpurchase.present? && record.lasttransaction < record.initialpurchase
+ if record.initialpurchase.present? && ((record.lasttransaction < record.initialpurchase) || (record.lasttransaction == record.initialpurchase && record.form.start_year_2026_or_later?))
record.errors.add :initialpurchase, I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_last_transaction")
record.errors.add :lasttransaction, I18n.t("validations.sales.sale_information.lasttransaction.must_be_after_initial_purchase")
end
diff --git a/lib/tasks/fix_sales_logs_with_invalid_initialpurchase_lasttransaction.rake b/lib/tasks/fix_sales_logs_with_invalid_initialpurchase_lasttransaction.rake
new file mode 100644
index 000000000..11ff853a1
--- /dev/null
+++ b/lib/tasks/fix_sales_logs_with_invalid_initialpurchase_lasttransaction.rake
@@ -0,0 +1,15 @@
+desc "We tightened the validation between initial purchase date in 2026, last transaction date and sale date so the two can no longer be equal. To avoid invalid logs we clear initialpurchase if it equals saledate and if initialpurchase = lasttransaction we clear both"
+task fix_sales_logs_with_invalid_initialpurchase_lasttransaction: :environment do
+ initial_purchase_equal_lasttransaction_logs = SalesLog.filter_by_year_or_later(2026).where("initialpurchase = lasttransaction")
+ lasttransaction_equal_saledate_logs = SalesLog.filter_by_year_or_later(2026).where("lasttransaction = saledate")
+
+ # this one must happen first since this will always result in a log that passes date validations
+ puts "Updating #{initial_purchase_equal_lasttransaction_logs.count} logs where initialpurchase = lasttransaction, #{initial_purchase_equal_lasttransaction_logs.map(&:id)}"
+ initial_purchase_equal_lasttransaction_logs.update!(initialpurchase: nil, lasttransaction: nil)
+
+ # this one could fail if lasttransaction == saledate == initialpurchase, but the above case will have already reset these logs
+ puts "Updating #{lasttransaction_equal_saledate_logs.count} logs where lasttransaction = saledate, #{lasttransaction_equal_saledate_logs.map(&:id)}"
+ lasttransaction_equal_saledate_logs.update!(lasttransaction: nil)
+
+ puts "Done"
+end
diff --git a/spec/models/validations/sales/sale_information_validations_spec.rb b/spec/models/validations/sales/sale_information_validations_spec.rb
index 8d4eb4cea..04f71b198 100644
--- a/spec/models/validations/sales/sale_information_validations_spec.rb
+++ b/spec/models/validations/sales/sale_information_validations_spec.rb
@@ -252,12 +252,27 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end
context "when initial purchase date == saledate" do
- let(:record) { build(:sales_log, initialpurchase: current_collection_start_date, saledate: current_collection_start_date) }
+ let(:record) { build(:sales_log, initialpurchase: collection_start_date_for_year(start_year), saledate: collection_start_date_for_year(start_year)) }
- it "does not add an error" do
- sale_information_validator.validate_staircasing_initial_purchase_date(record)
+ context "and 2025", metadata: { year: 25 } do
+ let(:start_year) { 2025 }
- expect(record.errors[:initialpurchase]).not_to be_present
+ it "does not add an error" do
+ sale_information_validator.validate_staircasing_initial_purchase_date(record)
+
+ expect(record.errors[:lasttransaction]).not_to be_present
+ end
+ end
+
+ context "and 2026", metadata: { year: 26 } do
+ let(:start_year) { 2026 }
+
+ it "adds error" do
+ sale_information_validator.validate_staircasing_initial_purchase_date(record)
+
+ expect(record.errors[:initialpurchase]).to eq([I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_saledate")])
+ expect(record.errors[:saledate]).to eq([I18n.t("validations.sales.sale_information.saledate.must_be_after_initial_purchase_date")])
+ end
end
end
end
@@ -315,12 +330,27 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end
context "when last transaction date == saledate" do
- let(:record) { build(:sales_log, lasttransaction: current_collection_start_date, saledate: current_collection_start_date) }
+ let(:record) { build(:sales_log, lasttransaction: collection_start_date_for_year(start_year), saledate: collection_start_date_for_year(start_year)) }
- it "does not add an error" do
- sale_information_validator.validate_staircasing_last_transaction_date(record)
+ context "and 2025", metadata: { year: 25 } do
+ let(:start_year) { 2025 }
- expect(record.errors[:lasttransaction]).not_to be_present
+ it "does not add an error" do
+ sale_information_validator.validate_staircasing_last_transaction_date(record)
+
+ expect(record.errors[:lasttransaction]).not_to be_present
+ end
+ end
+
+ context "and 2026", metadata: { year: 26 } do
+ let(:start_year) { 2026 }
+
+ it "adds error" do
+ sale_information_validator.validate_staircasing_last_transaction_date(record)
+
+ expect(record.errors[:lasttransaction]).to eq([I18n.t("validations.sales.sale_information.lasttransaction.must_be_before_saledate")])
+ expect(record.errors[:saledate]).to eq([I18n.t("validations.sales.sale_information.saledate.must_be_after_last_transaction_date")])
+ end
end
end
@@ -346,12 +376,27 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end
context "when last transaction date == initial purchase date" do
- let(:record) { build(:sales_log, lasttransaction: current_collection_start_date, initialpurchase: current_collection_start_date) }
+ let(:record) { build(:sales_log, lasttransaction: collection_start_date_for_year(start_year), initialpurchase: collection_start_date_for_year(start_year), saledate: collection_start_date_for_year(start_year) + 1.day) }
- it "does not add an error" do
- sale_information_validator.validate_staircasing_last_transaction_date(record)
+ context "and 2025", metadata: { year: 25 } do
+ let(:start_year) { 2025 }
- expect(record.errors[:lasttransaction]).not_to be_present
+ it "does not add an error" do
+ sale_information_validator.validate_staircasing_last_transaction_date(record)
+
+ expect(record.errors[:lasttransaction]).not_to be_present
+ end
+ end
+
+ context "and 2026", metadata: { year: 26 } do
+ let(:start_year) { 2026 }
+
+ it "adds error" do
+ sale_information_validator.validate_staircasing_last_transaction_date(record)
+
+ expect(record.errors[:lasttransaction]).to eq([I18n.t("validations.sales.sale_information.lasttransaction.must_be_after_initial_purchase")])
+ expect(record.errors[:initialpurchase]).to eq([I18n.t("validations.sales.sale_information.initialpurchase.must_be_before_last_transaction")])
+ end
end
end
end
From e0c3938b6b7b1c94ec632d98f34ac633fd1a28b4 Mon Sep 17 00:00:00 2001
From: Nat Dean-Lewis <94526761+natdeanlewissoftwire@users.noreply.github.com>
Date: Wed, 3 Jun 2026 16:55:34 +0100
Subject: [PATCH 32/34] CLDC-4470: Update vulnerable packages (#3349)
* feat: update addressable
* feat: update rack-session
* feat: update other high criticality dependencies
* feat: update other high criticality dependencies
* feat: update other high criticality dependencies
* feat: align with goovuk-components 6.x
* feat: update navbar styling
* feat: use helpers where required and update misc tests
* feat: add title test for support users
* refactor: linting
* feat: update application helper spec
* feat: add missing helpers
* refactor: make specs more readable
* refactor: lint
---
Gemfile | 4 +-
Gemfile.lock | 106 +-
.../bulk_upload_error_row_component.html.erb | 4 +-
.../bulk_upload_error_row_component.rb | 9 +-
...oad_error_summary_table_component.html.erb | 4 +-
...lk_upload_error_summary_table_component.rb | 3 +-
.../bulk_upload_summary_component.rb | 16 +-
...swers_summary_list_card_component.html.erb | 6 +-
...eck_answers_summary_list_card_component.rb | 11 +-
.../create_log_actions_component.html.erb | 18 +-
.../create_log_actions_component.rb | 19 +-
...ion_confirmation_banner_component.html.erb | 2 +-
...rotection_confirmation_banner_component.rb | 5 +-
.../document_list_component.html.erb | 2 +-
app/components/document_list_component.rb | 2 +-
.../lettings_log_summary_component.html.erb | 2 +-
.../lettings_log_summary_component.rb | 2 +-
...ing_stock_owners_banner_component.html.erb | 2 +-
.../missing_stock_owners_banner_component.rb | 9 +-
.../primary_navigation_component.html.erb | 2 +-
.../primary_navigation_component.rb | 2 +-
.../sales_log_summary_component.html.erb | 2 +-
app/components/sales_log_summary_component.rb | 2 +-
app/components/search_component.html.erb | 4 +-
app/components/search_component.rb | 2 +-
.../search_result_caption_component.rb | 2 +-
.../sub_navigation_component.html.erb | 4 +-
app/components/sub_navigation_component.rb | 2 +-
app/frontend/styles/_filter.scss | 2 +-
app/frontend/styles/_header.scss | 11 -
app/frontend/styles/_related-navigation.scss | 2 +-
app/frontend/styles/_tag.scss | 2 +-
app/frontend/styles/_testing-tools.scss | 2 +-
app/frontend/styles/application.scss | 12 +
app/helpers/application_helper.rb | 13 +-
app/views/layouts/application.html.erb | 30 +-
.../layouts/rails_admin/_navigation.html.erb | 18 +-
app/views/users/_user_list.html.erb | 4 +-
package.json | 4 +-
spec/helpers/application_helper_spec.rb | 46 +-
spec/requests/users_controller_spec.rb | 54 +-
webpack.config.js | 4 +-
yarn.lock | 1377 +++++++++--------
43 files changed, 985 insertions(+), 844 deletions(-)
diff --git a/Gemfile b/Gemfile
index c76a48bec..d68325a7f 100644
--- a/Gemfile
+++ b/Gemfile
@@ -18,7 +18,7 @@ gem "jsbundling-rails"
# Reduces boot times through caching; required in config/boot.rb
gem "bootsnap", ">= 1.4.4", require: false
# GOV UK frontend components
-gem "govuk-components", "~> 5.7"
+gem "govuk-components", "~> 6.2"
# GOV UK component form builder DSL
gem "govuk_design_system_formbuilder", "~> 5.7"
# Convert Markdown into GOV.UK frontend-styled HTML
@@ -40,7 +40,7 @@ gem "devise_two_factor_authentication"
gem "uk_postcode"
# Get rich data from postcode lookups. Wraps postcodes.io
# Use Ruby objects to build reusable markup. A React inspired evolution of the presenter pattern
-gem "view_component", "~> 3.9"
+gem "view_component", "~> 4.9"
# Use the AWS S3 SDK as storage mechanism
gem "aws-sdk-s3"
# Track changes to models for auditing or versioning.
diff --git a/Gemfile.lock b/Gemfile.lock
index c83c95414..903824128 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -78,8 +78,8 @@ GEM
minitest (>= 5.1, < 6)
securerandom (>= 0.3)
tzinfo (~> 2.0, >= 2.0.5)
- addressable (2.8.6)
- public_suffix (>= 2.0.2, < 6.0)
+ addressable (2.9.0)
+ public_suffix (>= 2.0.2, < 8.0)
ast (2.4.3)
auto_strip_attributes (2.6.0)
activerecord (>= 4.0)
@@ -123,7 +123,7 @@ GEM
erubi (~> 1.4)
parser (>= 2.4)
smart_properties
- bigdecimal (4.0.1)
+ bigdecimal (4.1.2)
bindex (0.8.1)
bootsnap (1.18.3)
msgpack (~> 1.2)
@@ -155,18 +155,21 @@ GEM
coercible (1.0.0)
descendants_tracker (~> 0.0.1)
concurrent-ruby (1.3.6)
- connection_pool (2.5.3)
+ connection_pool (2.5.5)
crack (1.0.0)
bigdecimal
rexml
crass (1.0.6)
+ cronex (0.15.0)
+ tzinfo
+ unicode (>= 0.4.4.5)
cssbundling-rails (1.4.0)
railties (>= 6.0.0)
csv (3.3.2)
date (3.5.1)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
- devise (5.0.3)
+ devise (5.0.4)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 7.0)
@@ -187,7 +190,7 @@ GEM
drb (2.2.3)
dumb_delegator (1.0.0)
encryptor (3.0.0)
- erb (6.0.2)
+ erb (6.0.4)
erb_lint (0.9.0)
activesupport
better_html (>= 2.0.1)
@@ -196,7 +199,7 @@ GEM
rubocop (>= 1)
smart_properties
erubi (1.13.1)
- et-orbi (1.2.11)
+ et-orbi (1.4.0)
tzinfo
event_stream_parser (1.0.0)
excon (0.111.0)
@@ -207,24 +210,24 @@ GEM
railties (>= 5.0.0)
faker (3.2.3)
i18n (>= 1.8.11, < 2)
- faraday (2.14.1)
+ faraday (2.14.2)
faraday-net_http (>= 2.0, < 3.5)
json
logger
faraday-multipart (1.0.4)
multipart-post (~> 2)
- faraday-net_http (3.1.0)
- net-http
+ faraday-net_http (3.4.3)
+ net-http (~> 0.5)
ffi (1.16.3)
- fugit (1.11.1)
- et-orbi (~> 1, >= 1.2.11)
+ fugit (1.12.2)
+ et-orbi (~> 1.4)
raabro (~> 1.4)
- globalid (1.2.1)
+ globalid (1.3.0)
activesupport (>= 6.1)
- govuk-components (5.7.0)
+ govuk-components (6.2.0)
html-attributes-utils (~> 1.0.0, >= 1.0.0)
pagy (>= 6, < 10)
- view_component (>= 3.9, < 3.17)
+ view_component (>= 4.9, < 4.10)
govuk_design_system_formbuilder (5.7.1)
actionview (>= 6.1)
activemodel (>= 6.1)
@@ -241,7 +244,7 @@ GEM
ice_nine (0.11.2)
iniparse (1.5.0)
io-console (0.8.2)
- irb (1.17.0)
+ irb (1.18.0)
pp (>= 0.6.0)
prism (>= 1.3.0)
rdoc (>= 4.0.0)
@@ -249,10 +252,10 @@ GEM
jmespath (1.6.2)
jsbundling-rails (1.3.0)
railties (>= 6.0.0)
- json (2.19.2)
+ json (2.19.7)
json-schema (4.1.1)
addressable (>= 2.8)
- jwt (2.8.0)
+ jwt (3.2.0)
base64
kaminari (1.2.2)
activesupport (>= 4.1.0)
@@ -290,9 +293,9 @@ GEM
msgpack (1.7.2)
multipart-post (2.4.1)
nested_form (0.3.2)
- net-http (0.4.1)
- uri
- net-imap (0.5.7)
+ net-http (0.9.1)
+ uri (>= 0.11.1)
+ net-imap (0.6.4)
date
net-protocol
net-pop (0.1.2)
@@ -302,22 +305,22 @@ GEM
net-smtp (0.5.1)
net-protocol
nio4r (2.7.4)
- nokogiri (1.19.1-arm64-darwin)
+ nokogiri (1.19.3-arm64-darwin)
racc (~> 1.4)
- nokogiri (1.19.1-x86_64-darwin)
+ nokogiri (1.19.3-x86_64-darwin)
racc (~> 1.4)
- nokogiri (1.19.1-x86_64-linux-gnu)
+ nokogiri (1.19.3-x86_64-linux-gnu)
racc (~> 1.4)
- nokogiri (1.19.1-x86_64-linux-musl)
+ nokogiri (1.19.3-x86_64-linux-musl)
racc (~> 1.4)
- notifications-ruby-client (6.0.0)
- jwt (>= 1.5, < 3)
+ notifications-ruby-client (6.4.0)
+ jwt (>= 1.5, < 4)
orm_adapter (0.5.0)
overcommit (0.63.0)
childprocess (>= 0.6.3, < 6)
iniparse (~> 1.4)
rexml (~> 3.2)
- pagy (9.3.2)
+ pagy (9.4.0)
paper_trail (15.2.0)
activerecord (>= 6.1)
request_store (~> 1.4)
@@ -350,19 +353,19 @@ GEM
psych (5.3.1)
date
stringio
- public_suffix (5.0.4)
+ public_suffix (7.0.5)
puma (6.5.0)
nio4r (~> 2.0)
pundit (2.3.1)
activesupport (>= 3.0.0)
raabro (1.4.0)
racc (1.8.1)
- rack (3.1.20)
+ rack (3.1.21)
rack-attack (6.7.0)
rack (>= 1.0, < 4)
rack-mini-profiler (3.3.1)
rack (>= 1.2.0)
- rack-session (2.1.1)
+ rack-session (2.1.2)
base64 (>= 0.1.0)
rack (>= 3.0.0)
rack-test (2.2.0)
@@ -408,7 +411,7 @@ GEM
tsort (>= 0.2)
zeitwerk (~> 2.6)
rainbow (3.1.1)
- rake (13.3.1)
+ rake (13.4.2)
randexp (0.1.7)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
@@ -419,7 +422,7 @@ GEM
tsort
redcarpet (3.6.0)
redis (4.8.1)
- redis-client (0.22.1)
+ redis-client (0.29.0)
connection_pool
regexp_parser (2.11.3)
reline (0.6.3)
@@ -508,15 +511,17 @@ GEM
sentry-ruby (~> 5.16.1)
sentry-ruby (5.16.1)
concurrent-ruby (~> 1.0, >= 1.0.2)
- sidekiq (7.2.4)
- concurrent-ruby (< 2)
- connection_pool (>= 2.3.0)
- rack (>= 2.2.4)
- redis-client (>= 0.19.0)
- sidekiq-cron (1.12.0)
- fugit (~> 1.8)
+ sidekiq (8.0.10)
+ connection_pool (>= 2.5.0)
+ json (>= 2.9.0)
+ logger (>= 1.6.2)
+ rack (>= 3.1.0)
+ redis-client (>= 0.23.2)
+ sidekiq-cron (2.4.0)
+ cronex (>= 0.13.0)
+ fugit (~> 1.8, >= 1.11.1)
globalid (>= 1.0.1)
- sidekiq (>= 6)
+ sidekiq (>= 6.5.0)
simplecov (0.22.0)
docile (~> 1.1)
simplecov-html (~> 0.11)
@@ -530,7 +535,7 @@ GEM
thor (1.4.0)
thread_safe (0.3.6)
timecop (0.9.8)
- timeout (0.4.3)
+ timeout (0.6.1)
tsort (0.2.0)
turbo-rails (2.0.13)
actionpack (>= 7.1.0)
@@ -538,17 +543,18 @@ GEM
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
uk_postcode (2.1.8)
+ unicode (0.4.4.5)
unicode-display_width (3.2.0)
unicode-emoji (~> 4.1)
unicode-emoji (4.2.0)
unread (0.14.0)
activerecord (>= 6.1)
- uri (1.0.4)
+ uri (1.1.1)
useragent (0.16.11)
- view_component (3.10.0)
- activesupport (>= 5.2.0, < 8.0)
- concurrent-ruby (~> 1.0)
- method_source (~> 1.0)
+ view_component (4.9.0)
+ actionview (>= 7.1.0)
+ activesupport (>= 7.1.0)
+ concurrent-ruby (~> 1)
virtus (2.0.0)
axiom-types (~> 0.1)
coercible (~> 1.0)
@@ -571,7 +577,7 @@ GEM
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
- zeitwerk (2.7.5)
+ zeitwerk (2.8.2)
PLATFORMS
arm64-darwin
@@ -599,7 +605,7 @@ DEPENDENCIES
factory_bot_rails
faker
faraday (>= 2.14.1)
- govuk-components (~> 5.7)
+ govuk-components (~> 6.2)
govuk_design_system_formbuilder (~> 5.7)
govuk_markdown
jsbundling-rails
@@ -643,7 +649,7 @@ DEPENDENCIES
tzinfo-data
uk_postcode
unread
- view_component (~> 3.9)
+ view_component (~> 4.9)
web-console (>= 4.1.0)
webmock
diff --git a/app/components/bulk_upload_error_row_component.html.erb b/app/components/bulk_upload_error_row_component.html.erb
index 8cfdb674e..4ce6e4f5c 100644
--- a/app/components/bulk_upload_error_row_component.html.erb
+++ b/app/components/bulk_upload_error_row_component.html.erb
@@ -13,7 +13,7 @@
<% if critical_errors.any? %>
Critical errors
These errors must be fixed to complete your logs.
- <%= govuk_table(html_attributes: { class: potential_errors.any? ? "" : "no-bottom-border" }) do |table| %>
+ <%= helpers.govuk_table(html_attributes: { class: potential_errors.any? ? "" : "no-bottom-border" }) do |table| %>
<%= table.with_head do |head| %>
<% head.with_row do |row| %>
<% row.with_cell(header: true, text: "Cell") %>
@@ -39,7 +39,7 @@
<% if potential_errors.any? %>
Confirmation needed
Potential data discrepancies exist in the following cells.
Please resolve all critical errors and review the cells with data discrepancies before re-uploading the file. Bulk confirmation of potential discrepancies is accessible only after all critical errors have been resolved.
- <%= govuk_table(html_attributes: { class: "no-bottom-border" }) do |table| %>
+ <%= helpers.govuk_table(html_attributes: { class: "no-bottom-border" }) do |table| %>
<%= table.with_head do |head| %>
<% head.with_row do |row| %>
<% row.with_cell(header: true, text: "Cell") %>
diff --git a/app/components/bulk_upload_error_row_component.rb b/app/components/bulk_upload_error_row_component.rb
index 1cb4de9d8..569f71b85 100644
--- a/app/components/bulk_upload_error_row_component.rb
+++ b/app/components/bulk_upload_error_row_component.rb
@@ -2,9 +2,8 @@ class BulkUploadErrorRowComponent < ViewComponent::Base
attr_reader :bulk_upload_errors
def initialize(bulk_upload_errors:)
+ super()
@bulk_upload_errors = bulk_upload_errors
-
- super
end
def row
@@ -18,7 +17,7 @@ class BulkUploadErrorRowComponent < ViewComponent::Base
def tenant_code_html
return if tenant_code.blank?
- content_tag :span, class: "govuk-!-margin-left-3" do
+ helpers.content_tag :span, class: "govuk-!-margin-left-3" do
"Tenant code: #{tenant_code}"
end
end
@@ -30,7 +29,7 @@ class BulkUploadErrorRowComponent < ViewComponent::Base
def purchaser_code_html
return if purchaser_code.blank?
- content_tag :span, class: "govuk-!-margin-left-3" do
+ helpers.content_tag :span, class: "govuk-!-margin-left-3" do
"Purchaser code: #{purchaser_code}"
end
end
@@ -42,7 +41,7 @@ class BulkUploadErrorRowComponent < ViewComponent::Base
def property_ref_html
return if property_ref.blank?
- content_tag :span, class: "govuk-!-margin-left-3" do
+ helpers.content_tag :span, class: "govuk-!-margin-left-3" do
"Property reference: #{property_ref}"
end
end
diff --git a/app/components/bulk_upload_error_summary_table_component.html.erb b/app/components/bulk_upload_error_summary_table_component.html.erb
index f9b42f34d..58489612a 100644
--- a/app/components/bulk_upload_error_summary_table_component.html.erb
+++ b/app/components/bulk_upload_error_summary_table_component.html.erb
@@ -3,7 +3,7 @@
<% sorted_errors.each do |error| %>
- <%= govuk_table do |table| %>
+ <%= helpers.govuk_table do |table| %>
<%= table.with_head do |head| %>
<% head.with_row do |row| %>
<% row.with_cell(text: question_for_field(error[0][1].to_sym), header: true) %>
@@ -13,7 +13,7 @@
<%= table.with_body do |body| %>
<% body.with_row do |row| %>
<% row.with_cell(text: error[0][2].html_safe) %>
- <% row.with_cell(text: pluralize(error[1], "error"), numeric: true) %>
+ <% row.with_cell(text: helpers.pluralize(error[1], "error"), numeric: true) %>
<% end %>
<% end %>
<% end %>
diff --git a/app/components/bulk_upload_error_summary_table_component.rb b/app/components/bulk_upload_error_summary_table_component.rb
index d15d5280e..db69fd9ec 100644
--- a/app/components/bulk_upload_error_summary_table_component.rb
+++ b/app/components/bulk_upload_error_summary_table_component.rb
@@ -6,9 +6,8 @@ class BulkUploadErrorSummaryTableComponent < ViewComponent::Base
delegate :question_for_field, to: :row_parser_class
def initialize(bulk_upload:)
+ super()
@bulk_upload = bulk_upload
-
- super
end
def sorted_errors
diff --git a/app/components/bulk_upload_summary_component.rb b/app/components/bulk_upload_summary_component.rb
index fa4cad414..2df854536 100644
--- a/app/components/bulk_upload_summary_component.rb
+++ b/app/components/bulk_upload_summary_component.rb
@@ -2,9 +2,9 @@ class BulkUploadSummaryComponent < ViewComponent::Base
attr_reader :bulk_upload
def initialize(bulk_upload:)
+ super()
@bulk_upload = bulk_upload
@bulk_upload_errors = bulk_upload.bulk_upload_errors
- super
end
def upload_status
@@ -27,9 +27,9 @@ class BulkUploadSummaryComponent < ViewComponent::Base
return if count.nil? || count <= 0
text = count > 1 ? (plural_text || singular_text.pluralize(count)) : singular_text
- content_tag(:p, class: "govuk-!-font-size-16 govuk-!-margin-bottom-1") do
- concat(content_tag(:strong, count))
- concat(" #{text}")
+ helpers.content_tag(:p, class: "govuk-!-font-size-16 govuk-!-margin-bottom-1") do
+ helpers.concat(helpers.content_tag(:strong, count))
+ helpers.concat(" #{text}")
end
end
@@ -44,11 +44,11 @@ class BulkUploadSummaryComponent < ViewComponent::Base
end
def download_lettings_file_link(bulk_upload)
- govuk_link_to "Download file", download_lettings_bulk_upload_path(bulk_upload), class: "govuk-link govuk-!-margin-right-2"
+ helpers.govuk_link_to "Download file", download_lettings_bulk_upload_path(bulk_upload), class: "govuk-link govuk-!-margin-right-2"
end
def download_sales_file_link(bulk_upload)
- govuk_link_to "Download file", download_sales_bulk_upload_path(bulk_upload), class: "govuk-link govuk-!-margin-right-2"
+ helpers.govuk_link_to "Download file", download_sales_bulk_upload_path(bulk_upload), class: "govuk-link govuk-!-margin-right-2"
end
def view_error_report_link(bulk_upload)
@@ -61,12 +61,12 @@ class BulkUploadSummaryComponent < ViewComponent::Base
"bulk_upload_#{bulk_upload.log_type}_result_path"
end
- govuk_link_to "View error report", send(path, bulk_upload), class: "govuk-link"
+ helpers.govuk_link_to "View error report", helpers.send(path, bulk_upload), class: "govuk-link"
end
def view_logs_link(bulk_upload)
return unless bulk_upload.status.to_s == "logs_uploaded_with_errors"
- govuk_link_to "View logs with errors", send("#{bulk_upload.log_type}_logs_path", bulk_upload_id: [bulk_upload.id]), class: "govuk-link"
+ helpers.govuk_link_to "View logs with errors", helpers.send("#{bulk_upload.log_type}_logs_path", bulk_upload_id: [bulk_upload.id]), class: "govuk-link"
end
end
diff --git a/app/components/check_answers_summary_list_card_component.html.erb b/app/components/check_answers_summary_list_card_component.html.erb
index 8b0c7d9b0..c9c974938 100644
--- a/app/components/check_answers_summary_list_card_component.html.erb
+++ b/app/components/check_answers_summary_list_card_component.html.erb
@@ -7,12 +7,12 @@
<% end %>
- <%= govuk_summary_list do |summary_list| %>
+ <%= helpers.govuk_summary_list do |summary_list| %>
<% applicable_questions.each do |question| %>
<% summary_list.with_row do |row| %>
<% row.with_key { get_question_label(question) } %>
<% row.with_value do %>
- <%= simple_format(
+ <%= helpers.simple_format(
get_answer_label(question),
wrapper_tag: "span",
class: "govuk-!-margin-right-4",
@@ -21,7 +21,7 @@
<% extra_value = question.get_extra_check_answer_value(log) %>
<% if extra_value && question.answer_label(log).present? %>
- <%= simple_format(
+ <%= helpers.simple_format(
extra_value,
wrapper_tag: "span",
class: "govuk-!-font-weight-regular app-!-colour-muted",
diff --git a/app/components/check_answers_summary_list_card_component.rb b/app/components/check_answers_summary_list_card_component.rb
index 1dc345f01..89345a0eb 100644
--- a/app/components/check_answers_summary_list_card_component.rb
+++ b/app/components/check_answers_summary_list_card_component.rb
@@ -2,12 +2,11 @@ class CheckAnswersSummaryListCardComponent < ViewComponent::Base
attr_reader :questions, :log, :user
def initialize(questions:, log:, user:, correcting_hard_validation: false)
+ super()
@questions = questions
@log = log
@user = user
@correcting_hard_validation = correcting_hard_validation
-
- super
end
def applicable_questions
@@ -34,16 +33,16 @@ class CheckAnswersSummaryListCardComponent < ViewComponent::Base
def action_href(question, log)
referrer = question.displayed_as_answered?(log) ? "check_answers" : "check_answers_new_answer"
- send("#{log.log_type}_#{question.page.id}_path", log, referrer:)
+ helpers.send("#{log.log_type}_#{question.page.id}_path", log, referrer:)
end
def correct_validation_action_href(question, log, _related_question_ids, correcting_hard_validation)
return action_href(question, log) unless correcting_hard_validation
if question.displayed_as_answered?(log)
- send("#{log.log_type}_confirm_clear_answer_path", log, question_id: question.id)
+ helpers.send("#{log.log_type}_confirm_clear_answer_path", log, question_id: question.id)
else
- send("#{log.log_type}_#{question.page.id}_path", log, referrer: "check_errors", related_question_ids: request.query_parameters["related_question_ids"], original_page_id: request.query_parameters["original_page_id"])
+ helpers.send("#{log.log_type}_#{question.page.id}_path", log, referrer: "check_errors", related_question_ids: request.query_parameters["related_question_ids"], original_page_id: request.query_parameters["original_page_id"])
end
end
@@ -56,7 +55,7 @@ private
"govuk-link govuk-link--no-visited-state"
end
- govuk_link_to question.check_answer_prompt, correct_validation_action_href(question, log, nil, @correcting_hard_validation), class: link_class
+ helpers.govuk_link_to question.check_answer_prompt, correct_validation_action_href(question, log, nil, @correcting_hard_validation), class: link_class
end
def number_of_buyers
diff --git a/app/components/create_log_actions_component.html.erb b/app/components/create_log_actions_component.html.erb
index 130072ec0..c8f557bce 100644
--- a/app/components/create_log_actions_component.html.erb
+++ b/app/components/create_log_actions_component.html.erb
@@ -1,11 +1,11 @@