diff --git a/app/helpers/bulk_upload/sales_log_to_csv.rb b/app/helpers/bulk_upload/sales_log_to_csv.rb
index 4e02623ee..19e34eea0 100644
--- a/app/helpers/bulk_upload/sales_log_to_csv.rb
+++ b/app/helpers/bulk_upload/sales_log_to_csv.rb
@@ -678,7 +678,9 @@ class BulkUpload::SalesLogToCsv
log.gender_same_as_sex5,
log.gender_description5,
log.gender_same_as_sex6,
- log.gender_description6, # 134
+ log.gender_description6,
+ log.hasservicechargeschanged,
+ log.newservicecharges, # 136
]
end
diff --git a/app/models/derived_variables/sales_log_variables.rb b/app/models/derived_variables/sales_log_variables.rb
index 268ee7e6a..b93acedb6 100644
--- a/app/models/derived_variables/sales_log_variables.rb
+++ b/app/models/derived_variables/sales_log_variables.rb
@@ -158,8 +158,12 @@ private
def number_of_household_members
return unless hholdcount.present? && jointpur.present?
- number_of_buyers = joint_purchase? ? 2 : 1
- hholdcount + number_of_buyers
+ if form.start_year_2026_or_later?
+ hholdcount
+ else
+ number_of_buyers = joint_purchase? ? 2 : 1
+ hholdcount + number_of_buyers
+ end
end
def total_elder
diff --git a/app/models/form/lettings/questions/layear.rb b/app/models/form/lettings/questions/layear.rb
index d8fa0a3a8..2ae03212d 100644
--- a/app/models/form/lettings/questions/layear.rb
+++ b/app/models/form/lettings/questions/layear.rb
@@ -8,7 +8,20 @@ class Form::Lettings::Questions::Layear < ::Form::Question
end
def answer_options
- if form.start_year_2024_or_later?
+ if form.start_year_2025_or_later?
+ {
+ "1" => { "value" => "Just moved to local authority area with this new let" },
+ "2" => { "value" => "Under 1 year" },
+ "7" => { "value" => "1 year but under 2 years" },
+ "8" => { "value" => "2 years but under 3 years" },
+ "9" => { "value" => "3 years but under 4 years" },
+ "10" => { "value" => "4 years but under 5 years" },
+ "11" => { "value" => "5 years but under 10 years" },
+ "12" => { "value" => "10 years or more" },
+ "divider" => { "value" => true },
+ "6" => { "value" => "Don’t know" },
+ }
+ elsif form.start_year_2024_or_later?
{
"1" => { "value" => "Just moved to local authority area with this new let" },
"2" => { "value" => "Less than 1 year" },
diff --git a/app/models/form/lettings/questions/waityear.rb b/app/models/form/lettings/questions/waityear.rb
index 7e0f2b77e..8745bf227 100644
--- a/app/models/form/lettings/questions/waityear.rb
+++ b/app/models/form/lettings/questions/waityear.rb
@@ -11,7 +11,7 @@ class Form::Lettings::Questions::Waityear < ::Form::Question
if form.start_year_2025_or_later?
return {
"13" => { "value" => "Household not on the housing register (or waiting list) in this area" },
- "2" => { "value" => "Less than 1 year" },
+ "2" => { "value" => "Under 1 year" },
"7" => { "value" => "1 year but under 2 years" },
"8" => { "value" => "2 years but under 3 years" },
"9" => { "value" => "3 years but under 4 years" },
diff --git a/app/models/form/question.rb b/app/models/form/question.rb
index b3e7a36f7..93a750039 100644
--- a/app/models/form/question.rb
+++ b/app/models/form/question.rb
@@ -373,8 +373,32 @@ private
# every year currently visible should have an explicit question number specified.
# however, form_handler.rb will still initialise the next form even if its not visible.
# so we have a fallback to the latest year for these future years so all question have a question number.
- def get_question_number_from_hash(hash)
- hash[form.start_date.year] || hash[hash.keys.max]
+ #
+ # some hashes are complex and require a second key to find the correct year.
+ # 2025 and before the question number used to depend on the ownershipsch and other log attributes
+ # 2026 and beyond we use the subsection ID for consistency
+ def get_question_number_from_hash(hash, value_key: nil)
+ year = if hash[form.start_date.year].present?
+ form.start_date.year
+ else
+ hash.keys.max
+ end
+
+ hash_value = hash[year]
+
+ return hash_value if hash_value.is_a?(Integer)
+
+ hash_value[value_key]
+ end
+
+ def get_person_question_number(base_hash, override_hash: nil)
+ buyer_override_question_number = override_hash&.dig(form.start_date.year, @person_index)
+
+ return buyer_override_question_number if buyer_override_question_number.present? && @buyer
+
+ base_question_number = base_hash[form.start_date.year] || base_hash[base_hash.keys.max]
+
+ base_question_number + (form.person_question_count * @person_index)
end
RADIO_YES_VALUE = {
diff --git a/app/models/form/sales/pages/buyer1_gender_same_as_sex.rb b/app/models/form/sales/pages/buyer1_gender_same_as_sex.rb
index cc73a8c95..8715ce556 100644
--- a/app/models/form/sales/pages/buyer1_gender_same_as_sex.rb
+++ b/app/models/form/sales/pages/buyer1_gender_same_as_sex.rb
@@ -15,7 +15,7 @@ class Form::Sales::Pages::Buyer1GenderSameAsSex < ::Form::Page
def questions
@questions ||= [
Form::Sales::Questions::GenderSameAsSex.new(nil, nil, self, person_index: 1, buyer: true),
- Form::Sales::Questions::GenderDescription.new(nil, nil, self, person_index: 1),
+ Form::Sales::Questions::GenderDescription.new(nil, nil, self, person_index: 1, buyer: true),
]
end
end
diff --git a/app/models/form/sales/pages/buyer2_gender_same_as_sex.rb b/app/models/form/sales/pages/buyer2_gender_same_as_sex.rb
index d8466ed1a..19354afd7 100644
--- a/app/models/form/sales/pages/buyer2_gender_same_as_sex.rb
+++ b/app/models/form/sales/pages/buyer2_gender_same_as_sex.rb
@@ -17,7 +17,7 @@ class Form::Sales::Pages::Buyer2GenderSameAsSex < ::Form::Page
def questions
@questions ||= [
Form::Sales::Questions::GenderSameAsSex.new(nil, nil, self, person_index: 2, buyer: true),
- Form::Sales::Questions::GenderDescription.new(nil, nil, self, person_index: 2),
+ Form::Sales::Questions::GenderDescription.new(nil, nil, self, person_index: 2, buyer: true),
]
end
end
diff --git a/app/models/form/sales/pages/person_known.rb b/app/models/form/sales/pages/person_known.rb
index c0affce76..2ab0ff3f5 100644
--- a/app/models/form/sales/pages/person_known.rb
+++ b/app/models/form/sales/pages/person_known.rb
@@ -16,18 +16,18 @@ class Form::Sales::Pages::PersonKnown < Form::Sales::Pages::Person
[{ "not_joint_purchase?" => true,
"hholdcount" => {
"operator" => ">=",
- "operand" => 1,
+ "operand" => form.start_year_2026_or_later? ? 2 : 1,
} }]
else
[{ "not_joint_purchase?" => true,
"hholdcount" => {
"operator" => ">=",
- "operand" => @person_index - 1,
+ "operand" => form.start_year_2026_or_later? ? @person_index : @person_index - 1,
} },
{ "joint_purchase?" => true,
"hholdcount" => {
"operator" => ">=",
- "operand" => @person_index - 2,
+ "operand" => form.start_year_2026_or_later? ? @person_index : @person_index - 2,
} }]
end
end
diff --git a/app/models/form/sales/pages/service_charge_changed.rb b/app/models/form/sales/pages/service_charge_changed.rb
new file mode 100644
index 000000000..000e34c03
--- /dev/null
+++ b/app/models/form/sales/pages/service_charge_changed.rb
@@ -0,0 +1,14 @@
+class Form::Sales::Pages::ServiceChargeChanged < ::Form::Page
+ def initialize(id, hsh, subsection)
+ super
+ @id = "service_charge_changed"
+ @copy_key = "sales.sale_information.servicecharges_changed"
+ end
+
+ def questions
+ @questions ||= [
+ Form::Sales::Questions::HasServiceChargesChanged.new(nil, nil, self),
+ Form::Sales::Questions::NewServiceCharges.new(nil, nil, self),
+ ]
+ end
+end
diff --git a/app/models/form/sales/questions/address_line1.rb b/app/models/form/sales/questions/address_line1.rb
index 2836fcc00..5d47bce23 100644
--- a/app/models/form/sales/questions/address_line1.rb
+++ b/app/models/form/sales/questions/address_line1.rb
@@ -7,7 +7,7 @@ class Form::Sales::Questions::AddressLine1 < ::Form::Question
@type = "text"
@plain_label = true
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@hide_question_number_on_page = true
end
@@ -18,5 +18,5 @@ class Form::Sales::Questions::AddressLine1 < ::Form::Question
].select(&:present?).join("\n")
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 15, 2024 => 16, 2025 => 14 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 15, 2024 => 16, 2025 => 14, 2026 => 14 }.freeze
end
diff --git a/app/models/form/sales/questions/address_search.rb b/app/models/form/sales/questions/address_search.rb
index c219f13f1..a429e4071 100644
--- a/app/models/form/sales/questions/address_search.rb
+++ b/app/models/form/sales/questions/address_search.rb
@@ -6,7 +6,7 @@ class Form::Sales::Questions::AddressSearch < ::Form::Question
@copy_key = "sales.property_information.address_search"
@plain_label = true
@bottom_guidance_partial = "address_search"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@hide_question_number_on_page = true
end
@@ -38,5 +38,5 @@ class Form::Sales::Questions::AddressSearch < ::Form::Question
answer_options(log, user).transform_values { |value| value["value"] } || {}
end
- QUESTION_NUMBER_FROM_YEAR = { 2024 => 15, 2025 => 13 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2024 => 15, 2025 => 13, 2026 => 13 }.freeze
end
diff --git a/app/models/form/sales/questions/age1.rb b/app/models/form/sales/questions/age1.rb
index 3d03334a8..01872c04a 100644
--- a/app/models/form/sales/questions/age1.rb
+++ b/app/models/form/sales/questions/age1.rb
@@ -19,8 +19,8 @@ class Form::Sales::Questions::Age1 < ::Form::Question
@min = 16
@max = 110
@step = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 20, 2024 => 22, 2025 => 20 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 20, 2024 => 22, 2025 => 20, 2026 => 21 }.freeze
end
diff --git a/app/models/form/sales/questions/age2.rb b/app/models/form/sales/questions/age2.rb
index ffc861398..ecdaada48 100644
--- a/app/models/form/sales/questions/age2.rb
+++ b/app/models/form/sales/questions/age2.rb
@@ -13,8 +13,8 @@ class Form::Sales::Questions::Age2 < ::Form::Question
@max = 110
@min = 16
@step = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 28, 2024 => 30, 2025 => 28 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 28, 2024 => 30, 2025 => 28, 2026 => 30 }.freeze
end
diff --git a/app/models/form/sales/questions/armed_forces.rb b/app/models/form/sales/questions/armed_forces.rb
index 3e35ee86c..9b55f2de8 100644
--- a/app/models/form/sales/questions/armed_forces.rb
+++ b/app/models/form/sales/questions/armed_forces.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::ArmedForces < ::Form::Question
@id = "hhregres"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -15,5 +15,5 @@ class Form::Sales::Questions::ArmedForces < ::Form::Question
"8" => { "value" => "Don’t know" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 62, 2024 => 64, 2025 => 61 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 62, 2024 => 64, 2025 => 61, 2026 => 69 }.freeze
end
diff --git a/app/models/form/sales/questions/armed_forces_spouse.rb b/app/models/form/sales/questions/armed_forces_spouse.rb
index b37c8fe0d..44201aabc 100644
--- a/app/models/form/sales/questions/armed_forces_spouse.rb
+++ b/app/models/form/sales/questions/armed_forces_spouse.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::ArmedForcesSpouse < ::Form::Question
@id = "armedforcesspouse"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -15,5 +15,5 @@ class Form::Sales::Questions::ArmedForcesSpouse < ::Form::Question
"7" => { "value" => "Don’t know" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 64, 2024 => 66, 2025 => 63 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 64, 2024 => 66, 2025 => 63, 2026 => 71 }.freeze
end
diff --git a/app/models/form/sales/questions/building_height_class.rb b/app/models/form/sales/questions/building_height_class.rb
index 016245fbc..51e2c3623 100644
--- a/app/models/form/sales/questions/building_height_class.rb
+++ b/app/models/form/sales/questions/building_height_class.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::BuildingHeightClass < ::Form::Question
@id = "buildheightclass"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
diff --git a/app/models/form/sales/questions/buyer1_age_known.rb b/app/models/form/sales/questions/buyer1_age_known.rb
index 19442bdaa..fd87e9c8d 100644
--- a/app/models/form/sales/questions/buyer1_age_known.rb
+++ b/app/models/form/sales/questions/buyer1_age_known.rb
@@ -22,7 +22,7 @@ class Form::Sales::Questions::Buyer1AgeKnown < ::Form::Question
],
}
@check_answers_card_number = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -31,5 +31,5 @@ class Form::Sales::Questions::Buyer1AgeKnown < ::Form::Question
"2" => { "value" => "Buyer prefers not to say" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 20, 2024 => 22, 2025 => 20 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 20, 2024 => 22, 2025 => 20, 2026 => 21 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer1_ethnic_background_arab.rb b/app/models/form/sales/questions/buyer1_ethnic_background_arab.rb
index c302f573f..b8359b7bd 100644
--- a/app/models/form/sales/questions/buyer1_ethnic_background_arab.rb
+++ b/app/models/form/sales/questions/buyer1_ethnic_background_arab.rb
@@ -6,7 +6,7 @@ class Form::Sales::Questions::Buyer1EthnicBackgroundArab < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -14,5 +14,5 @@ class Form::Sales::Questions::Buyer1EthnicBackgroundArab < ::Form::Question
"16" => { "value" => "Other ethnic group" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 23, 2024 => 25, 2025 => 23 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 23, 2024 => 25, 2025 => 23, 2026 => 25 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer1_ethnic_background_asian.rb b/app/models/form/sales/questions/buyer1_ethnic_background_asian.rb
index 46e9a8b61..c10b90048 100644
--- a/app/models/form/sales/questions/buyer1_ethnic_background_asian.rb
+++ b/app/models/form/sales/questions/buyer1_ethnic_background_asian.rb
@@ -6,7 +6,7 @@ class Form::Sales::Questions::Buyer1EthnicBackgroundAsian < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -17,5 +17,5 @@ class Form::Sales::Questions::Buyer1EthnicBackgroundAsian < ::Form::Question
"11" => { "value" => "Any other Asian or Asian British background" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 23, 2024 => 25, 2025 => 23 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 23, 2024 => 25, 2025 => 23, 2026 => 25 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer1_ethnic_background_black.rb b/app/models/form/sales/questions/buyer1_ethnic_background_black.rb
index 7d0e3e456..6ba3ddab5 100644
--- a/app/models/form/sales/questions/buyer1_ethnic_background_black.rb
+++ b/app/models/form/sales/questions/buyer1_ethnic_background_black.rb
@@ -6,7 +6,7 @@ class Form::Sales::Questions::Buyer1EthnicBackgroundBlack < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -15,5 +15,5 @@ class Form::Sales::Questions::Buyer1EthnicBackgroundBlack < ::Form::Question
"14" => { "value" => "Any other Black, African, Caribbean or Black British background" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 23, 2024 => 25, 2025 => 23 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 23, 2024 => 25, 2025 => 23, 2026 => 25 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer1_ethnic_background_mixed.rb b/app/models/form/sales/questions/buyer1_ethnic_background_mixed.rb
index 499affd32..70748baf8 100644
--- a/app/models/form/sales/questions/buyer1_ethnic_background_mixed.rb
+++ b/app/models/form/sales/questions/buyer1_ethnic_background_mixed.rb
@@ -6,7 +6,7 @@ class Form::Sales::Questions::Buyer1EthnicBackgroundMixed < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -16,5 +16,5 @@ class Form::Sales::Questions::Buyer1EthnicBackgroundMixed < ::Form::Question
"7" => { "value" => "Any other Mixed or Multiple ethnic background" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 23, 2024 => 25, 2025 => 23 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 23, 2024 => 25, 2025 => 23, 2026 => 25 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer1_ethnic_background_white.rb b/app/models/form/sales/questions/buyer1_ethnic_background_white.rb
index a085658d6..871139944 100644
--- a/app/models/form/sales/questions/buyer1_ethnic_background_white.rb
+++ b/app/models/form/sales/questions/buyer1_ethnic_background_white.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::Buyer1EthnicBackgroundWhite < ::Form::Question
@copy_key = "sales.household_characteristics.ethnic.ethnic_background_white"
@type = "radio"
@check_answers_card_number = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
def answer_options
@@ -27,5 +27,5 @@ class Form::Sales::Questions::Buyer1EthnicBackgroundWhite < ::Form::Question
end
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 23, 2024 => 25, 2025 => 23 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 23, 2024 => 25, 2025 => 23, 2026 => 25 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer1_ethnic_group.rb b/app/models/form/sales/questions/buyer1_ethnic_group.rb
index 6b07b1769..5afd80b48 100644
--- a/app/models/form/sales/questions/buyer1_ethnic_group.rb
+++ b/app/models/form/sales/questions/buyer1_ethnic_group.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::Buyer1EthnicGroup < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -18,5 +18,5 @@ class Form::Sales::Questions::Buyer1EthnicGroup < ::Form::Question
"17" => { "value" => "Buyer prefers not to say" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 22, 2024 => 24, 2025 => 22 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 22, 2024 => 24, 2025 => 22, 2026 => 24 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer1_income.rb b/app/models/form/sales/questions/buyer1_income.rb
index 36d607e7b..b06a1ca1f 100644
--- a/app/models/form/sales/questions/buyer1_income.rb
+++ b/app/models/form/sales/questions/buyer1_income.rb
@@ -10,9 +10,9 @@ class Form::Sales::Questions::Buyer1Income < ::Form::Question
@width = 5
@prefix = "£"
@check_answers_card_number = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@strip_commas = true
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 67, 2024 => 69, 2025 => 66 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 67, 2024 => 69, 2025 => 66, 2026 => 74 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer1_income_known.rb b/app/models/form/sales/questions/buyer1_income_known.rb
index d563bc63c..512a3b281 100644
--- a/app/models/form/sales/questions/buyer1_income_known.rb
+++ b/app/models/form/sales/questions/buyer1_income_known.rb
@@ -9,7 +9,7 @@ class Form::Sales::Questions::Buyer1IncomeKnown < ::Form::Question
"income1" => [0],
}
@check_answers_card_number = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@hidden_in_check_answers = {
"depends_on" => [
{
@@ -24,5 +24,5 @@ class Form::Sales::Questions::Buyer1IncomeKnown < ::Form::Question
"1" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 67, 2024 => 69, 2025 => 66 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 67, 2024 => 69, 2025 => 66, 2026 => 74 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer1_live_in_property.rb b/app/models/form/sales/questions/buyer1_live_in_property.rb
index 0ff223364..a690f4967 100644
--- a/app/models/form/sales/questions/buyer1_live_in_property.rb
+++ b/app/models/form/sales/questions/buyer1_live_in_property.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::Buyer1LiveInProperty < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -13,5 +13,5 @@ class Form::Sales::Questions::Buyer1LiveInProperty < ::Form::Question
"2" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 26, 2024 => 28, 2025 => 26 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 26, 2024 => 28, 2025 => 26, 2026 => 28 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer1_mortgage.rb b/app/models/form/sales/questions/buyer1_mortgage.rb
index e02637bda..7449ca9b0 100644
--- a/app/models/form/sales/questions/buyer1_mortgage.rb
+++ b/app/models/form/sales/questions/buyer1_mortgage.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::Buyer1Mortgage < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -21,5 +21,5 @@ class Form::Sales::Questions::Buyer1Mortgage < ::Form::Question
}
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 68, 2024 => 70, 2025 => 67 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 68, 2024 => 70, 2025 => 67, 2026 => 75 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer1_nationality.rb b/app/models/form/sales/questions/buyer1_nationality.rb
index 4d128d3d3..1cdccfecc 100644
--- a/app/models/form/sales/questions/buyer1_nationality.rb
+++ b/app/models/form/sales/questions/buyer1_nationality.rb
@@ -11,7 +11,7 @@ class Form::Sales::Questions::Buyer1Nationality < ::Form::Question
},
"value" => "Prefers not to say",
}]
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -22,5 +22,5 @@ class Form::Sales::Questions::Buyer1Nationality < ::Form::Question
"13" => { "value" => "Buyer prefers not to say" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 24, 2024 => 26, 2025 => 24 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 24, 2024 => 26, 2025 => 24, 2026 => 26 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer1_previous_tenure.rb b/app/models/form/sales/questions/buyer1_previous_tenure.rb
index 827c7763a..a74a4bd24 100644
--- a/app/models/form/sales/questions/buyer1_previous_tenure.rb
+++ b/app/models/form/sales/questions/buyer1_previous_tenure.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::Buyer1PreviousTenure < ::Form::Question
@id = "prevten"
@type = "radio"
@answer_options = answer_options
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
def answer_options
@@ -22,5 +22,5 @@ class Form::Sales::Questions::Buyer1PreviousTenure < ::Form::Question
}
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 56, 2024 => 58, 2025 => 56 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 56, 2024 => 58, 2025 => 56, 2026 => 64 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer1_working_situation.rb b/app/models/form/sales/questions/buyer1_working_situation.rb
index ea0e9e54f..1e9faa916 100644
--- a/app/models/form/sales/questions/buyer1_working_situation.rb
+++ b/app/models/form/sales/questions/buyer1_working_situation.rb
@@ -11,7 +11,7 @@ class Form::Sales::Questions::Buyer1WorkingSituation < ::Form::Question
},
"value" => "Prefers not to say",
}]
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
def answer_options
@@ -44,5 +44,5 @@ class Form::Sales::Questions::Buyer1WorkingSituation < ::Form::Question
end
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 25, 2024 => 27, 2025 => 25 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 25, 2024 => 27, 2025 => 25, 2026 => 27 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer2_age_known.rb b/app/models/form/sales/questions/buyer2_age_known.rb
index cc490e006..1aac63734 100644
--- a/app/models/form/sales/questions/buyer2_age_known.rb
+++ b/app/models/form/sales/questions/buyer2_age_known.rb
@@ -19,7 +19,7 @@ class Form::Sales::Questions::Buyer2AgeKnown < ::Form::Question
],
}
@check_answers_card_number = 2
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -27,5 +27,5 @@ class Form::Sales::Questions::Buyer2AgeKnown < ::Form::Question
"1" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 28, 2024 => 30, 2025 => 28 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 28, 2024 => 30, 2025 => 28, 2026 => 30 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer2_ethnic_background_arab.rb b/app/models/form/sales/questions/buyer2_ethnic_background_arab.rb
index 914f8588b..8bafdacca 100644
--- a/app/models/form/sales/questions/buyer2_ethnic_background_arab.rb
+++ b/app/models/form/sales/questions/buyer2_ethnic_background_arab.rb
@@ -6,7 +6,7 @@ class Form::Sales::Questions::Buyer2EthnicBackgroundArab < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 2
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -14,5 +14,5 @@ class Form::Sales::Questions::Buyer2EthnicBackgroundArab < ::Form::Question
"16" => { "value" => "Other ethnic group" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 31, 2024 => 33, 2025 => 31 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 31, 2024 => 33, 2025 => 31, 2026 => 34 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer2_ethnic_background_asian.rb b/app/models/form/sales/questions/buyer2_ethnic_background_asian.rb
index 12f6113b2..538d91132 100644
--- a/app/models/form/sales/questions/buyer2_ethnic_background_asian.rb
+++ b/app/models/form/sales/questions/buyer2_ethnic_background_asian.rb
@@ -6,7 +6,7 @@ class Form::Sales::Questions::Buyer2EthnicBackgroundAsian < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 2
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -17,5 +17,5 @@ class Form::Sales::Questions::Buyer2EthnicBackgroundAsian < ::Form::Question
"11" => { "value" => "Any other Asian or Asian British background" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 31, 2024 => 33, 2025 => 31 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 31, 2024 => 33, 2025 => 31, 2026 => 34 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer2_ethnic_background_black.rb b/app/models/form/sales/questions/buyer2_ethnic_background_black.rb
index 48935667f..a0a31e47d 100644
--- a/app/models/form/sales/questions/buyer2_ethnic_background_black.rb
+++ b/app/models/form/sales/questions/buyer2_ethnic_background_black.rb
@@ -6,7 +6,7 @@ class Form::Sales::Questions::Buyer2EthnicBackgroundBlack < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 2
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -15,5 +15,5 @@ class Form::Sales::Questions::Buyer2EthnicBackgroundBlack < ::Form::Question
"14" => { "value" => "Any other Black, African, Caribbean or Black British background" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 31, 2024 => 33, 2025 => 31 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 31, 2024 => 33, 2025 => 31, 2026 => 34 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer2_ethnic_background_mixed.rb b/app/models/form/sales/questions/buyer2_ethnic_background_mixed.rb
index f916ba75e..7f8e18363 100644
--- a/app/models/form/sales/questions/buyer2_ethnic_background_mixed.rb
+++ b/app/models/form/sales/questions/buyer2_ethnic_background_mixed.rb
@@ -6,7 +6,7 @@ class Form::Sales::Questions::Buyer2EthnicBackgroundMixed < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 2
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -16,5 +16,5 @@ class Form::Sales::Questions::Buyer2EthnicBackgroundMixed < ::Form::Question
"7" => { "value" => "Any other Mixed or Multiple ethnic background" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 31, 2024 => 33, 2025 => 31 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 31, 2024 => 33, 2025 => 31, 2026 => 34 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer2_ethnic_background_white.rb b/app/models/form/sales/questions/buyer2_ethnic_background_white.rb
index 6125bd2da..1e45bbd31 100644
--- a/app/models/form/sales/questions/buyer2_ethnic_background_white.rb
+++ b/app/models/form/sales/questions/buyer2_ethnic_background_white.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::Buyer2EthnicBackgroundWhite < ::Form::Question
@copy_key = "sales.household_characteristics.ethnicbuy2.ethnic_background_white"
@type = "radio"
@check_answers_card_number = 2
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
def answer_options
@@ -27,5 +27,5 @@ class Form::Sales::Questions::Buyer2EthnicBackgroundWhite < ::Form::Question
end
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 31, 2024 => 33, 2025 => 31 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 31, 2024 => 33, 2025 => 31, 2026 => 34 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer2_ethnic_group.rb b/app/models/form/sales/questions/buyer2_ethnic_group.rb
index 1a695313b..cfae8ea43 100644
--- a/app/models/form/sales/questions/buyer2_ethnic_group.rb
+++ b/app/models/form/sales/questions/buyer2_ethnic_group.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::Buyer2EthnicGroup < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 2
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -18,5 +18,5 @@ class Form::Sales::Questions::Buyer2EthnicGroup < ::Form::Question
"17" => { "value" => "Buyer prefers not to say" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 30, 2024 => 32, 2025 => 30 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 30, 2024 => 32, 2025 => 30, 2026 => 33 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer2_income.rb b/app/models/form/sales/questions/buyer2_income.rb
index fb27b9c4a..6da0bc220 100644
--- a/app/models/form/sales/questions/buyer2_income.rb
+++ b/app/models/form/sales/questions/buyer2_income.rb
@@ -10,9 +10,9 @@ class Form::Sales::Questions::Buyer2Income < ::Form::Question
@width = 5
@prefix = "£"
@check_answers_card_number = 2
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@strip_commas = true
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 69, 2024 => 71, 2025 => 68 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 69, 2024 => 71, 2025 => 68, 2026 => 76 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer2_income_known.rb b/app/models/form/sales/questions/buyer2_income_known.rb
index 6b0241df8..61c1583cf 100644
--- a/app/models/form/sales/questions/buyer2_income_known.rb
+++ b/app/models/form/sales/questions/buyer2_income_known.rb
@@ -9,7 +9,7 @@ class Form::Sales::Questions::Buyer2IncomeKnown < ::Form::Question
"income2" => [0],
}
@check_answers_card_number = 2
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@hidden_in_check_answers = {
"depends_on" => [
{
@@ -24,5 +24,5 @@ class Form::Sales::Questions::Buyer2IncomeKnown < ::Form::Question
"1" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 69, 2024 => 71, 2025 => 68 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 69, 2024 => 71, 2025 => 68, 2026 => 76 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer2_live_in_property.rb b/app/models/form/sales/questions/buyer2_live_in_property.rb
index a5fc82c37..de9924941 100644
--- a/app/models/form/sales/questions/buyer2_live_in_property.rb
+++ b/app/models/form/sales/questions/buyer2_live_in_property.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::Buyer2LiveInProperty < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 2
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -13,5 +13,5 @@ class Form::Sales::Questions::Buyer2LiveInProperty < ::Form::Question
"2" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 34, 2024 => 36, 2025 => 34 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 34, 2024 => 36, 2025 => 34, 2026 => 37 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer2_living_in.rb b/app/models/form/sales/questions/buyer2_living_in.rb
index 8ee1f2ad3..170154b39 100644
--- a/app/models/form/sales/questions/buyer2_living_in.rb
+++ b/app/models/form/sales/questions/buyer2_living_in.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::Buyer2LivingIn < ::Form::Question
@id = "buy2living"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -14,5 +14,5 @@ class Form::Sales::Questions::Buyer2LivingIn < ::Form::Question
"3" => { "value" => "Don’t know" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 60, 2024 => 62, 2025 => 59 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 60, 2024 => 62, 2025 => 59, 2026 => 67 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer2_mortgage.rb b/app/models/form/sales/questions/buyer2_mortgage.rb
index 05d94bde9..39fa45024 100644
--- a/app/models/form/sales/questions/buyer2_mortgage.rb
+++ b/app/models/form/sales/questions/buyer2_mortgage.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::Buyer2Mortgage < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 2
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -21,5 +21,5 @@ class Form::Sales::Questions::Buyer2Mortgage < ::Form::Question
}
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 70, 2024 => 72, 2025 => 69 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 70, 2024 => 72, 2025 => 69, 2026 => 77 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer2_nationality.rb b/app/models/form/sales/questions/buyer2_nationality.rb
index 93bb127aa..377729788 100644
--- a/app/models/form/sales/questions/buyer2_nationality.rb
+++ b/app/models/form/sales/questions/buyer2_nationality.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::Buyer2Nationality < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 2
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@inferred_check_answers_value = [{
"condition" => {
"national" => 13,
diff --git a/app/models/form/sales/questions/buyer2_relationship_to_buyer1.rb b/app/models/form/sales/questions/buyer2_relationship_to_buyer1.rb
index 7f3638d61..8084415e3 100644
--- a/app/models/form/sales/questions/buyer2_relationship_to_buyer1.rb
+++ b/app/models/form/sales/questions/buyer2_relationship_to_buyer1.rb
@@ -12,7 +12,7 @@ class Form::Sales::Questions::Buyer2RelationshipToBuyer1 < ::Form::Question
},
"value" => "Prefers not to say",
}]
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
def answer_options
@@ -33,5 +33,5 @@ class Form::Sales::Questions::Buyer2RelationshipToBuyer1 < ::Form::Question
end
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 27, 2024 => 29, 2025 => 27 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 27, 2024 => 29, 2025 => 27, 2026 => 29 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer2_relationship_to_buyer1_yes_no.rb b/app/models/form/sales/questions/buyer2_relationship_to_buyer1_yes_no.rb
index 84fa336bf..72b0f196e 100644
--- a/app/models/form/sales/questions/buyer2_relationship_to_buyer1_yes_no.rb
+++ b/app/models/form/sales/questions/buyer2_relationship_to_buyer1_yes_no.rb
@@ -16,8 +16,8 @@ class Form::Sales::Questions::Buyer2RelationshipToBuyer1YesNo < ::Form::Question
"value" => "Prefers not to say",
}]
@check_answers_card_number = 2
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
- QUESTION_NUMBER_FROM_YEAR = { 2025 => 27 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2025 => 27, 2026 => 29 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer2_working_situation.rb b/app/models/form/sales/questions/buyer2_working_situation.rb
index 32a7c93f4..2165c7023 100644
--- a/app/models/form/sales/questions/buyer2_working_situation.rb
+++ b/app/models/form/sales/questions/buyer2_working_situation.rb
@@ -12,7 +12,7 @@ class Form::Sales::Questions::Buyer2WorkingSituation < ::Form::Question
},
"value" => "Prefers not to say",
}]
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
def displayed_answer_options(_log, _user = nil)
@@ -51,5 +51,5 @@ class Form::Sales::Questions::Buyer2WorkingSituation < ::Form::Question
end
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 33, 2024 => 35, 2025 => 33 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 33, 2024 => 35, 2025 => 33, 2026 => 36 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer_company.rb b/app/models/form/sales/questions/buyer_company.rb
index a5dc69d8d..5acbdba89 100644
--- a/app/models/form/sales/questions/buyer_company.rb
+++ b/app/models/form/sales/questions/buyer_company.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::BuyerCompany < ::Form::Question
@id = "companybuy"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -12,5 +12,5 @@ class Form::Sales::Questions::BuyerCompany < ::Form::Question
"2" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 7, 2024 => 9 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 7, 2024 => 9, 2025 => 9, 2026 => 9 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer_interview.rb b/app/models/form/sales/questions/buyer_interview.rb
index ef40c4236..d5fc02353 100644
--- a/app/models/form/sales/questions/buyer_interview.rb
+++ b/app/models/form/sales/questions/buyer_interview.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::BuyerInterview < ::Form::Question
@copy_key = "sales.#{subsection.copy_key}.noint.#{joint_purchase ? 'joint_purchase' : 'not_joint_purchase'}"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -13,5 +13,5 @@ class Form::Sales::Questions::BuyerInterview < ::Form::Question
"1" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 18, 2024 => 13, 2025 => 11 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 18, 2024 => 13, 2025 => 11, 2026 => 11 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer_live.rb b/app/models/form/sales/questions/buyer_live.rb
index 315329088..011fc8a89 100644
--- a/app/models/form/sales/questions/buyer_live.rb
+++ b/app/models/form/sales/questions/buyer_live.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::BuyerLive < ::Form::Question
@id = "buylivein"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -12,5 +12,5 @@ class Form::Sales::Questions::BuyerLive < ::Form::Question
"2" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 8, 2024 => 10 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 8, 2024 => 10, 2025 => 10, 2026 => 10 }.freeze
end
diff --git a/app/models/form/sales/questions/buyer_previous.rb b/app/models/form/sales/questions/buyer_previous.rb
index 4daf963bf..7c8718eaa 100644
--- a/app/models/form/sales/questions/buyer_previous.rb
+++ b/app/models/form/sales/questions/buyer_previous.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::BuyerPrevious < ::Form::Question
@copy_key = "sales.sale_information.soctenant.#{joint_purchase ? 'joint_purchase' : 'not_joint_purchase'}"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
diff --git a/app/models/form/sales/questions/buyer_still_serving.rb b/app/models/form/sales/questions/buyer_still_serving.rb
index 7d31da3e4..3f2d9d8d9 100644
--- a/app/models/form/sales/questions/buyer_still_serving.rb
+++ b/app/models/form/sales/questions/buyer_still_serving.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::BuyerStillServing < ::Form::Question
@id = "hhregresstill"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -15,5 +15,5 @@ class Form::Sales::Questions::BuyerStillServing < ::Form::Question
"7" => { "value" => "Don’t know" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 63, 2024 => 65, 2025 => 62 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 63, 2024 => 65, 2025 => 62, 2026 => 70 }.freeze
end
diff --git a/app/models/form/sales/questions/buyers_organisations.rb b/app/models/form/sales/questions/buyers_organisations.rb
index 727a65ad0..f5fbccf93 100644
--- a/app/models/form/sales/questions/buyers_organisations.rb
+++ b/app/models/form/sales/questions/buyers_organisations.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::BuyersOrganisations < ::Form::Question
@id = "buyers_organisations"
@type = "checkbox"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
diff --git a/app/models/form/sales/questions/county.rb b/app/models/form/sales/questions/county.rb
index 174904a0b..0f45b6b0a 100644
--- a/app/models/form/sales/questions/county.rb
+++ b/app/models/form/sales/questions/county.rb
@@ -6,9 +6,9 @@ class Form::Sales::Questions::County < ::Form::Question
@type = "text"
@plain_label = true
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@hide_question_number_on_page = true
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 15, 2024 => 16, 2025 => 14 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 15, 2024 => 16, 2025 => 14, 2026 => 14 }.freeze
end
diff --git a/app/models/form/sales/questions/deposit_amount.rb b/app/models/form/sales/questions/deposit_amount.rb
index ede6335e1..3766bbd71 100644
--- a/app/models/form/sales/questions/deposit_amount.rb
+++ b/app/models/form/sales/questions/deposit_amount.rb
@@ -1,6 +1,6 @@
class Form::Sales::Questions::DepositAmount < ::Form::Question
- def initialize(id, hsh, subsection, ownershipsch:, optional:)
- super(id, hsh, subsection)
+ def initialize(id, hsh, page, ownershipsch:, optional:)
+ super(id, hsh, page)
@id = "deposit"
@type = "numeric"
@min = 0
@@ -9,7 +9,7 @@ class Form::Sales::Questions::DepositAmount < ::Form::Question
@width = 5
@prefix = "£"
@ownershipsch = ownershipsch
- @question_number = QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.fetch(form.start_date.year, QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.max_by { |k, _v| k }.last)[ownershipsch]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_SECTION, value_key: form.start_year_2026_or_later? ? subsection.id : ownershipsch)
@optional = optional
@top_guidance_partial = top_guidance_partial
@copy_key = copy_key
@@ -20,10 +20,11 @@ class Form::Sales::Questions::DepositAmount < ::Form::Question
log.outright_sale? && !log.mortgage_used?
end
- QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP = {
+ QUESTION_NUMBER_FROM_YEAR_AND_SECTION = {
2023 => { 1 => 95, 2 => 108, 3 => 116 },
2024 => { 1 => 96, 2 => 109, 3 => 116 },
2025 => { 1 => 85, 2 => 110 },
+ 2026 => { "shared_ownership_initial_purchase" => 93, "discounted_ownership_scheme" => 120 },
}.freeze
def top_guidance_partial
diff --git a/app/models/form/sales/questions/deposit_discount.rb b/app/models/form/sales/questions/deposit_discount.rb
index 3b1b22325..db1841419 100644
--- a/app/models/form/sales/questions/deposit_discount.rb
+++ b/app/models/form/sales/questions/deposit_discount.rb
@@ -8,10 +8,10 @@ class Form::Sales::Questions::DepositDiscount < ::Form::Question
@step = 1
@width = 5
@prefix = "£"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@top_guidance_partial = "financial_calculations_shared_ownership"
@strip_commas = true
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 96, 2024 => 97, 2025 => 86 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 96, 2024 => 97, 2025 => 86, 2026 => 94 }.freeze
end
diff --git a/app/models/form/sales/questions/discount.rb b/app/models/form/sales/questions/discount.rb
index 7249d3a6f..0927510a5 100644
--- a/app/models/form/sales/questions/discount.rb
+++ b/app/models/form/sales/questions/discount.rb
@@ -8,9 +8,9 @@ class Form::Sales::Questions::Discount < ::Form::Question
@step = 0.1
@width = 5
@suffix = "%"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@top_guidance_partial = "financial_calculations_discounted_ownership"
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 102, 2024 => 103, 2025 => 105 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 102, 2024 => 103, 2025 => 105, 2026 => 115 }.freeze
end
diff --git a/app/models/form/sales/questions/discounted_ownership_type.rb b/app/models/form/sales/questions/discounted_ownership_type.rb
index 9d8798f00..1b564d717 100644
--- a/app/models/form/sales/questions/discounted_ownership_type.rb
+++ b/app/models/form/sales/questions/discounted_ownership_type.rb
@@ -5,8 +5,8 @@ class Form::Sales::Questions::DiscountedOwnershipType < ::Form::Question
@copy_key = "sales.setup.type.discounted_ownership"
@type = "radio"
@top_guidance_partial = guidance_partial
- @answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @answer_options = form.start_year_2026_or_later? ? ANSWER_OPTIONS_2026_OR_LATER : ANSWER_OPTIONS
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -19,9 +19,18 @@ class Form::Sales::Questions::DiscountedOwnershipType < ::Form::Question
"22" => { "value" => "Any other equity loan scheme" },
}.freeze
+ ANSWER_OPTIONS_2026_OR_LATER = {
+ "8" => { "value" => "Right to Acquire (RTA)" },
+ "14" => { "value" => "Preserved Right to Buy (PRTB)" },
+ "9" => { "value" => "Right to Buy (RTB)" },
+ "29" => { "value" => "Rent to Buy - Full Ownership" },
+ "21" => { "value" => "Social HomeBuy for outright purchase" },
+ "22" => { "value" => "Any other equity loan scheme" },
+ }.freeze
+
def guidance_partial
"discounted_ownership_type_definitions" if form.start_date.year >= 2023
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 5, 2024 => 7, 2025 => 8 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 5, 2024 => 7, 2025 => 8, 2026 => 8 }.freeze
end
diff --git a/app/models/form/sales/questions/equity.rb b/app/models/form/sales/questions/equity.rb
index a2539b968..55b0aaa1e 100644
--- a/app/models/form/sales/questions/equity.rb
+++ b/app/models/form/sales/questions/equity.rb
@@ -9,11 +9,14 @@ class Form::Sales::Questions::Equity < ::Form::Question
@step = 0.1
@width = 5
@suffix = "%"
- @question_number = question_number_from_year[form.start_date.year] || question_number_from_year[question_number_from_year.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_SECTION, value_key: subsection.id)
@top_guidance_partial = "financial_calculations_shared_ownership"
end
- def question_number_from_year
- { 2023 => 89, 2024 => 90, 2025 => subsection.id == "shared_ownership_staircasing_transaction" ? 98 : 81 }
- end
+ QUESTION_NUMBER_FROM_YEAR_AND_SECTION = {
+ 2023 => 89,
+ 2024 => 90,
+ 2025 => { "shared_ownership_initial_purchase" => 81, "shared_ownership_staircasing_transaction" => 98 },
+ 2026 => { "shared_ownership_initial_purchase" => 89, "shared_ownership_staircasing_transaction" => 106 },
+ }.freeze
end
diff --git a/app/models/form/sales/questions/exchange_date.rb b/app/models/form/sales/questions/exchange_date.rb
index a29a7a6c7..5d829826b 100644
--- a/app/models/form/sales/questions/exchange_date.rb
+++ b/app/models/form/sales/questions/exchange_date.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::ExchangeDate < ::Form::Question
@id = "exdate"
@copy_key = "sales.sale_information.exchange_date"
@type = "date"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 81, 2024 => 83 }.freeze
diff --git a/app/models/form/sales/questions/extra_borrowing.rb b/app/models/form/sales/questions/extra_borrowing.rb
index 288ddb107..84f6cb770 100644
--- a/app/models/form/sales/questions/extra_borrowing.rb
+++ b/app/models/form/sales/questions/extra_borrowing.rb
@@ -1,12 +1,12 @@
class Form::Sales::Questions::ExtraBorrowing < ::Form::Question
- def initialize(id, hsh, subsection, ownershipsch:)
- super(id, hsh, subsection)
+ def initialize(id, hsh, page, ownershipsch:)
+ super(id, hsh, page)
@id = "extrabor"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@page = page
@ownershipsch = ownershipsch
- @question_number = QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.fetch(form.start_date.year, QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.max_by { |k, _v| k }.last)[ownershipsch]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_SECTION, value_key: form.start_year_2026_or_later? ? subsection.id : ownershipsch)
end
ANSWER_OPTIONS = {
@@ -16,9 +16,10 @@ class Form::Sales::Questions::ExtraBorrowing < ::Form::Question
"3" => { "value" => "Don’t know" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP = {
+ QUESTION_NUMBER_FROM_YEAR_AND_SECTION = {
2023 => { 1 => 94, 2 => 107, 3 => 115 },
2024 => { 1 => 95, 2 => 108, 3 => 115 },
2025 => { 2 => 109 },
+ 2026 => { "discounted_ownership_scheme" => 119 },
}.freeze
end
diff --git a/app/models/form/sales/questions/fromprop.rb b/app/models/form/sales/questions/fromprop.rb
index 16251d7be..2bf20d0da 100644
--- a/app/models/form/sales/questions/fromprop.rb
+++ b/app/models/form/sales/questions/fromprop.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::Fromprop < ::Form::Question
@type = "radio"
@page = page
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -27,5 +27,5 @@ class Form::Sales::Questions::Fromprop < ::Form::Question
}
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 86, 2024 => 87, 2025 => 78 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 86, 2024 => 87, 2025 => 78, 2026 => 86 }.freeze
end
diff --git a/app/models/form/sales/questions/gender_description.rb b/app/models/form/sales/questions/gender_description.rb
index 08ea67855..210633e39 100644
--- a/app/models/form/sales/questions/gender_description.rb
+++ b/app/models/form/sales/questions/gender_description.rb
@@ -1,14 +1,16 @@
class Form::Sales::Questions::GenderDescription < ::Form::Question
- def initialize(id, hsh, page, person_index:)
+ def initialize(id, hsh, page, person_index:, buyer: false)
super(id, hsh, page)
@id = "gender_description#{person_index}"
@type = "text"
@check_answers_card_number = person_index
+ @buyer = buyer
@person_index = person_index
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_person_question_number(BASE_QUESTION_NUMBERS, override_hash: BUYER_OVERRIDE_QUESTION_NUMBERS)
end
- QUESTION_NUMBER_FROM_YEAR = { 2026 => 0 }.freeze
+ BASE_QUESTION_NUMBERS = { 2026 => 32 }.freeze
+ BUYER_OVERRIDE_QUESTION_NUMBERS = { 2026 => { 1 => 23, 2 => 32 } }.freeze
def derived?(log)
log.public_send("gender_same_as_sex#{@person_index}") != 2
diff --git a/app/models/form/sales/questions/gender_identity1.rb b/app/models/form/sales/questions/gender_identity1.rb
index 42dbc1a21..ecaa5fda2 100644
--- a/app/models/form/sales/questions/gender_identity1.rb
+++ b/app/models/form/sales/questions/gender_identity1.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::GenderIdentity1 < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_number = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -15,5 +15,5 @@ class Form::Sales::Questions::GenderIdentity1 < ::Form::Question
"R" => { "value" => "Prefers not to say" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 21, 2024 => 23, 2025 => 21 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 21, 2024 => 23, 2025 => 21, 2026 => 22 }.freeze
end
diff --git a/app/models/form/sales/questions/gender_identity2.rb b/app/models/form/sales/questions/gender_identity2.rb
index 9f3472ea6..e81abfd75 100644
--- a/app/models/form/sales/questions/gender_identity2.rb
+++ b/app/models/form/sales/questions/gender_identity2.rb
@@ -12,7 +12,7 @@ class Form::Sales::Questions::GenderIdentity2 < ::Form::Question
},
"value" => "Prefers not to say",
}]
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -22,5 +22,5 @@ class Form::Sales::Questions::GenderIdentity2 < ::Form::Question
"R" => { "value" => "Buyer prefers not to say" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 29, 2024 => 31, 2025 => 29 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 29, 2024 => 31, 2025 => 29, 2026 => 31 }.freeze
end
diff --git a/app/models/form/sales/questions/gender_same_as_sex.rb b/app/models/form/sales/questions/gender_same_as_sex.rb
index a6acf9ebb..27fd8034a 100644
--- a/app/models/form/sales/questions/gender_same_as_sex.rb
+++ b/app/models/form/sales/questions/gender_same_as_sex.rb
@@ -9,10 +9,11 @@ class Form::Sales::Questions::GenderSameAsSex < ::Form::Question
@person_index = person_index
@buyer = buyer
@copy_key = "sales.household_characteristics.gender_same_as_sex#{person_index}.#{buyer ? 'buyer' : 'person'}" if person_index == 2
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_person_question_number(BASE_QUESTION_NUMBERS, override_hash: BUYER_OVERRIDE_QUESTION_NUMBERS)
end
- QUESTION_NUMBER_FROM_YEAR = { 2026 => 0 }.freeze
+ BASE_QUESTION_NUMBERS = { 2026 => 32 }.freeze
+ BUYER_OVERRIDE_QUESTION_NUMBERS = { 2026 => { 1 => 23, 2 => 32 } }.freeze
def answer_options
{
diff --git a/app/models/form/sales/questions/grant.rb b/app/models/form/sales/questions/grant.rb
index a5bd4c1a8..9a739d0f4 100644
--- a/app/models/form/sales/questions/grant.rb
+++ b/app/models/form/sales/questions/grant.rb
@@ -8,10 +8,10 @@ class Form::Sales::Questions::Grant < ::Form::Question
@step = 1
@width = 5
@prefix = "£"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@top_guidance_partial = "financial_calculations_discounted_ownership"
@strip_commas = true
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 101, 2024 => 102, 2025 => 104 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 101, 2024 => 102, 2025 => 104, 2026 => 114 }.freeze
end
diff --git a/app/models/form/sales/questions/handover_date.rb b/app/models/form/sales/questions/handover_date.rb
index 5862dc0e4..f1f0602af 100644
--- a/app/models/form/sales/questions/handover_date.rb
+++ b/app/models/form/sales/questions/handover_date.rb
@@ -4,8 +4,8 @@ class Form::Sales::Questions::HandoverDate < ::Form::Question
@id = "hodate"
@copy_key = "sales.sale_information.handover_date"
@type = "date"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 82, 2024 => 84, 2025 => 76 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 82, 2024 => 84, 2025 => 76, 2026 => 84 }.freeze
end
diff --git a/app/models/form/sales/questions/has_leasehold_charges.rb b/app/models/form/sales/questions/has_leasehold_charges.rb
index 36086ea36..220042e39 100644
--- a/app/models/form/sales/questions/has_leasehold_charges.rb
+++ b/app/models/form/sales/questions/has_leasehold_charges.rb
@@ -1,6 +1,6 @@
class Form::Sales::Questions::HasLeaseholdCharges < ::Form::Question
- def initialize(id, hsh, subsection, ownershipsch:)
- super(id, hsh, subsection)
+ def initialize(id, hsh, page, ownershipsch:)
+ super(id, hsh, page)
@id = "has_mscharge"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@@ -16,7 +16,7 @@ class Form::Sales::Questions::HasLeaseholdCharges < ::Form::Question
}
@ownershipsch = ownershipsch
@copy_key = "sales.sale_information.leaseholdcharges.has_mscharge"
- @question_number = QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.fetch(form.start_date.year, QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.max_by { |k, _v| k }.last)[ownershipsch]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_SECTION, value_key: form.start_year_2026_or_later? ? subsection.id : ownershipsch)
end
ANSWER_OPTIONS = {
@@ -24,8 +24,9 @@ class Form::Sales::Questions::HasLeaseholdCharges < ::Form::Question
"0" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP = {
+ QUESTION_NUMBER_FROM_YEAR_AND_SECTION = {
2024 => { 1 => 99, 2 => 110, 3 => 117 },
2025 => { 2 => 111 },
+ 2026 => 121,
}.freeze
end
diff --git a/app/models/form/sales/questions/has_management_fee.rb b/app/models/form/sales/questions/has_management_fee.rb
index 059e32acb..873241579 100644
--- a/app/models/form/sales/questions/has_management_fee.rb
+++ b/app/models/form/sales/questions/has_management_fee.rb
@@ -15,7 +15,7 @@ class Form::Sales::Questions::HasManagementFee < ::Form::Question
},
],
}
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -23,5 +23,5 @@ class Form::Sales::Questions::HasManagementFee < ::Form::Question
"0" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2025 => 89 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2025 => 89, 2026 => 97 }.freeze
end
diff --git a/app/models/form/sales/questions/has_service_charge.rb b/app/models/form/sales/questions/has_service_charge.rb
index 708c32f0d..00a757c9f 100644
--- a/app/models/form/sales/questions/has_service_charge.rb
+++ b/app/models/form/sales/questions/has_service_charge.rb
@@ -1,6 +1,6 @@
class Form::Sales::Questions::HasServiceCharge < ::Form::Question
- def initialize(id, hsh, subsection, staircasing:)
- super(id, hsh, subsection)
+ def initialize(id, hsh, page, staircasing:)
+ super(id, hsh, page)
@id = "has_mscharge"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@@ -16,7 +16,7 @@ class Form::Sales::Questions::HasServiceCharge < ::Form::Question
}
@copy_key = "sales.sale_information.servicecharges.has_servicecharge"
@staircasing = staircasing
- @question_number = question_number_from_year[form.start_date.year] || question_number_from_year[question_number_from_year.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_SECTION, value_key: subsection.id)
end
ANSWER_OPTIONS = {
@@ -24,11 +24,8 @@ class Form::Sales::Questions::HasServiceCharge < ::Form::Question
"0" => { "value" => "No" },
}.freeze
- def question_number_from_year
- if @staircasing
- { 2026 => 0 }.freeze
- else
- { 2025 => 88, 2026 => 0 }.freeze
- end
- end
+ QUESTION_NUMBER_FROM_YEAR_AND_SECTION = {
+ 2025 => 88,
+ 2026 => { "shared_ownership_initial_purchase" => 96, "shared_ownership_staircasing_transaction" => 110 },
+ }.freeze
end
diff --git a/app/models/form/sales/questions/has_service_charges_changed.rb b/app/models/form/sales/questions/has_service_charges_changed.rb
new file mode 100644
index 000000000..d86853bb5
--- /dev/null
+++ b/app/models/form/sales/questions/has_service_charges_changed.rb
@@ -0,0 +1,27 @@
+class Form::Sales::Questions::HasServiceChargesChanged < ::Form::Question
+ def initialize(id, hsh, page)
+ super
+ @id = "hasservicechargeschanged"
+ @type = "radio"
+ @answer_options = ANSWER_OPTIONS
+ @conditional_for = {
+ "newservicecharges" => [1],
+ }
+ @hidden_in_check_answers = {
+ "depends_on" => [
+ {
+ "hasservicechargeschanged" => 1,
+ },
+ ],
+ }
+ @copy_key = "sales.sale_information.servicecharges_changed.has_service_charges_changed"
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
+ end
+
+ ANSWER_OPTIONS = {
+ "1" => { "value" => "Yes" },
+ "2" => { "value" => "No" },
+ }.freeze
+
+ QUESTION_NUMBER_FROM_YEAR = { 2026 => 111 }.freeze
+end
diff --git a/app/models/form/sales/questions/household_disability.rb b/app/models/form/sales/questions/household_disability.rb
index 5a85d1dbe..b4b2ecc0d 100644
--- a/app/models/form/sales/questions/household_disability.rb
+++ b/app/models/form/sales/questions/household_disability.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::HouseholdDisability < ::Form::Question
@id = "disabled"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -14,5 +14,5 @@ class Form::Sales::Questions::HouseholdDisability < ::Form::Question
"3" => { "value" => "Don’t know" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 65, 2024 => 67, 2025 => 64 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 65, 2024 => 67, 2025 => 64, 2026 => 72 }.freeze
end
diff --git a/app/models/form/sales/questions/household_wheelchair.rb b/app/models/form/sales/questions/household_wheelchair.rb
index e1c62994f..a94206879 100644
--- a/app/models/form/sales/questions/household_wheelchair.rb
+++ b/app/models/form/sales/questions/household_wheelchair.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::HouseholdWheelchair < ::Form::Question
@id = "wheel"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -14,5 +14,5 @@ class Form::Sales::Questions::HouseholdWheelchair < ::Form::Question
"3" => { "value" => "Don’t know" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 66, 2024 => 68, 2025 => 65 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 66, 2024 => 68, 2025 => 65, 2026 => 73 }.freeze
end
diff --git a/app/models/form/sales/questions/housing_benefits.rb b/app/models/form/sales/questions/housing_benefits.rb
index cae27aeb4..d3c27e872 100644
--- a/app/models/form/sales/questions/housing_benefits.rb
+++ b/app/models/form/sales/questions/housing_benefits.rb
@@ -6,7 +6,7 @@ class Form::Sales::Questions::HousingBenefits < ::Form::Question
@type = "radio"
@answer_options = ANSWER_OPTIONS
@check_answers_card_title = "All buyers" if form.start_year_2026_or_later?
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -17,5 +17,5 @@ class Form::Sales::Questions::HousingBenefits < ::Form::Question
"4" => { "value" => "Don’t know " },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 71, 2024 => 73, 2025 => 70 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 71, 2024 => 73, 2025 => 70, 2026 => 78 }.freeze
end
diff --git a/app/models/form/sales/questions/joint_purchase.rb b/app/models/form/sales/questions/joint_purchase.rb
index a03e053bc..afb50ca13 100644
--- a/app/models/form/sales/questions/joint_purchase.rb
+++ b/app/models/form/sales/questions/joint_purchase.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::JointPurchase < ::Form::Question
@id = "jointpur"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -12,5 +12,5 @@ class Form::Sales::Questions::JointPurchase < ::Form::Question
"2" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 9, 2024 => 11, 2025 => 9 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 9, 2024 => 11, 2025 => 9, 2026 => 9 }.freeze
end
diff --git a/app/models/form/sales/questions/la_nominations.rb b/app/models/form/sales/questions/la_nominations.rb
index 82201b3e8..75ad85c71 100644
--- a/app/models/form/sales/questions/la_nominations.rb
+++ b/app/models/form/sales/questions/la_nominations.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::LaNominations < ::Form::Question
@copy_key = "sales.sale_information.la_nominations"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -15,5 +15,5 @@ class Form::Sales::Questions::LaNominations < ::Form::Question
"3" => { "value" => "Don’t know" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 83, 2024 => 85 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 83, 2024 => 85, 2025 => 85, 2026 => 93 }.freeze
end
diff --git a/app/models/form/sales/questions/leasehold_charges.rb b/app/models/form/sales/questions/leasehold_charges.rb
index e524bfa00..c51588b94 100644
--- a/app/models/form/sales/questions/leasehold_charges.rb
+++ b/app/models/form/sales/questions/leasehold_charges.rb
@@ -1,6 +1,6 @@
class Form::Sales::Questions::LeaseholdCharges < ::Form::Question
- def initialize(id, hsh, subsection, ownershipsch:)
- super(id, hsh, subsection)
+ def initialize(id, hsh, page, ownershipsch:)
+ super(id, hsh, page)
@id = "mscharge"
@type = "numeric"
@min = 1
@@ -9,13 +9,14 @@ class Form::Sales::Questions::LeaseholdCharges < ::Form::Question
@prefix = "£"
@copy_key = "sales.sale_information.leaseholdcharges.mscharge"
@ownershipsch = ownershipsch
- @question_number = QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.fetch(form.start_date.year, QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.max_by { |k, _v| k }.last)[ownershipsch]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_SECTION, value_key: form.start_year_2026_or_later? ? subsection.id : ownershipsch)
@strip_commas = true
end
- QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP = {
+ QUESTION_NUMBER_FROM_YEAR_AND_SECTION = {
2023 => { 1 => 98, 2 => 109, 3 => 117 },
2024 => { 1 => 99, 2 => 110, 3 => 117 },
2025 => { 2 => 111 },
+ 2026 => { "discounted_ownership_scheme" => 121 },
}.freeze
end
diff --git a/app/models/form/sales/questions/living_before_purchase.rb b/app/models/form/sales/questions/living_before_purchase.rb
index 06ff095d1..1faa07229 100644
--- a/app/models/form/sales/questions/living_before_purchase.rb
+++ b/app/models/form/sales/questions/living_before_purchase.rb
@@ -16,7 +16,7 @@ class Form::Sales::Questions::LivingBeforePurchase < ::Form::Question
],
}
@ownershipsch = ownershipsch
- @question_number = QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.fetch(form.start_date.year, QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.max_by { |k, _v| k }.last)[ownershipsch]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_SECTION, value_key: form.start_year_2026_or_later? ? subsection.id : ownershipsch)
end
ANSWER_OPTIONS = {
@@ -24,9 +24,10 @@ class Form::Sales::Questions::LivingBeforePurchase < ::Form::Question
"1" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP = {
+ QUESTION_NUMBER_FROM_YEAR_AND_SECTION = {
2023 => { 1 => 75, 2 => 99 },
2024 => { 1 => 77, 2 => 100 },
2025 => { 1 => 75, 2 => 102 },
+ 2026 => { "shared_ownership_initial_purchase" => 83, "discounted_ownership_scheme" => 112 },
}.freeze
end
diff --git a/app/models/form/sales/questions/living_before_purchase_years.rb b/app/models/form/sales/questions/living_before_purchase_years.rb
index 010aa6edc..30ff5fe8a 100644
--- a/app/models/form/sales/questions/living_before_purchase_years.rb
+++ b/app/models/form/sales/questions/living_before_purchase_years.rb
@@ -9,16 +9,17 @@ class Form::Sales::Questions::LivingBeforePurchaseYears < ::Form::Question
@step = 1
@width = 5
@ownershipsch = ownershipsch
- @question_number = QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.fetch(form.start_date.year, QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.max_by { |k, _v| k }.last)[ownershipsch]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_SECTION, value_key: form.start_year_2026_or_later? ? subsection.id : ownershipsch)
end
def suffix_label(log)
" #{'year'.pluralize(log[id])}"
end
- QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP = {
+ QUESTION_NUMBER_FROM_YEAR_AND_SECTION = {
2023 => { 1 => 75, 2 => 99 },
2024 => { 1 => 77, 2 => 100 },
2025 => { 1 => 75, 2 => 102 },
+ 2026 => { "shared_ownership_initial_purchase" => 83, "discounted_ownership_scheme" => 112 },
}.freeze
end
diff --git a/app/models/form/sales/questions/management_fee.rb b/app/models/form/sales/questions/management_fee.rb
index 6519172cc..af7ff574f 100644
--- a/app/models/form/sales/questions/management_fee.rb
+++ b/app/models/form/sales/questions/management_fee.rb
@@ -8,9 +8,9 @@ class Form::Sales::Questions::ManagementFee < ::Form::Question
@step = 0.01
@width = 5
@prefix = "£"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@strip_commas = true
end
- QUESTION_NUMBER_FROM_YEAR = { 2025 => 89 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2025 => 89, 2026 => 97 }.freeze
end
diff --git a/app/models/form/sales/questions/managing_organisation.rb b/app/models/form/sales/questions/managing_organisation.rb
index 2079f37f5..995604eaa 100644
--- a/app/models/form/sales/questions/managing_organisation.rb
+++ b/app/models/form/sales/questions/managing_organisation.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::ManagingOrganisation < ::Form::Question
@id = "managing_organisation_id"
@derived = true
@type = "select"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
def answer_options(log = nil, user = nil)
@@ -72,5 +72,5 @@ private
true
end
- QUESTION_NUMBER_FROM_YEAR = { 2024 => 2, 2025 => 2 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2024 => 2, 2025 => 2, 2026 => 2 }.freeze
end
diff --git a/app/models/form/sales/questions/monthly_rent.rb b/app/models/form/sales/questions/monthly_rent.rb
index 7bd3c99bd..4cfaac93a 100644
--- a/app/models/form/sales/questions/monthly_rent.rb
+++ b/app/models/form/sales/questions/monthly_rent.rb
@@ -7,9 +7,9 @@ class Form::Sales::Questions::MonthlyRent < ::Form::Question
@step = 0.01
@width = 5
@prefix = "£"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@strip_commas = true
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 97, 2024 => 98, 2025 => 87 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 97, 2024 => 98, 2025 => 87, 2026 => 95 }.freeze
end
diff --git a/app/models/form/sales/questions/monthly_rent_after_staircasing.rb b/app/models/form/sales/questions/monthly_rent_after_staircasing.rb
index 6ae820a6b..53e178f3a 100644
--- a/app/models/form/sales/questions/monthly_rent_after_staircasing.rb
+++ b/app/models/form/sales/questions/monthly_rent_after_staircasing.rb
@@ -8,9 +8,9 @@ class Form::Sales::Questions::MonthlyRentAfterStaircasing < ::Form::Question
@step = 0.01
@width = 5
@prefix = "£"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@strip_commas = true
end
- QUESTION_NUMBER_FROM_YEAR = { 2025 => 101 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2025 => 101, 2026 => 109 }.freeze
end
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 ff72a378f..042e2be32 100644
--- a/app/models/form/sales/questions/monthly_rent_before_staircasing.rb
+++ b/app/models/form/sales/questions/monthly_rent_before_staircasing.rb
@@ -8,9 +8,9 @@ class Form::Sales::Questions::MonthlyRentBeforeStaircasing < ::Form::Question
@step = 0.01
@width = 5
@prefix = "£"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@strip_commas = true
end
- QUESTION_NUMBER_FROM_YEAR = { 2025 => 100 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2025 => 100, 2026 => 108 }.freeze
end
diff --git a/app/models/form/sales/questions/mortgage_amount.rb b/app/models/form/sales/questions/mortgage_amount.rb
index a61dce8f3..81549c011 100644
--- a/app/models/form/sales/questions/mortgage_amount.rb
+++ b/app/models/form/sales/questions/mortgage_amount.rb
@@ -1,6 +1,6 @@
class Form::Sales::Questions::MortgageAmount < ::Form::Question
- def initialize(id, hsh, subsection, ownershipsch:)
- super(id, hsh, subsection)
+ def initialize(id, hsh, page, ownershipsch:)
+ super(id, hsh, page)
@id = "mortgage"
@type = "numeric"
@min = 1
@@ -8,15 +8,16 @@ class Form::Sales::Questions::MortgageAmount < ::Form::Question
@width = 5
@prefix = "£"
@ownershipsch = ownershipsch
- @question_number = QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.fetch(form.start_date.year, QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.max_by { |k, _v| k }.last)[ownershipsch]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_SECTION, value_key: form.start_year_2026_or_later? ? subsection.id : ownershipsch)
@top_guidance_partial = top_guidance_partial
@strip_commas = true
end
- QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP = {
+ QUESTION_NUMBER_FROM_YEAR_AND_SECTION = {
2023 => { 1 => 91, 2 => 104, 3 => 112 },
2024 => { 1 => 92, 2 => 105, 3 => 113 },
2025 => { 1 => 83, 2 => 107 },
+ 2026 => { "shared_ownership_initial_purchase" => 91, "discounted_ownership_scheme" => 117 },
}.freeze
def derived?(log)
diff --git a/app/models/form/sales/questions/mortgage_length.rb b/app/models/form/sales/questions/mortgage_length.rb
index 493deb11d..cf21b349d 100644
--- a/app/models/form/sales/questions/mortgage_length.rb
+++ b/app/models/form/sales/questions/mortgage_length.rb
@@ -1,6 +1,6 @@
class Form::Sales::Questions::MortgageLength < ::Form::Question
- def initialize(id, hsh, subsection, ownershipsch:)
- super(id, hsh, subsection)
+ def initialize(id, hsh, page, ownershipsch:)
+ super(id, hsh, page)
@id = "mortlen"
@type = "numeric"
@min = 0
@@ -8,17 +8,17 @@ class Form::Sales::Questions::MortgageLength < ::Form::Question
@step = 1
@width = 5
@ownershipsch = ownershipsch
- @question_number = QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.fetch(form.start_date.year, QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.max_by { |k, _v| k }.last)[ownershipsch]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_SECTION, value_key: form.start_year_2026_or_later? ? subsection.id : ownershipsch)
end
def suffix_label(log)
" #{'year'.pluralize(log[id])}"
end
- QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP = {
+ QUESTION_NUMBER_FROM_YEAR_AND_SECTION = {
2023 => { 1 => 93, 2 => 106, 3 => 114 },
2024 => { 1 => 94, 2 => 107, 3 => 114 },
2025 => { 1 => 84, 2 => 108 },
- 2026 => { 1 => 84, 2 => 108 },
+ 2026 => { "shared_ownership_initial_purchase" => 92, "discounted_ownership_scheme" => 118 },
}.freeze
end
diff --git a/app/models/form/sales/questions/mortgage_length_known.rb b/app/models/form/sales/questions/mortgage_length_known.rb
index 5d2598771..b38071578 100644
--- a/app/models/form/sales/questions/mortgage_length_known.rb
+++ b/app/models/form/sales/questions/mortgage_length_known.rb
@@ -10,12 +10,12 @@ class Form::Sales::Questions::MortgageLengthKnown < ::Form::Question
{ "mortlen_known" => 0 },
],
}
- @question_number = QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.fetch(form.start_date.year, QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.max_by { |k, _v| k }.last)[ownershipsch]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_SECTION, value_key: form.start_year_2026_or_later? ? subsection.id : ownershipsch)
end
ANSWER_OPTIONS = { "0" => { "value" => "Yes" }, "1" => { "value" => "No" } }.freeze
- QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP = {
- 2026 => { 1 => 84, 2 => 108 },
+ QUESTION_NUMBER_FROM_YEAR_AND_SECTION = {
+ 2026 => { "shared_ownership_initial_purchase" => 92, "discounted_ownership_scheme" => 118 },
}.freeze
end
diff --git a/app/models/form/sales/questions/mortgageused.rb b/app/models/form/sales/questions/mortgageused.rb
index fc5818886..67fd900d3 100644
--- a/app/models/form/sales/questions/mortgageused.rb
+++ b/app/models/form/sales/questions/mortgageused.rb
@@ -1,18 +1,16 @@
class Form::Sales::Questions::Mortgageused < ::Form::Question
- def initialize(id, hsh, subsection, ownershipsch:)
- super(id, hsh, subsection)
+ def initialize(id, hsh, page, ownershipsch:)
+ super(id, hsh, page)
@id = "mortgageused"
@type = "radio"
@answer_options = ANSWER_OPTIONS
@ownershipsch = ownershipsch
- @question_number = question_number_from_year_and_ownership.fetch(form.start_date.year, question_number_from_year_and_ownership.max_by { |k, _v| k }.last)[ownershipsch]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_SECTION, value_key: form.start_year_2025_or_later? ? subsection.id : ownershipsch)
@top_guidance_partial = top_guidance_partial
end
def displayed_answer_options(log, _user = nil)
- if log.outright_sale? && log.saledate && !form.start_year_2024_or_later?
- answer_options_without_dont_know
- elsif log.stairowned_100? || log.outright_sale? || (log.is_staircase? && form.start_year_2025_or_later?)
+ if form.start_year_2026_or_later? || log.stairowned_100? || log.outright_sale? || (log.is_staircase? && form.start_year_2025_or_later?)
ANSWER_OPTIONS
else
answer_options_without_dont_know
@@ -30,13 +28,12 @@ class Form::Sales::Questions::Mortgageused < ::Form::Question
ANSWER_OPTIONS.reject { |key, _v| %w[3 divider].include?(key) }
end
- def question_number_from_year_and_ownership
- {
- 2023 => { 1 => 90, 2 => 103, 3 => 111 },
- 2024 => { 1 => 91, 2 => 104, 3 => 112 },
- 2025 => { 1 => subsection.id == "shared_ownership_staircasing_transaction" ? 99 : 82, 2 => 106 },
- }
- end
+ QUESTION_NUMBER_FROM_YEAR_AND_SECTION = {
+ 2023 => { 1 => 90, 2 => 103, 3 => 111 },
+ 2024 => { 1 => 91, 2 => 104, 3 => 112 },
+ 2025 => { "shared_ownership_initial_purchase" => 82, "shared_ownership_staircasing_transaction" => 99, "discounted_ownership_scheme" => 106 },
+ 2026 => { "shared_ownership_initial_purchase" => 90, "shared_ownership_staircasing_transaction" => 107, "discounted_ownership_scheme" => 116 },
+ }.freeze
def top_guidance_partial
return "financial_calculations_shared_ownership" if @ownershipsch == 1
diff --git a/app/models/form/sales/questions/nationality_all.rb b/app/models/form/sales/questions/nationality_all.rb
index 5610e0264..088e09f69 100644
--- a/app/models/form/sales/questions/nationality_all.rb
+++ b/app/models/form/sales/questions/nationality_all.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::NationalityAll < ::Form::Question
@answer_options = GlobalConstants::COUNTRIES_ANSWER_OPTIONS
@check_answers_card_number = buyer_index
@buyer_index = buyer_index
- @question_number = QUESTION_NUMBER_FROM_YEAR_AND_BUYER_INDEX.fetch(form.start_date.year, QUESTION_NUMBER_FROM_YEAR_AND_BUYER_INDEX.max_by { |k, _v| k }.last)[buyer_index]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_BUYER_INDEX, value_key: buyer_index)
end
def answer_label(log, _current_user = nil)
@@ -20,6 +20,7 @@ class Form::Sales::Questions::NationalityAll < ::Form::Question
2023 => { 1 => 24, 2 => 32 },
2024 => { 1 => 26, 2 => 34 },
2025 => { 1 => 24, 2 => 32 },
+ 2026 => { 1 => 26, 2 => 35 },
}.freeze
def label_from_value(value)
diff --git a/app/models/form/sales/questions/nationality_all_group.rb b/app/models/form/sales/questions/nationality_all_group.rb
index c8a8385f6..86ff68596 100644
--- a/app/models/form/sales/questions/nationality_all_group.rb
+++ b/app/models/form/sales/questions/nationality_all_group.rb
@@ -7,7 +7,7 @@ class Form::Sales::Questions::NationalityAllGroup < ::Form::Question
@conditional_for = buyer_index == 1 ? { "nationality_all" => [12] } : { "nationality_all_buyer2" => [12] }
@hidden_in_check_answers = { "depends_on" => [{ id => 12 }] }
@buyer_index = buyer_index
- @question_number = QUESTION_NUMBER_FROM_YEAR_AND_BUYER_INDEX.fetch(form.start_date.year, QUESTION_NUMBER_FROM_YEAR_AND_BUYER_INDEX.max_by { |k, _v| k }.last)[buyer_index]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_BUYER_INDEX, value_key: buyer_index)
end
ANSWER_OPTIONS = {
@@ -20,5 +20,6 @@ class Form::Sales::Questions::NationalityAllGroup < ::Form::Question
2023 => { 1 => 24, 2 => 32 },
2024 => { 1 => 26, 2 => 34 },
2025 => { 1 => 24, 2 => 32 },
+ 2026 => { 1 => 26, 2 => 35 },
}.freeze
end
diff --git a/app/models/form/sales/questions/new_service_charges.rb b/app/models/form/sales/questions/new_service_charges.rb
new file mode 100644
index 000000000..baf36fa42
--- /dev/null
+++ b/app/models/form/sales/questions/new_service_charges.rb
@@ -0,0 +1,17 @@
+class Form::Sales::Questions::NewServiceCharges < ::Form::Question
+ def initialize(id, hsh, page)
+ super
+ @id = "newservicecharges"
+ @type = "numeric"
+ @min = 0
+ @max = 9999.99
+ @step = 0.01
+ @width = 5
+ @prefix = "£"
+ @copy_key = "sales.sale_information.servicecharges_changed.new_service_charges"
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
+ @strip_commas = true
+ end
+
+ QUESTION_NUMBER_FROM_YEAR = { 2026 => 111 }.freeze
+end
diff --git a/app/models/form/sales/questions/number_joint_buyers.rb b/app/models/form/sales/questions/number_joint_buyers.rb
index 668dfa1a4..6382651bb 100644
--- a/app/models/form/sales/questions/number_joint_buyers.rb
+++ b/app/models/form/sales/questions/number_joint_buyers.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::NumberJointBuyers < ::Form::Question
@id = "jointmore"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -14,5 +14,5 @@ class Form::Sales::Questions::NumberJointBuyers < ::Form::Question
"3" => { "value" => "Don’t know" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 10, 2024 => 12, 2025 => 10 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 10, 2024 => 12, 2025 => 10, 2026 => 10 }.freeze
end
diff --git a/app/models/form/sales/questions/number_of_others_in_property.rb b/app/models/form/sales/questions/number_of_others_in_property.rb
index 9ff4e44be..ffb692cc0 100644
--- a/app/models/form/sales/questions/number_of_others_in_property.rb
+++ b/app/models/form/sales/questions/number_of_others_in_property.rb
@@ -5,11 +5,11 @@ class Form::Sales::Questions::NumberOfOthersInProperty < ::Form::Question
@copy_key = joint_purchase ? "sales.household_characteristics.hholdcount.joint_purchase" : "sales.household_characteristics.hholdcount.not_joint_purchase"
@type = "numeric"
@width = 2
- @min = 0
+ @min = form.start_year_2026_or_later? ? 1 : 0
@max = 15
@step = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 35, 2024 => 37, 2025 => 35 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 35, 2024 => 37, 2025 => 35, 2026 => 38 }.freeze
end
diff --git a/app/models/form/sales/questions/other_ownership_type.rb b/app/models/form/sales/questions/other_ownership_type.rb
index 84742b7ea..e516f045d 100644
--- a/app/models/form/sales/questions/other_ownership_type.rb
+++ b/app/models/form/sales/questions/other_ownership_type.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::OtherOwnershipType < ::Form::Question
@copy_key = "sales.setup.type.outright_ownership.othtype"
@type = "text"
@width = 10
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
QUESTION_NUMBER_FROM_YEAR = { 2023 => 6, 2024 => 8 }.freeze
diff --git a/app/models/form/sales/questions/outright_ownership_type.rb b/app/models/form/sales/questions/outright_ownership_type.rb
index f56b63d78..d944963e7 100644
--- a/app/models/form/sales/questions/outright_ownership_type.rb
+++ b/app/models/form/sales/questions/outright_ownership_type.rb
@@ -9,7 +9,7 @@ class Form::Sales::Questions::OutrightOwnershipType < ::Form::Question
@conditional_for = {
"othtype" => [12],
}
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
diff --git a/app/models/form/sales/questions/ownership_scheme.rb b/app/models/form/sales/questions/ownership_scheme.rb
index 09d96c2fe..6b938b57c 100644
--- a/app/models/form/sales/questions/ownership_scheme.rb
+++ b/app/models/form/sales/questions/ownership_scheme.rb
@@ -3,7 +3,7 @@ class Form::Sales::Questions::OwnershipScheme < ::Form::Question
super
@id = "ownershipsch"
@type = "radio"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
def answer_options
@@ -27,5 +27,5 @@ class Form::Sales::Questions::OwnershipScheme < ::Form::Question
end
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 3, 2024 => 5 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 3, 2024 => 5, 2025 => 5, 2026 => 5 }.freeze
end
diff --git a/app/models/form/sales/questions/owning_organisation_id.rb b/app/models/form/sales/questions/owning_organisation_id.rb
index 54afdb123..902d2ff29 100644
--- a/app/models/form/sales/questions/owning_organisation_id.rb
+++ b/app/models/form/sales/questions/owning_organisation_id.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::OwningOrganisationId < ::Form::Question
@id = "owning_organisation_id"
@derived = true
@type = "select"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
def answer_options(log = nil, user = nil)
@@ -93,5 +93,5 @@ private
"#{name} (inactive as of #{merge_date.to_fs(:govuk_date)})"
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => nil, 2024 => 1, 2025 => 1 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2024 => 1, 2025 => 1, 2026 => 1 }.freeze
end
diff --git a/app/models/form/sales/questions/person_age.rb b/app/models/form/sales/questions/person_age.rb
index 0e570d649..fe38d38e3 100644
--- a/app/models/form/sales/questions/person_age.rb
+++ b/app/models/form/sales/questions/person_age.rb
@@ -13,13 +13,8 @@ class Form::Sales::Questions::PersonAge < ::Form::Question
@max = 110
@step = 1
@person_index = person_index
- @question_number = question_number
+ @question_number = get_person_question_number(BASE_QUESTION_NUMBERS)
end
- BASE_QUESTION_NUMBERS = { 2023 => 29, 2024 => 31, 2025 => 29 }.freeze
- def question_number
- base_question_number = BASE_QUESTION_NUMBERS[form.start_date.year] || BASE_QUESTION_NUMBERS[BASE_QUESTION_NUMBERS.keys.max]
-
- base_question_number + (4 * @person_index)
- end
+ BASE_QUESTION_NUMBERS = { 2023 => 29, 2024 => 31, 2025 => 29, 2026 => 30 }.freeze
end
diff --git a/app/models/form/sales/questions/person_age_known.rb b/app/models/form/sales/questions/person_age_known.rb
index d3b3a8350..18c0a5455 100644
--- a/app/models/form/sales/questions/person_age_known.rb
+++ b/app/models/form/sales/questions/person_age_known.rb
@@ -27,10 +27,10 @@ class Form::Sales::Questions::PersonAgeKnown < ::Form::Question
"1" => { "value" => "No" },
}.freeze
- BASE_QUESTION_NUMBERS = { 2023 => 29, 2024 => 31, 2025 => 29 }.freeze
+ BASE_QUESTION_NUMBERS = { 2023 => 29, 2024 => 31, 2025 => 29, 2026 => 30 }.freeze
def question_number
base_question_number = BASE_QUESTION_NUMBERS[form.start_date.year] || BASE_QUESTION_NUMBERS[BASE_QUESTION_NUMBERS.keys.max]
- base_question_number + (4 * @person_index)
+ base_question_number + (form.person_question_count * @person_index)
end
end
diff --git a/app/models/form/sales/questions/person_gender_identity.rb b/app/models/form/sales/questions/person_gender_identity.rb
index 5682a2b95..ce4c4e0ef 100644
--- a/app/models/form/sales/questions/person_gender_identity.rb
+++ b/app/models/form/sales/questions/person_gender_identity.rb
@@ -12,7 +12,7 @@ class Form::Sales::Questions::PersonGenderIdentity < ::Form::Question
"value" => "Prefers not to say",
}]
@person_index = person_index
- @question_number = question_number
+ @question_number = get_person_question_number(BASE_QUESTION_NUMBERS)
end
ANSWER_OPTIONS = {
@@ -23,9 +23,4 @@ class Form::Sales::Questions::PersonGenderIdentity < ::Form::Question
}.freeze
BASE_QUESTION_NUMBERS = { 2023 => 30, 2024 => 32, 2025 => 30 }.freeze
- def question_number
- base_question_number = BASE_QUESTION_NUMBERS[form.start_date.year] || BASE_QUESTION_NUMBERS[BASE_QUESTION_NUMBERS.keys.max]
-
- base_question_number + (4 * @person_index)
- end
end
diff --git a/app/models/form/sales/questions/person_relationship_to_buyer_1.rb b/app/models/form/sales/questions/person_relationship_to_buyer_1.rb
index 9ac0791a4..be8f0974c 100644
--- a/app/models/form/sales/questions/person_relationship_to_buyer_1.rb
+++ b/app/models/form/sales/questions/person_relationship_to_buyer_1.rb
@@ -41,6 +41,6 @@ class Form::Sales::Questions::PersonRelationshipToBuyer1 < ::Form::Question
30
end
- base_question_number + (4 * @person_index)
+ base_question_number + (form.person_question_count * @person_index)
end
end
diff --git a/app/models/form/sales/questions/person_relationship_to_buyer_1_yes_no.rb b/app/models/form/sales/questions/person_relationship_to_buyer_1_yes_no.rb
index 11086b877..480b4a31e 100644
--- a/app/models/form/sales/questions/person_relationship_to_buyer_1_yes_no.rb
+++ b/app/models/form/sales/questions/person_relationship_to_buyer_1_yes_no.rb
@@ -16,14 +16,8 @@ class Form::Sales::Questions::PersonRelationshipToBuyer1YesNo < ::Form::Question
}]
@check_answers_card_number = person_index
@person_index = person_index
- @question_number = question_number
+ @question_number = get_person_question_number(BASE_QUESTION_NUMBERS)
end
- def question_number
- base_question_number = BASE_QUESTION_NUMBERS[form.start_date.year] || BASE_QUESTION_NUMBERS[BASE_QUESTION_NUMBERS.keys.max]
-
- base_question_number + (4 * @person_index)
- end
-
- BASE_QUESTION_NUMBERS = { 2025 => 28 }.freeze
+ BASE_QUESTION_NUMBERS = { 2025 => 28, 2026 => 29 }.freeze
end
diff --git a/app/models/form/sales/questions/person_sex_registered_at_birth.rb b/app/models/form/sales/questions/person_sex_registered_at_birth.rb
index 2ea4e35df..0828dbbcf 100644
--- a/app/models/form/sales/questions/person_sex_registered_at_birth.rb
+++ b/app/models/form/sales/questions/person_sex_registered_at_birth.rb
@@ -5,7 +5,8 @@ class Form::Sales::Questions::PersonSexRegisteredAtBirth < ::Form::Question
@copy_key = "sales.household_characteristics.sexrab2.person" if person_index == 2
@check_answers_card_number = person_index
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @person_index = person_index
+ @question_number = get_person_question_number(BASE_QUESTION_NUMBERS)
end
ANSWER_OPTIONS = {
@@ -15,7 +16,7 @@ class Form::Sales::Questions::PersonSexRegisteredAtBirth < ::Form::Question
"R" => { "value" => "Person prefers not to say" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2026 => 0 }.freeze
+ BASE_QUESTION_NUMBERS = { 2023 => 30, 2024 => 32, 2025 => 31, 2026 => 31 }.freeze
def label_from_value(value, _log = nil, _user = nil)
return unless value
diff --git a/app/models/form/sales/questions/person_working_situation.rb b/app/models/form/sales/questions/person_working_situation.rb
index 39c18a22a..dd4743811 100644
--- a/app/models/form/sales/questions/person_working_situation.rb
+++ b/app/models/form/sales/questions/person_working_situation.rb
@@ -11,7 +11,7 @@ class Form::Sales::Questions::PersonWorkingSituation < ::Form::Question
"value" => "Prefers not to say",
}]
@person_index = person_index
- @question_number = question_number
+ @question_number = get_person_question_number(BASE_QUESTION_NUMBERS)
@answer_options = answer_options
end
@@ -63,10 +63,5 @@ class Form::Sales::Questions::PersonWorkingSituation < ::Form::Question
end
end
- BASE_QUESTION_NUMBERS = { 2023 => 31, 2024 => 33, 2025 => 31 }.freeze
- def question_number
- base_question_number = BASE_QUESTION_NUMBERS[form.start_date.year] || BASE_QUESTION_NUMBERS[BASE_QUESTION_NUMBERS.keys.max]
-
- base_question_number + (4 * @person_index)
- end
+ BASE_QUESTION_NUMBERS = { 2023 => 31, 2024 => 33, 2025 => 31, 2026 => 33 }.freeze
end
diff --git a/app/models/form/sales/questions/postcode_for_full_address.rb b/app/models/form/sales/questions/postcode_for_full_address.rb
index e99ec108b..49170c07c 100644
--- a/app/models/form/sales/questions/postcode_for_full_address.rb
+++ b/app/models/form/sales/questions/postcode_for_full_address.rb
@@ -18,10 +18,10 @@ class Form::Sales::Questions::PostcodeForFullAddress < ::Form::Question
}
@plain_label = true
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@hide_question_number_on_page = true
@bottom_guidance_partial = "address_fallback"
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 15, 2024 => 16, 2025 => 14 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 15, 2024 => 16, 2025 => 14, 2026 => 14 }.freeze
end
diff --git a/app/models/form/sales/questions/previous_bedrooms.rb b/app/models/form/sales/questions/previous_bedrooms.rb
index ad6efd971..2051e4cf7 100644
--- a/app/models/form/sales/questions/previous_bedrooms.rb
+++ b/app/models/form/sales/questions/previous_bedrooms.rb
@@ -7,8 +7,8 @@ class Form::Sales::Questions::PreviousBedrooms < ::Form::Question
@min = 1
@max = 6
@step = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 85, 2024 => 86, 2025 => 77 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 85, 2024 => 86, 2025 => 77, 2026 => 85 }.freeze
end
diff --git a/app/models/form/sales/questions/previous_la_known.rb b/app/models/form/sales/questions/previous_la_known.rb
index 21104e3e2..6f4bd4478 100644
--- a/app/models/form/sales/questions/previous_la_known.rb
+++ b/app/models/form/sales/questions/previous_la_known.rb
@@ -18,7 +18,7 @@ class Form::Sales::Questions::PreviousLaKnown < ::Form::Question
@conditional_for = {
"prevloc" => [1],
}
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
@@ -27,5 +27,5 @@ class Form::Sales::Questions::PreviousLaKnown < ::Form::Question
"0" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 58, 2024 => 60, 2025 => 58 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 58, 2024 => 60, 2025 => 58, 2026 => 66 }.freeze
end
diff --git a/app/models/form/sales/questions/previous_postcode.rb b/app/models/form/sales/questions/previous_postcode.rb
index 7d8ecb072..d8fbc9b48 100644
--- a/app/models/form/sales/questions/previous_postcode.rb
+++ b/app/models/form/sales/questions/previous_postcode.rb
@@ -16,9 +16,9 @@ class Form::Sales::Questions::PreviousPostcode < ::Form::Question
"is_previous_la_inferred" => true,
},
}
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 57, 2024 => 59, 2025 => 57 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 57, 2024 => 59, 2025 => 57, 2026 => 65 }.freeze
end
diff --git a/app/models/form/sales/questions/previous_postcode_known.rb b/app/models/form/sales/questions/previous_postcode_known.rb
index 0baa33f58..4e70b7ef2 100644
--- a/app/models/form/sales/questions/previous_postcode_known.rb
+++ b/app/models/form/sales/questions/previous_postcode_known.rb
@@ -18,7 +18,7 @@ class Form::Sales::Questions::PreviousPostcodeKnown < ::Form::Question
},
],
}
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
@@ -27,5 +27,5 @@ class Form::Sales::Questions::PreviousPostcodeKnown < ::Form::Question
"1" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 57, 2024 => 59, 2025 => 57 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 57, 2024 => 59, 2025 => 57, 2026 => 65 }.freeze
end
diff --git a/app/models/form/sales/questions/previous_tenure.rb b/app/models/form/sales/questions/previous_tenure.rb
index 42053f833..0e845cfe6 100644
--- a/app/models/form/sales/questions/previous_tenure.rb
+++ b/app/models/form/sales/questions/previous_tenure.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::PreviousTenure < ::Form::Question
@type = "radio"
@page = page
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -17,5 +17,5 @@ class Form::Sales::Questions::PreviousTenure < ::Form::Question
"10" => { "value" => "Don’t know" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 87, 2024 => 88, 2025 => 79 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 87, 2024 => 88, 2025 => 79, 2026 => 87 }.freeze
end
diff --git a/app/models/form/sales/questions/previous_tenure_buyer2.rb b/app/models/form/sales/questions/previous_tenure_buyer2.rb
index 5723088d7..71629252b 100644
--- a/app/models/form/sales/questions/previous_tenure_buyer2.rb
+++ b/app/models/form/sales/questions/previous_tenure_buyer2.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::PreviousTenureBuyer2 < ::Form::Question
@id = "prevtenbuy2"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -20,5 +20,5 @@ class Form::Sales::Questions::PreviousTenureBuyer2 < ::Form::Question
"0" => { "value" => "Don’t know" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 61, 2024 => 63, 2025 => 60 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 61, 2024 => 63, 2025 => 60, 2026 => 68 }.freeze
end
diff --git a/app/models/form/sales/questions/prevloc.rb b/app/models/form/sales/questions/prevloc.rb
index 95a34ef55..e516d78c4 100644
--- a/app/models/form/sales/questions/prevloc.rb
+++ b/app/models/form/sales/questions/prevloc.rb
@@ -10,7 +10,7 @@ class Form::Sales::Questions::Prevloc < ::Form::Question
},
"value" => "Not known",
}]
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
@@ -18,5 +18,5 @@ class Form::Sales::Questions::Prevloc < ::Form::Question
{ "" => "Select an option" }.merge(LocalAuthority.active(form.start_date).map { |la| [la.code, la.name] }.to_h)
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 58, 2024 => 60, 2025 => 58 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 58, 2024 => 60, 2025 => 58, 2026 => 66 }.freeze
end
diff --git a/app/models/form/sales/questions/prevown.rb b/app/models/form/sales/questions/prevown.rb
index 25f852bdc..922d55546 100644
--- a/app/models/form/sales/questions/prevown.rb
+++ b/app/models/form/sales/questions/prevown.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::Prevown < ::Form::Question
@copy_key = "sales.income_benefits_and_savings.prevown.#{joint_purchase ? 'joint_purchase' : 'not_joint_purchase'}"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -15,5 +15,5 @@ class Form::Sales::Questions::Prevown < ::Form::Question
"3" => { "value" => "Don’t know" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 73, 2024 => 75, 2025 => 72 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 73, 2024 => 75, 2025 => 72, 2026 => 80 }.freeze
end
diff --git a/app/models/form/sales/questions/prevshared.rb b/app/models/form/sales/questions/prevshared.rb
index f4ca3b1ff..8d6902119 100644
--- a/app/models/form/sales/questions/prevshared.rb
+++ b/app/models/form/sales/questions/prevshared.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::Prevshared < ::Form::Question
@id = "prevshared"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -14,5 +14,5 @@ class Form::Sales::Questions::Prevshared < ::Form::Question
"3" => { "value" => "Don’t know" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 74, 2024 => 76, 2025 => 73 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 74, 2024 => 76, 2025 => 73, 2026 => 81 }.freeze
end
diff --git a/app/models/form/sales/questions/privacy_notice.rb b/app/models/form/sales/questions/privacy_notice.rb
index 3ce2606ed..aac52baca 100644
--- a/app/models/form/sales/questions/privacy_notice.rb
+++ b/app/models/form/sales/questions/privacy_notice.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::PrivacyNotice < ::Form::Question
@id = "privacynotice"
@copy_key = "sales.#{subsection.copy_key}.privacynotice.#{joint_purchase ? 'joint_purchase' : 'not_joint_purchase'}"
@type = "checkbox"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@joint_purchase = joint_purchase
@top_guidance_partial = guidance
end
@@ -32,5 +32,5 @@ class Form::Sales::Questions::PrivacyNotice < ::Form::Question
@joint_purchase ? "privacy_notice_buyer_joint_purchase" : "privacy_notice_buyer"
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 19, 2024 => 14, 2025 => 12 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 19, 2024 => 14, 2025 => 12, 2026 => 12 }.freeze
end
diff --git a/app/models/form/sales/questions/property_building_type.rb b/app/models/form/sales/questions/property_building_type.rb
index 4af2f1b39..a1bc3a7d8 100644
--- a/app/models/form/sales/questions/property_building_type.rb
+++ b/app/models/form/sales/questions/property_building_type.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::PropertyBuildingType < ::Form::Question
@copy_key = "sales.property_information.builtype"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -13,5 +13,5 @@ class Form::Sales::Questions::PropertyBuildingType < ::Form::Question
"2" => { "value" => "Converted from previous residential or non-residential property" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 13, 2024 => 20, 2025 => 18 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 13, 2024 => 20, 2025 => 18, 2026 => 19 }.freeze
end
diff --git a/app/models/form/sales/questions/property_local_authority.rb b/app/models/form/sales/questions/property_local_authority.rb
index 294c29172..a4848ec6d 100644
--- a/app/models/form/sales/questions/property_local_authority.rb
+++ b/app/models/form/sales/questions/property_local_authority.rb
@@ -3,7 +3,7 @@ class Form::Sales::Questions::PropertyLocalAuthority < ::Form::Question
super
@id = "la"
@type = "select"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
end
@@ -15,5 +15,5 @@ class Form::Sales::Questions::PropertyLocalAuthority < ::Form::Question
log.saledate && log.saledate.year >= 2023 && log.is_la_inferred?
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 16, 2024 => 17, 2025 => 15 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 16, 2024 => 17, 2025 => 15, 2026 => 15 }.freeze
end
diff --git a/app/models/form/sales/questions/property_number_of_bedrooms.rb b/app/models/form/sales/questions/property_number_of_bedrooms.rb
index 734891d4a..3d130b1c8 100644
--- a/app/models/form/sales/questions/property_number_of_bedrooms.rb
+++ b/app/models/form/sales/questions/property_number_of_bedrooms.rb
@@ -8,8 +8,8 @@ class Form::Sales::Questions::PropertyNumberOfBedrooms < ::Form::Question
@min = 1
@max = 9
@step = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 11, 2024 => 18, 2025 => 17 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 11, 2024 => 18, 2025 => 17, 2026 => 18 }.freeze
end
diff --git a/app/models/form/sales/questions/property_unit_type.rb b/app/models/form/sales/questions/property_unit_type.rb
index 3602d0293..9854b5c81 100644
--- a/app/models/form/sales/questions/property_unit_type.rb
+++ b/app/models/form/sales/questions/property_unit_type.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::PropertyUnitType < ::Form::Question
@copy_key = "sales.property_information.proptype"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -16,5 +16,5 @@ class Form::Sales::Questions::PropertyUnitType < ::Form::Question
"9" => { "value" => "Other" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 12, 2024 => 19, 2025 => 16 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 12, 2024 => 19, 2025 => 16, 2026 => 16 }.freeze
end
diff --git a/app/models/form/sales/questions/property_wheelchair_accessible.rb b/app/models/form/sales/questions/property_wheelchair_accessible.rb
index 17c99d9c5..2858fb0c0 100644
--- a/app/models/form/sales/questions/property_wheelchair_accessible.rb
+++ b/app/models/form/sales/questions/property_wheelchair_accessible.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::PropertyWheelchairAccessible < ::Form::Question
@copy_key = "sales.property_information.wchair"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -15,5 +15,5 @@ class Form::Sales::Questions::PropertyWheelchairAccessible < ::Form::Question
"3" => { "value" => "Don’t know" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 17, 2024 => 21, 2025 => 19 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 17, 2024 => 21, 2025 => 19, 2026 => 20 }.freeze
end
diff --git a/app/models/form/sales/questions/purchase_price.rb b/app/models/form/sales/questions/purchase_price.rb
index d37d549ce..24aecd7ec 100644
--- a/app/models/form/sales/questions/purchase_price.rb
+++ b/app/models/form/sales/questions/purchase_price.rb
@@ -3,20 +3,21 @@ class Form::Sales::Questions::PurchasePrice < ::Form::Question
super(id, hsh, page)
@id = "value"
@type = "numeric"
- @min = 0
+ @min = form.start_year_2026_or_later? ? 15_000 : 0
@step = 0.01
@width = 5
@prefix = "£"
@ownership_sch = ownershipsch
- @question_number = QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.fetch(form.start_date.year, QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP.max_by { |k, _v| k }.last)[ownershipsch]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_SECTION, value_key: form.start_year_2026_or_later? ? subsection.id : ownershipsch)
@top_guidance_partial = top_guidance_partial
@strip_commas = true
end
- QUESTION_NUMBER_FROM_YEAR_AND_OWNERSHIP = {
+ QUESTION_NUMBER_FROM_YEAR_AND_SECTION = {
2023 => { 2 => 100, 3 => 110 },
2024 => { 2 => 101, 3 => 111 },
2025 => { 2 => 103 },
+ 2026 => { "discounted_ownership_scheme" => 113 },
}.freeze
def copy_key
diff --git a/app/models/form/sales/questions/purchaser_code.rb b/app/models/form/sales/questions/purchaser_code.rb
index fd3b126e9..4eb8259e6 100644
--- a/app/models/form/sales/questions/purchaser_code.rb
+++ b/app/models/form/sales/questions/purchaser_code.rb
@@ -4,8 +4,8 @@ class Form::Sales::Questions::PurchaserCode < ::Form::Question
@id = "purchid"
@type = "text"
@width = 10
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 2, 2024 => 4 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 2, 2024 => 4, 2025 => 4, 2026 => 4 }.freeze
end
diff --git a/app/models/form/sales/questions/resale.rb b/app/models/form/sales/questions/resale.rb
index 7c030079e..c0fcb6059 100644
--- a/app/models/form/sales/questions/resale.rb
+++ b/app/models/form/sales/questions/resale.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::Resale < ::Form::Question
@id = "resale"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -12,5 +12,5 @@ class Form::Sales::Questions::Resale < ::Form::Question
"2" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 80, 2024 => 82, 2025 => 74 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 80, 2024 => 82, 2025 => 74, 2026 => 82 }.freeze
end
diff --git a/app/models/form/sales/questions/sale_date.rb b/app/models/form/sales/questions/sale_date.rb
index a60a5eddf..8878a9ff2 100644
--- a/app/models/form/sales/questions/sale_date.rb
+++ b/app/models/form/sales/questions/sale_date.rb
@@ -3,8 +3,8 @@ class Form::Sales::Questions::SaleDate < ::Form::Question
super
@id = "saledate"
@type = "date"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 1, 2024 => 3, 2025 => 3 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 1, 2024 => 3, 2025 => 3, 2026 => 3 }.freeze
end
diff --git a/app/models/form/sales/questions/savings.rb b/app/models/form/sales/questions/savings.rb
index 6a6cb3893..fd351ae23 100644
--- a/app/models/form/sales/questions/savings.rb
+++ b/app/models/form/sales/questions/savings.rb
@@ -8,9 +8,9 @@ class Form::Sales::Questions::Savings < ::Form::Question
@prefix = "£"
@step = 10
@min = 0
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@strip_commas = true
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 72, 2024 => 74, 2025 => 71 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 72, 2024 => 74, 2025 => 71, 2026 => 79 }.freeze
end
diff --git a/app/models/form/sales/questions/savings_nk.rb b/app/models/form/sales/questions/savings_nk.rb
index 6aaf6de5e..f3e2220a5 100644
--- a/app/models/form/sales/questions/savings_nk.rb
+++ b/app/models/form/sales/questions/savings_nk.rb
@@ -15,7 +15,7 @@ class Form::Sales::Questions::SavingsNk < ::Form::Question
},
],
}
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -23,5 +23,5 @@ class Form::Sales::Questions::SavingsNk < ::Form::Question
"1" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 72, 2024 => 74, 2025 => 71 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 72, 2024 => 74, 2025 => 71, 2026 => 79 }.freeze
end
diff --git a/app/models/form/sales/questions/service_charge.rb b/app/models/form/sales/questions/service_charge.rb
index f3aec4a2b..2fc0d45f0 100644
--- a/app/models/form/sales/questions/service_charge.rb
+++ b/app/models/form/sales/questions/service_charge.rb
@@ -1,6 +1,6 @@
class Form::Sales::Questions::ServiceCharge < ::Form::Question
- def initialize(id, hsh, subsection, staircasing:)
- super(id, hsh, subsection)
+ def initialize(id, hsh, page, staircasing:)
+ super(id, hsh, page)
@id = "mscharge"
@type = "numeric"
@min = 1
@@ -10,15 +10,12 @@ class Form::Sales::Questions::ServiceCharge < ::Form::Question
@prefix = "£"
@copy_key = "sales.sale_information.servicecharges.servicecharge"
@staircasing = staircasing
- @question_number = question_number_from_year[form.start_date.year] || question_number_from_year[question_number_from_year.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_SECTION, value_key: subsection.id)
@strip_commas = true
end
- def question_number_from_year
- if @staircasing
- { 2026 => 0 }.freeze
- else
- { 2025 => 88, 2026 => 0 }.freeze
- end
- end
+ QUESTION_NUMBER_FROM_YEAR_AND_SECTION = {
+ 2025 => 88,
+ 2026 => { "shared_ownership_initial_purchase" => 96, "shared_ownership_staircasing_transaction" => 110 },
+ }.freeze
end
diff --git a/app/models/form/sales/questions/sex_registered_at_birth1.rb b/app/models/form/sales/questions/sex_registered_at_birth1.rb
index 23a1e65c2..ebc67c71e 100644
--- a/app/models/form/sales/questions/sex_registered_at_birth1.rb
+++ b/app/models/form/sales/questions/sex_registered_at_birth1.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::SexRegisteredAtBirth1 < ::Form::Question
@type = "radio"
@check_answers_card_number = 1
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -15,7 +15,7 @@ class Form::Sales::Questions::SexRegisteredAtBirth1 < ::Form::Question
"R" => { "value" => "Buyer prefers not to say" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2026 => 0 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2026 => 22 }.freeze
def label_from_value(value, _log = nil, _user = nil)
return unless value
diff --git a/app/models/form/sales/questions/sex_registered_at_birth2.rb b/app/models/form/sales/questions/sex_registered_at_birth2.rb
index 5c8f2b3a6..4f9a48612 100644
--- a/app/models/form/sales/questions/sex_registered_at_birth2.rb
+++ b/app/models/form/sales/questions/sex_registered_at_birth2.rb
@@ -6,7 +6,7 @@ class Form::Sales::Questions::SexRegisteredAtBirth2 < ::Form::Question
@copy_key = "sales.household_characteristics.sexrab2.buyer"
@check_answers_card_number = 2
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -16,7 +16,7 @@ class Form::Sales::Questions::SexRegisteredAtBirth2 < ::Form::Question
"R" => { "value" => "Buyer prefers not to say" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2026 => 0 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2026 => 31 }.freeze
def label_from_value(value, _log = nil, _user = nil)
return unless value
diff --git a/app/models/form/sales/questions/shared_ownership_type.rb b/app/models/form/sales/questions/shared_ownership_type.rb
index 9ac998313..ee226b26c 100644
--- a/app/models/form/sales/questions/shared_ownership_type.rb
+++ b/app/models/form/sales/questions/shared_ownership_type.rb
@@ -6,7 +6,7 @@ class Form::Sales::Questions::SharedOwnershipType < ::Form::Question
@top_guidance_partial = "shared_ownership_type_definitions"
@type = "radio"
@answer_options = answer_options
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
def answer_options
@@ -34,5 +34,5 @@ class Form::Sales::Questions::SharedOwnershipType < ::Form::Question
end
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 4, 2024 => 6 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 4, 2024 => 6, 2025 => 6, 2026 => 6 }.freeze
end
diff --git a/app/models/form/sales/questions/staircase.rb b/app/models/form/sales/questions/staircase.rb
index 4d925ec3f..d55a8dfa7 100644
--- a/app/models/form/sales/questions/staircase.rb
+++ b/app/models/form/sales/questions/staircase.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::Staircase < ::Form::Question
@id = "staircase"
@copy_key = "sales.#{page.subsection.copy_key}.staircasing"
@type = "radio"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
def answer_options
@@ -23,5 +23,5 @@ class Form::Sales::Questions::Staircase < ::Form::Question
end
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 76, 2024 => 78, 2025 => 7 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 76, 2024 => 78, 2025 => 7, 2026 => 7 }.freeze
end
diff --git a/app/models/form/sales/questions/staircase_bought.rb b/app/models/form/sales/questions/staircase_bought.rb
index e13a9c9f3..87e9d5ab0 100644
--- a/app/models/form/sales/questions/staircase_bought.rb
+++ b/app/models/form/sales/questions/staircase_bought.rb
@@ -9,9 +9,9 @@ class Form::Sales::Questions::StaircaseBought < ::Form::Question
@max = 100
@step = 0.1
@suffix = "%"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@top_guidance_partial = "financial_calculations_shared_ownership"
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 77, 2024 => 79, 2025 => 90 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 77, 2024 => 79, 2025 => 90, 2026 => 98 }.freeze
end
diff --git a/app/models/form/sales/questions/staircase_count.rb b/app/models/form/sales/questions/staircase_count.rb
index 76d56a823..50d217412 100644
--- a/app/models/form/sales/questions/staircase_count.rb
+++ b/app/models/form/sales/questions/staircase_count.rb
@@ -8,8 +8,8 @@ class Form::Sales::Questions::StaircaseCount < ::Form::Question
@min = 2
@max = 10
@step = 1
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
- QUESTION_NUMBER_FROM_YEAR = { 2025 => 94 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2025 => 94, 2026 => 102 }.freeze
end
diff --git a/app/models/form/sales/questions/staircase_first_time.rb b/app/models/form/sales/questions/staircase_first_time.rb
index bf532ae6e..dceff17b9 100644
--- a/app/models/form/sales/questions/staircase_first_time.rb
+++ b/app/models/form/sales/questions/staircase_first_time.rb
@@ -4,7 +4,7 @@ class Form::Sales::Questions::StaircaseFirstTime < ::Form::Question
@id = "firststair"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -12,5 +12,5 @@ class Form::Sales::Questions::StaircaseFirstTime < ::Form::Question
"2" => { "value" => "No" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2025 => 93 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2025 => 93, 2026 => 101 }.freeze
end
diff --git a/app/models/form/sales/questions/staircase_initial_date.rb b/app/models/form/sales/questions/staircase_initial_date.rb
index dc4b54308..eb03a8b2f 100644
--- a/app/models/form/sales/questions/staircase_initial_date.rb
+++ b/app/models/form/sales/questions/staircase_initial_date.rb
@@ -4,8 +4,8 @@ class Form::Sales::Questions::StaircaseInitialDate < ::Form::Question
@id = "initialpurchase"
@copy_key = "sales.sale_information.stairprevious.initialpurchase"
@type = "date"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
- QUESTION_NUMBER_FROM_YEAR = { 2025 => 96 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2025 => 96, 2026 => 104 }.freeze
end
diff --git a/app/models/form/sales/questions/staircase_last_date.rb b/app/models/form/sales/questions/staircase_last_date.rb
index 31e2dff55..2dcf94f45 100644
--- a/app/models/form/sales/questions/staircase_last_date.rb
+++ b/app/models/form/sales/questions/staircase_last_date.rb
@@ -4,8 +4,8 @@ class Form::Sales::Questions::StaircaseLastDate < ::Form::Question
@id = "lasttransaction"
@copy_key = "sales.sale_information.stairprevious.lasttransaction"
@type = "date"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
- QUESTION_NUMBER_FROM_YEAR = { 2025 => 95 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2025 => 95, 2026 => 103 }.freeze
end
diff --git a/app/models/form/sales/questions/staircase_owned.rb b/app/models/form/sales/questions/staircase_owned.rb
index 6bcdc829d..f2cac1b23 100644
--- a/app/models/form/sales/questions/staircase_owned.rb
+++ b/app/models/form/sales/questions/staircase_owned.rb
@@ -9,8 +9,8 @@ class Form::Sales::Questions::StaircaseOwned < ::Form::Question
@max = 100
@step = 0.1
@suffix = "%"
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 78, 2024 => 80, 2025 => 91 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 78, 2024 => 80, 2025 => 91, 2026 => 99 }.freeze
end
diff --git a/app/models/form/sales/questions/staircase_sale.rb b/app/models/form/sales/questions/staircase_sale.rb
index 3ea2ca38d..22fbf7e0b 100644
--- a/app/models/form/sales/questions/staircase_sale.rb
+++ b/app/models/form/sales/questions/staircase_sale.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::StaircaseSale < ::Form::Question
@copy_key = form.start_year_2025_or_later? ? "sales.sale_information.staircasesale" : "sales.sale_information.about_staircasing.staircasesale"
@type = "radio"
@answer_options = ANSWER_OPTIONS
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -15,5 +15,5 @@ class Form::Sales::Questions::StaircaseSale < ::Form::Question
"3" => { "value" => "Don’t know" },
}.freeze
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 79, 2024 => 81, 2025 => 92 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 79, 2024 => 81, 2025 => 92, 2026 => 100 }.freeze
end
diff --git a/app/models/form/sales/questions/town_or_city.rb b/app/models/form/sales/questions/town_or_city.rb
index 7f2762689..6483a6780 100644
--- a/app/models/form/sales/questions/town_or_city.rb
+++ b/app/models/form/sales/questions/town_or_city.rb
@@ -6,9 +6,9 @@ class Form::Sales::Questions::TownOrCity < ::Form::Question
@type = "text"
@plain_label = true
@disable_clearing_if_not_routed_or_dynamic_answer_options = true
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@hide_question_number_on_page = true
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 15, 2024 => 16, 2025 => 14 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 15, 2024 => 16, 2025 => 14, 2026 => 14 }.freeze
end
diff --git a/app/models/form/sales/questions/uprn.rb b/app/models/form/sales/questions/uprn.rb
index 715851b92..841818d58 100644
--- a/app/models/form/sales/questions/uprn.rb
+++ b/app/models/form/sales/questions/uprn.rb
@@ -5,7 +5,7 @@ class Form::Sales::Questions::Uprn < ::Form::Question
@copy_key = "sales.property_information.uprn.uprn"
@type = "text"
@width = 10
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
@inferred_check_answers_value = [
{
"condition" => { "uprn_known" => 0 },
@@ -35,5 +35,5 @@ class Form::Sales::Questions::Uprn < ::Form::Question
"\n\n#{value.join("\n")}"
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 14, 2024 => 15, 2025 => 13 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 14, 2024 => 15, 2025 => 13, 2026 => 13 }.freeze
end
diff --git a/app/models/form/sales/questions/uprn_known.rb b/app/models/form/sales/questions/uprn_known.rb
index 2b9a83327..af84c09f9 100644
--- a/app/models/form/sales/questions/uprn_known.rb
+++ b/app/models/form/sales/questions/uprn_known.rb
@@ -18,7 +18,7 @@ class Form::Sales::Questions::UprnKnown < ::Form::Question
{ "uprn_known" => 1 },
],
}
- @question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)
end
ANSWER_OPTIONS = {
@@ -30,5 +30,5 @@ class Form::Sales::Questions::UprnKnown < ::Form::Question
I18n.t("validations.sales.property_information.uprn_known.invalid")
end
- QUESTION_NUMBER_FROM_YEAR = { 2023 => 14, 2024 => 15, 2025 => 13 }.freeze
+ QUESTION_NUMBER_FROM_YEAR = { 2023 => 14, 2024 => 15, 2025 => 13, 2026 => 13 }.freeze
end
diff --git a/app/models/form/sales/questions/value.rb b/app/models/form/sales/questions/value.rb
index c8b9cadd3..e731fda8e 100644
--- a/app/models/form/sales/questions/value.rb
+++ b/app/models/form/sales/questions/value.rb
@@ -4,16 +4,19 @@ class Form::Sales::Questions::Value < ::Form::Question
@id = "value"
@copy_key = form.start_year_2025_or_later? ? "sales.sale_information.value.#{page.id}" : "sales.sale_information.value"
@type = "numeric"
- @min = 0
+ @min = form.start_year_2026_or_later? ? 15_000 : 0
@step = 1
@width = 5
@prefix = "£"
- @question_number = question_number_from_year[form.start_date.year] || question_number_from_year[question_number_from_year.keys.max]
+ @question_number = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR_AND_SECTION, value_key: subsection.id)
@top_guidance_partial = "financial_calculations_shared_ownership"
@strip_commas = true
end
- def question_number_from_year
- { 2023 => 88, 2024 => 89, 2025 => subsection.id == "shared_ownership_staircasing_transaction" ? 97 : 80 }
- end
+ QUESTION_NUMBER_FROM_YEAR_AND_SECTION = {
+ 2023 => 88,
+ 2024 => 89,
+ 2025 => { "shared_ownership_initial_purchase" => 80, "shared_ownership_staircasing_transaction" => 97 },
+ 2026 => { "shared_ownership_initial_purchase" => 88, "shared_ownership_staircasing_transaction" => 105 },
+ }.freeze
end
diff --git a/app/models/form/sales/subsections/shared_ownership_staircasing_transaction.rb b/app/models/form/sales/subsections/shared_ownership_staircasing_transaction.rb
index cfd00e5e1..1af25a140 100644
--- a/app/models/form/sales/subsections/shared_ownership_staircasing_transaction.rb
+++ b/app/models/form/sales/subsections/shared_ownership_staircasing_transaction.rb
@@ -26,6 +26,7 @@ class Form::Sales::Subsections::SharedOwnershipStaircasingTransaction < ::Form::
Form::Sales::Pages::MonthlyRentStaircasingOwned.new(nil, nil, self),
Form::Sales::Pages::MonthlyRentStaircasing.new(nil, nil, self),
(Form::Sales::Pages::ServiceChargeStaircasing.new("service_charge_staircasing", nil, self) if form.start_year_2026_or_later?),
+ (Form::Sales::Pages::ServiceChargeChanged.new(nil, nil, self) if form.start_year_2026_or_later?),
Form::Sales::Pages::MonthlyChargesValueCheck.new("monthly_charges_shared_ownership_value_check", nil, self),
].compact
end
diff --git a/app/models/log.rb b/app/models/log.rb
index d5469da6f..5500991b6 100644
--- a/app/models/log.rb
+++ b/app/models/log.rb
@@ -346,9 +346,9 @@ class Log < ApplicationRecord
end
def clear_gender_description_unless_gender_not_same_as_sex!
- # we do this as the gender same as sex page always contains the gender description box that's hidden
- # default submit will send a "" for gender description. this ensure it's nil in this case
- # as well as blanking it if the user writes it in mistakenly in bulk upload
+ # gender_description is always routed to (even when hidden on the page), so default submit will set it as ""
+ # This method ensures gender_description is cleared if gender is the same as sex
+ # This also has the benefit of clearing a mistakenly input gender_description in bulk upload if gender is the same as sex
max_person = lettings? ? 8 : 6
(1..max_person).each do |person_index|
gender_same_as_sex = public_send("gender_same_as_sex#{person_index}")
diff --git a/app/models/sales_log.rb b/app/models/sales_log.rb
index 654808d3a..4d6e152a2 100644
--- a/app/models/sales_log.rb
+++ b/app/models/sales_log.rb
@@ -18,6 +18,7 @@ class SalesLog < Log
include Validations::Sales::SoftValidations
include Validations::SoftValidations
include MoneyFormattingHelper
+ include CollectionTimeHelper
self.inheritance_column = :_type_disabled
@@ -37,6 +38,8 @@ class SalesLog < Log
belongs_to :managing_organisation, class_name: "Organisation", optional: true
scope :filter_by_year, ->(year) { where(saledate: Time.zone.local(year.to_i, 4, 1)...Time.zone.local(year.to_i + 1, 4, 1)) }
+ scope :filter_by_year_or_later, ->(year) { where("sales_logs.saledate >= ?", Time.zone.local(year.to_i, 4, 1)) }
+ scope :filter_by_year_or_earlier, ->(year) { where("sales_logs.saledate < ?", Time.zone.local(year.to_i + 1, 4, 1)) }
scope :filter_by_years_or_nil, lambda { |years, _user = nil|
first_year = years.shift
query = filter_by_year(first_year)
@@ -69,12 +72,14 @@ class SalesLog < Log
}
scope :age1_answered, -> { where.not(age1: nil).or(where(age1_known: [1, 2])) }
scope :ecstat1_answered, -> { where.not(ecstat1: nil).or(where("saledate >= ?", Time.zone.local(2025, 4, 1))) }
+ scope :sex1_answered, -> { where.not(sex1: nil).filter_by_year_or_earlier(2025).or(where.not(sexrab1: nil).filter_by_year_or_later(2026)) }
+ scope :address_answered, -> { where.not(postcode_full: nil).where.not(address_line1: nil).or(where.not(uprn: nil)) }
scope :duplicate_logs, lambda { |log|
visible.where(log.slice(*DUPLICATE_LOG_ATTRIBUTES))
.where.not(id: log.id)
.where.not(saledate: nil)
- .where.not(sex1: nil)
- .where.not(postcode_full: nil)
+ .sex1_answered
+ .address_answered
.ecstat1_answered
.age1_answered
}
@@ -84,8 +89,8 @@ class SalesLog < Log
scope = visible
.group(*DUPLICATE_LOG_ATTRIBUTES)
.where.not(saledate: nil)
- .where.not(sex1: nil)
- .where.not(postcode_full: nil)
+ .sex1_answered
+ .address_answered
.age1_answered
.ecstat1_answered
.having("COUNT(*) > 1")
@@ -98,7 +103,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 ecstat1 postcode_full].freeze
+ DUPLICATE_LOG_ATTRIBUTES = %w[owning_organisation_id purchid saledate age1_known age1 sex1 sexrab1 ecstat1 postcode_full uprn address_line1].freeze
def lettings?
false
@@ -268,6 +273,22 @@ class SalesLog < Log
value * equity / 100
end
+ def expected_shared_ownership_deposit_value_tolerance
+ return 1 unless value && equity
+
+ # we found that a fixed tolerance was not quite what we wanted here.
+ # CORE wants it so if a user say, has a 66.666% equity they can enter either 66.6% or 66.7% (or 66.5%)
+ # so in 2026 we base our tolerance off of a discount 0.1% higher or lower
+ if form.start_year_2026_or_later?
+ lower_bound = value * ((equity - 0.1) / 100)
+ upper_bound = value * ((equity + 0.1) / 100)
+
+ (upper_bound - lower_bound) / 2
+ else
+ 1
+ end
+ end
+
def stairbought_part_of_value
return unless value && stairbought
@@ -468,6 +489,22 @@ class SalesLog < Log
value - discount_amount
end
+ def value_with_discount_tolerance
+ return 1 if value.blank? || discount.nil?
+
+ # we found that a simple tolerance was not quite what we wanted here.
+ # CORE wants it so if a user say, has a 66.6% discount then can enter either 66.6% or 66.7%
+ # so in 2026 we base our tolerance off of a discount 0.1% higher or lower
+ if form.start_year_2026_or_later?
+ discount_amount_lower_bound = value * (discount - 0.1) / 100
+ discount_amount_upper_bound = value * (discount + 0.1) / 100
+
+ (discount_amount_upper_bound - discount_amount_lower_bound) / 2
+ else
+ discount ? value * 0.05 / 100 : 1
+ end
+ end
+
def mortgage_deposit_and_grant_total
return if deposit.blank?
@@ -506,10 +543,12 @@ class SalesLog < Log
["owning_organisation_id",
"saledate",
"purchid",
+ "address_line1",
+ "postcode_full",
+ "uprn",
"age1",
- "sex1",
"ecstat1",
- uprn.blank? ? "postcode_full" : "uprn"].compact
+ form.start_year_2026_or_later? ? "sexrab1" : "sex1"].compact
end
def soctenant_is_inferred?
@@ -583,4 +622,8 @@ class SalesLog < Log
def mscharge_value
mscharge if discounted_ownership_sale? || !form.start_year_2025_or_later?
end
+
+ def hasservicechargeschanged_label
+ form.get_question(:hasservicechargeschanged, self)&.label_from_value(hasservicechargeschanged)
+ end
end
diff --git a/app/models/validations/sales/financial_validations.rb b/app/models/validations/sales/financial_validations.rb
index 0bb32ca53..2443578c0 100644
--- a/app/models/validations/sales/financial_validations.rb
+++ b/app/models/validations/sales/financial_validations.rb
@@ -139,6 +139,15 @@ module Validations::Sales::FinancialValidations
end
end
+ def validate_newservicecharges_different_from_mscharge(record)
+ return unless record.hasservicechargeschanged == 1 && record.newservicecharges && record.has_mscharge == 1 && record.mscharge
+
+ if record.newservicecharges == record.mscharge
+ record.errors.add :newservicecharges, I18n.t("validations.sales.financial.newservicecharges.same_as_previous")
+ record.errors.add :mscharge, I18n.t("validations.sales.financial.mscharge.same_as_new")
+ end
+ end
+
private
def is_relationship_child?(relationship)
diff --git a/app/models/validations/sales/sale_information_validations.rb b/app/models/validations/sales/sale_information_validations.rb
index 063c16599..9d65bc799 100644
--- a/app/models/validations/sales/sale_information_validations.rb
+++ b/app/models/validations/sales/sale_information_validations.rb
@@ -80,10 +80,9 @@ module Validations::Sales::SaleInformationValidations
return unless record.mortgage || record.mortgageused == 2 || record.mortgageused == 3
return unless record.discount || record.grant || record.type == 29
- # When a percentage discount is used, a percentage tolerance is needed to account for rounding errors
- tolerance = record.discount ? record.value * 0.05 / 100 : 1
+ tolerance = record.value_with_discount_tolerance
- if over_tolerance?(record.mortgage_deposit_and_grant_total, record.value_with_discount, tolerance, strict: !record.discount.nil?) && record.discounted_ownership_sale?
+ if over_tolerance?(record.mortgage_deposit_and_grant_total, record.value_with_discount, tolerance, strict: !record.discount.nil? || record.form.start_year_2026_or_later?) && record.discounted_ownership_sale?
deposit_and_grant_sentence = record.grant.present? ? ", cash deposit (#{record.field_formatted_as_currency('deposit')}), and grant (#{record.field_formatted_as_currency('grant')})" : " and cash deposit (#{record.field_formatted_as_currency('deposit')})"
discount_sentence = record.discount.present? ? " (#{record.field_formatted_as_currency('value')}) subtracted by the sum of the full purchase price (#{record.field_formatted_as_currency('value')}) multiplied by the percentage discount (#{record.discount}%)" : ""
%i[mortgageused mortgage value deposit discount grant].each do |field|
@@ -204,10 +203,12 @@ module Validations::Sales::SaleInformationValidations
def check_non_staircasing_socialhomebuy_mortgage(record)
return unless record.cashdis
+ tolerance = record.expected_shared_ownership_deposit_value_tolerance
+
if record.mortgage_used?
return unless record.mortgage
- if over_tolerance?(record.mortgage_deposit_and_discount_total, record.expected_shared_ownership_deposit_value, 1)
+ if over_tolerance?(record.mortgage_deposit_and_discount_total, record.expected_shared_ownership_deposit_value, tolerance, strict: record.form.start_year_2026_or_later?)
%i[mortgage value deposit cashdis equity].each do |field|
record.errors.add field, I18n.t("validations.sales.sale_information.#{field}.non_staircasing_mortgage.mortgage_used_socialhomebuy",
mortgage: record.field_formatted_as_currency("mortgage"),
@@ -228,7 +229,7 @@ module Validations::Sales::SaleInformationValidations
expected_shared_ownership_deposit_value: record.field_formatted_as_currency("expected_shared_ownership_deposit_value")).html_safe
end
elsif record.mortgage_not_used?
- if over_tolerance?(record.deposit_and_discount_total, record.expected_shared_ownership_deposit_value, 1)
+ if over_tolerance?(record.deposit_and_discount_total, record.expected_shared_ownership_deposit_value, tolerance, strict: record.form.start_year_2026_or_later?)
%i[mortgageused value deposit cashdis equity].each do |field|
record.errors.add field, I18n.t("validations.sales.sale_information.#{field}.non_staircasing_mortgage.mortgage_not_used_socialhomebuy",
deposit_and_discount_total: record.field_formatted_as_currency("deposit_and_discount_total"),
@@ -250,10 +251,12 @@ module Validations::Sales::SaleInformationValidations
end
def check_non_staircasing_non_socialhomebuy_mortgage(record)
+ tolerance = record.expected_shared_ownership_deposit_value_tolerance
+
if record.mortgage_used?
return unless record.mortgage
- if over_tolerance?(record.mortgage_and_deposit_total, record.expected_shared_ownership_deposit_value, 1)
+ if over_tolerance?(record.mortgage_and_deposit_total, record.expected_shared_ownership_deposit_value, tolerance, strict: record.form.start_year_2026_or_later?)
%i[mortgage value deposit equity].each do |field|
record.errors.add field, I18n.t("validations.sales.sale_information.#{field}.non_staircasing_mortgage.mortgage_used",
mortgage: record.field_formatted_as_currency("mortgage"),
@@ -272,7 +275,7 @@ module Validations::Sales::SaleInformationValidations
expected_shared_ownership_deposit_value: record.field_formatted_as_currency("expected_shared_ownership_deposit_value")).html_safe
end
elsif record.mortgage_not_used?
- if over_tolerance?(record.deposit, record.expected_shared_ownership_deposit_value, 1)
+ if over_tolerance?(record.deposit, record.expected_shared_ownership_deposit_value, tolerance, strict: record.form.start_year_2026_or_later?)
%i[mortgageused value deposit equity].each do |field|
record.errors.add field, I18n.t("validations.sales.sale_information.#{field}.non_staircasing_mortgage.mortgage_not_used",
deposit: record.field_formatted_as_currency("deposit"),
@@ -369,14 +372,11 @@ module Validations::Sales::SaleInformationValidations
def validate_mortgage_used_dont_know(record)
return unless record.mortgage_use_unknown?
+ return if record.form.start_year_2026_or_later?
if record.discounted_ownership_sale?
record.errors.add :mortgageused, I18n.t("validations.invalid_option", question: "was a mortgage used for the purchase of this property?")
end
- if record.outright_sale? && record.saledate && !record.form.start_year_2024_or_later?
- record.errors.add :mortgageused, I18n.t("validations.invalid_option", question: "was a mortgage used for the purchase of this property?")
- record.errors.add :saledate, I18n.t("validations.sales.sale_information.saledate.mortgage_used_year")
- end
if record.shared_ownership_scheme? && record.is_not_staircasing?
record.errors.add :mortgageused, I18n.t("validations.invalid_option", question: "was a mortgage used for the purchase of this property?")
record.errors.add :staircase, I18n.t("validations.sales.sale_information.staircase.mortgage_used_value")
diff --git a/app/models/validations/sales/soft_validations.rb b/app/models/validations/sales/soft_validations.rb
index 3569c379f..ce7a812d2 100644
--- a/app/models/validations/sales/soft_validations.rb
+++ b/app/models/validations/sales/soft_validations.rb
@@ -117,6 +117,7 @@ module Validations::Sales::SoftValidations
def mortgage_plus_deposit_less_than_discounted_value?
return unless mortgage && deposit && value && discount
+ return if form.start_year_2026_or_later?
discounted_value = value * (100 - discount) / 100
mortgage + deposit < discounted_value
diff --git a/app/services/bulk_upload/sales/year2025/row_parser.rb b/app/services/bulk_upload/sales/year2025/row_parser.rb
index b6ffbef2f..83266b388 100644
--- a/app/services/bulk_upload/sales/year2025/row_parser.rb
+++ b/app/services/bulk_upload/sales/year2025/row_parser.rb
@@ -535,6 +535,8 @@ class BulkUpload::Sales::Year2025::RowParser
"field_2", # saledate
"field_3", # saledate
"field_7", # purchaser_code
+ "field_16", # uprn
+ "field_17", # address_line1
"field_21", # postcode
"field_22", # postcode
"field_28", # age1
@@ -1304,6 +1306,8 @@ private
ecstat1
owning_organisation
postcode_full
+ uprn
+ address_line1
purchid
]
end
@@ -1474,6 +1478,8 @@ private
errors.add(:field_1, error_message) # Sale completion date
errors.add(:field_2, error_message) # Sale completion date
errors.add(:field_3, error_message) # Sale completion date
+ errors.add(:field_16, error_message) # UPRN
+ errors.add(:field_17, error_message) # Address line 1
errors.add(:field_21, error_message) # Postcode
errors.add(:field_22, error_message) # Postcode
errors.add(:field_28, error_message) # Buyer 1 age
diff --git a/app/services/bulk_upload/sales/year2026/csv_parser.rb b/app/services/bulk_upload/sales/year2026/csv_parser.rb
index 868246eda..44d067faa 100644
--- a/app/services/bulk_upload/sales/year2026/csv_parser.rb
+++ b/app/services/bulk_upload/sales/year2026/csv_parser.rb
@@ -4,7 +4,7 @@ class BulkUpload::Sales::Year2026::CsvParser
include CollectionTimeHelper
# TODO: CLDC-4162: Update when 2026 format is known
- FIELDS = 134
+ FIELDS = 136
FORM_YEAR = 2026
attr_reader :path
@@ -29,7 +29,7 @@ class BulkUpload::Sales::Year2026::CsvParser
def cols
# TODO: CLDC-4162: Update when 2026 format is known
- @cols ||= ("A".."ED").to_a
+ @cols ||= ("A".."EF").to_a
end
def row_parsers
diff --git a/app/services/bulk_upload/sales/year2026/row_parser.rb b/app/services/bulk_upload/sales/year2026/row_parser.rb
index 64acf19cd..e1d3ff314 100644
--- a/app/services/bulk_upload/sales/year2026/row_parser.rb
+++ b/app/services/bulk_upload/sales/year2026/row_parser.rb
@@ -47,7 +47,7 @@ class BulkUpload::Sales::Year2026::RowParser
field_38: "What is buyer 2’s nationality?",
field_39: "What is buyer 2 or person 2’s working situation?",
field_40: "Will buyer 2 live in the property?",
- field_41: "Besides the buyers, how many people will live in the property?",
+ field_41: "In total, how many people live in the property?",
field_42: "Is person 3 the partner of buyer 1?",
field_43: "Age of person 3",
@@ -149,6 +149,8 @@ class BulkUpload::Sales::Year2026::RowParser
field_132: "If 'No', enter person 5's gender identity",
field_133: "Is the gender person 6 identifies with the same as their sex registered at birth?",
field_134: "If 'No', enter person 6's gender identity",
+ field_135: "Will the service charge change after this staircasing transaction takes place?",
+ field_136: "What are the new total monthly service charges for the property?",
}.freeze
ERROR_BASE_KEY = "validations.sales.2026.bulk_upload".freeze
@@ -328,6 +330,9 @@ class BulkUpload::Sales::Year2026::RowParser
attribute :field_133, :integer
attribute :field_134, :string
+ attribute :field_135, :integer
+ attribute :field_136, :decimal
+
validates :field_1,
presence: {
message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "sale completion date (day)."),
@@ -405,7 +410,7 @@ class BulkUpload::Sales::Year2026::RowParser
validates :field_11,
inclusion: {
- in: [8, 9, 14, 21, 22, 27, 29],
+ in: [8, 9, 14, 21, 22, 29],
if: proc { field_11.present? },
category: :setup,
question: QUESTIONS[:field_11].downcase,
@@ -583,6 +588,8 @@ class BulkUpload::Sales::Year2026::RowParser
"field_2", # saledate
"field_3", # saledate
"field_7", # purchaser_code
+ "field_16", # uprn
+ "field_17", # address_line1
"field_21", # postcode
"field_22", # postcode
"field_28", # age1
@@ -730,7 +737,7 @@ private
end
def rtb_like_sale_type?
- [9, 14, 27, 29].include?(field_11)
+ [9, 14, 29].include?(field_11)
end
def invalid_fields
@@ -880,6 +887,7 @@ private
sexrab4: %i[field_48],
sexrab5: %i[field_52],
sexrab6: %i[field_56],
+
buildheightclass: %i[field_122],
gender_same_as_sex1: %i[field_123],
@@ -894,6 +902,9 @@ private
gender_description5: %i[field_132],
gender_same_as_sex6: %i[field_133],
gender_description6: %i[field_134],
+
+ hasservicechargeschanged: %i[field_135],
+ newservicecharges: %i[field_136],
}
end
@@ -943,6 +954,9 @@ private
attributes["gender_same_as_sex6"] = field_133
attributes["gender_description6"] = field_134
+ attributes["hasservicechargeschanged"] = field_135
+ attributes["newservicecharges"] = field_136
+
attributes["relat2"] = relationship_from_is_partner(field_34)
attributes["relat3"] = relationship_from_is_partner(field_42)
attributes["relat4"] = relationship_from_is_partner(field_46)
@@ -1395,6 +1409,8 @@ private
ecstat1
owning_organisation
postcode_full
+ uprn
+ address_line1
purchid
]
end
@@ -1565,6 +1581,8 @@ private
errors.add(:field_1, error_message) # Sale completion date
errors.add(:field_2, error_message) # Sale completion date
errors.add(:field_3, error_message) # Sale completion date
+ errors.add(:field_16, error_message) # UPRN
+ errors.add(:field_17, error_message) # Address line 1
errors.add(:field_21, error_message) # Postcode
errors.add(:field_22, error_message) # Postcode
errors.add(:field_28, error_message) # Buyer 1 age
diff --git a/app/services/exports/sales_log_export_constants.rb b/app/services/exports/sales_log_export_constants.rb
index 771db7362..63e2899ea 100644
--- a/app/services/exports/sales_log_export_constants.rb
+++ b/app/services/exports/sales_log_export_constants.rb
@@ -157,7 +157,11 @@ module Exports::SalesLogExportConstants
YEAR_2025_EXPORT_FIELDS << "SEX#{index}"
end
- YEAR_2026_EXPORT_FIELDS = Set["BUILDHEIGHTCLASS"]
+ YEAR_2026_EXPORT_FIELDS = Set[
+ "BUILDHEIGHTCLASS",
+ "HASSERVICECHARGESCHANGED",
+ "NEWSERVICECHARGES",
+ ]
(1..6).each do |index|
YEAR_2026_EXPORT_FIELDS << "SEXRAB#{index}"
diff --git a/app/services/exports/sales_log_export_service.rb b/app/services/exports/sales_log_export_service.rb
index d64fe7f6c..05232e959 100644
--- a/app/services/exports/sales_log_export_service.rb
+++ b/app/services/exports/sales_log_export_service.rb
@@ -135,6 +135,9 @@ module Exports
attribute_hash["hasestatefee"] = sales_log.has_management_fee
attribute_hash["estatefee"] = sales_log.management_fee
+ attribute_hash["hasservicechargeschanged"] = sales_log.hasservicechargeschanged
+ attribute_hash["newservicecharges"] = sales_log.newservicecharges
+
attribute_hash["stairlastday"] = sales_log.lasttransaction&.day
attribute_hash["stairlastmonth"] = sales_log.lasttransaction&.month
attribute_hash["stairlastyear"] = sales_log.lasttransaction&.year
diff --git a/app/views/form/guidance/_address_fallback.html.erb b/app/views/form/guidance/_address_fallback.html.erb
index 4ee0bd608..b980e6992 100644
--- a/app/views/form/guidance/_address_fallback.html.erb
+++ b/app/views/form/guidance/_address_fallback.html.erb
@@ -1,3 +1,3 @@
- <%= govuk_link_to "Clear address and search instead", address_search_input_path(@log.log_type, @log.id), class: "govuk-button govuk-button--secondary" %>
+ <%= govuk_link_to "Clear address and search by UPRN instead", address_search_input_path(@log.log_type, @log.id), class: "govuk-button govuk-button--secondary" %>
diff --git a/config/locales/forms/2025/lettings/tenancy_information.en.yml b/config/locales/forms/2025/lettings/tenancy_information.en.yml
index fa0fa9089..02d35a2ca 100644
--- a/config/locales/forms/2025/lettings/tenancy_information.en.yml
+++ b/config/locales/forms/2025/lettings/tenancy_information.en.yml
@@ -21,27 +21,27 @@ en:
tenancy_type:
page_header: ""
tenancy:
- check_answer_label: "Type of main tenancy"
+ check_answer_label: "Type of tenancy"
check_answer_prompt: ""
hint_text: ""
question_text: "What is the type of tenancy?"
tenancyother:
- check_answer_label: ""
+ check_answer_label: "Type of tenancy (other)"
check_answer_prompt: ""
hint_text: ""
- question_text: "Please state the tenancy type"
+ question_text: "Please state the type of tenancy"
starter_tenancy_type:
page_header: ""
tenancy:
- check_answer_label: "Type of main tenancy after the starter or introductory period has ended"
+ check_answer_label: "Type of tenancy"
check_answer_prompt: ""
- hint_text: ""
- question_text: "What is the type of tenancy after the starter or introductory period has ended?"
+ hint_text: "This is for the main tenancy after any starter or introductory period."
+ question_text: "What is the type of tenancy?"
tenancyother:
- check_answer_label: ""
+ check_answer_label: "Type of tenancy (other)"
check_answer_prompt: ""
hint_text: ""
- question_text: "Please state the tenancy type"
+ question_text: "Please state the type of tenancy"
tenancylength:
tenancy_length:
diff --git a/config/locales/forms/2026/lettings/tenancy_information.en.yml b/config/locales/forms/2026/lettings/tenancy_information.en.yml
index 65f110e93..6a481095a 100644
--- a/config/locales/forms/2026/lettings/tenancy_information.en.yml
+++ b/config/locales/forms/2026/lettings/tenancy_information.en.yml
@@ -21,27 +21,27 @@ en:
tenancy_type:
page_header: ""
tenancy:
- check_answer_label: "Type of main tenancy"
+ check_answer_label: "Type of tenancy"
check_answer_prompt: ""
hint_text: ""
question_text: "What is the type of tenancy?"
tenancyother:
- check_answer_label: ""
+ check_answer_label: "Type of tenancy (other)"
check_answer_prompt: ""
hint_text: ""
- question_text: "Please state the tenancy type"
+ question_text: "Please state the type of tenancy"
starter_tenancy_type:
page_header: ""
tenancy:
- check_answer_label: "Type of main tenancy after the starter or introductory period has ended"
+ check_answer_label: "Type of tenancy"
check_answer_prompt: ""
- hint_text: ""
- question_text: "What is the type of tenancy after the starter or introductory period has ended?"
+ hint_text: "This is for the main tenancy after any starter or introductory period."
+ question_text: "What is the type of tenancy?"
tenancyother:
- check_answer_label: ""
+ check_answer_label: "Type of tenancy (other)"
check_answer_prompt: ""
hint_text: ""
- question_text: "Please state the tenancy type"
+ question_text: "Please state the type of tenancy"
tenancylength:
tenancy_length:
diff --git a/config/locales/forms/2026/sales/guidance.en.yml b/config/locales/forms/2026/sales/guidance.en.yml
index 3bfb50966..923d1d1ee 100644
--- a/config/locales/forms/2026/sales/guidance.en.yml
+++ b/config/locales/forms/2026/sales/guidance.en.yml
@@ -18,7 +18,6 @@ en:
title: "Discounted Ownership Type Definitions"
content: "Right to Acquire (RTA): a discounted sale of a property built or purchased after 31 March 1997 to tenants of a private registered provider.
Preserved Right to Buy (PRTB): a discounted sale of a property that used to be owned by a council to tenants of a private registered provider.
- Voluntary Right to Buy (VRTB): a discounted sale to tenants in this PRP owned property, as part of a pilot scheme.
Right to Buy (RTB): a discounted sale to tenants in this council owned property.
Rent to Buy full ownership: a sale on full ownership terms following a period of discounted rent.
Social HomeBuy for outright purchase: a discounted sale to tenants of a private registered provider on full ownership terms.
diff --git a/config/locales/forms/2026/sales/household_characteristics.en.yml b/config/locales/forms/2026/sales/household_characteristics.en.yml
index f3027d322..6d816a925 100644
--- a/config/locales/forms/2026/sales/household_characteristics.en.yml
+++ b/config/locales/forms/2026/sales/household_characteristics.en.yml
@@ -256,16 +256,16 @@ en:
hholdcount:
joint_purchase:
page_header: ""
- check_answer_label: "Number of other people living in the property"
+ check_answer_label: "Number of people living in the property"
check_answer_prompt: ""
- hint_text: "Include all people living in the property who are not the buyers. In later questions you will only be asked for details about the first 4 other people for a joint purchase."
- question_text: "Besides the buyers, how many other people live or will live in the property?"
+ hint_text: "Include all people who are living or will live in the property."
+ question_text: "In total, how many people live in the property?"
not_joint_purchase:
page_header: ""
- check_answer_label: "Number of other people living in the property"
+ check_answer_label: "Number of people living in the property"
check_answer_prompt: ""
- hint_text: "Include all people living in the property who are not the buyer. In later questions you will only be asked for details about the first 5 other people for a sole purchase."
- question_text: "Besides the buyer, how many other people live or will live in the property?"
+ hint_text: "Include all people who are living or will live in the property."
+ question_text: "In total, how many people live in the property?"
details_known_2:
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 b253e4074..d41683352 100644
--- a/config/locales/forms/2026/sales/sale_information.en.yml
+++ b/config/locales/forms/2026/sales/sale_information.en.yml
@@ -285,13 +285,26 @@ en:
hint_text: ""
question_text: "Enter the total monthly charge"
+ servicecharges_changed:
+ page_header: ""
+ has_service_charges_changed:
+ check_answer_label: "Service charge will change"
+ check_answer_prompt: "Tell us if the service charge will change"
+ hint_text: "This includes any charges for day-to-day maintenance and repairs, building insurance, and any contributions to a sinking or reserved fund. It does not include estate management fees."
+ question_text: "Will the service charge change after this staircasing transaction takes place?"
+ new_service_charges:
+ check_answer_label: "New monthly service charges"
+ check_answer_prompt: ""
+ hint_text: ""
+ question_text: "Enter the new total monthly charge"
+
purchase_price:
discounted_ownership:
page_header: "About the price of the property"
check_answer_label: "Purchase price"
check_answer_prompt: ""
- hint_text: "For all schemes, including Right to Acquire (RTA), Right to Buy (RTB), Voluntary Right to Buy (VRTB) or Preserved Right to Buy (PRTB) sales, enter the full price of the property without any discount"
question_text: "What is the full purchase price?"
+ hint_text: "For all schemes, including Right to Acquire (RTA), Right to Buy (RTB) or Preserved Right to Buy (PRTB) sales, enter the full price of the property without any discount."
outright_sale:
page_header: "About the price of the property"
check_answer_label: "Purchase price"
@@ -303,14 +316,14 @@ en:
page_header: "About the price of the property"
check_answer_label: "Percentage discount"
check_answer_prompt: ""
- hint_text: "For Right to Buy (RTB), Preserved Right to Buy (PRTB), and Voluntary Right to Buy (VRTB)If discount capped, enter capped %If the property is being sold to an existing tenant under the RTB, PRTB, or VRTB schemes, enter the % discount from the full market value that is being given."
+ hint_text: "For Right to Buy (RTB) and Preserved Right to Buy (PRTB).For capped discount, enter capped %.If the property is sold to an existing tenant under RTB or PRTB, enter % discount from full market value."
question_text: "What was the percentage discount?"
grant:
page_header: "About the price of the property"
check_answer_label: "Amount of any loan, grant or subsidy"
check_answer_prompt: ""
- hint_text: "For all schemes except Right to Buy (RTB), Preserved Right to Buy (PRTB), Voluntary Right to Buy (VRTB) and Rent to Buy"
+ hint_text: "For all schemes except Right to Buy (RTB), Preserved Right to Buy (PRTB) and Rent to Buy"
question_text: "What was the amount of any loan, grant, discount or subsidy given?"
management_fee:
diff --git a/config/locales/validations/sales/financial.en.yml b/config/locales/validations/sales/financial.en.yml
index 6e248e6e0..3918d2a22 100644
--- a/config/locales/validations/sales/financial.en.yml
+++ b/config/locales/validations/sales/financial.en.yml
@@ -48,6 +48,10 @@ en:
mscharge:
monthly_leasehold_charges:
not_zero: "Monthly leasehold charges cannot be £0 if the property has monthly charges."
+ same_as_new: "You said that the service charge will change and you entered the same amount as the new service charge. If the service charge will not change, answer 'No' to that question before entering the service charge here."
+
+ newservicecharges:
+ same_as_previous: "You said that the service charge will change and you entered the same amount as the previous question. If the service charge will not change, answer 'No'."
resale:
equity_over_max: "The maximum initial equity stake is %{max_equity}%."
diff --git a/config/sale_range_data/2026.csv b/config/sale_range_data/2026.csv
new file mode 100644
index 000000000..4ba2e9566
--- /dev/null
+++ b/config/sale_range_data/2026.csv
@@ -0,0 +1,1185 @@
+la_name,la,bedrooms,soft_min,soft_max
+Adur,E07000223,1,120822,426553
+Adur,E07000223,2,210125,458072
+Adur,E07000223,3,298377,628273
+Adur,E07000223,4,365617,895132
+Amber Valley,E07000032,1,94556,292073
+Amber Valley,E07000032,2,94556,292073
+Amber Valley,E07000032,3,117670,388731
+Amber Valley,E07000032,4,224834,803727
+Arun,E07000224,1,97708,464376
+Arun,E07000224,2,173353,464376
+Arun,E07000224,3,236390,543173
+Arun,E07000224,4,335149,922448
+Ashfield,E07000170,1,73544,238492
+Ashfield,E07000170,2,82999,238492
+Ashfield,E07000170,3,98759,284719
+Ashfield,E07000170,4,189112,522160
+Ashford,E07000105,1,97708,414996
+Ashford,E07000105,2,99809,414996
+Ashford,E07000105,3,227985,517958
+Ashford,E07000105,4,324643,1069535
+Babergh,E07000200,1,108214,408693
+Babergh,E07000200,2,141834,408693
+Babergh,E07000200,3,204872,531616
+Babergh,E07000200,4,325693,1174598
+Barking and Dagenham,E09000002,1,84050,365617
+Barking and Dagenham,E09000002,2,98759,382427
+Barking and Dagenham,E09000002,3,210125,483287
+Barking and Dagenham,E09000002,4,294175,631425
+Barnet,E09000003,1,135530,513755
+Barnet,E09000003,2,195416,663994
+Barnet,E09000003,3,397136,1022257
+Barnet,E09000003,4,624071,2151678
+Barnsley,E08000038,1,67240,214327
+Barnsley,E08000038,2,67240,214327
+Barnsley,E08000038,3,89303,276314
+Barnsley,E08000038,4,167049,548426
+Basildon,E07000066,1,91404,436009
+Basildon,E07000066,2,138682,436009
+Basildon,E07000066,3,260555,541071
+Basildon,E07000066,4,359313,1067434
+Basingstoke and Deane,E07000084,1,108214,427604
+Basingstoke and Deane,E07000084,2,132379,427604
+Basingstoke and Deane,E07000084,3,262656,551578
+Basingstoke and Deane,E07000084,4,376123,1064282
+Bassetlaw,E07000171,1,88252,298377
+Bassetlaw,E07000171,2,88252,298377
+Bassetlaw,E07000171,3,99809,340402
+Bassetlaw,E07000171,4,177555,598856
+Bath and North East Somerset,E06000022,1,113467,580995
+Bath and North East Somerset,E06000022,2,147087,580995
+Bath and North East Somerset,E06000022,3,237441,727032
+Bath and North East Somerset,E06000022,4,362465,1531810
+Bedford,E06000055,1,91404,333048
+Bedford,E06000055,2,114518,333048
+Bedford,E06000055,3,200669,445465
+Bedford,E06000055,4,354060,903537
+Bexley,E09000004,1,104012,428655
+Bexley,E09000004,2,135530,428655
+Bexley,E09000004,3,298377,554729
+Bexley,E09000004,4,392933,927701
+Birmingham,E08000025,1,75645,356162
+Birmingham,E08000025,2,101911,356162
+Birmingham,E08000025,3,130277,431806
+Birmingham,E08000025,4,189112,960270
+Blaby,E07000129,1,106113,340402
+Blaby,E07000129,2,106113,340402
+Blaby,E07000129,3,184910,371921
+Blaby,E07000129,4,272112,690260
+Blackburn with Darwen,E06000008,1,57784,223783
+Blackburn with Darwen,E06000008,2,70392,223783
+Blackburn with Darwen,E06000008,3,88252,296276
+Blackburn with Darwen,E06000008,4,140784,580995
+Blackpool,E06000009,1,56734,217479
+Blackpool,E06000009,2,78797,217479
+Blackpool,E06000009,3,95607,253200
+Blackpool,E06000009,4,109265,429705
+Bolsover,E07000033,1,77746,212226
+Bolsover,E07000033,2,77746,212226
+Bolsover,E07000033,3,82999,266858
+Bolsover,E07000033,4,161796,517958
+Bolton,E08000001,1,73544,239542
+Bolton,E08000001,2,79847,239542
+Bolton,E08000001,3,99809,324643
+Bolton,E08000001,4,167049,727032
+Boston,E07000136,1,55683,245846
+Boston,E07000136,2,55683,245846
+Boston,E07000136,3,106113,294175
+Boston,E07000136,4,202770,486439
+"Bournemouth, Christchurch and Poole",E06000058,1,133429,476983
+"Bournemouth, Christchurch and Poole",E06000058,2,188062,476983
+"Bournemouth, Christchurch and Poole",E06000058,3,272112,627223
+"Bournemouth, Christchurch and Poole",E06000058,4,353010,1260749
+Bracknell Forest,E06000036,1,90354,465426
+Bracknell Forest,E06000036,2,150239,465426
+Bracknell Forest,E06000036,3,325693,624071
+Bracknell Forest,E06000036,4,398186,1131522
+Bradford,E08000032,1,61987,277365
+Bradford,E08000032,2,73544,277365
+Bradford,E08000032,3,91404,348807
+Bradford,E08000032,4,118721,762753
+Braintree,E07000067,1,120822,405541
+Braintree,E07000067,2,158644,405541
+Braintree,E07000067,3,260555,509553
+Braintree,E07000067,4,353010,1124168
+Breckland,E07000143,1,99809,300478
+Breckland,E07000143,2,123974,300478
+Breckland,E07000143,3,164948,396085
+Breckland,E07000143,4,250049,758551
+Brent,E09000005,1,104012,596754
+Brent,E09000005,2,152340,779563
+Brent,E09000005,3,369820,1259698
+Brent,E09000005,4,529514,2593991
+Brentwood,E07000068,1,139733,506401
+Brentwood,E07000068,2,233239,671349
+Brentwood,E07000068,3,383478,856259
+Brentwood,E07000068,4,485388,1767150
+Brighton and Hove,E06000043,1,176505,502198
+Brighton and Hove,E06000043,2,257403,582046
+Brighton and Hove,E06000043,3,334098,807930
+Brighton and Hove,E06000043,4,437060,1419393
+"Bristol, City of",E06000023,1,138682,398186
+"Bristol, City of",E06000023,2,175454,536869
+"Bristol, City of",E06000023,3,231137,653488
+"Bristol, City of",E06000023,4,316238,1331141
+Broadland,E07000144,1,120822,319390
+Broadland,E07000144,2,133429,319390
+Broadland,E07000144,3,214327,412895
+Broadland,E07000144,4,287871,715475
+Bromley,E09000006,1,189112,533717
+Bromley,E09000006,2,263707,600957
+Bromley,E09000006,3,336200,786917
+Bromley,E09000006,4,475933,1482430
+Bromsgrove,E07000234,1,113467,463325
+Bromsgrove,E07000234,2,115569,463325
+Bromsgrove,E07000234,3,185960,530565
+Bromsgrove,E07000234,4,330947,1041168
+Broxbourne,E07000095,1,161796,458072
+Broxbourne,E07000095,2,240593,458072
+Broxbourne,E07000095,3,354060,628273
+Broxbourne,E07000095,4,463325,1363710
+Broxtowe,E07000172,1,94556,283668
+Broxtowe,E07000172,2,104012,283668
+Broxtowe,E07000172,3,143935,363516
+Broxtowe,E07000172,4,224834,753297
+Buckinghamshire,E06000060,1,150239,620919
+Buckinghamshire,E06000060,2,162847,620919
+Buckinghamshire,E06000060,3,299428,827892
+Buckinghamshire,E06000060,4,438110,1838592
+Burnley,E07000117,1,49379,214327
+Burnley,E07000117,2,58835,214327
+Burnley,E07000117,3,78797,270010
+Burnley,E07000117,4,140784,453870
+Bury,E08000002,1,85101,304681
+Bury,E08000002,2,94556,304681
+Bury,E08000002,3,130277,371921
+Bury,E08000002,4,214327,756449
+Calderdale,E08000033,1,70392,270010
+Calderdale,E08000033,2,75645,270010
+Calderdale,E08000033,3,98759,375073
+Calderdale,E08000033,4,155492,715475
+Cambridge,E07000008,1,132379,575742
+Cambridge,E07000008,2,165999,633526
+Cambridge,E07000008,3,323592,831044
+Cambridge,E07000008,4,506401,1863807
+Camden,E09000007,1,244795,769057
+Camden,E09000007,2,428655,1401532
+Camden,E09000007,3,533717,2420638
+Camden,E09000007,4,963422,5753217
+Cannock Chase,E07000192,1,71442,236390
+Cannock Chase,E07000192,2,106113,236390
+Cannock Chase,E07000192,3,140784,310985
+Cannock Chase,E07000192,4,217479,487490
+Canterbury,E07000106,1,91404,444414
+Canterbury,E07000106,2,159695,444414
+Canterbury,E07000106,3,227985,564185
+Canterbury,E07000106,4,340402,1027510
+Castle Point,E07000069,1,148138,444414
+Castle Point,E07000069,2,209074,444414
+Castle Point,E07000069,3,270010,517958
+Castle Point,E07000069,4,361415,970777
+Central Bedfordshire,E06000056,1,100860,399237
+Central Bedfordshire,E06000056,2,128176,399237
+Central Bedfordshire,E06000056,3,243745,512705
+Central Bedfordshire,E06000056,4,377174,899334
+Charnwood,E07000130,1,90354,322542
+Charnwood,E07000130,2,105062,322542
+Charnwood,E07000130,3,160745,379275
+Charnwood,E07000130,4,273162,766956
+Chelmsford,E07000070,1,85101,475933
+Chelmsford,E07000070,2,119771,475933
+Chelmsford,E07000070,3,315187,644033
+Chelmsford,E07000070,4,428655,1135725
+Cheltenham,E07000078,1,112417,465426
+Cheltenham,E07000078,2,167049,487490
+Cheltenham,E07000078,3,215378,609362
+Cheltenham,E07000078,4,313086,1221876
+Cherwell,E07000177,1,109265,412895
+Cherwell,E07000177,2,109265,412895
+Cherwell,E07000177,3,224834,517958
+Cherwell,E07000177,4,342503,953967
+Cheshire East,E06000049,1,93506,433908
+Cheshire East,E06000049,2,93506,433908
+Cheshire East,E06000049,3,126075,540021
+Cheshire East,E06000049,4,275263,1145180
+Cheshire West and Chester,E06000050,1,79847,358263
+Cheshire West and Chester,E06000050,2,89303,358263
+Cheshire West and Chester,E06000050,3,116619,429705
+Cheshire West and Chester,E06000050,4,241644,930853
+Chesterfield,E07000034,1,69341,229036
+Chesterfield,E07000034,2,90354,229036
+Chesterfield,E07000034,3,111366,337250
+Chesterfield,E07000034,4,184910,600957
+Chichester,E07000225,1,96657,582046
+Chichester,E07000225,2,110316,582046
+Chichester,E07000225,3,268960,751196
+Chichester,E07000225,4,391883,2000388
+Chorley,E07000118,1,69341,318339
+Chorley,E07000118,2,95607,318339
+Chorley,E07000118,3,117670,375073
+Chorley,E07000118,4,223783,683956
+City of London,E09000001,1,445465,979182
+City of London,E09000001,2,650336,2608699
+City of London,E09000001,3,1662087,5513675
+City of London,E09000001,4,1844896,2184247
+Colchester,E07000071,1,109265,365617
+Colchester,E07000071,2,156543,365617
+Colchester,E07000071,3,244795,467528
+Colchester,E07000071,4,347757,885676
+Cornwall,E06000052,1,93506,387680
+Cornwall,E06000052,2,97708,387680
+Cornwall,E06000052,3,153391,500097
+Cornwall,E06000052,4,238492,824740
+Cotswold,E07000079,1,70392,629324
+Cotswold,E07000079,2,115569,629324
+Cotswold,E07000079,3,172302,775361
+Cotswold,E07000079,4,389782,1530759
+County Durham,E06000047,1,52531,221682
+County Durham,E06000047,2,52531,221682
+County Durham,E06000047,3,68291,285770
+County Durham,E06000047,4,140784,566286
+Coventry,E08000026,1,84050,264757
+Coventry,E08000026,2,112417,264757
+Coventry,E08000026,3,157594,378225
+Coventry,E08000026,4,225884,748044
+Crawley,E07000226,1,151290,369820
+Crawley,E07000226,2,219580,397136
+Crawley,E07000226,3,300478,504300
+Crawley,E07000226,4,361415,758551
+Croydon,E09000008,1,110316,423401
+Croydon,E09000008,2,174404,528464
+Croydon,E09000008,3,325693,660842
+Croydon,E09000008,4,443363,1159889
+Cumberland,E06000063,1,64088,258454
+Cumberland,E06000063,2,77746,258454
+Cumberland,E06000063,3,91404,333048
+Cumberland,E06000063,4,146037,550527
+Dacorum,E07000096,1,165999,590451
+Dacorum,E07000096,2,223783,592552
+Dacorum,E07000096,3,338301,800575
+Dacorum,E07000096,4,455971,1685201
+Darlington,E06000005,1,53582,229036
+Darlington,E06000005,2,66189,229036
+Darlington,E06000005,3,87202,296276
+Darlington,E06000005,4,176505,586248
+Dartford,E07000107,1,111366,411845
+Dartford,E07000107,2,111366,411845
+Dartford,E07000107,3,293124,533717
+Dartford,E07000107,4,406591,919296
+Derby,E06000015,1,64088,245846
+Derby,E06000015,2,89303,245846
+Derby,E06000015,3,111366,336200
+Derby,E06000015,4,225884,616716
+Derbyshire Dales,E07000035,1,69341,452819
+Derbyshire Dales,E07000035,2,84050,452819
+Derbyshire Dales,E07000035,3,172302,573641
+Derbyshire Dales,E07000035,4,286820,928752
+Doncaster,E08000017,1,73544,222732
+Doncaster,E08000017,2,74594,222732
+Doncaster,E08000017,3,89303,273162
+Doncaster,E08000017,4,164948,555780
+Dorset,E06000059,1,107164,449667
+Dorset,E06000059,2,151290,449667
+Dorset,E06000059,3,220631,587299
+Dorset,E06000059,4,313086,1097902
+Dover,E07000108,1,104012,366668
+Dover,E07000108,2,114518,366668
+Dover,E07000108,3,181758,478034
+Dover,E07000108,4,253200,912992
+Dudley,E08000027,1,72493,267909
+Dudley,E08000027,2,97708,267909
+Dudley,E08000027,3,130277,354060
+Dudley,E08000027,4,199619,620919
+Ealing,E09000009,1,122923,548426
+Ealing,E09000009,2,185960,725981
+Ealing,E09000009,3,322542,1045371
+Ealing,E09000009,4,499046,2098096
+East Cambridgeshire,E07000009,1,114518,367718
+East Cambridgeshire,E07000009,2,121872,367718
+East Cambridgeshire,E07000009,3,216429,475933
+East Cambridgeshire,E07000009,4,316238,874119
+East Devon,E07000040,1,87202,438110
+East Devon,E07000040,2,109265,438110
+East Devon,E07000040,3,172302,566286
+East Devon,E07000040,4,308883,1072687
+East Hampshire,E07000085,1,116619,550527
+East Hampshire,E07000085,2,144986,550527
+East Hampshire,E07000085,3,275263,694462
+East Hampshire,E07000085,4,418148,1309078
+East Hertfordshire,E07000242,1,136581,551578
+East Hertfordshire,E07000242,2,161796,551578
+East Hertfordshire,E07000242,3,333048,779563
+East Hertfordshire,E07000242,4,488540,1510797
+East Lindsey,E07000137,1,65139,305732
+East Lindsey,E07000137,2,80898,305732
+East Lindsey,E07000137,3,107164,342503
+East Lindsey,E07000137,4,190163,667146
+East Riding of Yorkshire,E06000011,1,75645,307833
+East Riding of Yorkshire,E06000011,2,96657,307833
+East Riding of Yorkshire,E06000011,3,127126,359313
+East Riding of Yorkshire,E06000011,4,195416,685007
+East Staffordshire,E07000193,1,76696,315187
+East Staffordshire,E07000193,2,95607,315187
+East Staffordshire,E07000193,3,121872,361415
+East Staffordshire,E07000193,4,224834,718627
+East Suffolk,E07000244,1,89303,395035
+East Suffolk,E07000244,2,119771,395035
+East Suffolk,E07000244,3,140784,459123
+East Suffolk,E07000244,4,235340,872018
+Eastbourne,E07000061,1,115569,354060
+Eastbourne,E07000061,2,161796,354060
+Eastbourne,E07000061,3,226935,473831
+Eastbourne,E07000061,4,293124,831044
+Eastleigh,E07000086,1,108214,371921
+Eastleigh,E07000086,2,111366,371921
+Eastleigh,E07000086,3,193315,490641
+Eastleigh,E07000086,4,351959,894081
+Elmbridge,E07000207,1,138682,818436
+Elmbridge,E07000207,2,253200,818436
+Elmbridge,E07000207,3,441262,1122066
+Elmbridge,E07000207,4,637729,2678041
+Enfield,E09000010,1,120822,484338
+Enfield,E09000010,2,167049,572590
+Enfield,E09000010,3,320440,819487
+Enfield,E09000010,4,475933,1539164
+Epping Forest,E07000072,1,125024,665045
+Epping Forest,E07000072,2,274213,665045
+Epping Forest,E07000072,3,372972,881474
+Epping Forest,E07000072,4,520059,1916338
+Epsom and Ewell,E07000208,1,174404,661893
+Epsom and Ewell,E07000208,2,257403,661893
+Epsom and Ewell,E07000208,3,410794,886727
+Epsom and Ewell,E07000208,4,598856,1502392
+Erewash,E07000036,1,86151,257403
+Erewash,E07000036,2,94556,257403
+Erewash,E07000036,3,127126,345655
+Erewash,E07000036,4,201720,669247
+Exeter,E07000041,1,107164,383478
+Exeter,E07000041,2,123974,383478
+Exeter,E07000041,3,215378,476983
+Exeter,E07000041,4,314137,959220
+Fareham,E07000087,1,120822,399237
+Fareham,E07000087,2,181758,399237
+Fareham,E07000087,3,253200,496945
+Fareham,E07000087,4,340402,900385
+Fenland,E07000010,1,80898,256352
+Fenland,E07000010,2,114518,256352
+Fenland,E07000010,3,147087,331997
+Fenland,E07000010,4,219580,567337
+Folkestone and Hythe,E07000112,1,100860,387680
+Folkestone and Hythe,E07000112,2,110316,387680
+Folkestone and Hythe,E07000112,3,198568,524261
+Folkestone and Hythe,E07000112,4,274213,842600
+Forest of Dean,E07000080,1,96657,419199
+Forest of Dean,E07000080,2,113467,419199
+Forest of Dean,E07000080,3,168100,497996
+Forest of Dean,E07000080,4,250049,832094
+Fylde,E07000119,1,82999,376123
+Fylde,E07000119,2,104012,388731
+Fylde,E07000119,3,120822,388731
+Fylde,E07000119,4,229036,728082
+Gateshead,E08000037,1,56734,218530
+Gateshead,E08000037,2,68291,218530
+Gateshead,E08000037,3,89303,321491
+Gateshead,E08000037,4,143935,556831
+Gedling,E07000173,1,73544,275263
+Gedling,E07000173,2,97708,275263
+Gedling,E07000173,3,140784,359313
+Gedling,E07000173,4,221682,713374
+Gloucester,E07000081,1,76696,287871
+Gloucester,E07000081,2,120822,287871
+Gloucester,E07000081,3,172302,379275
+Gloucester,E07000081,4,273162,591501
+Gosport,E07000088,1,101911,351959
+Gosport,E07000088,2,132379,353010
+Gosport,E07000088,3,192264,405541
+Gosport,E07000088,4,257403,755399
+Gravesham,E07000109,1,80898,412895
+Gravesham,E07000109,2,118721,412895
+Gravesham,E07000109,3,259504,524261
+Gravesham,E07000109,4,348807,1056928
+Great Yarmouth,E07000145,1,85101,274213
+Great Yarmouth,E07000145,2,89303,274213
+Great Yarmouth,E07000145,3,110316,336200
+Great Yarmouth,E07000145,4,170201,559983
+Greenwich,E09000011,1,110316,565236
+Greenwich,E09000011,2,151290,673450
+Greenwich,E09000011,3,270010,847854
+Greenwich,E09000011,4,391883,1697808
+Guildford,E07000209,1,118721,600957
+Guildford,E07000209,2,229036,704969
+Guildford,E07000209,3,369820,903537
+Guildford,E07000209,4,501148,2058172
+Hackney,E09000012,1,172302,666096
+Hackney,E09000012,2,224834,893030
+Hackney,E09000012,3,403440,1377368
+Hackney,E09000012,4,698665,2024552
+Halton,E06000006,1,72493,243745
+Halton,E06000006,2,82999,243745
+Halton,E06000006,3,97708,312035
+Halton,E06000006,4,165999,554729
+Hammersmith and Fulham,E09000013,1,196467,754348
+Hammersmith and Fulham,E09000013,2,377174,1191408
+Hammersmith and Fulham,E09000013,3,462275,1687302
+Hammersmith and Fulham,E09000013,4,1009650,3305263
+Harborough,E07000131,1,61987,437060
+Harborough,E07000131,2,61987,437060
+Harborough,E07000131,3,147087,510603
+Harborough,E07000131,4,336200,1021207
+Haringey,E09000014,1,148138,562084
+Haringey,E09000014,2,239542,822639
+Haringey,E09000014,3,387680,1220825
+Haringey,E09000014,4,614615,2518346
+Harlow,E07000073,1,121872,351959
+Harlow,E07000073,2,158644,402389
+Harlow,E07000073,3,270010,511654
+Harlow,E07000073,4,366668,878322
+Harrow,E09000015,1,122923,511654
+Harrow,E09000015,2,268960,594653
+Harrow,E09000015,3,399237,798474
+Harrow,E09000015,4,544223,1533911
+Hart,E07000089,1,102961,549476
+Hart,E07000089,2,142885,549476
+Hart,E07000089,3,335149,673450
+Hart,E07000089,4,485388,1365811
+Hartlepool,E06000001,1,53582,231137
+Hartlepool,E06000001,2,53582,231137
+Hartlepool,E06000001,3,73544,248998
+Hartlepool,E06000001,4,127126,533717
+Hastings,E07000062,1,100860,324643
+Hastings,E07000062,2,148138,363516
+Hastings,E07000062,3,203821,417098
+Hastings,E07000062,4,268960,694462
+Havant,E07000090,1,93506,395035
+Havant,E07000090,2,137632,395035
+Havant,E07000090,3,218530,478034
+Havant,E07000090,4,295225,816335
+Havering,E09000016,1,130277,450718
+Havering,E09000016,2,194365,459123
+Havering,E09000016,3,320440,627223
+Havering,E09000016,4,392933,1176699
+"Herefordshire, County of",E06000019,1,93506,400288
+"Herefordshire, County of",E06000019,2,99809,400288
+"Herefordshire, County of",E06000019,3,154442,475933
+"Herefordshire, County of",E06000019,4,270010,844702
+Hertsmere,E07000098,1,170201,635628
+Hertsmere,E07000098,2,301529,635628
+Hertsmere,E07000098,3,420250,876220
+Hertsmere,E07000098,4,564185,2130665
+High Peak,E07000037,1,105062,307833
+High Peak,E07000037,2,120822,307833
+High Peak,E07000037,3,153391,412895
+High Peak,E07000037,4,235340,768006
+Hillingdon,E09000017,1,126075,479085
+Hillingdon,E09000017,2,187011,550527
+Hillingdon,E09000017,3,382427,752247
+Hillingdon,E09000017,4,484338,1350052
+Hinckley and Bosworth,E07000132,1,94556,313086
+Hinckley and Bosworth,E07000132,2,105062,313086
+Hinckley and Bosworth,E07000132,3,156543,399237
+Hinckley and Bosworth,E07000132,4,257403,801626
+Horsham,E07000227,1,133429,505350
+Horsham,E07000227,2,133429,505350
+Horsham,E07000227,3,283668,711272
+Horsham,E07000227,4,473831,1444608
+Hounslow,E09000018,1,113467,537919
+Hounslow,E09000018,2,147087,699716
+Hounslow,E09000018,3,315187,988637
+Hounslow,E09000018,4,453870,2619206
+Huntingdonshire,E07000011,1,87202,371921
+Huntingdonshire,E07000011,2,101911,371921
+Huntingdonshire,E07000011,3,198568,455971
+Huntingdonshire,E07000011,4,303630,777462
+Hyndburn,E07000120,1,63037,203821
+Hyndburn,E07000120,2,63037,203821
+Hyndburn,E07000120,3,82999,293124
+Hyndburn,E07000120,4,160745,559983
+Ipswich,E07000202,1,92455,295225
+Ipswich,E07000202,2,119771,295225
+Ipswich,E07000202,3,173353,381377
+Ipswich,E07000202,4,241644,812132
+Isle of Wight,E06000046,1,91404,336200
+Isle of Wight,E06000046,2,125024,336200
+Isle of Wight,E06000046,3,176505,431806
+Isle of Wight,E06000046,4,227985,790069
+Islington,E09000019,1,193315,707070
+Islington,E09000019,2,380326,1167243
+Islington,E09000019,3,467528,1804972
+Islington,E09000019,4,727032,2695901
+Kensington and Chelsea,E09000020,1,223783,1204015
+Kensington and Chelsea,E09000020,2,571539,2260943
+Kensington and Chelsea,E09000020,3,674501,4012333
+Kensington and Chelsea,E09000020,4,1341647,12676829
+King's Lynn and West Norfolk,E07000146,1,73544,329896
+King's Lynn and West Norfolk,E07000146,2,117670,329896
+King's Lynn and West Norfolk,E07000146,3,153391,389782
+King's Lynn and West Norfolk,E07000146,4,232188,742791
+"Kingston upon Hull, City of",E06000010,1,59886,180707
+"Kingston upon Hull, City of",E06000010,2,64088,180707
+"Kingston upon Hull, City of",E06000010,3,79847,246897
+"Kingston upon Hull, City of",E06000010,4,105062,396085
+Kingston upon Thames,E09000021,1,149189,619868
+Kingston upon Thames,E09000021,2,309934,675551
+Kingston upon Thames,E09000021,3,380326,893030
+Kingston upon Thames,E09000021,4,524261,1868009
+Kirklees,E08000034,1,67240,248998
+Kirklees,E08000034,2,80898,248998
+Kirklees,E08000034,3,110316,340402
+Kirklees,E08000034,4,189112,717576
+Knowsley,E08000011,1,70392,213277
+Knowsley,E08000011,2,70392,213277
+Knowsley,E08000011,3,89303,287871
+Knowsley,E08000011,4,128176,459123
+Lambeth,E09000022,1,158644,610413
+Lambeth,E09000022,2,231137,803727
+Lambeth,E09000022,3,374022,1201914
+Lambeth,E09000022,4,547375,1961515
+Lancaster,E07000121,1,75645,298377
+Lancaster,E07000121,2,89303,298377
+Lancaster,E07000121,3,120822,361415
+Lancaster,E07000121,4,140784,667146
+Leeds,E08000035,1,82999,308883
+Leeds,E08000035,2,96657,308883
+Leeds,E08000035,3,120822,414996
+Leeds,E08000035,4,172302,838398
+Leicester,E06000016,1,45177,268960
+Leicester,E06000016,2,78797,268960
+Leicester,E06000016,3,97708,347757
+Leicester,E06000016,4,224834,695513
+Lewes,E07000063,1,133429,504300
+Lewes,E07000063,2,194365,504300
+Lewes,E07000063,3,239542,692361
+Lewes,E07000063,4,346706,1312229
+Lewisham,E09000023,1,161796,483287
+Lewisham,E09000023,2,226935,644033
+Lewisham,E09000023,3,340402,841550
+Lewisham,E09000023,4,464376,1469823
+Lichfield,E07000194,1,95607,412895
+Lichfield,E07000194,2,95607,412895
+Lichfield,E07000194,3,168100,504300
+Lichfield,E07000194,4,282618,945562
+Lincoln,E07000138,1,59886,245846
+Lincoln,E07000138,2,80898,245846
+Lincoln,E07000138,3,126075,319390
+Lincoln,E07000138,4,185960,537919
+Liverpool,E08000012,1,72493,308883
+Liverpool,E08000012,2,72493,308883
+Liverpool,E08000012,3,90354,363516
+Liverpool,E08000012,4,131328,754348
+Luton,E06000032,1,117670,333048
+Luton,E06000032,2,147087,333048
+Luton,E06000032,3,241644,441262
+Luton,E06000032,4,296276,720728
+Maidstone,E07000110,1,71442,433908
+Maidstone,E07000110,2,115569,433908
+Maidstone,E07000110,3,206973,540021
+Maidstone,E07000110,4,383478,1049573
+Maldon,E07000074,1,120822,492743
+Maldon,E07000074,2,120822,492743
+Maldon,E07000074,3,279466,584147
+Maldon,E07000074,4,382427,1325887
+Malvern Hills,E07000235,1,98759,427604
+Malvern Hills,E07000235,2,98759,427604
+Malvern Hills,E07000235,3,192264,561033
+Malvern Hills,E07000235,4,315187,899334
+Manchester,E08000003,1,100860,331997
+Manchester,E08000003,2,100860,418148
+Manchester,E08000003,3,104012,493793
+Manchester,E08000003,4,157594,1057978
+Mansfield,E07000174,1,73544,257403
+Mansfield,E07000174,2,76696,257403
+Mansfield,E07000174,3,98759,291023
+Mansfield,E07000174,4,175454,519008
+Medway,E06000035,1,68291,358263
+Medway,E06000035,2,140784,358263
+Medway,E06000035,3,215378,462275
+Medway,E06000035,4,295225,723880
+Melton,E07000133,1,58835,375073
+Melton,E07000133,2,58835,375073
+Melton,E07000133,3,164948,443363
+Melton,E07000133,4,252150,1001245
+Mendip,E07000187,1,105062,398186
+Mendip,E07000187,2,115569,398186
+Mendip,E07000187,3,212226,501148
+Mendip,E07000187,4,305732,1083193
+Merton,E09000024,1,195416,663994
+Merton,E09000024,2,251099,756449
+Merton,E09000024,3,353010,969726
+Merton,E09000024,4,485388,2558269
+Mid Devon,E07000042,1,95607,392933
+Mid Devon,E07000042,2,110316,392933
+Mid Devon,E07000042,3,180707,502198
+Mid Devon,E07000042,4,278415,888828
+Mid Suffolk,E07000203,1,106113,371921
+Mid Suffolk,E07000203,2,118721,371921
+Mid Suffolk,E07000203,3,208024,479085
+Mid Suffolk,E07000203,4,300478,918245
+Mid Sussex,E07000228,1,178606,523211
+Mid Sussex,E07000228,2,234289,523211
+Mid Sussex,E07000228,3,336200,680804
+Mid Sussex,E07000228,4,449667,1342697
+Middlesbrough,E06000002,1,51481,217479
+Middlesbrough,E06000002,2,59886,217479
+Middlesbrough,E06000002,3,76696,259504
+Middlesbrough,E06000002,4,174404,508502
+Milton Keynes,E06000042,1,64088,360364
+Milton Keynes,E06000042,2,89303,360364
+Milton Keynes,E06000042,3,197517,472781
+Milton Keynes,E06000042,4,338301,879372
+Mole Valley,E07000210,1,164948,709171
+Mole Valley,E07000210,2,248998,718627
+Mole Valley,E07000210,3,409743,936106
+Mole Valley,E07000210,4,589400,1825985
+New Forest,E07000091,1,120822,482236
+New Forest,E07000091,2,190163,530565
+New Forest,E07000091,3,259504,721779
+New Forest,E07000091,4,361415,1205066
+Newark and Sherwood,E07000175,1,88252,337250
+Newark and Sherwood,E07000175,2,88252,337250
+Newark and Sherwood,E07000175,3,116619,383478
+Newark and Sherwood,E07000175,4,222732,791120
+Newcastle upon Tyne,E08000021,1,55683,279466
+Newcastle upon Tyne,E08000021,2,66189,279466
+Newcastle upon Tyne,E08000021,3,84050,363516
+Newcastle upon Tyne,E08000021,4,161796,790069
+Newcastle-under-Lyme,E07000195,1,88252,234289
+Newcastle-under-Lyme,E07000195,2,88252,234289
+Newcastle-under-Lyme,E07000195,3,115569,331997
+Newcastle-under-Lyme,E07000195,4,195416,653488
+Newham,E09000025,1,106113,491692
+Newham,E09000025,2,141834,634577
+Newham,E09000025,3,235340,758551
+Newham,E09000025,4,405541,1057978
+North Devon,E07000043,1,88252,396085
+North Devon,E07000043,2,105062,396085
+North Devon,E07000043,3,161796,446515
+North Devon,E07000043,4,243745,793221
+North East Derbyshire,E07000038,1,75645,307833
+North East Derbyshire,E07000038,2,75645,307833
+North East Derbyshire,E07000038,3,111366,404490
+North East Derbyshire,E07000038,4,219580,842600
+North East Lincolnshire,E06000012,1,50430,243745
+North East Lincolnshire,E06000012,2,66189,243745
+North East Lincolnshire,E06000012,3,82999,270010
+North East Lincolnshire,E06000012,4,153391,536869
+North Hertfordshire,E07000099,1,102961,504300
+North Hertfordshire,E07000099,2,150239,504300
+North Hertfordshire,E07000099,3,303630,717576
+North Hertfordshire,E07000099,4,432857,1487684
+North Kesteven,E07000139,1,80898,323592
+North Kesteven,E07000139,2,80898,323592
+North Kesteven,E07000139,3,141834,350908
+North Kesteven,E07000139,4,238492,605159
+North Lincolnshire,E06000013,1,68291,277365
+North Lincolnshire,E06000013,2,79847,277365
+North Lincolnshire,E06000013,3,95607,291023
+North Lincolnshire,E06000013,4,177555,534768
+North Norfolk,E07000147,1,100860,384528
+North Norfolk,E07000147,2,130277,384528
+North Norfolk,E07000147,3,168100,484338
+North Norfolk,E07000147,4,239542,1023308
+North Northamptonshire,E06000061,1,75645,315187
+North Northamptonshire,E06000061,2,90354,315187
+North Northamptonshire,E06000061,3,161796,388731
+North Northamptonshire,E06000061,4,257403,746994
+North Somerset,E06000024,1,102961,410794
+North Somerset,E06000024,2,138682,410794
+North Somerset,E06000024,3,212226,561033
+North Somerset,E06000024,4,292073,1054826
+North Tyneside,E08000022,1,66189,251099
+North Tyneside,E08000022,2,66189,251099
+North Tyneside,E08000022,3,87202,356162
+North Tyneside,E08000022,4,195416,591501
+North Warwickshire,E07000218,1,107164,351959
+North Warwickshire,E07000218,2,112417,351959
+North Warwickshire,E07000218,3,146037,413946
+North Warwickshire,E07000218,4,247947,924549
+North West Leicestershire,E07000134,1,98759,300478
+North West Leicestershire,E07000134,2,98759,300478
+North West Leicestershire,E07000134,3,123974,380326
+North West Leicestershire,E07000134,4,258454,699716
+North Yorkshire,E06000065,1,77746,366668
+North Yorkshire,E06000065,2,102961,366668
+North Yorkshire,E06000065,3,136581,473831
+North Yorkshire,E06000065,4,223783,959220
+Northumberland,E06000057,1,58835,318339
+Northumberland,E06000057,2,60936,318339
+Northumberland,E06000057,3,90354,359313
+Northumberland,E06000057,4,179657,754348
+Norwich,E07000148,1,78797,251099
+Norwich,E07000148,2,78797,329896
+Norwich,E07000148,3,141834,444414
+Norwich,E07000148,4,219580,916144
+Nottingham,E06000018,1,68291,289972
+Nottingham,E06000018,2,75645,289972
+Nottingham,E06000018,3,85101,334098
+Nottingham,E06000018,4,157594,727032
+Nuneaton and Bedworth,E07000219,1,90354,254251
+Nuneaton and Bedworth,E07000219,2,93506,254251
+Nuneaton and Bedworth,E07000219,3,135530,340402
+Nuneaton and Bedworth,E07000219,4,214327,608311
+Oadby and Wigston,E07000135,1,86151,288922
+Oadby and Wigston,E07000135,2,119771,288922
+Oadby and Wigston,E07000135,3,179657,382427
+Oadby and Wigston,E07000135,4,281567,869917
+Oldham,E08000004,1,80898,250049
+Oldham,E08000004,2,80898,250049
+Oldham,E08000004,3,101911,340402
+Oldham,E08000004,4,152340,753297
+Oxford,E07000178,1,120822,626172
+Oxford,E07000178,2,189112,674501
+Oxford,E07000178,3,313086,758551
+Oxford,E07000178,4,420250,2164285
+Pendle,E07000122,1,56734,239542
+Pendle,E07000122,2,57784,239542
+Pendle,E07000122,3,77746,349858
+Pendle,E07000122,4,148138,668197
+Peterborough,E06000031,1,71442,268960
+Peterborough,E06000031,2,85101,268960
+Peterborough,E06000031,3,144986,321491
+Peterborough,E06000031,4,213277,665045
+Plymouth,E06000026,1,87202,305732
+Plymouth,E06000026,2,90354,305732
+Plymouth,E06000026,3,140784,353010
+Plymouth,E06000026,4,208024,606210
+Portsmouth,E06000044,1,101911,317288
+Portsmouth,E06000044,2,138682,325693
+Portsmouth,E06000044,3,193315,430756
+Portsmouth,E06000044,4,263707,835246
+Preston,E07000123,1,45177,241644
+Preston,E07000123,2,78797,241644
+Preston,E07000123,3,100860,314137
+Preston,E07000123,4,188062,619868
+Reading,E06000038,1,134480,413946
+Reading,E06000038,2,217479,449667
+Reading,E06000038,3,304681,632476
+Reading,E06000038,4,408693,1096851
+Redbridge,E09000026,1,97708,474882
+Redbridge,E09000026,2,154442,610413
+Redbridge,E09000026,3,339352,789019
+Redbridge,E09000026,4,465426,1269154
+Redcar and Cleveland,E06000003,1,58835,233239
+Redcar and Cleveland,E06000003,2,58835,233239
+Redcar and Cleveland,E06000003,3,78797,260555
+Redcar and Cleveland,E06000003,4,151290,460173
+Redditch,E07000236,1,54632,282618
+Redditch,E07000236,2,97708,282618
+Redditch,E07000236,3,150239,371921
+Redditch,E07000236,4,245846,598856
+Reigate and Banstead,E07000211,1,147087,548426
+Reigate and Banstead,E07000211,2,147087,548426
+Reigate and Banstead,E07000211,3,365617,824740
+Reigate and Banstead,E07000211,4,497996,1787111
+Ribble Valley,E07000124,1,110316,334098
+Ribble Valley,E07000124,2,110316,334098
+Ribble Valley,E07000124,3,125024,461224
+Ribble Valley,E07000124,4,268960,893030
+Richmond upon Thames,E09000027,1,208024,761702
+Richmond upon Thames,E09000027,2,329896,934005
+Richmond upon Thames,E09000027,3,459123,1293318
+Richmond upon Thames,E09000027,4,654539,2522548
+Rochdale,E08000005,1,69341,214327
+Rochdale,E08000005,2,71442,214327
+Rochdale,E08000005,3,97708,301529
+Rochdale,E08000005,4,165999,567337
+Rochford,E07000075,1,140784,471730
+Rochford,E07000075,2,225884,471730
+Rochford,E07000075,3,305732,558932
+Rochford,E07000075,4,387680,965523
+Rossendale,E07000125,1,60936,270010
+Rossendale,E07000125,2,73544,270010
+Rossendale,E07000125,3,102961,365617
+Rossendale,E07000125,4,179657,702867
+Rother,E07000064,1,99809,387680
+Rother,E07000064,2,143935,434958
+Rother,E07000064,3,222732,599906
+Rother,E07000064,4,334098,1112611
+Rotherham,E08000018,1,66189,235340
+Rotherham,E08000018,2,69341,235340
+Rotherham,E08000018,3,86151,291023
+Rotherham,E08000018,4,165999,548426
+Rugby,E07000220,1,104012,327795
+Rugby,E07000220,2,104012,327795
+Rugby,E07000220,3,175454,421300
+Rugby,E07000220,4,299428,797424
+Runnymede,E07000212,1,136581,517958
+Runnymede,E07000212,2,169150,555780
+Runnymede,E07000212,3,380326,781664
+Runnymede,E07000212,4,512705,1569632
+Rushcliffe,E07000176,1,94556,488540
+Rushcliffe,E07000176,2,94556,488540
+Rushcliffe,E07000176,3,170201,504300
+Rushcliffe,E07000176,4,314137,906689
+Rushmoor,E07000092,1,101911,393984
+Rushmoor,E07000092,2,174404,393984
+Rushmoor,E07000092,3,302580,529514
+Rushmoor,E07000092,4,412895,793221
+Rutland,E06000017,1,85101,371921
+Rutland,E06000017,2,85101,431806
+Rutland,E06000017,3,182809,587299
+Rutland,E06000017,4,318339,1205066
+Salford,E08000006,1,89303,339352
+Salford,E08000006,2,99809,339352
+Salford,E08000006,3,125024,378225
+Salford,E08000006,4,200669,748044
+Sandwell,E08000028,1,68291,230087
+Sandwell,E08000028,2,91404,230087
+Sandwell,E08000028,3,119771,308883
+Sandwell,E08000028,4,176505,444414
+Sefton,E08000014,1,74594,344605
+Sefton,E08000014,2,81949,344605
+Sefton,E08000014,3,99809,359313
+Sefton,E08000014,4,173353,802677
+Sevenoaks,E07000111,1,177555,646134
+Sevenoaks,E07000111,2,177555,646134
+Sevenoaks,E07000111,3,312035,897233
+Sevenoaks,E07000111,4,448616,2157982
+Sheffield,E08000039,1,72493,303630
+Sheffield,E08000039,2,75645,303630
+Sheffield,E08000039,3,102961,403440
+Sheffield,E08000039,4,201720,879372
+Shropshire,E06000051,1,80898,388731
+Shropshire,E06000051,2,102961,388731
+Shropshire,E06000051,3,156543,444414
+Shropshire,E06000051,4,240593,811082
+Slough,E06000039,1,155492,425503
+Slough,E06000039,2,214327,441262
+Slough,E06000039,3,336200,653488
+Slough,E06000039,4,412895,958169
+Solihull,E08000029,1,89303,492743
+Solihull,E08000029,2,118721,492743
+Solihull,E08000029,3,154442,545274
+Solihull,E08000029,4,327795,1218724
+Somerset,E06000066,1,92455,359313
+Somerset,E06000066,2,114518,359313
+Somerset,E06000066,3,172302,447566
+Somerset,E06000066,4,265808,875170
+South Cambridgeshire,E07000012,1,130277,486439
+South Cambridgeshire,E07000012,2,156543,486439
+South Cambridgeshire,E07000012,3,258454,653488
+South Cambridgeshire,E07000012,4,384528,1164091
+South Derbyshire,E07000039,1,89303,315187
+South Derbyshire,E07000039,2,89303,315187
+South Derbyshire,E07000039,3,142885,362465
+South Derbyshire,E07000039,4,245846,713374
+South Gloucestershire,E06000025,1,90354,377174
+South Gloucestershire,E06000025,2,136581,377174
+South Gloucestershire,E06000025,3,251099,486439
+South Gloucestershire,E06000025,4,369820,849955
+South Hams,E07000044,1,100860,480135
+South Hams,E07000044,2,100860,480135
+South Hams,E07000044,3,197517,663994
+South Hams,E07000044,4,319390,1128370
+South Holland,E07000140,1,66189,265808
+South Holland,E07000140,2,66189,265808
+South Holland,E07000140,3,131328,350908
+South Holland,E07000140,4,226935,593603
+South Kesteven,E07000141,1,80898,341453
+South Kesteven,E07000141,2,88252,341453
+South Kesteven,E07000141,3,136581,427604
+South Kesteven,E07000141,4,238492,862562
+South Norfolk,E07000149,1,101911,347757
+South Norfolk,E07000149,2,101911,347757
+South Norfolk,E07000149,3,203821,460173
+South Norfolk,E07000149,4,281567,773259
+South Oxfordshire,E07000179,1,144986,587299
+South Oxfordshire,E07000179,2,144986,587299
+South Oxfordshire,E07000179,3,277365,748044
+South Oxfordshire,E07000179,4,420250,1812326
+South Ribble,E07000126,1,91404,268960
+South Ribble,E07000126,2,91404,268960
+South Ribble,E07000126,3,130277,321491
+South Ribble,E07000126,4,215378,611463
+South Staffordshire,E07000196,1,86151,351959
+South Staffordshire,E07000196,2,93506,351959
+South Staffordshire,E07000196,3,161796,453870
+South Staffordshire,E07000196,4,245846,811082
+South Tyneside,E08000023,1,55683,236390
+South Tyneside,E08000023,2,64088,236390
+South Tyneside,E08000023,3,76696,308883
+South Tyneside,E08000023,4,154442,595704
+Southampton,E06000045,1,76696,242694
+Southampton,E06000045,2,141834,331997
+Southampton,E06000045,3,205922,428655
+Southampton,E06000045,4,253200,758551
+Southend-on-Sea,E06000033,1,121872,430756
+Southend-on-Sea,E06000033,2,147087,480135
+Southend-on-Sea,E06000033,3,264757,628273
+Southend-on-Sea,E06000033,4,359313,1082143
+Southwark,E09000028,1,137632,645083
+Southwark,E09000028,2,176505,885676
+Southwark,E09000028,3,326744,1199813
+Southwark,E09000028,4,548426,2388068
+Spelthorne,E07000213,1,216429,534768
+Spelthorne,E07000213,2,279466,553679
+Spelthorne,E07000213,3,374022,733336
+Spelthorne,E07000213,4,500097,1205066
+St Albans,E07000240,1,184910,780614
+St Albans,E07000240,2,288922,780614
+St Albans,E07000240,3,423401,1028561
+St Albans,E07000240,4,648235,1973072
+St. Helens,E08000013,1,72493,215378
+St. Helens,E08000013,2,74594,215378
+St. Helens,E08000013,3,92455,300478
+St. Helens,E08000013,4,165999,599906
+Stafford,E07000197,1,72493,343554
+Stafford,E07000197,2,82999,343554
+Stafford,E07000197,3,142885,412895
+Stafford,E07000197,4,245846,702867
+Staffordshire Moorlands,E07000198,1,91404,330947
+Staffordshire Moorlands,E07000198,2,104012,330947
+Staffordshire Moorlands,E07000198,3,134480,422351
+Staffordshire Moorlands,E07000198,4,205922,789019
+Stevenage,E07000243,1,84050,374022
+Stevenage,E07000243,2,104012,374022
+Stevenage,E07000243,3,283668,481186
+Stevenage,E07000243,4,313086,810031
+Stockport,E08000007,1,90354,378225
+Stockport,E08000007,2,95607,378225
+Stockport,E08000007,3,165999,503249
+Stockport,E08000007,4,287871,1034865
+Stockton-on-Tees,E06000004,1,56734,234289
+Stockton-on-Tees,E06000004,2,56734,234289
+Stockton-on-Tees,E06000004,3,81949,287871
+Stockton-on-Tees,E06000004,4,170201,613564
+Stoke-on-Trent,E06000021,1,68291,188062
+Stoke-on-Trent,E06000021,2,68291,188062
+Stoke-on-Trent,E06000021,3,80898,274213
+Stoke-on-Trent,E06000021,4,170201,515856
+Stratford-on-Avon,E07000221,1,107164,465426
+Stratford-on-Avon,E07000221,2,107164,465426
+Stratford-on-Avon,E07000221,3,189112,619868
+Stratford-on-Avon,E07000221,4,366668,1277559
+Stroud,E07000082,1,94556,416047
+Stroud,E07000082,2,115569,416047
+Stroud,E07000082,3,210125,562084
+Stroud,E07000082,4,315187,1072687
+Sunderland,E08000024,1,57784,203821
+Sunderland,E08000024,2,63037,203821
+Sunderland,E08000024,3,77746,268960
+Sunderland,E08000024,4,132379,490641
+Surrey Heath,E07000214,1,152340,548426
+Surrey Heath,E07000214,2,152340,548426
+Surrey Heath,E07000214,3,349858,697614
+Surrey Heath,E07000214,4,504300,1323786
+Sutton,E09000029,1,121872,423401
+Sutton,E09000029,2,224834,472781
+Sutton,E09000029,3,345655,660842
+Sutton,E09000029,4,483287,1195610
+Swale,E07000113,1,110316,354060
+Swale,E07000113,2,115569,354060
+Swale,E07000113,3,197517,465426
+Swale,E07000113,4,303630,900385
+Swindon,E06000030,1,109265,302580
+Swindon,E06000030,2,112417,302580
+Swindon,E06000030,3,198568,412895
+Swindon,E06000030,4,307833,733336
+Tameside,E08000008,1,93506,225884
+Tameside,E08000008,2,105062,225884
+Tameside,E08000008,3,132379,320440
+Tameside,E08000008,4,199619,648235
+Tamworth,E07000199,1,97708,256352
+Tamworth,E07000199,2,110316,256352
+Tamworth,E07000199,3,151290,363516
+Tamworth,E07000199,4,232188,580995
+Tandridge,E07000215,1,180707,573641
+Tandridge,E07000215,2,214327,573641
+Tandridge,E07000215,3,374022,836297
+Tandridge,E07000215,4,507451,1869060
+Teignbridge,E07000045,1,93506,400288
+Teignbridge,E07000045,2,107164,400288
+Teignbridge,E07000045,3,198568,487490
+Teignbridge,E07000045,4,287871,908790
+Telford and Wrekin,E06000020,1,81949,247947
+Telford and Wrekin,E06000020,2,91404,247947
+Telford and Wrekin,E06000020,3,112417,317288
+Telford and Wrekin,E06000020,4,200669,590451
+Tendring,E07000076,1,78797,343554
+Tendring,E07000076,2,130277,343554
+Tendring,E07000076,3,175454,449667
+Tendring,E07000076,4,267909,874119
+Test Valley,E07000093,1,107164,480135
+Test Valley,E07000093,2,109265,487490
+Test Valley,E07000093,3,205922,550527
+Test Valley,E07000093,4,340402,1104206
+North Gloucestershire,E07000083,1,68291,348807
+North Gloucestershire,E07000083,2,97708,348807
+North Gloucestershire,E07000083,3,148138,486439
+North Gloucestershire,E07000083,4,336200,885676
+Thanet,E07000114,1,96657,360364
+Thanet,E07000114,2,146037,360364
+Thanet,E07000114,3,206973,462275
+Thanet,E07000114,4,278415,777462
+Three Rivers,E07000102,1,204872,548426
+Three Rivers,E07000102,2,274213,737538
+Three Rivers,E07000102,3,403440,955017
+Three Rivers,E07000102,4,584147,2041362
+Thurrock,E06000034,1,128176,382427
+Thurrock,E06000034,2,168100,382427
+Thurrock,E06000034,3,264757,489591
+Thurrock,E06000034,4,360364,768006
+Tonbridge and Malling,E07000115,1,117670,450718
+Tonbridge and Malling,E07000115,2,127126,450718
+Tonbridge and Malling,E07000115,3,279466,659792
+Tonbridge and Malling,E07000115,4,419199,1255496
+Torbay,E06000027,1,88252,365617
+Torbay,E06000027,2,114518,365617
+Torbay,E06000027,3,165999,423401
+Torbay,E06000027,4,224834,743842
+Torridge,E07000046,1,105062,355111
+Torridge,E07000046,2,130277,355111
+Torridge,E07000046,3,172302,489591
+Torridge,E07000046,4,237441,770107
+Tower Hamlets,E09000030,1,146037,588349
+Tower Hamlets,E09000030,2,194365,832094
+Tower Hamlets,E09000030,3,248998,1274407
+Tower Hamlets,E09000030,4,427604,1810225
+Trafford,E08000009,1,97708,494844
+Trafford,E08000009,2,143935,494844
+Trafford,E08000009,3,202770,591501
+Trafford,E08000009,4,329896,1555974
+Tunbridge Wells,E07000116,1,97708,551578
+Tunbridge Wells,E07000116,2,136581,551578
+Tunbridge Wells,E07000116,3,310985,804778
+Tunbridge Wells,E07000116,4,467528,1650530
+Uttlesford,E07000077,1,78797,517958
+Uttlesford,E07000077,2,134480,517958
+Uttlesford,E07000077,3,254251,655589
+Uttlesford,E07000077,4,454920,1428849
+Vale of White Horse,E07000180,1,93506,451768
+Vale of White Horse,E07000180,2,126075,451768
+Vale of White Horse,E07000180,3,261605,558932
+Vale of White Horse,E07000180,4,390832,1104206
+Wakefield,E08000036,1,70392,222732
+Wakefield,E08000036,2,84050,222732
+Wakefield,E08000036,3,101911,307833
+Wakefield,E08000036,4,182809,577843
+Walsall,E08000030,1,75645,262656
+Walsall,E08000030,2,94556,262656
+Walsall,E08000030,3,115569,365617
+Walsall,E08000030,4,194365,814234
+Waltham Forest,E09000031,1,139733,513755
+Waltham Forest,E09000031,2,244795,613564
+Waltham Forest,E09000031,3,382427,783766
+Waltham Forest,E09000031,4,486439,1020156
+Wandsworth,E09000032,1,163897,682906
+Wandsworth,E09000032,2,271061,928752
+Wandsworth,E09000032,3,438110,1335343
+Wandsworth,E09000032,4,765905,2601345
+Warrington,E06000007,1,88252,344605
+Warrington,E06000007,2,102961,344605
+Warrington,E06000007,3,128176,428655
+Warrington,E06000007,4,239542,903537
+Warwick,E07000222,1,99809,451768
+Warwick,E07000222,2,132379,451768
+Warwick,E07000222,3,253200,617767
+Warwick,E07000222,4,402389,1196661
+Watford,E07000103,1,189112,492743
+Watford,E07000103,2,267909,522160
+Watford,E07000103,3,383478,811082
+Watford,E07000103,4,496945,1427798
+Waverley,E07000216,1,154442,690260
+Waverley,E07000216,2,196467,690260
+Waverley,E07000216,3,364567,886727
+Waverley,E07000216,4,538970,2104400
+Wealden,E07000065,1,122923,496945
+Wealden,E07000065,2,165999,496945
+Wealden,E07000065,3,252150,659792
+Wealden,E07000065,4,371921,1446709
+Welwyn Hatfield,E07000241,1,99809,460173
+Welwyn Hatfield,E07000241,2,141834,563134
+Welwyn Hatfield,E07000241,3,316238,786917
+Welwyn Hatfield,E07000241,4,470680,1636872
+West Berkshire,E06000037,1,92455,491692
+West Berkshire,E06000037,2,130277,491692
+West Berkshire,E06000037,3,298377,663994
+West Berkshire,E06000037,4,431806,1461418
+West Devon,E07000047,1,90354,402389
+West Devon,E07000047,2,138682,402389
+West Devon,E07000047,3,195416,503249
+West Devon,E07000047,4,246897,971827
+West Lancashire,E07000127,1,54632,391883
+West Lancashire,E07000127,2,77746,391883
+West Lancashire,E07000127,3,77746,412895
+West Lancashire,E07000127,4,127126,840499
+West Lindsey,E07000142,1,74594,304681
+West Lindsey,E07000142,2,74594,304681
+West Lindsey,E07000142,3,105062,355111
+West Lindsey,E07000142,4,185960,659792
+West Northamptonshire,E06000062,1,56734,354060
+West Northamptonshire,E06000062,2,94556,354060
+West Northamptonshire,E06000062,3,176505,454920
+West Northamptonshire,E06000062,4,305732,904587
+West Oxfordshire,E07000181,1,113467,461224
+West Oxfordshire,E07000181,2,116619,461224
+West Oxfordshire,E07000181,3,266858,607261
+West Oxfordshire,E07000181,4,360364,1147281
+West Suffolk,E07000245,1,99809,350908
+West Suffolk,E07000245,2,120822,350908
+West Suffolk,E07000245,3,182809,453870
+West Suffolk,E07000245,4,265808,853107
+Westminster,E09000033,1,267909,979182
+Westminster,E09000033,2,455971,1952059
+Westminster,E09000033,3,534768,3224365
+Westminster,E09000033,4,829993,10992679
+Westmorland,E06000064,1,77746,329896
+Westmorland,E06000064,2,77746,329896
+Westmorland,E06000064,3,109265,437060
+Westmorland,E06000064,4,185960,735437
+Wigan,E08000010,1,77746,232188
+Wigan,E08000010,2,77746,232188
+Wigan,E08000010,3,94556,303630
+Wigan,E08000010,4,188062,506401
+Wiltshire,E06000054,1,99809,418148
+Wiltshire,E06000054,2,114518,418148
+Wiltshire,E06000054,3,214327,538970
+Wiltshire,E06000054,4,325693,1087396
+Winchester,E07000094,1,118721,595704
+Winchester,E07000094,2,131328,630374
+Winchester,E07000094,3,284719,853107
+Winchester,E07000094,4,437060,1542316
+Windsor and Maidenhead,E06000040,1,217479,663994
+Windsor and Maidenhead,E06000040,2,293124,663994
+Windsor and Maidenhead,E06000040,3,402389,929802
+Windsor and Maidenhead,E06000040,4,570489,1965718
+Wirral,E08000015,1,73544,334098
+Wirral,E08000015,2,85101,334098
+Wirral,E08000015,3,107164,358263
+Wirral,E08000015,4,153391,780614
+Woking,E07000217,1,182809,544223
+Woking,E07000217,2,266858,544223
+Woking,E07000217,3,375073,835246
+Woking,E07000217,4,513755,1670492
+Wokingham,E06000041,1,133429,521110
+Wokingham,E06000041,2,143935,521110
+Wokingham,E06000041,3,277365,654539
+Wokingham,E06000041,4,494844,1239736
+Wolverhampton,E08000031,1,40974,237441
+Wolverhampton,E08000031,2,66189,237441
+Wolverhampton,E08000031,3,96657,312035
+Wolverhampton,E08000031,4,161796,671349
+Worcester,E07000237,1,86151,295225
+Worcester,E07000237,2,131328,295225
+Worcester,E07000237,3,181758,403440
+Worcester,E07000237,4,277365,757500
+Worthing,E07000229,1,140784,439161
+Worthing,E07000229,2,179657,444414
+Worthing,E07000229,3,283668,559983
+Worthing,E07000229,4,375073,824740
+Wychavon,E07000238,1,95607,412895
+Wychavon,E07000238,2,95607,431806
+Wychavon,E07000238,3,159695,521110
+Wychavon,E07000238,4,305732,925600
+Wyre,E07000128,1,68291,313086
+Wyre,E07000128,2,82999,313086
+Wyre,E07000128,3,109265,363516
+Wyre,E07000128,4,190163,618818
+Wyre Forest,E07000239,1,89303,341453
+Wyre Forest,E07000239,2,95607,341453
+Wyre Forest,E07000239,3,139733,380326
+Wyre Forest,E07000239,4,220631,787968
+York,E06000014,1,99809,395035
+York,E06000014,2,164948,395035
+York,E06000014,3,210125,505350
+York,E06000014,4,307833,938207
diff --git a/db/migrate/20260305095832_add_service_charge_changed_to_sales_logs.rb b/db/migrate/20260305095832_add_service_charge_changed_to_sales_logs.rb
new file mode 100644
index 000000000..364997d7e
--- /dev/null
+++ b/db/migrate/20260305095832_add_service_charge_changed_to_sales_logs.rb
@@ -0,0 +1,8 @@
+class AddServiceChargeChangedToSalesLogs < ActiveRecord::Migration[7.2]
+ def change
+ change_table :sales_logs, bulk: true do |t|
+ t.column :hasservicechargeschanged, :integer
+ t.column :newservicecharges, :decimal, precision: 10, scale: 2
+ end
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index e98de52d3..37e5c764e 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_02_25_135309) do
+ActiveRecord::Schema[7.2].define(version: 2026_03_05_095832) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -824,8 +824,10 @@ ActiveRecord::Schema[7.2].define(version: 2026_02_25_135309) do
t.string "sexrab4"
t.string "sexrab5"
t.string "sexrab6"
- t.integer "mortlen_known"
t.integer "buildheightclass"
+ t.integer "mortlen_known"
+ t.integer "hasservicechargeschanged"
+ t.decimal "newservicecharges", precision: 10, scale: 2
t.integer "gender_same_as_sex1"
t.integer "gender_same_as_sex2"
t.integer "gender_same_as_sex3"
diff --git a/spec/factories/sales_log.rb b/spec/factories/sales_log.rb
index 51bca33b8..ddc47bb53 100644
--- a/spec/factories/sales_log.rb
+++ b/spec/factories/sales_log.rb
@@ -67,6 +67,7 @@ FactoryBot.define do
sexrab1 { "F" }
sex1 { "F" }
ecstat1 { 1 }
+ address_line1 { "same address line 1" }
postcode_full { "A1 1AA" }
noint { 2 }
uprn_known { 0 }
diff --git a/spec/features/sales_log_spec.rb b/spec/features/sales_log_spec.rb
index 97e6549d0..d576e7601 100644
--- a/spec/features/sales_log_spec.rb
+++ b/spec/features/sales_log_spec.rb
@@ -352,16 +352,6 @@ RSpec.describe "Sales Log Features" do
end
context "when a log becomes a duplicate" do
- before do
- Timecop.freeze(Time.zone.local(2024, 3, 3))
- Singleton.__init__(FormHandler)
- end
-
- after do
- Timecop.return
- Singleton.__init__(FormHandler)
- end
-
context "and updating duplicate log" do
let(:user) { create(:user, :data_coordinator) }
let(:sales_log) { create(:sales_log, :duplicate, assigned_to: user) }
diff --git a/spec/fixtures/exports/sales_log_26_27.xml b/spec/fixtures/exports/sales_log_26_27.xml
index a4545f95d..ee80db67f 100644
--- a/spec/fixtures/exports/sales_log_26_27.xml
+++ b/spec/fixtures/exports/sales_log_26_27.xml
@@ -20,7 +20,7 @@
1
1
1
- 4
+ 6
14
E09000033
10000
@@ -163,5 +163,7 @@
+
+
diff --git a/spec/fixtures/files/2026_27_sales_bulk_upload.csv b/spec/fixtures/files/2026_27_sales_bulk_upload.csv
index efab2c088..3f4dc0142 100644
--- a/spec/fixtures/files/2026_27_sales_bulk_upload.csv
+++ b/spec/fixtures/files/2026_27_sales_bulk_upload.csv
@@ -1,23 +1,23 @@
-Section,Setting up this sales log,,,,,,,,,,,,,,,Property information,,,,,,,,,,,,Household characteristics,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Household situation,,,,,,,Other household information,,,,,"Income, benefits and outgoings",,,,,,,,Shared ownership - initial purchase,,,,,,,,,,,,,,,,,,Shared ownership - staircasing transaction,,,,,,,,,,,,,,,,Discounted ownership,,,,,,,,,,,,,,,,,,,,,,
-Question,What is the sale completion date? - day DD,What is the sale completion date? - month MM,What is the sale completion date? - year YY,Which organisation owned this property before the sale?,Which organisation is reporting this sale?,What is the CORE username of the account this sale log should be assigned to? ,What is the purchaser code?,Is this a shared ownership or discounted ownership sale?,What is the type of shared ownership sale?,Is this a staircasing transaction?,What is the type of discounted ownership sale?,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 or been given access to the MHCLG privacy notice?,"If known, enter this property’s UPRN",Address Line 1,Address Line 2,Town or city,County,Part 1 of the property's postcode,Part 2 of the property's postcode,What is the property's local authority?,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?,What is buyer 1's sex?,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 the partner of buyer 1?,What is buyer 2 or person 2's age?,What is buyer 2 or person 2's sex?,Which of the following best describes buyer 2's ethnic background?,What is buyer 2's nationality?,Which of these best describes 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 sex?,Which of these best describes 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?,Which of these best describes 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?,Which of these best describes 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?,Which of these best describes 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,What is the local authority 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?,What is buyer 1's annual income?,Was buyer 1's income used for a mortgage application?,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?,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?,What is the day of the practical completion or handover date? - DD,What is the month of the practical completion or handover date? - MM,What is the year of the practical completion or handover date? - YY,How many bedrooms did the buyer's previous property have?,What was the previous property type?,What was the buyer’s previous tenure?,What is the full purchase price?,What was the initial percentage share 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 are the total monthly service charges for the property?,What are the total monthly estate management fees for the property?,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 buyer has engaged in staircasing in the home?,What was the day of the initial purchase of a share in the property? DD,What was the month of the initial purchase of a share in the property? MM,What was the year of the initial purchase of a share in the property? YYYY,"Including this time, how many times has the shared owner engaged in staircasing in the home?",What was the day of the last staircasing transaction? DD,What was the month of the last staircasing transaction? MM,What was the year of the last staircasing transaction? YYYY,What is the full purchase price for this staircasing transaction?,What was the percentage share purchased in the initial transaction?,Was a mortgage used for this staircasing transaction?,What was the basic monthly rent prior to staircasing?,What is the basic monthly rent after staircasing?,How long did the buyer(s) live in the property before purchasing it?,What is the full purchase price?,"What was the amount of any loan, grant, discount or subsidy given?",What was the percentage discount?,Was a mortgage used to buy this property?,What is the mortgage amount?,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?,What are the total monthly leasehold charges for the property?,What is the building height classification?,Is the gender buyer 1 identifies with the same as their sex registered at birth?,"If 'No', enter buyer 1's gender identity",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",Is the gender person 3 identifies with the same as their sex registered at birth?,"If 'No', enter person 3's gender identity",Is the gender person 4 identifies with the same as their sex registered at birth?,"If 'No', enter person 4's gender identity",Is the gender person 5 identifies with the same as their sex registered at birth?,"If 'No', enter person 5's gender identity",Is the gender person 6 identifies with the same as their sex registered at birth?,"If 'No', enter person 6's gender identity"
+Section,Setting up this sales log,,,,,,,,,,,,,,,Property information,,,,,,,,,,,,Household characteristics,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,Household situation,,,,,,,Other household information,,,,,"Income, benefits and outgoings",,,,,,,,Shared ownership - initial purchase,,,,,,,,,,,,,,,,,,Shared ownership - staircasing transaction,,,,,,,,,,,,,,,,Discounted ownership,,,,,,,,,,,,,,,,,,,,,,,,
+Question,What is the sale completion date? - day DD,What is the sale completion date? - month MM,What is the sale completion date? - year YY,Which organisation owned this property before the sale?,Which organisation is reporting this sale?,What is the CORE username of the account this sale log should be assigned to? ,What is the purchaser code?,Is this a shared ownership or discounted ownership sale?,What is the type of shared ownership sale?,Is this a staircasing transaction?,What is the type of discounted ownership sale?,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 or been given access to the MHCLG privacy notice?,"If known, enter this property’s UPRN",Address Line 1,Address Line 2,Town or city,County,Part 1 of the property's postcode,Part 2 of the property's postcode,What is the property's local authority?,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?,What is buyer 1's sex?,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 the partner of buyer 1?,What is buyer 2 or person 2's age?,What is buyer 2 or person 2's sex?,Which of the following best describes buyer 2's ethnic background?,What is buyer 2's nationality?,Which of these best describes 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?,Which of these best describes 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?,Which of these best describes 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?,Which of these best describes 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?,Which of these best describes 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,What is the local authority 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?,What is buyer 1's annual income?,Was buyer 1's income used for a mortgage application?,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?,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?,What is the day of the practical completion or handover date? - DD,What is the month of the practical completion or handover date? - MM,What is the year of the practical completion or handover date? - YY,How many bedrooms did the buyer's previous property have?,What was the previous property type?,What was the buyer’s previous tenure?,What is the full purchase price?,What was the initial percentage share 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 are the total monthly service charges for the property?,What are the total monthly estate management fees for the property?,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 buyer has engaged in staircasing in the home?,What was the day of the initial purchase of a share in the property? DD,What was the month of the initial purchase of a share in the property? MM,What was the year of the initial purchase of a share in the property? YYYY,"Including this time, how many times has the shared owner engaged in staircasing in the home?",What was the day of the last staircasing transaction? DD,What was the month of the last staircasing transaction? MM,What was the year of the last staircasing transaction? YYYY,What is the full purchase price for this staircasing transaction?,What was the percentage share purchased in the initial transaction?,Was a mortgage used for this staircasing transaction?,What was the basic monthly rent prior to staircasing?,What is the basic monthly rent after staircasing?,How long did the buyer(s) live in the property before purchasing it?,What is the full purchase price?,"What was the amount of any loan, grant, discount or subsidy given?",What was the percentage discount?,Was a mortgage used to buy this property?,What is the mortgage amount?,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?,What are the total monthly leasehold charges for the property?,What is the building height classification?,Is the gender buyer 1 identifies with the same as their sex registered at birth?,"If 'No', enter buyer 1's gender identity",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",Is the gender person 3 identifies with the same as their sex registered at birth?,"If 'No', enter person 3's gender identity",Is the gender person 4 identifies with the same as their sex registered at birth?,"If 'No', enter person 4's gender identity",Is the gender person 5 identifies with the same as their sex registered at birth?,"If 'No', enter person 5's gender identity",Is the gender person 6 identifies with the same as their sex registered at birth?,"If 'No', enter person 6's gender identity",Will the service charge change after this staircasing transaction takes place?,What are the new total monthly service charges for the property?
Additional info,,,,"You can find the org ID on the CORE service under 'Stock owners' or, if your organisation is the stock owner, under 'About your organisation'","You can find the org ID on the CORE service under 'Managing agents' or, if your organisation is the managing agent, under 'About your organisation'","If left empty, the sales log will be assigned to the account used to upload the log.",This is how you usually refer to this buyer on your own systems,"Sales logs are no longer required for outright and other sales.
A shared ownership sale is when the purchaser buys an initial share of up to 75% of the property value and pays rent to the Private Registered Provider (PRP) on the remaining portion, or a subsequent staircasing transaction",See specification for full description of each scheme,"A staircasing transaction is when the household purchases more shares in their property, increasing the proportion they own and decreasing the proportion the housing association owns. Once the household purchases 100% of the shares, they own the property.",See specification for full description of each scheme,This is where two or more people are named as legal owners of the property after the purchase.,,You should still try to answer all questions even if the buyer wasn't interviewed in person,"Make sure the buyer has seen or been given access to the Ministry of Housing, Communities and Local Government (MHCLG) privacy notice before completing this log. This is a legal requirement under data protection legislation.","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 UPRN is 10010457355.
-The UPRN may not be the same as the property reference assigned by your organisation.",,,,,Combined with field 28 it should be a postcode which lies within the local authority given in field 29.,Combined with field 27 it should be a postcode which lies within the local authority given in field 29.,,,"For bedsits, enter ‘1’",,"This is whether someone who uses a wheelchair is able to make full use of all of the property’s rooms and facilities, including use of both inside and outside space, and entering and exiting the property.","Buyer 1 is the person in the household who does the most paid work. If it’s a joint purchase and the buyers do the same amount of paid work, buyer 1 is whoever is the oldest.",,,"If buyer 1 is a dual national of the United Kingdom and another country, enter United Kingdom. If they are a dual national of two other countries, they should decide which country to enter.","Buyer 1 is the person in the household who does the most paid work. If it’s a joint purchase and the buyers do the same amount of paid work, buyer 1 is whoever is the oldest.",,,,,,"If buyer 2 is a dual national of the United Kingdom and another country, enter United Kingdom. If they are a dual national of two other countries, they should decide which country to enter.",,,"You can provide details for a maximum of 4 other people if there are 2 buyers, or 5 other people if there is only one buyer",,,,,,,,,,,,,,,,,,This is also known as the household's 'last settled home',,,,,,"A regular is somebody who has served in the Royal Navy, the Royal Marines, the Royal Air Force or army full time and does not include reserve forces",,"A regular is somebody who has served in the Royal Navy, the Royal Marines, the Royal Air Force or army full time and does not include reserve forces",This includes any long-term health condition that has an impact on the person's day-to-day life,This can be inside or outside the home,"Provide the gross annual income (i.e. salary before tax) plus the annual amount of benefits, Universal Credit or pensions, and income from investments",,"Provide the gross annual income (i.e. salary before tax) plus the annual amount of benefits, Universal Credit or pensions, and income from investments",,,Enter their total savings to the nearest £10,,For any buyer,"If the social landlord has previously sold the property to another buyer and is now reselling the property, enter 'yes'. If this is the first time the property has been sold, enter 'no'.","If the buyers haven't been living in the property, enter '0'",This is the date on which the building contractor hands over responsibility for the completed property to the private registered provider (PRP).,,,"For bedsits, enter ‘1’",,,"Enter the full purchase price of the property before any discounts are applied. For shared ownership, enter the full purchase price paid for 100% equity (this is equal to the value of the share owned by the PRP plus the value bought by the purchaser).","This is the initial stake purchased. Enter the amount of initial equity held by the purchaser (for example, 25% or 50%)",,Enter the amount of mortgage agreed with the mortgage lender. Exclude any deposits or cash payments.,,Enter the total cash sum paid by the buyer towards the property that was not funded by the mortgage,Enter the total cash discount given on the property being purchased through the Social HomeBuy scheme,Before any charges,"This includes any charges for day-to-day maintenance and repairs, buildings insurance, and any contributions to a sinking or reserve fund. It does not include estate management fees.","Estate management fees are typically used for the maintenance of communal gardens, payments, private roads, car parks or play areas within new build estates.",,,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.,,,,,,,,,"Enter the full purchase price of the property before any discounts are applied. For shared ownership, enter the full purchase price paid for 100% equity (this is equal to the value of the share owned by the PRP plus the value bought by the purchaser).","This is the initial stake purchased. Enter the amount of initial equity held by the purchaser (for example, 25% or 50%)",,,,,"For all schemes, including Right to Acquire (RTA), Right to Buy (RTB), Voluntary Right to Buy (VRTB) or Preserved Right to Buy (PRTB) sales, enter the full price of the property without any discount","For all schemes except Right to Buy (RTB), Preserved Right to Buy (PRTB), Voluntary Right to Buy (VRTB) and Rent to Buy","For Right to Buy (RTB), Preserved Right to Buy (PRTB) and Voluntary Right to Buy (VRTB). For capped discount, enter capped %. If property is sold to an existing tenant under RTB, PRTB or VRTB, enter % discount from full market value.",,Enter the amount of mortgage agreed with the mortgage lender. Exclude any deposits or cash payments.,,This is 'Yes' if the mortgage includes borrowing beyond the purchase price of the property,Enter the total cash sum paid by the purchaser towards the property that was not funded by the mortgage. This excludes any grant or loan.,"For example, service and management charges",,,,,,,,,,,,,
+The UPRN may not be the same as the property reference assigned by your organisation.",,,,,Combined with field 28 it should be a postcode which lies within the local authority given in field 29.,Combined with field 27 it should be a postcode which lies within the local authority given in field 29.,,,"For bedsits, enter ‘1’",,"This is whether someone who uses a wheelchair is able to make full use of all of the property’s rooms and facilities, including use of both inside and outside space, and entering and exiting the property.","Buyer 1 is the person in the household who does the most paid work. If it’s a joint purchase and the buyers do the same amount of paid work, buyer 1 is whoever is the oldest.",,,"If buyer 1 is a dual national of the United Kingdom and another country, enter United Kingdom. If they are a dual national of two other countries, they should decide which country to enter.","Buyer 1 is the person in the household who does the most paid work. If it’s a joint purchase and the buyers do the same amount of paid work, buyer 1 is whoever is the oldest.",,,,,,"If buyer 2 is a dual national of the United Kingdom and another country, enter United Kingdom. If they are a dual national of two other countries, they should decide which country to enter.",,,"You can provide details for a maximum of 4 other people if there are 2 buyers, or 5 other people if there is only one buyer",,,,,,,,,,,,,,,,,,This is also known as the household's 'last settled home',,,,,,"A regular is somebody who has served in the Royal Navy, the Royal Marines, the Royal Air Force or army full time and does not include reserve forces",,"A regular is somebody who has served in the Royal Navy, the Royal Marines, the Royal Air Force or army full time and does not include reserve forces",This includes any long-term health condition that has an impact on the person's day-to-day life,This can be inside or outside the home,"Provide the gross annual income (i.e. salary before tax) plus the annual amount of benefits, Universal Credit or pensions, and income from investments",,"Provide the gross annual income (i.e. salary before tax) plus the annual amount of benefits, Universal Credit or pensions, and income from investments",,,Enter their total savings to the nearest £10,,For any buyer,"If the social landlord has previously sold the property to another buyer and is now reselling the property, enter 'yes'. If this is the first time the property has been sold, enter 'no'.","If the buyers haven't been living in the property, enter '0'",This is the date on which the building contractor hands over responsibility for the completed property to the private registered provider (PRP).,,,"For bedsits, enter ‘1’",,,"Enter the full purchase price of the property before any discounts are applied. For shared ownership, enter the full purchase price paid for 100% equity (this is equal to the value of the share owned by the PRP plus the value bought by the purchaser).","This is the initial stake purchased. Enter the amount of initial equity held by the purchaser (for example, 25% or 50%)",,Enter the amount of mortgage agreed with the mortgage lender. Exclude any deposits or cash payments.,,Enter the total cash sum paid by the buyer towards the property that was not funded by the mortgage,Enter the total cash discount given on the property being purchased through the Social HomeBuy scheme,Before any charges,"This includes any charges for day-to-day maintenance and repairs, buildings insurance, and any contributions to a sinking or reserve fund. It does not include estate management fees.","Estate management fees are typically used for the maintenance of communal gardens, payments, private roads, car parks or play areas within new build estates.",,,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.,,,,,,,,,"Enter the full purchase price of the property before any discounts are applied. For shared ownership, enter the full purchase price paid for 100% equity (this is equal to the value of the share owned by the PRP plus the value bought by the purchaser).","This is the initial stake purchased. Enter the amount of initial equity held by the purchaser (for example, 25% or 50%)",,,,,"For all schemes, including Right to Acquire (RTA), Right to Buy (RTB) or Preserved Right to Buy (PRTB) sales, enter the full price of the property without any discount.","For all schemes except Right to Buy (RTB), Preserved Right to Buy (PRTB) and Rent to Buy","For Right to Buy (RTB) and Preserved Right to Buy (PRTB). For capped discount, enter capped %. If the property is sold to an existing tenant under RTB or PRTB, enter % discount from full market value.",,Enter the amount of mortgage agreed with the mortgage lender. Exclude any deposits or cash payments.,,This is 'Yes' if the mortgage includes borrowing beyond the purchase price of the property,Enter the total cash sum paid by the purchaser towards the property that was not funded by the mortgage. This excludes any grant or loan.,"For example, service and management charges",,,,,,,,,,,,,,,
Values,Jan-31,01-Dec,25 - 26,Alphanumeric,Alphanumeric,Email format,"Alphanumeric, punctuation can be used as long as not the field separator.
Max 9 characters.",01-Feb,"2, 16, 18, 24, 28 or 30 - 32",01-Feb,"8, 9, 14, 21, 22, 27 or 29",01-Feb,01-Mar,01-Feb,1,"Numeric, max 12 digits",Alphanumeric,,Text,,"Alphanumeric,
2 - 4 characters","Alphanumeric,
3 characters","9 character ONS code, beginning with 'E' (https://www.get-information-schools.service.gov.uk/Guidance/LaNameCodes) ",1 - 4 or 9,01-Sep,01-Feb,01-Mar,"16 - 110
or R",,Jan-20,"3 digit ISO country code, see specification",0 - 8 or 10,01-Feb,01-Mar,1 - 110 or R,,Jan-20,"3 digit ISO country code, see specification",0 - 10,01-Feb,0 - 5,01-Mar,1 - 110 or R,,0 - 10,01-Mar,1 - 110 or R,,0 - 10,01-Mar,1 - 110 or R,,0 - 10,01-Mar,1 - 110 or R,,0 - 10,"1 - 7, 9 or R",01-Feb,"Alphanumeric,
2 - 4 characters","Alphanumeric,
- 3 characters","9 character ONS code, beginning with 'E' (https://www.get-information-schools.service.gov.uk/Guidance/LaNameCodes) ",01-Mar,"1 - 7, 9 or R","1, 3, 7 or 8",04-Jun,04-Jul,01-Mar,,0 - 99999 or R,01-Feb,0 - 99999 or R,01-Feb,01-Apr,0 - 999990 or R,01-Mar,,01-Feb,Integer <= 80,Jan-31,01-Dec,22 - 26,01-Sep,1 - 4 or 9,1 - 3 or 9 - 10,0 - 999999,0 - 100,01-Feb,0 - 999999,Integer <= 60,0 - 999999,,0 - 9999.99,,,1 - 100,,01-Mar,01-Feb,Jan-31,01-Dec,1980-2026,02-Oct,Jan-31,01-Dec,1980-2026,0 - 999999,0 - 100,01-Mar,0 - 9999.99,,Integer <= 80,0 - 999999,,0 - 100,01-Feb,0 - 999999,Integer <= 60,01-Mar,0 - 999999,0 - 9999.99,1-3,1-3,Text,1-3,Text,1-3,Text,1-3,Text,1-3,Text,1-3,Text
+ 3 characters","9 character ONS code, beginning with 'E' (https://www.get-information-schools.service.gov.uk/Guidance/LaNameCodes) ",01-Mar,"1 - 7, 9 or R","1, 3, 7 or 8",04-Jun,04-Jul,01-Mar,,0 - 99999 or R,01-Feb,0 - 99999 or R,01-Feb,01-Apr,0 - 999990 or R,01-Mar,,01-Feb,Integer <= 80,Jan-31,01-Dec,22 - 26,01-Sep,1 - 4 or 9,1 - 3 or 9 - 10,0 - 999999,0 - 100,01-Feb,0 - 999999,Integer <= 60,0 - 999999,,0 - 9999.99,,,1 - 100,,01-Mar,01-Feb,Jan-31,01-Dec,1980-2026,02-Oct,Jan-31,01-Dec,1980-2026,0 - 999999,0 - 100,01-Mar,0 - 9999.99,,Integer <= 80,0 - 999999,,0 - 100,01-Feb,0 - 999999,Integer <= 60,01-Mar,0 - 999999,0 - 9999.99,1-3,1-3,Text,1-3,Text,1-3,Text,1-3,Text,1-3,Text,1-3,Text,1-2,Text
Can be empty?,No,,,No,No,Yes,Yes,No,"Yes, if the purchase was not made through a shared ownership scheme (if field 8 = 2)","Yes, if the purchase was not made through a shared ownership scheme (if field 8 = 2)","Yes, if the purchase was not made through a discounted ownership scheme (if field 8 = 1)",No,"Yes, if the sale is not a joint purchase (if field 12 = 2)",No,No,"Yes, if property's full address is known (if fields 16, 18, 20 and 21 are not empty)","Yes, if property's UPRN is known (if field 16 is not empty)",Yes,"Yes, if property's UPRN is known (if field 16 is not empty)",Yes,"Yes, if property's UPRN and local authority are known (if fields 16 and 23 are not empty",,No,,,"Yes, if the purchase is a staircasing transaction (if field 10 = 1)",,No,,"Yes, if the purchase is a staircasing transaction (if field 10 = 1)",,,,"Yes, if sale is not a joint purchase (if field 12 = 2) and the other fields about this person (fields 35, 36 and 39) are also empty","Yes, if sale is not a joint purchase (if field 12 = 2) and the other fields about this person (fields 35, 36 and 39) are also empty",,"Yes, if sale is not a joint purchase (if field 12 = 2), or if the purchase is a staircasing transaction (if field 10 = 1)",,"Yes, if sale is not a joint purchase (if field 12 = 2) and the other fields about this person (fields 35, 36 and 39) are also empty, or if the purchase is a staircasing transaction (if field 10 = 1)","Yes, if sale is not a joint purchase (if field 12 = 2), or if the purchase is a staircasing transaction (if field 10 = 1)","Yes, if purchase is a staircasing transaction (if field 10 = 1)","Yes, if all fields about this person (fields 42 - 45) are also empty, or if the purchase is a staircasing transaction (if field 10 = 1)",,,,"Yes, if all fields about this person (fields 46 - 49) are also empty, or if the purchase is a staircasing transaction (if field 10 = 1)",,,,"Yes, if all fields about this person (fields 50 - 53) are also empty, or if the purchase is a staircasing transaction (if field 10 = 1)",,,,"Yes, if all fields about this person (fields 54 - 57) are also empty, or if the purchase is a staircasing transaction (if field 10 = 1)",,,,"Yes, if the purchase is a staircasing transaction (if field 10 = 1)","Yes, if sale is discounted ownership (if field 8 = 2), or if the purchase is a staircasing transaction (if field 10 = 1)","Yes, if postcode of buyer 1's last settled accommodation is unknown (if field 59 = 2)
Yes, if sale is discounted ownership (if field 8 = 2), or if the purchase is a staircasing transaction (if field 10 = 1)",,Yes,"Yes, if sale is not a joint purchase (if field 12 = 2), or if the purchase is a staircasing transaction (if field 10 = 1)","Yes, if sale is not a joint purchase (if field 12 = 2), or if buyer is not known to have been living at the same address as buyer 1 at the time of purchase (if field 63 = 1 or 3), or if the purchase is a staircasing transaction (if field 10 = 1)","Yes, if the purchase is a staircasing transaction (if field 10 = 1)","Yes, if none of the buyers are known to have served as a regular in the UK armed forces (if field 65 = 7, 3 or 8), or if the purchase is a staircasing transaction (if field 10 = 1)","Yes, if the purchase is a staircasing transaction (if field 10 = 1)",,,"Yes, if the purchase is a staircasing transaction (if field 10 = 1)","Yes, if buyer 1's income is not known (if field 70 = R), or if the purchase is a staircasing transaction (if field 10 = 1)","Yes, if sale is not a joint purchase (if field 12 = 2), or if the purchase is a staircasing transaction (if field 10 = 1)","Yes, if sale is not a joint purchase (if field 12 = 2) or if buyer 2's income is not known (if field 70 = R), or if the purchase is a staircasing transaction (if field 10 = 1)","Yes, if the purchase is a staircasing transaction (if field 10 = 1)",,,"Yes, if the purchasers did not previously own a property or if it is not known (if field 76 = 2 or 3), or if the purchase is a staircasing transaction (if field 10 = 1)","Yes, if the purchase was not made through a shared ownership scheme (if field 8 = 2) or if this is a staircasing transaction (if field 10 = 1)","Yes, if the purchase was not made through a shared ownership scheme (if field 8 = 2), if this is a resale (if field 78 = 1) or if this is a staircasing transaction (if field 10 = 1)",,,,"Yes, if the purchase was not made through a shared ownership scheme (if field 8 = 2), or if the purchase is a staircasing transaction (if field 10 = 1)
-Yes, if the buyer was not a private registered provider, housing association or local authority tenant immediately before sale (if field 58 is not 1 or 2)",,,"Yes, if the purchase was not made through a shared ownership scheme (if field 8 = 2), or if the purchase is a staircasing transaction (if field 10 = 1)",,,"Yes, if the purchase was not made through a shared ownership scheme (if field 8 = 2), if the purchase is a staircasing transaction (if field 10 = 1) or if a mortgage was not used (if field 88 = 2)",,"Yes, if the purchase was not made through a shared ownership scheme (if field 8 = 2), or if the purchase is a staircasing transaction (if field 10 = 1)","Yes, if the purchase was not made through a shared ownership scheme (if field 8 = 2), if the purchase is a staircasing transaction (if field 10 = 1), or if the type of shared ownership sale is not Social Homebuy (if field 9 is not 18)","Yes, if there are no monthy charges or fees, if the purchase was not made through a shared ownership scheme (if field 8 = 2), or if the purchase is a staircasing transaction (if field 10 = 1)",,,"Yes, if this is not a shared ownership transaction (if field 8 = 2), or if it is not a staircasing transaction (if field 10 = 2)",,"Yes, if this is not a shared ownership transaction (if field 8 = 2), or if it is not a staircasing transaction (if field 10 = 2), or if the buyers do not own 100% of the property (if field 97 is less than 100)","Yes, if this is not a shared ownership transaction (if field 8 = 2), or if it is not a staircasing transaction (if field 10 = 2)",,,,"Yes, if this is not a shared ownership transaction (if field 8 = 2), or if it is not a staircasing transaction (if field 10 = 2), and if this is the first time the buyer has engaged in staircasing in the home (if field 99 = 1)",,,,"Yes, if this is not a shared ownership transaction (if field 8 = 2), or if it is not a staircasing transaction (if field 10 = 2)",,,,"Yes, if this is not a shared ownership transaction (if field 8 = 2), or if it is not a staircasing transaction (if field 10 = 2), or if the buyers now own 100% of the property (if field 97 = 100)","Yes, if the purchase was not made through a discounted ownership scheme (if field 8 = 1)",,"Yes, if the purchase was not made through a discounted ownership scheme (if field 8 = 1) or if the type of discounted sale is PRTB, VRTB, RTB, or Rent to Buy (if field 11 is 9, 14, 27 or 29)","Yes, if the purchase was not made through a discounted ownership scheme (if field 8 = 1) or if the type of discounted sale is not PRTB, VRTB, RTB, or Rent to Buy (if field 11 is 8, 21, 22)","Yes, if the purchase was not made through a discounted ownership scheme (if field 8 = 1)","Yes, if the purchase was not made through a discounted ownership scheme (if field 8 = 1) or if a mortgage was not used (if field 116 = 2)",,,"Yes, if the purchase was not made through a discounted ownership scheme (if field 8 = 1)","Yes, if there are no leasehold charges or if the purchase was not made through a discounted ownership scheme (if field 8 = 1)",,No,"Yes, if 'No' is not selected for gender same as sex (if field 123 is not 2)",No,"Yes, if 'No' is not selected for gender same as sex (if field 125 is not 2)",No,"Yes, if 'No' is not selected for gender same as sex (if field 127 is not 2)",No,"Yes, if 'No' is not selected for gender same as sex (if field 129 is not 2)",No,"Yes, if 'No' is not selected for gender same as sex (if field 131 is not 2)",No,"Yes, if 'No' is not selected for gender same as sex (if field 133 is not 2)"
+Yes, if the buyer was not a private registered provider, housing association or local authority tenant immediately before sale (if field 58 is not 1 or 2)",,,"Yes, if the purchase was not made through a shared ownership scheme (if field 8 = 2), or if the purchase is a staircasing transaction (if field 10 = 1)",,,"Yes, if the purchase was not made through a shared ownership scheme (if field 8 = 2), if the purchase is a staircasing transaction (if field 10 = 1) or if a mortgage was not used (if field 88 = 2)",,"Yes, if the purchase was not made through a shared ownership scheme (if field 8 = 2), or if the purchase is a staircasing transaction (if field 10 = 1)","Yes, if the purchase was not made through a shared ownership scheme (if field 8 = 2), if the purchase is a staircasing transaction (if field 10 = 1), or if the type of shared ownership sale is not Social Homebuy (if field 9 is not 18)","Yes, if there are no monthy charges or fees, if the purchase was not made through a shared ownership scheme (if field 8 = 2), or if the purchase is a staircasing transaction (if field 10 = 1)",,,"Yes, if this is not a shared ownership transaction (if field 8 = 2), or if it is not a staircasing transaction (if field 10 = 2)",,"Yes, if this is not a shared ownership transaction (if field 8 = 2), or if it is not a staircasing transaction (if field 10 = 2), or if the buyers do not own 100% of the property (if field 97 is less than 100)","Yes, if this is not a shared ownership transaction (if field 8 = 2), or if it is not a staircasing transaction (if field 10 = 2)",,,,"Yes, if this is not a shared ownership transaction (if field 8 = 2), or if it is not a staircasing transaction (if field 10 = 2), and if this is the first time the buyer has engaged in staircasing in the home (if field 99 = 1)",,,,"Yes, if this is not a shared ownership transaction (if field 8 = 2), or if it is not a staircasing transaction (if field 10 = 2)",,,,"Yes, if this is not a shared ownership transaction (if field 8 = 2), or if it is not a staircasing transaction (if field 10 = 2), or if the buyers now own 100% of the property (if field 97 = 100)","Yes, if the purchase was not made through a discounted ownership scheme (if field 8 = 1)",,"Yes, if the purchase was not made through a discounted ownership scheme (if field 8 = 1) or if the type of discounted sale is PRTB, RTB, or Rent to Buy (if field 11 is 9, 14 or 29)","Yes, if the purchase was not made through a discounted ownership scheme (if field 8 = 1) or if the type of discounted sale is not PRTB, RTB, or Rent to Buy (if field 11 is 8, 21, 22)","Yes, if the purchase was not made through a discounted ownership scheme (if field 8 = 1)","Yes, if the purchase was not made through a discounted ownership scheme (if field 8 = 1) or if a mortgage was not used (if field 116 = 2)",,,"Yes, if the purchase was not made through a discounted ownership scheme (if field 8 = 1)","Yes, if there are no leasehold charges or if the purchase was not made through a discounted ownership scheme (if field 8 = 1)",,No,"Yes, if 'No' is not selected for gender same as sex (if field 123 is not 2)",No,"Yes, if 'No' is not selected for gender same as sex (if field 125 is not 2)",No,"Yes, if 'No' is not selected for gender same as sex (if field 127 is not 2)",No,"Yes, if 'No' is not selected for gender same as sex (if field 129 is not 2)",No,"Yes, if 'No' is not selected for gender same as sex (if field 131 is not 2)",No,"Yes, if 'No' is not selected for gender same as sex (if field 133 is not 2)"
Types of sales the question applies to,All,,,,,,,,Shared ownership only,Shared ownership only,Discounted ownership only,All,Joint purchase only,All,,All,,,,,,,,,,Shared ownership - initial purchase and discounted ownership,,All,,Shared ownership - initial purchase and discounted ownership,,,,Joint purchases,,,Joint purchases which are shared ownership - initial purchase and discounted ownership,,,,Shared ownership - initial purchase and discounted ownership,,,,,,,,,,,,,,,,,Shared ownership - initial purchase and discounted ownership,Shared ownership - initial purchase,,,Shared ownership - initial purchase and discounted ownership,Joint purchases which are shared ownership - initial purchase and discounted ownership,,Shared ownership - initial purchase and discounted ownership,,,,,Shared ownership - initial purchase and discounted ownership,,Joint purchases which are shared ownership - initial purchase and discounted ownership,,Shared ownership - initial purchase and discounted ownership,,,,Shared ownership - initial purchase only,,,,,,,,,,,,,,,,,,Shared ownership - staircasing transaction only,,,,,,,,,,,,,,,,Discounted ownership only,,,,,,,,,,,All,All,All,All,All,All,All,All,All,All,All,All
Duplicate check field?,Yes,,,,,,,,,,,,,,,,,,,,Yes,,,,,,,Yes,,,,Yes,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,
-Field number,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134
+Field number,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,133,134,135,136
,4,9,26,ORG1,ORG1,support@example.com,1,2,,,8,2,3,1,1,,a,a,a,a,aa1,1aa,E09000001,1,1,2,3,20,,20,GBR,10,1,,,,,,,,0,,,,,,,,,,,,,,,,,1,2,,,,,,8,,7,3,3,10000,2,,,4,20000,3,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,30,400000,10000,25,2,,,,390000,0,,1,,,,,,,,,,,
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 4139ae5b0..92ed08f82 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,Less than 1 year,1 year but under 2 years,Loss of tied accommodation,,,Other supported housing,No,Yes,TN23 6LZ,Yes,No,Ashford,E07000105,Yes,,Yes,,,,No,No,Yes,No,No,,,,Yes,No,Weekly,268,,Universal Credit housing element,Yes,All,,,Every 2 weeks,200.0,100.0,,50.0,25.0,40.0,20.0,35.0,17.5,325.0,162.5,,,,Yes,Yes,12.0,6.0,,,,,,,,,,,,,,,,,,,,
+,in_progress,,s.port@jeemayle.com,s.port@jeemayle.com,false,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 eb7cfd35c..993301989 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?,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 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,multiple_partners_value_check,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,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,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,,,,,,,,,,,,,,,,,,,,
+,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/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 57f4aabdd..9873aa207 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,Less than 1 year,1 year but under 2 years,Loss of tied accommodation,,Other supported housing,No,Yes,TN23 6LZ,Ashford,Yes,,Yes,,,,No,No,Yes,No,No,,,No,Weekly,268,Universal Credit housing element,Yes,All,,,Every 2 weeks,200.0,50.0,40.0,35.0,325.0,Yes,12.0,,,,,,,,,,,,,,,,,,,,
+,in_progress,,choreographer@owtluk.com,false,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/lettings_log_csv_export_non_support_labels_26.csv b/spec/fixtures/files/lettings_log_csv_export_non_support_labels_26.csv
index 6cf8b42f7..baea1d973 100644
--- a/spec/fixtures/files/lettings_log_csv_export_non_support_labels_26.csv
+++ b/spec/fixtures/files/lettings_log_csv_export_non_support_labels_26.csv
@@ -1,3 +1,3 @@
Log ID,Status of log,ID of a set of duplicate logs,User the log is assigned to,Is the user in the assigned_to column the data protection officer?,Time and date the log was created,User who last updated the log,Time and date the log was last updated,Was the log submitted in-service or via bulk upload?,Year collection period opened,ID of a set of bulk uploaded logs,Which organisation owns this property?,Which organisation manages this letting?,What is the needs type?,What is the letting type?,Is this letting a renewal?,What is the tenancy start date?,"What is the rent type? (grouped into SR, IR or AR)",What is the rent type?,Which type of Intermediate Rent is this letting?,Which 'Other' type of Intermediate Rent is this letting?,Is this a London Affordable Rent letting?,What is the tenant code?,What is the property reference?,Has the tenant seen the MHCLG privacy notice?,Is this the first time the property has been let as social housing?,What rent product was the property most recently let as?,What is the reason for the property being vacant?,Is this property new to the social rented sector?,Is the UPRN known?,"If known, property's UPRN",Address line 1,Address line 2,Town or City,County,Postcode,What is the property's local authority?,What type of unit is the property?,Is the property built or adapted to wheelchair-user standards?,How many bedrooms does the property have?,What is the void date?,Number of days the property was vacant,Were any major repairs carried out during the void period?,What date were any major repairs completed on?,Is this letting in sheltered accommodation?,Is this a joint tenancy?,Is this a starter tenancy?,What is the type of tenancy?,"If 'Other', what is the type of tenancy?",What is the length of the fixed-term tenancy to the nearest year?,How many people live in the household at this letting?,"Where household characteristics have a 'Refused' option for some or all of: AGE1-AGE8, SEX1-SEX8, RELAT2-RELAT8, ECSTAT1-ECSTAT8",What is the lead tenant's age?,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?,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?,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?,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?,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?,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?,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?,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?",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?,What was the source of referral for this letting?,What was the source of referral for this letting?,Was the household income refused?,How often does the household receive income?,How much income does the household have in total?,Is the tenant likely to be receiving any of these housing-related benefits?,"Does the tenant receive housing-related benefits? Yes if hb = Universal Credit housing element or Housing benefit, No if hb = Don't Know, Neither, Tenant prefers not to say or blank","How much of the household's income is from Universal Credit, state pensions or benefits?",Does the household pay rent or other charges for the accommodation?,Does the household pay rent or other charges for the accommodation? - flag for when household_charge is answered no,How often does the household pay rent and other charges?,What is the basic rent?,What is the service charge?,What is the personal service charge?,What is the support charge?,Total charge to the tenant,"After the household has received any housing-related benefits, will they still need to pay for rent and charges?",Estimated outstanding amount,What scheme does this letting belong to?,"From scheme code, we map to the scheme name",Does the scheme contain confidential information?,"What is this type of scheme? (Direct access hostel), Foyer, Housing for older people or Other supported housing",Is this scheme registered under the Care Standards Act 2000?,Which organisation owns the housing stock for this scheme?,What client group is this scheme intended for?,Does this scheme provide for another client group?,What is the other client group?,What support does this scheme provide?,Intended length of stay,Date scheme was created,Which location is this letting for?,What is the postcode for this location?,What is the name of this location?,How many units are at this location?,What is the most common type of unit at this location?,What are the mobility standards for the majority of the units in this location?,What is the local authority of this postcode?,When did the first property in this location become available under this scheme?
id,status,duplicate_set_id,assigned_to,is_dpo,created_at,updated_by,updated_at,creation_method,collection_start_year,bulk_upload_id,owning_organisation_name,managing_organisation_name,needstype,lettype,renewal,startdate,renttype,renttype_detail,irproduct,irproduct_other,lar,tenancycode,propcode,declaration,first_time_property_let_as_social_housing,unitletas,rsnvac,newprop,uprn_known,uprn,address_line1,address_line2,town_or_city,county,postcode_full,la_label,unittype_gn,wchair,beds,voiddate,vacdays,majorrepairs,mrcdate,sheltered,joint,startertenancy,tenancy,tenancyother,tenancylength,hhmemb,refused,age1,sexrab1,gender_same_as_sex1,gender_description1,ethnic_group,ethnic,nationality_all,ecstat1,age2,relat2,sexrab2,gender_same_as_sex2,gender_description2,ecstat2,age3,relat3,sexrab3,gender_same_as_sex3,gender_description3,ecstat3,age4,relat4,sexrab4,gender_same_as_sex4,gender_description4,ecstat4,age5,relat5,sexrab5,gender_same_as_sex5,gender_description5,ecstat5,age6,relat6,sexrab6,gender_same_as_sex6,gender_description6,ecstat6,age7,relat7,sexrab7,gender_same_as_sex7,gender_description7,ecstat7,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,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_register,referral_noms,referral_org,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,2026-04-01T00:00:00+01:00,,2026-04-01T00:00:00+01:00,single log,2026,,MHCLG,MHCLG,General needs,Affordable rent general needs local authority,No,2026-04-01,Affordable Rent,Affordable Rent,,,No,HIJKLMN,ABCDEFG,Yes,No,Affordable rent basis,Tenant abandoned property,No,No,,Address line 1,,London,,NW9 5LL,Barnet,House,Yes,3,2026-03-30,1,Yes,2026-03-31,,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,4,Yes,35,Female,Yes,,White,Irish,Australia,Other,32,Yes,Male,"No, enter gender identity",Non-binary,Not seeking work,Not known,Prefers not to say,Prefers not to say,Prefers not to say,,Prefers not to say,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,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,Renewal to the same tenant in the same property,,,No,Weekly,268,Universal Credit housing element,Yes,All,,,Every 2 weeks,200.0,50.0,40.0,35.0,325.0,Yes,12.0,,,,,,,,,,,,,,,,,,,,
+,in_progress,,choreographer@owtluk.com,false,2026-04-01T00:00:00+01:00,,2026-04-01T00:00:00+01:00,single log,2026,,MHCLG,MHCLG,General needs,Affordable rent general needs local authority,No,2026-04-01,Affordable Rent,Affordable Rent,,,No,HIJKLMN,ABCDEFG,Yes,No,Affordable rent basis,Tenant abandoned property,No,No,,Address line 1,,London,,NW9 5LL,Barnet,House,Yes,3,2026-03-30,1,Yes,2026-03-31,,Don’t know,Yes,Assured Shorthold Tenancy (AST) – Fixed term,,2,4,Yes,35,Female,Yes,,White,Irish,Australia,Other,32,Yes,Male,"No, enter gender identity",Non-binary,Not seeking work,Not known,Prefers not to say,Prefers not to say,Prefers not to say,,Prefers not to say,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,Ashford,Yes,,Yes,,,,No,No,Yes,No,No,Renewal to the same tenant in the same property,,,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_codes_26.csv b/spec/fixtures/files/sales_logs_csv_export_codes_26.csv
index 73d276957..b1f3e1c15 100644
--- a/spec/fixtures/files/sales_logs_csv_export_codes_26.csv
+++ b/spec/fixtures/files/sales_logs_csv_export_codes_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 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?,"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 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?,"Besides the buyer(s), how many other people live or will live in the property?",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.
-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
-,completed,,MHCLG,,MHCLG,,2026-04-01T00:00:00+01:00,billyboy@eyeklaud.com,,billyboy@eyeklaud.com,,2026-04-01T00:00:00+01:00,,,1,,2026,1,4,2026,,2,8,,1,1,2,1,1,"1, Test Street",,Test Town,,AA1 1AA,true,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,1,2,2,1,1,30,F,1,,17,17,826,1,1,P,35,M,2,Nonbinary,17,,826,1,1,3,X,14,F,1,,9,X,-9,R,2,Genderfluid,3,R,-9,R,3,,10,,,,,,,6,1,0,SW1A,1AA,1,E09000033,Westminster,3,,1,4,5,1,1,0,13400,1,0,13400,1,4,1,,1,2,,10,,,,,,,110000.0,,,1,20000.0,10,80000.0,,,,,,,,,,,,,,,,,,,10000.0,,1,1,100.0,
+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 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?,"Besides the buyer(s), how many other people live or will live in the property?",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,,,1,,2026,1,4,2026,,2,8,,1,1,2,1,1,"1, Test Street",,Test Town,,AA1 1AA,true,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,1,2,2,1,1,30,F,1,,17,17,826,1,1,P,35,M,2,Nonbinary,17,,826,1,1,5,X,14,F,1,,9,X,-9,R,2,Genderfluid,3,R,-9,R,3,,10,,,,,,,6,1,0,SW1A,1AA,1,E09000033,Westminster,3,,1,4,5,1,1,0,13400,1,0,13400,1,4,1,,1,2,,10,,,,,,,110000.0,,,1,20000.0,10,80000.0,,,,,,,,,,,,,,,,,,,10000.0,,1,1,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 017bf2c0d..de7897339 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 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?,"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 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?,"Besides the buyer(s), how many other people live or will live in the property?",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.
-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
-,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,3,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,
+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 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?,"Besides the buyer(s), how many other people live or will live in the property?",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,,,
diff --git a/spec/fixtures/files/sales_logs_csv_export_non_support_codes_26.csv b/spec/fixtures/files/sales_logs_csv_export_non_support_codes_26.csv
index b9f8c7dd7..a701c8899 100644
--- a/spec/fixtures/files/sales_logs_csv_export_non_support_codes_26.csv
+++ b/spec/fixtures/files/sales_logs_csv_export_non_support_codes_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 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?,"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 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?
-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
-,completed,,MHCLG,,MHCLG,,2026-04-01T00:00:00+01:00,billyboy@eyeklaud.com,,2026-04-01T00:00:00+01:00,,,1,,2026,1,4,2026,,2,8,,1,1,2,1,1,1,,,1,"1, Test Street",,Test Town,,SW1A,1AA,E09000033,Westminster,1,2,2,1,1,30,F,1,,17,17,826,1,1,P,35,M,2,Nonbinary,17,,826,1,1,3,X,14,F,1,,9,X,-9,R,2,Genderfluid,3,R,-9,R,3,,10,,,,,,,6,1,0,SW1A,1AA,1,E09000033,Westminster,3,,1,4,5,1,1,0,13400,1,0,13400,1,4,1,,1,2,,10,,,,,,,110000.0,,1,20000.0,10,80000.0,,,,,,,,,,,,,,,,,,,10000.0,,1,1,100.0
+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?,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,,,1,,2026,1,4,2026,,2,8,,1,1,2,1,1,1,,,1,"1, Test Street",,Test Town,,SW1A,1AA,E09000033,Westminster,1,2,2,1,1,30,F,1,,17,17,826,1,1,P,35,M,2,Nonbinary,17,,826,1,1,5,X,14,F,1,,9,X,-9,R,2,Genderfluid,3,R,-9,R,3,,10,,,,,,,6,1,0,SW1A,1AA,1,E09000033,Westminster,3,,1,4,5,1,1,0,13400,1,0,13400,1,4,1,,1,2,,10,,,,,,,110000.0,,1,20000.0,10,80000.0,,,,,,,,,,,,,,,,,,,10000.0,,1,1,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 4ee122278..732829543 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 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?,"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 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?
-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
-,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,3,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
+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?,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,,
diff --git a/spec/fixtures/variable_definitions/sales_download_26_27.csv b/spec/fixtures/variable_definitions/sales_download_26_27.csv
index 4e67490e0..7581af191 100644
--- a/spec/fixtures/variable_definitions/sales_download_26_27.csv
+++ b/spec/fixtures/variable_definitions/sales_download_26_27.csv
@@ -17,3 +17,6 @@ gender_same_as_sex5,Is the gender person 5 identifies with the same as their sex
gender_description5,If 'No', enter person 5's gender identity
gender_same_as_sex6,Is the gender person 6 identifies with the same as their sex registered at birth?
gender_description6,If 'No', enter person 6's gender identity
+hasservicechargeschanged,Will the service charge change after this staircasing transaction takes place?
+newservicecharges,What are the new total monthly service charges for the property?
+hholdcount,In total, how many people live in the property?
diff --git a/spec/lib/tasks/log_variable_definitions_spec.rb b/spec/lib/tasks/log_variable_definitions_spec.rb
index 8852897d6..f80da0660 100644
--- a/spec/lib/tasks/log_variable_definitions_spec.rb
+++ b/spec/lib/tasks/log_variable_definitions_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe "log_variable_definitions" do
subject(:task) { Rake::Task["data_import:add_variable_definitions"] }
let(:path) { "spec/fixtures/variable_definitions" }
- let(:total_variable_definitions_count) { 463 }
+ let(:total_variable_definitions_count) { 466 }
before do
Rake.application.rake_require("tasks/log_variable_definitions")
diff --git a/spec/models/form/lettings/questions/layear_spec.rb b/spec/models/form/lettings/questions/layear_spec.rb
index 5ea537514..b7023c711 100644
--- a/spec/models/form/lettings/questions/layear_spec.rb
+++ b/spec/models/form/lettings/questions/layear_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Form::Lettings::Questions::Layear, type: :model do
let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1)) }
before do
- allow(form).to receive(:start_year_2024_or_later?).and_return(false)
+ allow(form).to receive_messages(start_year_2024_or_later?: false, start_year_2025_or_later?: false)
allow(page).to receive(:subsection).and_return(subsection)
allow(subsection).to receive(:form).and_return(form)
end
@@ -68,6 +68,27 @@ RSpec.describe Form::Lettings::Questions::Layear, type: :model do
end
end
+ context "with 2025/26 form" do
+ before do
+ allow(form).to receive(:start_year_2025_or_later?).and_return(true)
+ end
+
+ it "has the correct answer_options" do
+ expect(question.answer_options).to eq({
+ "1" => { "value" => "Just moved to local authority area with this new let" },
+ "2" => { "value" => "Under 1 year" },
+ "7" => { "value" => "1 year but under 2 years" },
+ "8" => { "value" => "2 years but under 3 years" },
+ "9" => { "value" => "3 years but under 4 years" },
+ "10" => { "value" => "4 years but under 5 years" },
+ "11" => { "value" => "5 years but under 10 years" },
+ "12" => { "value" => "10 years or more" },
+ "divider" => { "value" => true },
+ "6" => { "value" => "Don’t know" },
+ })
+ end
+ end
+
it "has the correct check_answers_card_number" do
expect(question.check_answers_card_number).to eq(0)
end
diff --git a/spec/models/form/lettings/questions/waityear_spec.rb b/spec/models/form/lettings/questions/waityear_spec.rb
index cf5cd746f..9ebf8dec1 100644
--- a/spec/models/form/lettings/questions/waityear_spec.rb
+++ b/spec/models/form/lettings/questions/waityear_spec.rb
@@ -85,7 +85,7 @@ RSpec.describe Form::Lettings::Questions::Waityear, type: :model do
it "has the correct answer_options" do
expect(question.answer_options).to eq({
"13" => { "value" => "Household not on the housing register (or waiting list) in this area" },
- "2" => { "value" => "Less than 1 year" },
+ "2" => { "value" => "Under 1 year" },
"7" => { "value" => "1 year but under 2 years" },
"8" => { "value" => "2 years but under 3 years" },
"9" => { "value" => "3 years but under 4 years" },
diff --git a/spec/models/form/sales/pages/buyer1_gender_same_as_sex_spec.rb b/spec/models/form/sales/pages/buyer1_gender_same_as_sex_spec.rb
index f0bba9e4e..f5b192cee 100644
--- a/spec/models/form/sales/pages/buyer1_gender_same_as_sex_spec.rb
+++ b/spec/models/form/sales/pages/buyer1_gender_same_as_sex_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Form::Sales::Pages::Buyer1GenderSameAsSex, type: :model do
let(:page_id) { nil }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: current_collection_start_date)) }
+ let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: current_collection_start_date, person_question_count: 4)) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
diff --git a/spec/models/form/sales/pages/buyer2_gender_same_as_sex_spec.rb b/spec/models/form/sales/pages/buyer2_gender_same_as_sex_spec.rb
index 1bcc90129..787647364 100644
--- a/spec/models/form/sales/pages/buyer2_gender_same_as_sex_spec.rb
+++ b/spec/models/form/sales/pages/buyer2_gender_same_as_sex_spec.rb
@@ -7,7 +7,7 @@ RSpec.describe Form::Sales::Pages::Buyer2GenderSameAsSex, type: :model do
let(:page_id) { nil }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: current_collection_start_date)) }
+ let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: current_collection_start_date, person_question_count: 4)) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
diff --git a/spec/models/form/sales/pages/deposit_spec.rb b/spec/models/form/sales/pages/deposit_spec.rb
index acb6556a8..c967c7bd8 100644
--- a/spec/models/form/sales/pages/deposit_spec.rb
+++ b/spec/models/form/sales/pages/deposit_spec.rb
@@ -5,8 +5,8 @@ RSpec.describe Form::Sales::Pages::Deposit, type: :model do
let(:page_id) { nil }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, enabled?: true, depends_on: true) }
- let(:form) { instance_double(Form, start_year_2024_or_later?: false, start_date: Time.zone.local(2023, 4, 1), depends_on_met: true) }
+ let(:subsection) { instance_double(Form::Subsection, enabled?: true, depends_on: true, id: "shared_ownership_initial_purchase") }
+ let(:form) { instance_double(Form, start_year_2024_or_later?: false, start_date: Time.zone.local(2023, 4, 1), depends_on_met: true, start_year_2026_or_later?: false) }
let(:optional) { false }
before do
diff --git a/spec/models/form/sales/pages/discounted_ownership_type_spec.rb b/spec/models/form/sales/pages/discounted_ownership_type_spec.rb
index afb4d2757..6456f8d65 100644
--- a/spec/models/form/sales/pages/discounted_ownership_type_spec.rb
+++ b/spec/models/form/sales/pages/discounted_ownership_type_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Pages::DiscountedOwnershipType, type: :model do
let(:page_id) { nil }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date:)) }
+ let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date:, start_year_2026_or_later?: true)) }
let(:start_date) { Time.zone.today }
it "has correct subsection" do
diff --git a/spec/models/form/sales/pages/extra_borrowing_spec.rb b/spec/models/form/sales/pages/extra_borrowing_spec.rb
index 3bbdfb5a5..01ebf856b 100644
--- a/spec/models/form/sales/pages/extra_borrowing_spec.rb
+++ b/spec/models/form/sales/pages/extra_borrowing_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Pages::ExtraBorrowing, type: :model do
let(:page_id) { nil }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1))) }
+ 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)) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
diff --git a/spec/models/form/sales/pages/leasehold_charges_spec.rb b/spec/models/form/sales/pages/leasehold_charges_spec.rb
index 2f2cfba17..cf659c003 100644
--- a/spec/models/form/sales/pages/leasehold_charges_spec.rb
+++ b/spec/models/form/sales/pages/leasehold_charges_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Pages::LeaseholdCharges, type: :model do
let(:page_id) { nil }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1))) }
+ 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)) }
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 4d7a0944a..8127dfb2d 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, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1))) }
+ 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)) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
diff --git a/spec/models/form/sales/pages/mortgage_length_spec.rb b/spec/models/form/sales/pages/mortgage_length_spec.rb
index 4fdf9b880..6387e1a17 100644
--- a/spec/models/form/sales/pages/mortgage_length_spec.rb
+++ b/spec/models/form/sales/pages/mortgage_length_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Pages::MortgageLength, type: :model do
let(:page_id) { nil }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1))) }
+ 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)) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
diff --git a/spec/models/form/sales/pages/number_of_others_in_property_spec.rb b/spec/models/form/sales/pages/number_of_others_in_property_spec.rb
index fe036bf72..ef71be1f6 100644
--- a/spec/models/form/sales/pages/number_of_others_in_property_spec.rb
+++ b/spec/models/form/sales/pages/number_of_others_in_property_spec.rb
@@ -1,13 +1,19 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::NumberOfOthersInProperty, type: :model do
+ include CollectionTimeHelper
+
subject(:page) { described_class.new(page_id, page_definition, subsection, joint_purchase:) }
let(:page_id) { "number_of_others_in_property" }
let(:page_definition) { nil }
let(:joint_purchase) { false }
- let(:form) { Form.new(nil, 2024, [], "sales") }
- let(:subsection) { instance_double(Form::Subsection, form:, enabled?: true, depends_on: nil) }
+ let(:form) { instance_double(Form, start_date: current_collection_start_date, start_year_2026_or_later?: true, start_year_2025_or_later?: true) }
+ let(:subsection) { instance_double(Form::Subsection, depends_on: nil) }
+
+ before do
+ allow(subsection).to receive(:form).and_return(form)
+ end
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
@@ -25,7 +31,7 @@ RSpec.describe Form::Sales::Pages::NumberOfOthersInProperty, type: :model do
expect(page.description).to be_nil
end
- context "with joint purchase" do
+ context "when the page expects a joint purchase" do
let(:page_id) { "number_of_others_in_property_joint_purchase" }
let(:joint_purchase) { true }
@@ -39,7 +45,9 @@ RSpec.describe Form::Sales::Pages::NumberOfOthersInProperty, type: :model do
end
context "with 2024 logs" do
- context "with joint purchase" do
+ let(:form) { instance_double(Form, start_date: collection_start_date_for_year(2024), start_year_2026_or_later?: false, start_year_2025_or_later?: false, depends_on_met: true) }
+
+ context "when the sales log is a joint purchase" do
context "when buyer has seen privacy notice and buyer interviewed" do
let(:log) { build(:sales_log, privacynotice: 1, jointpur: 1, noint: 0) }
@@ -73,11 +81,11 @@ RSpec.describe Form::Sales::Pages::NumberOfOthersInProperty, type: :model do
end
end
- context "with non joint purchase" do
+ context "when the sales log is not a joint purchase" do
context "when buyer has seen privacy notice and buyer interviewed" do
let(:log) { build(:sales_log, privacynotice: 1, jointpur: 2, noint: 0) }
- it "routes to the page" do
+ it "does not route to the page" do
expect(page).not_to be_routed_to(log, nil)
end
end
@@ -85,7 +93,7 @@ RSpec.describe Form::Sales::Pages::NumberOfOthersInProperty, type: :model do
context "when buyer has seen privacy notice and buyer not interviewed" do
let(:log) { build(:sales_log, privacynotice: 1, jointpur: 2, noint: 1) }
- it "routes to the page" do
+ it "does not route to the page" do
expect(page).not_to be_routed_to(log, nil)
end
end
@@ -101,7 +109,7 @@ RSpec.describe Form::Sales::Pages::NumberOfOthersInProperty, type: :model do
context "and buyer has not seen privacy notice and buyer not interviewed" do
let(:log) { build(:sales_log, privacynotice: nil, jointpur: 2, noint: 1) }
- it "routes to the page" do
+ it "does not route to the page" do
expect(page).not_to be_routed_to(log, nil)
end
end
@@ -109,9 +117,29 @@ RSpec.describe Form::Sales::Pages::NumberOfOthersInProperty, type: :model do
end
context "with 2025 logs" do
- let(:form) { Form.new(nil, 2025, [], "sales") }
+ let(:form) { instance_double(Form, start_date: collection_start_date_for_year(2025), start_year_2026_or_later?: false, start_year_2025_or_later?: true, depends_on_met: true) }
+
+ context "and the sales log is not a staircasing transaction" do
+ let(:log) { build(:sales_log, privacynotice: 1, jointpur: 1, noint: 0, staircase: 2) }
+
+ it "routes to the page" do
+ expect(page.routed_to?(log, nil)).to be(true)
+ end
+ end
+
+ context "and the sales log is a staircasing transaction" do
+ let(:log) { build(:sales_log, privacynotice: 1, jointpur: 1, noint: 0, staircase: 1) }
+
+ it "does not route to the page" do
+ expect(page).not_to be_routed_to(log, nil)
+ end
+ end
+ end
+
+ context "with 2026 logs" do
+ let(:form) { instance_double(Form, start_date: current_collection_start_date, start_year_2026_or_later?: true, start_year_2025_or_later?: true, depends_on_met: true) }
- context "and staircase is not 1" do
+ context "and the sales log is not a staircasing transaction" do
let(:log) { build(:sales_log, privacynotice: 1, jointpur: 1, noint: 0, staircase: 2) }
it "routes to the page" do
@@ -119,7 +147,7 @@ RSpec.describe Form::Sales::Pages::NumberOfOthersInProperty, type: :model do
end
end
- context "and staircase is 1" do
+ context "and the sales log is a staircasing transaction" do
let(:log) { build(:sales_log, privacynotice: 1, jointpur: 1, noint: 0, staircase: 1) }
it "does not route to the page" do
diff --git a/spec/models/form/sales/pages/person_age_spec.rb b/spec/models/form/sales/pages/person_age_spec.rb
index 0cd79bd02..a9621dce1 100644
--- a/spec/models/form/sales/pages/person_age_spec.rb
+++ b/spec/models/form/sales/pages/person_age_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Pages::PersonAge, type: :model do
let(:page_id) { "person_1_age" }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1))) }
+ let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), person_question_count: 4)) }
let(:person_index) { 1 }
it "has correct subsection" do
diff --git a/spec/models/form/sales/pages/person_gender_identity_spec.rb b/spec/models/form/sales/pages/person_gender_identity_spec.rb
index 73cb734af..2102a41b7 100644
--- a/spec/models/form/sales/pages/person_gender_identity_spec.rb
+++ b/spec/models/form/sales/pages/person_gender_identity_spec.rb
@@ -4,7 +4,7 @@ RSpec.describe Form::Sales::Pages::PersonGenderIdentity, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection, person_index:) }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1))) }
+ let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), person_question_count: 4)) }
let(:person_index) { 1 }
let(:page_id) { "person_2_gender_identity" }
diff --git a/spec/models/form/sales/pages/person_gender_same_as_sex_spec.rb b/spec/models/form/sales/pages/person_gender_same_as_sex_spec.rb
index da8113af0..e020b6d28 100644
--- a/spec/models/form/sales/pages/person_gender_same_as_sex_spec.rb
+++ b/spec/models/form/sales/pages/person_gender_same_as_sex_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Form::Sales::Pages::PersonGenderSameAsSex, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection, person_index:) }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: current_collection_start_date)) }
+ let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: current_collection_start_date, person_question_count: 4)) }
let(:person_index) { 2 }
let(:page_id) { "person_2_gender_same_as_sex" }
diff --git a/spec/models/form/sales/pages/person_known_spec.rb b/spec/models/form/sales/pages/person_known_spec.rb
index 141473138..c462331eb 100644
--- a/spec/models/form/sales/pages/person_known_spec.rb
+++ b/spec/models/form/sales/pages/person_known_spec.rb
@@ -3,11 +3,13 @@ require "rails_helper"
RSpec.describe Form::Sales::Pages::PersonKnown, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection, person_index:) }
- context "without joint purchase" do
- let(:page_id) { "person_2_known" }
- let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection) }
- let(:person_index) { 2 }
+ let(:page_id) { "person_2_known" }
+ let(:page_definition) { nil }
+ let(:person_index) { 2 }
+
+ context "with pre-2026 form" do
+ let(:form) { instance_double(Form, start_year_2026_or_later?: false) }
+ let(:subsection) { instance_double(Form::Subsection, form:) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
@@ -152,5 +154,145 @@ RSpec.describe Form::Sales::Pages::PersonKnown, type: :model do
])
end
end
+
+ context "with person 6" do
+ let(:page_id) { "person_6_known" }
+ let(:person_index) { 6 }
+
+ it "has correct depends_on" do
+ expect(page.depends_on).to eq([
+ {
+ "not_joint_purchase?" => true,
+ "hholdcount" => {
+ "operator" => ">=",
+ "operand" => 5,
+ },
+ },
+ {
+ "joint_purchase?" => true,
+ "hholdcount" => {
+ "operator" => ">=",
+ "operand" => 4,
+ },
+ },
+ ])
+ end
+ end
+ end
+
+ context "with 2026 form" do
+ let(:form) { instance_double(Form, start_year_2026_or_later?: true) }
+ let(:subsection) { instance_double(Form::Subsection, form:) }
+
+ context "with person 2" do
+ let(:page_id) { "person_2_known" }
+ let(:person_index) { 2 }
+
+ it "has correct depends_on" do
+ expect(page.depends_on).to eq([{
+ "not_joint_purchase?" => true,
+ "hholdcount" => {
+ "operator" => ">=",
+ "operand" => 2,
+ },
+ }])
+ end
+ end
+
+ context "with person 3" do
+ let(:page_id) { "person_3_known" }
+ let(:person_index) { 3 }
+
+ it "has correct depends_on" do
+ expect(page.depends_on).to eq([
+ {
+ "not_joint_purchase?" => true,
+ "hholdcount" => {
+ "operator" => ">=",
+ "operand" => 3,
+ },
+ },
+ {
+ "joint_purchase?" => true,
+ "hholdcount" => {
+ "operator" => ">=",
+ "operand" => 3,
+ },
+ },
+ ])
+ end
+ end
+
+ context "with person 4" do
+ let(:page_id) { "person_4_known" }
+ let(:person_index) { 4 }
+
+ it "has correct depends_on" do
+ expect(page.depends_on).to eq([
+ {
+ "not_joint_purchase?" => true,
+ "hholdcount" => {
+ "operator" => ">=",
+ "operand" => 4,
+ },
+ },
+ {
+ "joint_purchase?" => true,
+ "hholdcount" => {
+ "operator" => ">=",
+ "operand" => 4,
+ },
+ },
+ ])
+ end
+ end
+
+ context "with person 5" do
+ let(:page_id) { "person_5_known" }
+ let(:person_index) { 5 }
+
+ it "has correct depends_on" do
+ expect(page.depends_on).to eq([
+ {
+ "not_joint_purchase?" => true,
+ "hholdcount" => {
+ "operator" => ">=",
+ "operand" => 5,
+ },
+ },
+ {
+ "joint_purchase?" => true,
+ "hholdcount" => {
+ "operator" => ">=",
+ "operand" => 5,
+ },
+ },
+ ])
+ end
+ end
+
+ context "with person 6" do
+ let(:page_id) { "person_6_known" }
+ let(:person_index) { 6 }
+
+ it "has correct depends_on" do
+ expect(page.depends_on).to eq([
+ {
+ "not_joint_purchase?" => true,
+ "hholdcount" => {
+ "operator" => ">=",
+ "operand" => 6,
+ },
+ },
+ {
+ "joint_purchase?" => true,
+ "hholdcount" => {
+ "operator" => ">=",
+ "operand" => 6,
+ },
+ },
+ ])
+ end
+ end
end
end
diff --git a/spec/models/form/sales/pages/person_relationship_to_buyer1_spec.rb b/spec/models/form/sales/pages/person_relationship_to_buyer1_spec.rb
index aeb196337..88f7ba88f 100644
--- a/spec/models/form/sales/pages/person_relationship_to_buyer1_spec.rb
+++ b/spec/models/form/sales/pages/person_relationship_to_buyer1_spec.rb
@@ -4,7 +4,7 @@ RSpec.describe Form::Sales::Pages::PersonRelationshipToBuyer1, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection, person_index:) }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2024_or_later?: false)) }
+ let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2024_or_later?: false, person_question_count: 4)) }
let(:person_index) { 1 }
let(:page_id) { "person_1_relationship_to_buyer_1" }
diff --git a/spec/models/form/sales/pages/person_relationship_to_buyer1_yes_no_spec.rb b/spec/models/form/sales/pages/person_relationship_to_buyer1_yes_no_spec.rb
index a8215a0ba..12bb0da7c 100644
--- a/spec/models/form/sales/pages/person_relationship_to_buyer1_yes_no_spec.rb
+++ b/spec/models/form/sales/pages/person_relationship_to_buyer1_yes_no_spec.rb
@@ -4,7 +4,7 @@ RSpec.describe Form::Sales::Pages::PersonRelationshipToBuyer1YesNo, type: :model
subject(:page) { described_class.new(page_id, page_definition, subsection, person_index:) }
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: Time.zone.local(2025, 4, 1), person_question_count: 4)) }
let(:person_index) { 1 }
let(:page_id) { "person_1_relationship_to_buyer_1" }
diff --git a/spec/models/form/sales/pages/person_sex_registered_at_birth_spec.rb b/spec/models/form/sales/pages/person_sex_registered_at_birth_spec.rb
index fa116818c..33f4f9e72 100644
--- a/spec/models/form/sales/pages/person_sex_registered_at_birth_spec.rb
+++ b/spec/models/form/sales/pages/person_sex_registered_at_birth_spec.rb
@@ -4,7 +4,7 @@ RSpec.describe Form::Sales::Pages::PersonSexRegisteredAtBirth, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection, person_index:) }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2026, 4, 1))) }
+ let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2026, 4, 1), person_question_count: 4)) }
let(:person_index) { 1 }
let(:page_id) { "person_2_sex_registered_at_birth" }
diff --git a/spec/models/form/sales/pages/person_working_situation_spec.rb b/spec/models/form/sales/pages/person_working_situation_spec.rb
index 91d23f34f..131768b78 100644
--- a/spec/models/form/sales/pages/person_working_situation_spec.rb
+++ b/spec/models/form/sales/pages/person_working_situation_spec.rb
@@ -4,7 +4,7 @@ RSpec.describe Form::Sales::Pages::PersonWorkingSituation, type: :model do
subject(:page) { described_class.new(page_id, page_definition, subsection, person_index:) }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2025_or_later?: false)) }
+ let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2025_or_later?: false, person_question_count: 4)) }
let(:person_index) { 2 }
let(:page_id) { "person_2_working_situation" }
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 27ab0b422..e26221554 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, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1))) }
+ 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)) }
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 ad857ee9f..8ceb58f4a 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(:form).and_return(instance_double(Form, start_year_2024_or_later?: false, start_date: Time.zone.local(2023, 4, 1)))
+ 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")
end
it "has correct subsection" do
diff --git a/spec/models/form/sales/pages/service_charge_changed_spec.rb b/spec/models/form/sales/pages/service_charge_changed_spec.rb
new file mode 100644
index 000000000..245c62874
--- /dev/null
+++ b/spec/models/form/sales/pages/service_charge_changed_spec.rb
@@ -0,0 +1,31 @@
+require "rails_helper"
+
+RSpec.describe Form::Sales::Pages::ServiceChargeChanged, 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: collection_start_date_for_year(2026))) }
+
+ it "has correct subsection" do
+ expect(page.subsection).to eq(subsection)
+ end
+
+ it "has correct questions" do
+ expect(page.questions.map(&:id)).to eq(%w[hasservicechargeschanged newservicecharges])
+ end
+
+ it "has the correct id" do
+ expect(page.id).to eq("service_charge_changed")
+ end
+
+ it "has the correct description" do
+ expect(page.description).to be_nil
+ end
+
+ it "has correct depends_on" do
+ expect(page.depends_on).to be_nil
+ end
+end
diff --git a/spec/models/form/sales/pages/service_charge_spec.rb b/spec/models/form/sales/pages/service_charge_spec.rb
index 73fd4cdf8..0c1bf60c6 100644
--- a/spec/models/form/sales/pages/service_charge_spec.rb
+++ b/spec/models/form/sales/pages/service_charge_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Pages::ServiceCharge, type: :model do
let(:page_id) { nil }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1))) }
+ 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)) }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
diff --git a/spec/models/form/sales/pages/service_charge_staircasing_spec.rb b/spec/models/form/sales/pages/service_charge_staircasing_spec.rb
index a29df7b82..aaf453b8c 100644
--- a/spec/models/form/sales/pages/service_charge_staircasing_spec.rb
+++ b/spec/models/form/sales/pages/service_charge_staircasing_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Pages::ServiceChargeStaircasing, type: :model do
let(:page_id) { nil }
let(:page_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2026, 4, 1))) }
+ let(:subsection) { instance_double(Form::Subsection, id: "shared_ownership_staircasing_transaction", form: instance_double(Form, start_date: Time.zone.local(2026, 4, 1), 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/value_shared_ownership_spec.rb b/spec/models/form/sales/pages/value_shared_ownership_spec.rb
index 579084b35..e7e709d28 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)), id: "shared_ownership") }
+ 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") }
before do
allow(page.subsection.form).to receive(:start_year_2025_or_later?).and_return(false)
diff --git a/spec/models/form/sales/questions/deposit_amount_spec.rb b/spec/models/form/sales/questions/deposit_amount_spec.rb
index 6dd019b67..5256648b3 100644
--- a/spec/models/form/sales/questions/deposit_amount_spec.rb
+++ b/spec/models/form/sales/questions/deposit_amount_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Form::Sales::Questions::DepositAmount, type: :model do
let(:optional) { false }
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(: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))) }
context "when the ownership type is shared" do
let(:log) { build(:sales_log, :completed, ownershipsch: 1, mortgageused: 2) }
diff --git a/spec/models/form/sales/questions/discounted_ownership_type_spec.rb b/spec/models/form/sales/questions/discounted_ownership_type_spec.rb
index 356367f0b..f7ad25f1f 100644
--- a/spec/models/form/sales/questions/discounted_ownership_type_spec.rb
+++ b/spec/models/form/sales/questions/discounted_ownership_type_spec.rb
@@ -6,8 +6,9 @@ RSpec.describe Form::Sales::Questions::DiscountedOwnershipType, type: :model do
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page, subsection:) }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date:)) }
+ let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date:, start_year_2026_or_later?: start_year_2026_or_later)) }
let(:start_date) { Time.zone.today }
+ let(:start_year_2026_or_later) { true }
it "has correct page" do
expect(question.page).to eq(page)
@@ -25,16 +26,35 @@ RSpec.describe Form::Sales::Questions::DiscountedOwnershipType, type: :model do
expect(question.derived?(nil)).to be false
end
- it "has the correct answer_options" do
- expect(question.answer_options).to eq({
- "8" => { "value" => "Right to Acquire (RTA)" },
- "14" => { "value" => "Preserved Right to Buy (PRTB)" },
- "27" => { "value" => "Voluntary Right to Buy (VRTB)" },
- "9" => { "value" => "Right to Buy (RTB)" },
- "29" => { "value" => "Rent to Buy - Full Ownership" },
- "21" => { "value" => "Social HomeBuy for outright purchase" },
- "22" => { "value" => "Any other equity loan scheme" },
- })
+ context "when form is for 2025 or earlier" do
+ let(:start_year_2026_or_later) { false }
+
+ it "has the correct answer_options including option 27" do
+ expect(question.answer_options).to eq({
+ "8" => { "value" => "Right to Acquire (RTA)" },
+ "14" => { "value" => "Preserved Right to Buy (PRTB)" },
+ "27" => { "value" => "Voluntary Right to Buy (VRTB)" },
+ "9" => { "value" => "Right to Buy (RTB)" },
+ "29" => { "value" => "Rent to Buy - Full Ownership" },
+ "21" => { "value" => "Social HomeBuy for outright purchase" },
+ "22" => { "value" => "Any other equity loan scheme" },
+ })
+ end
+ end
+
+ context "when form is for 2026 or later" do
+ let(:start_year_2026_or_later) { true }
+
+ it "has the correct answer_options without option 27" do
+ expect(question.answer_options).to eq({
+ "8" => { "value" => "Right to Acquire (RTA)" },
+ "14" => { "value" => "Preserved Right to Buy (PRTB)" },
+ "9" => { "value" => "Right to Buy (RTB)" },
+ "29" => { "value" => "Rent to Buy - Full Ownership" },
+ "21" => { "value" => "Social HomeBuy for outright purchase" },
+ "22" => { "value" => "Any other equity loan scheme" },
+ })
+ end
end
describe "partial guidance" do
diff --git a/spec/models/form/sales/questions/extra_borrowing_spec.rb b/spec/models/form/sales/questions/extra_borrowing_spec.rb
index 935140914..1cb1e38d9 100644
--- a/spec/models/form/sales/questions/extra_borrowing_spec.rb
+++ b/spec/models/form/sales/questions/extra_borrowing_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Questions::ExtraBorrowing, type: :model do
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(: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))) }
it "has correct page" do
expect(question.page).to eq(page)
diff --git a/spec/models/form/sales/questions/gender_description_spec.rb b/spec/models/form/sales/questions/gender_description_spec.rb
index e8ae2ce83..70f53100c 100644
--- a/spec/models/form/sales/questions/gender_description_spec.rb
+++ b/spec/models/form/sales/questions/gender_description_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Form::Sales::Questions::GenderDescription, type: :model do
let(:page) { instance_double(Form::Page) }
let(:person_index) { 2 }
let(:subsection) { instance_double(Form::Subsection) }
- let(:form) { instance_double(Form, start_date: current_collection_start_date) }
+ let(:form) { instance_double(Form, start_date: current_collection_start_date, person_question_count: 4) }
before do
allow(page).to receive(:subsection).and_return(subsection)
diff --git a/spec/models/form/sales/questions/gender_same_as_sex_spec.rb b/spec/models/form/sales/questions/gender_same_as_sex_spec.rb
index 61a5c5820..764aea055 100644
--- a/spec/models/form/sales/questions/gender_same_as_sex_spec.rb
+++ b/spec/models/form/sales/questions/gender_same_as_sex_spec.rb
@@ -10,7 +10,7 @@ RSpec.describe Form::Sales::Questions::GenderSameAsSex, type: :model do
let(:page) { instance_double(Form::Page) }
let(:person_index) { 2 }
let(:subsection) { instance_double(Form::Subsection) }
- let(:form) { instance_double(Form, start_date: current_collection_start_date) }
+ let(:form) { instance_double(Form, start_date: current_collection_start_date, person_question_count: 4) }
before do
allow(page).to receive(:subsection).and_return(subsection)
diff --git a/spec/models/form/sales/questions/has_leasehold_charges_spec.rb b/spec/models/form/sales/questions/has_leasehold_charges_spec.rb
index 9d518dfdc..139e04cdf 100644
--- a/spec/models/form/sales/questions/has_leasehold_charges_spec.rb
+++ b/spec/models/form/sales/questions/has_leasehold_charges_spec.rb
@@ -3,7 +3,7 @@ require "rails_helper"
RSpec.describe Form::Sales::Questions::HasLeaseholdCharges, type: :model do
subject(:question) { described_class.new(question_id, question_definition, page, ownershipsch: 1) }
- let(:form) { instance_double(Form, start_date: Time.zone.local(2025, 4, 4)) }
+ let(:form) { instance_double(Form, start_date: Time.zone.local(2025, 4, 4), start_year_2026_or_later?: false) }
let(:question_id) { nil }
let(:question_definition) { nil }
let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, id: "shared_ownership", form:)) }
diff --git a/spec/models/form/sales/questions/has_service_charge_spec.rb b/spec/models/form/sales/questions/has_service_charge_spec.rb
index d64609bb0..c795b44d9 100644
--- a/spec/models/form/sales/questions/has_service_charge_spec.rb
+++ b/spec/models/form/sales/questions/has_service_charge_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Questions::HasServiceCharge, type: :model do
let(:question_id) { nil }
let(:question_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date:)) }
+ let(:subsection) { instance_double(Form::Subsection, id: "shared_ownership_initial_purchase", form: instance_double(Form, start_date:, start_year_2026_or_later?: false)) }
let(:page) { instance_double(Form::Page, subsection:) }
let(:start_date) { Time.utc(2025, 5, 1) }
let(:staircasing) { false }
@@ -67,24 +67,23 @@ RSpec.describe Form::Sales::Questions::HasServiceCharge, type: :model do
context "with 2026/27 form" do
let(:start_date) { Time.utc(2026, 4, 1) }
-
- before do
- allow(subsection.form).to receive(:start_year_2026_or_later?).and_return(true)
- end
+ let(:subsection) { instance_double(Form::Subsection, id: subsection_id, form: instance_double(Form, start_date:, start_year_2026_or_later?: true)) }
context "when staircasing" do
let(:staircasing) { true }
+ let(:subsection_id) { "shared_ownership_staircasing_transaction" }
it "has the correct question number" do
- expect(question.question_number).to eq(0)
+ expect(question.question_number).to eq(110)
end
end
context "when not staircasing" do
let(:staircasing) { false }
+ let(:subsection_id) { "shared_ownership_initial_purchase" }
it "has the correct question number" do
- expect(question.question_number).to eq(0)
+ expect(question.question_number).to eq(96)
end
end
end
diff --git a/spec/models/form/sales/questions/has_service_charges_changed_spec.rb b/spec/models/form/sales/questions/has_service_charges_changed_spec.rb
new file mode 100644
index 000000000..4bfd73486
--- /dev/null
+++ b/spec/models/form/sales/questions/has_service_charges_changed_spec.rb
@@ -0,0 +1,56 @@
+require "rails_helper"
+
+RSpec.describe Form::Sales::Questions::HasServiceChargesChanged, type: :model do
+ include CollectionTimeHelper
+
+ subject(:question) { described_class.new(question_id, question_definition, page) }
+
+ let(:question_id) { nil }
+ let(:question_definition) { nil }
+ let(:subsection) { instance_double(Form::Subsection, id: "shared_ownership_staircasing_transaction", form: instance_double(Form, start_date:, start_year_2026_or_later?: true)) }
+ let(:page) { instance_double(Form::Page, subsection:) }
+ let(:start_date) { collection_start_date_for_year(2026) }
+
+ it "has correct page" do
+ expect(question.page).to eq(page)
+ end
+
+ it "has the correct id" do
+ expect(question.id).to eq("hasservicechargeschanged")
+ end
+
+ it "has the correct type" do
+ expect(question.type).to eq("radio")
+ end
+
+ it "is not marked as derived" do
+ expect(question.derived?(nil)).to be false
+ end
+
+ it "has the correct answer_options" do
+ expect(question.answer_options).to eq({
+ "1" => { "value" => "Yes" },
+ "2" => { "value" => "No" },
+ })
+ end
+
+ it "has correct conditional for" do
+ expect(question.conditional_for).to eq({
+ "newservicecharges" => [1],
+ })
+ end
+
+ it "has correct hidden_in_check_answers for" do
+ expect(question.hidden_in_check_answers).to eq({
+ "depends_on" => [
+ {
+ "hasservicechargeschanged" => 1,
+ },
+ ],
+ })
+ end
+
+ it "has the correct question number" do
+ expect(question.question_number).to eq(111)
+ end
+end
diff --git a/spec/models/form/sales/questions/leasehold_charges_spec.rb b/spec/models/form/sales/questions/leasehold_charges_spec.rb
index 35c2dd589..88819ffee 100644
--- a/spec/models/form/sales/questions/leasehold_charges_spec.rb
+++ b/spec/models/form/sales/questions/leasehold_charges_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Questions::LeaseholdCharges, type: :model do
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(: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))) }
it "has correct page" do
expect(question.page).to eq(page)
diff --git a/spec/models/form/sales/questions/living_before_purchase_spec.rb b/spec/models/form/sales/questions/living_before_purchase_spec.rb
index 9ac76887a..1bec2c0a3 100644
--- a/spec/models/form/sales/questions/living_before_purchase_spec.rb
+++ b/spec/models/form/sales/questions/living_before_purchase_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Questions::LivingBeforePurchase, type: :model do
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(: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))) }
it "has correct page" do
expect(question.page).to eq(page)
diff --git a/spec/models/form/sales/questions/living_before_purchase_years_spec.rb b/spec/models/form/sales/questions/living_before_purchase_years_spec.rb
index ddf5abd8f..e16a70518 100644
--- a/spec/models/form/sales/questions/living_before_purchase_years_spec.rb
+++ b/spec/models/form/sales/questions/living_before_purchase_years_spec.rb
@@ -6,7 +6,7 @@ RSpec.describe Form::Sales::Questions::LivingBeforePurchaseYears, type: :model d
let(:question_id) { nil }
let(:question_definition) { nil }
let(:start_date) { Time.utc(2024, 2, 8) }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date:)) }
+ let(:subsection) { instance_double(Form::Subsection, id: "shared_ownership_initial_purchase", form: instance_double(Form, start_date:, start_year_2026_or_later?: false)) }
let(:page) { instance_double(Form::Page, subsection:) }
context "when 2022" do
diff --git a/spec/models/form/sales/questions/mortgage_amount_spec.rb b/spec/models/form/sales/questions/mortgage_amount_spec.rb
index 9d5e68804..12da4bc1f 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, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1)))) }
+ 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))) }
it "has correct page" do
expect(question.page).to be(page)
diff --git a/spec/models/form/sales/questions/mortgage_length_spec.rb b/spec/models/form/sales/questions/mortgage_length_spec.rb
index 90c0ccab5..51fbdc128 100644
--- a/spec/models/form/sales/questions/mortgage_length_spec.rb
+++ b/spec/models/form/sales/questions/mortgage_length_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Questions::MortgageLength, type: :model do
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(: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))) }
it "has correct page" do
expect(question.page).to eq(page)
diff --git a/spec/models/form/sales/questions/mortgageused_spec.rb b/spec/models/form/sales/questions/mortgageused_spec.rb
index 93ce3ed4c..804067348 100644
--- a/spec/models/form/sales/questions/mortgageused_spec.rb
+++ b/spec/models/form/sales/questions/mortgageused_spec.rb
@@ -1,6 +1,8 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::Mortgageused, type: :model do
+ include CollectionTimeHelper
+
subject(:question) { described_class.new(question_id, question_definition, page, ownershipsch:) }
let(:question_id) { nil }
@@ -9,25 +11,41 @@ RSpec.describe Form::Sales::Questions::Mortgageused, type: :model do
let(:staircase) { nil }
let(:saledate) { Time.zone.today }
let(:log) { build(:sales_log, :in_progress, ownershipsch:, stairowned:, staircase:) }
-
- context "when the form start year is 2024" do
- let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1)) }
- let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form:, id: "shared_ownership")) }
- let(:saledate) { Time.zone.local(2024, 5, 1) }
+ let(:start_year_2024_or_later?) { true }
+ let(:start_year_2025_or_later?) { true }
+ let(:start_year_2026_or_later?) { true }
+ let(:subsection_id) { "shared_ownership_initial_purchase" }
+ let(:form) { instance_double(Form, start_date: saledate, start_year_2024_or_later?: start_year_2024_or_later?, start_year_2025_or_later?: start_year_2025_or_later?, start_year_2026_or_later?: start_year_2026_or_later?) }
+ let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form:, id: subsection_id)) }
+
+ context "when it is a shared ownership scheme" do
let(:ownershipsch) { 1 }
- before do
- allow(form).to receive_messages(start_year_2024_or_later?: true, start_year_2025_or_later?: false)
+ it "has the correct top_guidance_partial" do
+ expect(question.top_guidance_partial).to eq("financial_calculations_shared_ownership")
+ end
+ end
+
+ context "when it is a discounted ownership sale" do
+ let(:ownershipsch) { 2 }
+
+ it "has the correct top_guidance_partial" do
+ expect(question.top_guidance_partial).to eq("financial_calculations_discounted_ownership")
end
+ end
+
+ context "when it is an outright sale" do
+ let(:ownershipsch) { 3 }
- it "has the correct answer_options" do
- expect(question.answer_options).to eq({
- "1" => { "value" => "Yes" },
- "2" => { "value" => "No" },
- "divider" => { "value" => true },
- "3" => { "value" => "Don’t know" },
- })
+ it "has the correct top_guidance_partial" do
+ expect(question.top_guidance_partial).to eq("financial_calculations_outright_sale")
end
+ end
+
+ context "when the form start year is 2024", metadata: { year: 24 } do
+ let(:saledate) { collection_start_date_for_year(2024) }
+ let(:start_year_2025_or_later?) { false }
+ let(:start_year_2026_or_later?) { false }
context "when it is a discounted ownership sale" do
let(:ownershipsch) { 2 }
@@ -44,24 +62,22 @@ RSpec.describe Form::Sales::Questions::Mortgageused, type: :model do
context "when it is an outright sale" do
let(:ownershipsch) { 3 }
- context "and the saledate is before 24/25" do
- let(:saledate) { Time.zone.local(2023, 5, 1) }\
-
- it "does show the don't know option" do
- expect_the_question_to_show_dont_know
- end
+ it "shows the correct question number" do
+ expect(question.question_number).to eq 112
end
- context "and the saledate is 24/25" do
- it "shows the don't know option" do
- expect_the_question_to_show_dont_know
- end
+ it "shows the don't know option" do
+ expect_the_question_to_show_dont_know
end
end
context "when it is a shared ownership scheme" do
let(:ownershipsch) { 1 }
+ it "shows the correct question number" do
+ expect(question.question_number).to eq 91
+ end
+
context "and it is a staircasing transaction" do
let(:staircase) { 1 }
@@ -92,17 +108,13 @@ RSpec.describe Form::Sales::Questions::Mortgageused, type: :model do
end
end
- context "when the form start year is 2025" do
- let(:form) { instance_double(Form, start_date: Time.zone.local(2025, 4, 1)) }
- let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form:, id: "shared_ownership")) }
- let(:saledate) { Time.zone.local(2025, 5, 1) }
-
- before do
- allow(form).to receive_messages(start_year_2024_or_later?: true, start_year_2025_or_later?: true)
- end
+ context "when the form start year is 2025", metadata: { year: 25 } do
+ let(:saledate) { collection_start_date_for_year(2025) }
+ let(:start_year_2026_or_later?) { false }
context "when it is a discounted ownership sale" do
let(:ownershipsch) { 2 }
+ let(:subsection_id) { "discounted_ownership_scheme" }
it "shows the correct question number" do
expect(question.question_number).to eq 106
@@ -116,10 +128,14 @@ RSpec.describe Form::Sales::Questions::Mortgageused, type: :model do
context "when it is a shared ownership scheme" do
let(:ownershipsch) { 1 }
+ it "shows the correct question number" do
+ expect(question.question_number).to eq 82
+ end
+
context "and it is a staircasing transaction" do
let(:staircase) { 1 }
- it "does show the don't know option" do
+ it "shows the don't know option" do
expect_the_question_to_show_dont_know
end
@@ -142,6 +158,53 @@ RSpec.describe Form::Sales::Questions::Mortgageused, type: :model do
end
end
+ context "when the form start year is 2026", metadata: { year: 26 } do
+ let(:saledate) { collection_start_date_for_year(2026) }
+
+ context "when it is a discounted ownership sale" do
+ let(:ownershipsch) { 2 }
+ let(:subsection_id) { "discounted_ownership_scheme" }
+
+ it "shows the correct question number" do
+ expect(question.question_number).to eq 116
+ end
+
+ it "shows the don't know option" do
+ expect_the_question_to_show_dont_know
+ end
+ end
+
+ context "when it is a shared ownership scheme" do
+ let(:ownershipsch) { 1 }
+
+ context "and it is a staircasing transaction" do
+ let(:staircase) { 1 }
+ let(:subsection_id) { "shared_ownership_staircasing_transaction" }
+
+ it "shows the correct question number" do
+ expect(question.question_number).to eq 107
+ end
+
+ it "shows the don't know option" do
+ expect_the_question_to_show_dont_know
+ end
+ end
+
+ context "and it is not a staircasing transaction" do
+ let(:staircase) { 2 }
+ let(:subsection_id) { "shared_ownership_initial_purchase" }
+
+ it "shows the correct question number" do
+ expect(question.question_number).to eq 90
+ end
+
+ it "shows the don't know option" do
+ expect_the_question_to_show_dont_know
+ end
+ end
+ end
+ end
+
private
def expect_the_question_not_to_show_dont_know
diff --git a/spec/models/form/sales/questions/new_service_charges_spec.rb b/spec/models/form/sales/questions/new_service_charges_spec.rb
new file mode 100644
index 000000000..9bbfc6dd2
--- /dev/null
+++ b/spec/models/form/sales/questions/new_service_charges_spec.rb
@@ -0,0 +1,53 @@
+require "rails_helper"
+
+RSpec.describe Form::Sales::Questions::NewServiceCharges, type: :model do
+ include CollectionTimeHelper
+
+ subject(:question) { described_class.new(question_id, question_definition, page) }
+
+ let(:question_id) { nil }
+ let(:question_definition) { nil }
+ let(:subsection) { instance_double(Form::Subsection, id: "shared_ownership_staircasing_transaction", form: instance_double(Form, start_date:, start_year_2026_or_later?: true)) }
+ let(:page) { instance_double(Form::Page, subsection:) }
+ let(:start_date) { collection_start_date_for_year(2026) }
+
+ it "has correct page" do
+ expect(question.page).to eq(page)
+ end
+
+ it "has the correct id" do
+ expect(question.id).to eq("newservicecharges")
+ end
+
+ it "has the correct type" do
+ expect(question.type).to eq("numeric")
+ end
+
+ it "is not marked as derived" do
+ expect(question.derived?(nil)).to be false
+ end
+
+ it "has the correct width" do
+ expect(question.width).to be 5
+ end
+
+ it "has the correct min" do
+ expect(question.min).to be 0
+ end
+
+ it "has the correct max" do
+ expect(question.max).to be 9999.99
+ end
+
+ it "has the correct step" do
+ expect(question.step).to be 0.01
+ end
+
+ it "has the correct prefix" do
+ expect(question.prefix).to eq("£")
+ end
+
+ it "has the correct question number" do
+ expect(question.question_number).to eq(111)
+ end
+end
diff --git a/spec/models/form/sales/questions/number_of_others_in_property_spec.rb b/spec/models/form/sales/questions/number_of_others_in_property_spec.rb
index 7bf19dbe3..6d926c9c4 100644
--- a/spec/models/form/sales/questions/number_of_others_in_property_spec.rb
+++ b/spec/models/form/sales/questions/number_of_others_in_property_spec.rb
@@ -5,30 +5,45 @@ RSpec.describe Form::Sales::Questions::NumberOfOthersInProperty, type: :model do
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(:joint_purchase) { true }
- it "has correct page" do
- expect(question.page).to be(page)
- end
+ context "with 2023 form" do
+ let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2026_or_later?: false))) }
- it "has the correct id" do
- expect(question.id).to eq("hholdcount")
- end
+ it "has correct page" do
+ expect(question.page).to be(page)
+ end
- it "has the correct type" do
- expect(question.type).to eq("numeric")
- end
+ it "has the correct id" do
+ expect(question.id).to eq("hholdcount")
+ end
- it "is not marked as derived" do
- expect(question.derived?(nil)).to be false
- end
+ it "has the correct type" do
+ expect(question.type).to eq("numeric")
+ end
- it "has the correct min" do
- expect(question.min).to be 0
+ it "is not marked as derived" do
+ expect(question.derived?(nil)).to be false
+ end
+
+ it "has the correct min" do
+ expect(question.min).to be 0
+ end
+
+ it "has the correct max" do
+ expect(question.max).to be 15
+ end
end
- it "has the correct max" do
- expect(question.max).to be 15
+ context "with 2026 form" do
+ let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2026, 4, 1), start_year_2026_or_later?: true))) }
+
+ it "has the correct min" do
+ expect(question.min).to be 1
+ end
+
+ it "has the correct max" do
+ expect(question.max).to be 15
+ end
end
end
diff --git a/spec/models/form/sales/questions/person_age_known_spec.rb b/spec/models/form/sales/questions/person_age_known_spec.rb
index 2f2c12c33..610932296 100644
--- a/spec/models/form/sales/questions/person_age_known_spec.rb
+++ b/spec/models/form/sales/questions/person_age_known_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Questions::PersonAgeKnown, type: :model do
let(:question_id) { "age3_known" }
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(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), person_question_count: 4))) }
let(:person_index) { 2 }
it "has correct page" do
diff --git a/spec/models/form/sales/questions/person_age_spec.rb b/spec/models/form/sales/questions/person_age_spec.rb
index 772ee20e0..5187eb856 100644
--- a/spec/models/form/sales/questions/person_age_spec.rb
+++ b/spec/models/form/sales/questions/person_age_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Questions::PersonAge, type: :model do
let(:question_id) { "age3" }
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), start_year_2024_or_later?: false))) }
+ let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2024_or_later?: false, person_question_count: 4))) }
let(:person_index) { 2 }
it "has correct page" do
diff --git a/spec/models/form/sales/questions/person_gender_identity_spec.rb b/spec/models/form/sales/questions/person_gender_identity_spec.rb
index 32c2a30aa..b431e9e92 100644
--- a/spec/models/form/sales/questions/person_gender_identity_spec.rb
+++ b/spec/models/form/sales/questions/person_gender_identity_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Form::Sales::Questions::PersonGenderIdentity, type: :model do
let(:page) { instance_double(Form::Page) }
let(:person_index) { 2 }
let(:subsection) { instance_double(Form::Subsection) }
- let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1)) }
+ let(:form) { instance_double(Form, start_date: Time.zone.local(2023, 4, 1), person_question_count: 4) }
before do
allow(page).to receive(:subsection).and_return(subsection)
diff --git a/spec/models/form/sales/questions/person_relationship_to_buyer1_spec.rb b/spec/models/form/sales/questions/person_relationship_to_buyer1_spec.rb
index 0bc00c179..af93fe8dd 100644
--- a/spec/models/form/sales/questions/person_relationship_to_buyer1_spec.rb
+++ b/spec/models/form/sales/questions/person_relationship_to_buyer1_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Questions::PersonRelationshipToBuyer1, type: :model
let(:question_id) { "relat2" }
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), start_year_2024_or_later?: false))) }
+ let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1), start_year_2024_or_later?: false, person_question_count: 4))) }
let(:person_index) { 2 }
it "has correct page" do
diff --git a/spec/models/form/sales/questions/person_relationship_to_buyer1_yes_no_spec.rb b/spec/models/form/sales/questions/person_relationship_to_buyer1_yes_no_spec.rb
index cdfedc41e..d9d8830ca 100644
--- a/spec/models/form/sales/questions/person_relationship_to_buyer1_yes_no_spec.rb
+++ b/spec/models/form/sales/questions/person_relationship_to_buyer1_yes_no_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Questions::PersonRelationshipToBuyer1YesNo, type: :m
let(:question_id) { "relat2" }
let(:question_definition) { nil }
- let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2025, 4, 1)))) }
+ let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2025, 4, 1), person_question_count: 4))) }
let(:person_index) { 2 }
it "has correct page" do
diff --git a/spec/models/form/sales/questions/person_sex_registered_at_birth_spec.rb b/spec/models/form/sales/questions/person_sex_registered_at_birth_spec.rb
index eb5f10687..fb408263d 100644
--- a/spec/models/form/sales/questions/person_sex_registered_at_birth_spec.rb
+++ b/spec/models/form/sales/questions/person_sex_registered_at_birth_spec.rb
@@ -8,7 +8,7 @@ RSpec.describe Form::Sales::Questions::PersonSexRegisteredAtBirth, type: :model
let(:page) { instance_double(Form::Page) }
let(:person_index) { 2 }
let(:subsection) { instance_double(Form::Subsection) }
- let(:form) { instance_double(Form, start_date: Time.zone.local(2026, 4, 1)) }
+ let(:form) { instance_double(Form, start_date: Time.zone.local(2026, 4, 1), person_question_count: 4) }
before do
allow(page).to receive(:subsection).and_return(subsection)
diff --git a/spec/models/form/sales/questions/person_working_situation_spec.rb b/spec/models/form/sales/questions/person_working_situation_spec.rb
index c6a215741..c4f692e86 100644
--- a/spec/models/form/sales/questions/person_working_situation_spec.rb
+++ b/spec/models/form/sales/questions/person_working_situation_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Questions::PersonWorkingSituation, type: :model do
let(:question_id) { "ecstat2" }
let(:question_definition) { nil }
- let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1), start_year_2025_or_later?: false) }
+ let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1), start_year_2025_or_later?: false, person_question_count: 4) }
let(:page) { instance_double(Form::Page, subsection: instance_double(Form::Subsection, form:)) }
let(:person_index) { 2 }
@@ -43,7 +43,7 @@ RSpec.describe Form::Sales::Questions::PersonWorkingSituation, type: :model do
end
context "with start year before 2025" do
- let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1), start_year_2025_or_later?: false) }
+ let(:form) { instance_double(Form, start_date: Time.zone.local(2024, 4, 1), start_year_2025_or_later?: false, person_question_count: 4) }
it "uses the old ordering for answer options" do
expect(question.answer_options.keys).to eq(%w[1 2 3 4 6 8 5 0 10 7 9])
@@ -51,7 +51,7 @@ RSpec.describe Form::Sales::Questions::PersonWorkingSituation, type: :model do
end
context "with start year from 2025" do
- let(:form) { instance_double(Form, start_date: Time.zone.local(2025, 4, 1), start_year_2025_or_later?: true) }
+ let(:form) { instance_double(Form, start_date: Time.zone.local(2025, 4, 1), start_year_2025_or_later?: true, person_question_count: 4) }
it "uses the new ordering for answer options" do
expect(question.answer_options.keys).to eq(%w[1 2 3 4 5 6 7 8 9 0 10])
diff --git a/spec/models/form/sales/questions/purchase_price_spec.rb b/spec/models/form/sales/questions/purchase_price_spec.rb
index c3d2999a0..47081edb4 100644
--- a/spec/models/form/sales/questions/purchase_price_spec.rb
+++ b/spec/models/form/sales/questions/purchase_price_spec.rb
@@ -1,11 +1,15 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::PurchasePrice, type: :model do
+ include CollectionTimeHelper
+
subject(:question) { described_class.new(question_id, question_definition, page, ownershipsch: 1) }
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) { 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?))) }
it "has correct page" do
expect(question.page).to eq(page)
@@ -30,6 +34,8 @@ RSpec.describe Form::Sales::Questions::PurchasePrice, type: :model do
context "when discounted ownership scheme" do
subject(:question) { described_class.new(question_id, question_definition, page, ownershipsch: 2) }
+ let(:start_year) { 2023 }
+
it "has the correct question_number" do
expect(question.question_number).to eq(100)
end
@@ -38,6 +44,8 @@ RSpec.describe Form::Sales::Questions::PurchasePrice, type: :model do
context "when outright sale" do
subject(:question) { described_class.new(question_id, question_definition, page, ownershipsch: 3) }
+ let(:start_year) { 2023 }
+
it "has the correct question_number" do
expect(question.question_number).to eq(110)
end
@@ -51,7 +59,20 @@ RSpec.describe Form::Sales::Questions::PurchasePrice, type: :model do
expect(question.prefix).to eq("£")
end
- it "has correct min" do
- expect(question.min).to eq(0)
+ context "with year 2025", metadata: { year: 25 } do
+ let(:start_year) { 2025 }
+
+ it "has correct min" do
+ expect(question.min).to eq(0)
+ end
+ end
+
+ context "with year 2026", metadata: { year: 26 } do
+ let(:start_year) { 2026 }
+ let(:start_year_2026_or_later?) { true }
+
+ it "has correct min" do
+ expect(question.min).to eq(15_000)
+ end
end
end
diff --git a/spec/models/form/sales/questions/service_charge_spec.rb b/spec/models/form/sales/questions/service_charge_spec.rb
index 21104d2b5..0639a6b24 100644
--- a/spec/models/form/sales/questions/service_charge_spec.rb
+++ b/spec/models/form/sales/questions/service_charge_spec.rb
@@ -5,7 +5,7 @@ RSpec.describe Form::Sales::Questions::ServiceCharge, type: :model do
let(:question_id) { nil }
let(:question_definition) { nil }
- let(:subsection) { instance_double(Form::Subsection, form: instance_double(Form, start_date:)) }
+ let(:subsection) { instance_double(Form::Subsection, id: "shared_ownership_initial_purchase", form: instance_double(Form, start_date:, start_year_2026_or_later?: false)) }
let(:page) { instance_double(Form::Page, subsection:) }
let(:start_date) { Time.utc(2023, 4, 1) }
let(:staircasing) { false }
@@ -56,24 +56,23 @@ RSpec.describe Form::Sales::Questions::ServiceCharge, type: :model do
context "with 2026/27 form" do
let(:start_date) { Time.utc(2026, 4, 1) }
-
- before do
- allow(subsection.form).to receive(:start_year_2026_or_later?).and_return(true)
- end
+ let(:subsection) { instance_double(Form::Subsection, id: subsection_id, form: instance_double(Form, start_date:, start_year_2026_or_later?: true)) }
context "when staircasing" do
let(:staircasing) { true }
+ let(:subsection_id) { "shared_ownership_staircasing_transaction" }
it "has the correct question number" do
- expect(question.question_number).to eq(0)
+ expect(question.question_number).to eq(110)
end
end
context "when not staircasing" do
let(:staircasing) { false }
+ let(:subsection_id) { "shared_ownership_initial_purchase" }
it "has the correct question number" do
- expect(question.question_number).to eq(0)
+ expect(question.question_number).to eq(96)
end
end
end
diff --git a/spec/models/form/sales/questions/value_spec.rb b/spec/models/form/sales/questions/value_spec.rb
index bed4c7f96..2ebbf6d89 100644
--- a/spec/models/form/sales/questions/value_spec.rb
+++ b/spec/models/form/sales/questions/value_spec.rb
@@ -1,11 +1,15 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::Value, 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, id: "value_shared_ownership", subsection: instance_double(Form::Subsection, form: instance_double(Form, start_date: Time.zone.local(2023, 4, 1)), id: "shared_ownership")) }
+ 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)
@@ -35,7 +39,20 @@ RSpec.describe Form::Sales::Questions::Value, type: :model do
expect(question.prefix).to eq("£")
end
- it "has correct min" do
- expect(question.min).to eq(0)
+ context "with year 2025", metadata: { year: 25 } do
+ let(:start_year) { 2025 }
+
+ it "has correct min" do
+ expect(question.min).to eq(0)
+ end
+ end
+
+ context "with year 2026", metadata: { year: 26 } do
+ let(:start_year) { 2026 }
+ let(:start_year_2026_or_later?) { true }
+
+ it "has correct min" do
+ expect(question.min).to eq(15_000)
+ end
end
end
diff --git a/spec/models/form/sales/subsections/shared_ownership_staircasing_transaction_spec.rb b/spec/models/form/sales/subsections/shared_ownership_staircasing_transaction_spec.rb
index 3efe482d8..cc811682b 100644
--- a/spec/models/form/sales/subsections/shared_ownership_staircasing_transaction_spec.rb
+++ b/spec/models/form/sales/subsections/shared_ownership_staircasing_transaction_spec.rb
@@ -77,6 +77,7 @@ RSpec.describe Form::Sales::Subsections::SharedOwnershipStaircasingTransaction,
monthly_rent_staircasing_owned
monthly_rent_staircasing
service_charge_staircasing
+ service_charge_changed
monthly_charges_shared_ownership_value_check
],
)
diff --git a/spec/models/validations/sales/financial_validations_spec.rb b/spec/models/validations/sales/financial_validations_spec.rb
index 80d10718b..f55f4aa8b 100644
--- a/spec/models/validations/sales/financial_validations_spec.rb
+++ b/spec/models/validations/sales/financial_validations_spec.rb
@@ -478,4 +478,63 @@ RSpec.describe Validations::Sales::FinancialValidations do
expect(record.errors).to be_empty
end
end
+
+ describe "#validate_newservicecharges_different_from_mscharge" do
+ let(:record) { FactoryBot.build(:sales_log, ownershipsch: 1, staircase: 1) }
+
+ it "does not add errors when hasservicechargeschanged is nil" do
+ record.hasservicechargeschanged = nil
+ record.newservicecharges = 100
+ record.has_mscharge = 1
+ record.mscharge = 100
+ financial_validator.validate_newservicecharges_different_from_mscharge(record)
+ expect(record.errors).to be_empty
+ end
+
+ it "does not add errors when hasservicechargeschanged is 2 (No)" do
+ record.hasservicechargeschanged = 2
+ record.newservicecharges = 100
+ record.has_mscharge = 1
+ record.mscharge = 100
+ financial_validator.validate_newservicecharges_different_from_mscharge(record)
+ expect(record.errors).to be_empty
+ end
+
+ it "does not add errors when newservicecharges is nil" do
+ record.hasservicechargeschanged = 1
+ record.newservicecharges = nil
+ record.has_mscharge = 1
+ record.mscharge = 100
+ financial_validator.validate_newservicecharges_different_from_mscharge(record)
+ expect(record.errors).to be_empty
+ end
+
+ it "does not add errors when mscharge is nil" do
+ record.hasservicechargeschanged = 1
+ record.newservicecharges = 100
+ record.has_mscharge = 2
+ record.mscharge = nil
+ financial_validator.validate_newservicecharges_different_from_mscharge(record)
+ expect(record.errors).to be_empty
+ end
+
+ it "does not add errors when newservicecharges is different from mscharge" do
+ record.hasservicechargeschanged = 1
+ record.newservicecharges = 150
+ record.has_mscharge = 1
+ record.mscharge = 100
+ financial_validator.validate_newservicecharges_different_from_mscharge(record)
+ expect(record.errors).to be_empty
+ end
+
+ it "adds an error when hasservicechargeschanged is 1 (Yes) and newservicecharges equals mscharge" do
+ record.hasservicechargeschanged = 1
+ record.newservicecharges = 100
+ record.has_mscharge = 1
+ record.mscharge = 100
+ financial_validator.validate_newservicecharges_different_from_mscharge(record)
+ expect(record.errors["newservicecharges"]).to include(match I18n.t("validations.sales.financial.newservicecharges.same_as_previous"))
+ expect(record.errors["mscharge"]).to include(match I18n.t("validations.sales.financial.mscharge.same_as_new"))
+ end
+ end
end
diff --git a/spec/models/validations/sales/sale_information_validations_spec.rb b/spec/models/validations/sales/sale_information_validations_spec.rb
index 1731f19ac..7a4537322 100644
--- a/spec/models/validations/sales/sale_information_validations_spec.rb
+++ b/spec/models/validations/sales/sale_information_validations_spec.rb
@@ -663,6 +663,46 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
expect(record.errors["grant"]).to be_empty
end
end
+
+ context "with year 2026", :aggregate_failures do
+ let(:saledate) { Time.zone.local(2026, 4, 1) }
+
+ context "when mortgage and deposit is exact" do
+ let(:record) { FactoryBot.build(:sales_log, saledate:, mortgage: 85_000, deposit: 5_000, value: 100_000, discount: 10, ownershipsch: 2, type: 9) }
+
+ it "does not add an error" do
+ sale_information_validator.validate_discounted_ownership_value(record)
+ expect(record.errors["mortgage"]).to be_empty
+ expect(record.errors["value"]).to be_empty
+ expect(record.errors["deposit"]).to be_empty
+ expect(record.errors["discount"]).to be_empty
+ end
+ end
+
+ context "when mortgage and deposit is within 0.1% discount tolerance" do
+ let(:record) { FactoryBot.build(:sales_log, saledate:, mortgage: 85_000, deposit: 5_000, value: 100_000, discount: 10.1, ownershipsch: 2, type: 9) }
+
+ it "does not add an error" do
+ sale_information_validator.validate_discounted_ownership_value(record)
+ expect(record.errors["mortgage"]).to be_empty
+ expect(record.errors["value"]).to be_empty
+ expect(record.errors["deposit"]).to be_empty
+ expect(record.errors["discount"]).to be_empty
+ end
+ end
+
+ context "when mortgage and deposit is outside 0.1% discount tolerance" do
+ let(:record) { FactoryBot.build(:sales_log, saledate:, mortgage: 85_000, deposit: 5_000, value: 100_000, discount: 10.2, ownershipsch: 2, type: 9) }
+
+ it "adds an error" do
+ sale_information_validator.validate_discounted_ownership_value(record)
+ expect(record.errors["mortgage"]).not_to be_empty
+ expect(record.errors["value"]).not_to be_empty
+ expect(record.errors["deposit"]).not_to be_empty
+ expect(record.errors["discount"]).not_to be_empty
+ end
+ end
+ end
end
describe "#validate_outright_sale_value_matches_mortgage_plus_deposit" do
@@ -1171,6 +1211,82 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
end
end
end
+
+ context "with year 2026", :aggregate_failures do
+ let(:saledate) { Time.zone.local(2026, 4, 1) }
+
+ context "when mortgage and deposit is exact" do
+ let(:record) { FactoryBot.build(:sales_log, mortgageused: 1, mortgage: 10_000, staircase: 2, deposit: 5_000, value: 100_000, equity: 15, ownershipsch: 1, type: 30, saledate:) }
+
+ it "does not add an error" do
+ sale_information_validator.validate_non_staircasing_mortgage(record)
+ expect(record.errors["mortgage"]).to be_empty
+ expect(record.errors["value"]).to be_empty
+ expect(record.errors["deposit"]).to be_empty
+ expect(record.errors["equity"]).to be_empty
+ end
+ end
+
+ context "when mortgage and deposit is within 0.1% equity tolerance" do
+ let(:record) { FactoryBot.build(:sales_log, mortgageused: 1, mortgage: 10_000, staircase: 2, deposit: 5_000, value: 100_000, equity: 15.1, ownershipsch: 1, type: 30, saledate:) }
+
+ it "does not add an error" do
+ sale_information_validator.validate_non_staircasing_mortgage(record)
+ expect(record.errors["mortgage"]).to be_empty
+ expect(record.errors["value"]).to be_empty
+ expect(record.errors["deposit"]).to be_empty
+ expect(record.errors["equity"]).to be_empty
+ end
+ end
+
+ context "when mortgage and deposit is outside 0.1% equity tolerance" do
+ let(:record) { FactoryBot.build(:sales_log, mortgageused: 1, mortgage: 10_000, staircase: 2, deposit: 5_000, value: 100_000, equity: 15.2, ownershipsch: 1, type: 30, saledate:) }
+
+ it "adds an error" do
+ sale_information_validator.validate_non_staircasing_mortgage(record)
+ expect(record.errors["mortgage"]).not_to be_empty
+ expect(record.errors["value"]).not_to be_empty
+ expect(record.errors["deposit"]).not_to be_empty
+ expect(record.errors["equity"]).not_to be_empty
+ end
+ end
+
+ context "when deposit (no mortgage) is exact" do
+ let(:record) { FactoryBot.build(:sales_log, mortgageused: 2, staircase: 2, deposit: 15_000, value: 100_000, equity: 15, ownershipsch: 1, type: 30, saledate:) }
+
+ it "does not add an error" do
+ sale_information_validator.validate_non_staircasing_mortgage(record)
+ expect(record.errors["mortgageused"]).to be_empty
+ expect(record.errors["value"]).to be_empty
+ expect(record.errors["deposit"]).to be_empty
+ expect(record.errors["equity"]).to be_empty
+ end
+ end
+
+ context "when deposit (no mortgage) is within 0.1% equity tolerance" do
+ let(:record) { FactoryBot.build(:sales_log, mortgageused: 2, staircase: 2, deposit: 15_000, value: 100_000, equity: 15.1, ownershipsch: 1, type: 30, saledate:) }
+
+ it "does not add an error" do
+ sale_information_validator.validate_non_staircasing_mortgage(record)
+ expect(record.errors["mortgageused"]).to be_empty
+ expect(record.errors["value"]).to be_empty
+ expect(record.errors["deposit"]).to be_empty
+ expect(record.errors["equity"]).to be_empty
+ end
+ end
+
+ context "when deposit (no mortgage) is outside 0.1% equity tolerance" do
+ let(:record) { FactoryBot.build(:sales_log, mortgageused: 2, staircase: 2, deposit: 15_000, value: 100_000, equity: 15.2, ownershipsch: 1, type: 30, saledate:) }
+
+ it "adds an error" do
+ sale_information_validator.validate_non_staircasing_mortgage(record)
+ expect(record.errors["mortgageused"]).not_to be_empty
+ expect(record.errors["value"]).not_to be_empty
+ expect(record.errors["deposit"]).not_to be_empty
+ expect(record.errors["equity"]).not_to be_empty
+ end
+ end
+ end
end
describe "#validate_staircasing_mortgage" do
@@ -1385,76 +1501,156 @@ RSpec.describe Validations::Sales::SaleInformationValidations do
sale_information_validator.validate_mortgage_used_dont_know(sales_log)
end
- context "when mortgageused is don't know" do
- let(:mortgageused) { 3 }
+ context "when 2025", metadata: { year: 25 } do
+ let(:saledate) { collection_start_date_for_year(2025) }
- context "and it is a discounted ownership sale" do
- let(:ownershipsch) { 2 }
+ context "when mortgageused is don't know" do
+ let(:mortgageused) { 3 }
- it "adds an error" do
- expect(sales_log.errors[:mortgageused]).to include "Enter a valid value for was a mortgage used for the purchase of this property?"
+ context "and it is a discounted ownership sale" do
+ let(:ownershipsch) { 2 }
+
+ it "adds an error" do
+ expect(sales_log.errors[:mortgageused]).to include "Enter a valid value for was a mortgage used for the purchase of this property?"
+ end
end
- end
- context "and it is an outright sale" do
- let(:ownershipsch) { 3 }
+ context "and it is an outright sale" do
+ let(:ownershipsch) { 3 }
- it "does not add any errors" do
- expect(sales_log.errors).to be_empty
+ it "does not add any errors" do
+ expect(sales_log.errors).to be_empty
+ end
end
- end
- context "and it is a shared ownership scheme sale" do
- let(:ownershipsch) { 1 }
+ context "and it is a shared ownership scheme sale" do
+ let(:ownershipsch) { 1 }
- context "and a staircasing transaction" do
- let(:staircase) { 1 }
+ context "and a staircasing transaction" do
+ let(:staircase) { 1 }
- context "and stairowned is nil" do
- let(:stairowned) { nil }
+ context "and stairowned is nil" do
+ let(:stairowned) { nil }
- it "does not add an error" do
- expect(sales_log.errors).to be_empty
+ it "does not add an error" do
+ expect(sales_log.errors).to be_empty
+ end
end
- end
- context "and stairowned is less than 100" do
- let(:stairowned) { 50 }
+ context "and stairowned is less than 100" do
+ let(:stairowned) { 50 }
- it "adds errors" do
- expect(sales_log.errors[:mortgageused]).to include "The percentage owned has to be 100% if the mortgage used is 'Don’t know'"
- expect(sales_log.errors[:stairowned]).to include "The percentage owned has to be 100% if the mortgage used is 'Don’t know'"
+ it "adds errors" do
+ expect(sales_log.errors[:mortgageused]).to include "The percentage owned has to be 100% if the mortgage used is 'Don’t know'"
+ expect(sales_log.errors[:stairowned]).to include "The percentage owned has to be 100% if the mortgage used is 'Don’t know'"
+ end
+ end
+
+ context "and stairowned is 100" do
+ let(:stairowned) { 100 }
+
+ it "does not add an error" do
+ expect(sales_log.errors).to be_empty
+ end
end
end
- context "and stairowned is 100" do
- let(:stairowned) { 100 }
+ context "and not a staircasing transaction" do
+ let(:staircase) { 2 }
- it "does not add an error" do
- expect(sales_log.errors).to be_empty
+ it "adds errors" do
+ expect(sales_log.errors[:mortgageused]).to include "Enter a valid value for was a mortgage used for the purchase of this property?"
+ expect(sales_log.errors[:staircase]).to include "You must answer either ‘yes’ or ‘no’ to the question ‘was a mortgage used’ for staircasing transactions."
end
end
end
+ end
- context "and not a staircasing transaction" do
- let(:staircase) { 2 }
+ context "when mortgageused is not don't know" do
+ let(:mortgageused) { 1 }
- it "adds errors" do
- expect(sales_log.errors[:mortgageused]).to include "Enter a valid value for was a mortgage used for the purchase of this property?"
- expect(sales_log.errors[:staircase]).to include "You must answer either ‘yes’ or ‘no’ to the question ‘was a mortgage used’ for staircasing transactions."
+ context "and it is a discounted ownership sale" do
+ let(:ownershipsch) { 2 }
+
+ it "does not add an error" do
+ expect(sales_log.errors).to be_empty
end
end
end
end
- context "when mortgageused is not don't know" do
- let(:mortgageused) { 1 }
+ context "when 2026", metadata: { year: 26 } do
+ let(:saledate) { collection_start_date_for_year(2026) }
- context "and it is a discounted ownership sale" do
- let(:ownershipsch) { 2 }
+ context "when mortgageused is don't know" do
+ let(:mortgageused) { 3 }
- it "does not add an error" do
- expect(sales_log.errors).to be_empty
+ context "and it is a discounted ownership sale" do
+ let(:ownershipsch) { 2 }
+
+ it "does not add any errors" do
+ expect(sales_log.errors).to be_empty
+ end
+ end
+
+ context "and it is an outright sale" do
+ let(:ownershipsch) { 3 }
+
+ it "does not add any errors" do
+ expect(sales_log.errors).to be_empty
+ end
+ end
+
+ context "and it is a shared ownership scheme sale" do
+ let(:ownershipsch) { 1 }
+
+ context "and a staircasing transaction" do
+ let(:staircase) { 1 }
+
+ context "and stairowned is nil" do
+ let(:stairowned) { nil }
+
+ it "does not add an error" do
+ expect(sales_log.errors).to be_empty
+ end
+ end
+
+ context "and stairowned is less than 100" do
+ let(:stairowned) { 50 }
+
+ it "does not add any errors" do
+ expect(sales_log.errors).to be_empty
+ end
+ end
+
+ context "and stairowned is 100" do
+ let(:stairowned) { 100 }
+
+ it "does not add an error" do
+ expect(sales_log.errors).to be_empty
+ end
+ end
+ end
+
+ context "and not a staircasing transaction" do
+ let(:staircase) { 2 }
+
+ it "does not add any errors" do
+ expect(sales_log.errors).to be_empty
+ end
+ end
+ end
+ end
+
+ context "when mortgageused is not don't know" do
+ let(:mortgageused) { 1 }
+
+ context "and it is a discounted ownership sale" do
+ let(:ownershipsch) { 2 }
+
+ it "does not add an error" do
+ expect(sales_log.errors).to be_empty
+ end
end
end
end
diff --git a/spec/requests/duplicate_logs_controller_spec.rb b/spec/requests/duplicate_logs_controller_spec.rb
index b254dcb15..69140f1e9 100644
--- a/spec/requests/duplicate_logs_controller_spec.rb
+++ b/spec/requests/duplicate_logs_controller_spec.rb
@@ -170,7 +170,8 @@ RSpec.describe DuplicateLogsController, type: :request do
expect(page).to have_content("- Buyer 1’s gender identity", count: 3)
expect(page).to have_content("- Buyer 1’s working situation", count: 3)
expect(page).to have_content("- Postcode", count: 3)
- expect(page).to have_link("Change", count: 21)
+ expect(page).to have_content("- Address line 1", count: 3)
+ expect(page).to have_link("Change", count: 24)
expect(page).to have_link("Change", href: "/sales-logs/#{sales_log.id}/purchaser-code?first_remaining_duplicate_id=#{duplicate_logs[0].id}&organisation_id=#{sales_log.owning_organisation_id}&original_log_id=#{sales_log.id}&referrer=duplicate_logs")
expect(page).to have_link("Change", href: "/sales-logs/#{duplicate_logs[0].id}/purchaser-code?first_remaining_duplicate_id=#{sales_log.id}&organisation_id=#{sales_log.owning_organisation_id}&original_log_id=#{sales_log.id}&referrer=duplicate_logs")
expect(page).to have_link("Change", href: "/sales-logs/#{duplicate_logs[1].id}/purchaser-code?first_remaining_duplicate_id=#{sales_log.id}&organisation_id=#{sales_log.owning_organisation_id}&original_log_id=#{sales_log.id}&referrer=duplicate_logs")
@@ -216,7 +217,8 @@ RSpec.describe DuplicateLogsController, type: :request do
expect(page).to have_content("- Buyer 1’s gender identity", count: 1)
expect(page).to have_content("- Buyer 1’s working situation", count: 1)
expect(page).to have_content("- Postcode", count: 1)
- expect(page).to have_link("Change", count: 7)
+ expect(page).to have_content("- Address line 1", count: 1)
+ expect(page).to have_link("Change", count: 8)
expect(page).to have_link("Change", href: "/sales-logs/#{sales_log.id}/purchaser-code?original_log_id=#{sales_log.id}&referrer=interruption_screen")
end
@@ -242,7 +244,8 @@ RSpec.describe DuplicateLogsController, type: :request do
expect(page).to have_content("- Buyer 1’s gender identity", count: 1)
expect(page).to have_content("- Buyer 1’s working situation", count: 1)
expect(page).to have_content("- Postcode", count: 1)
- expect(page).to have_link("Change", count: 7)
+ expect(page).to have_content("- Address line 1", count: 1)
+ expect(page).to have_link("Change", count: 8)
expect(page).to have_link("Change", href: "/sales-logs/#{sales_log.id}/purchaser-code?original_log_id=#{sales_log.id}&referrer=interruption_screen")
end
@@ -377,7 +380,8 @@ RSpec.describe DuplicateLogsController, type: :request do
expect(page).to have_content("- Buyer 1’s gender identity", count: 3)
expect(page).to have_content("- Buyer 1’s working situation", count: 3)
expect(page).to have_content("- Postcode", count: 3)
- expect(page).to have_link("Change", count: 18)
+ expect(page).to have_content("- Address line 1", count: 3)
+ expect(page).to have_link("Change", count: 21)
expect(page).to have_link("Change", href: "/sales-logs/#{sales_log.id}/purchaser-code?first_remaining_duplicate_id=#{duplicate_logs[0].id}&original_log_id=#{sales_log.id}&referrer=duplicate_logs")
expect(page).to have_link("Change", href: "/sales-logs/#{duplicate_logs[0].id}/purchaser-code?first_remaining_duplicate_id=#{sales_log.id}&original_log_id=#{sales_log.id}&referrer=duplicate_logs")
expect(page).to have_link("Change", href: "/sales-logs/#{duplicate_logs[1].id}/purchaser-code?first_remaining_duplicate_id=#{sales_log.id}&original_log_id=#{sales_log.id}&referrer=duplicate_logs")
@@ -405,7 +409,8 @@ RSpec.describe DuplicateLogsController, type: :request do
expect(page).to have_content("- Buyer 1’s gender identity", count: 1)
expect(page).to have_content("- Buyer 1’s working situation", count: 1)
expect(page).to have_content("- Postcode", count: 1)
- expect(page).to have_link("Change", count: 6)
+ expect(page).to have_content("- Address line 1", count: 1)
+ expect(page).to have_link("Change", count: 7)
expect(page).to have_link("Change", href: "/sales-logs/#{sales_log.id}/purchaser-code?original_log_id=#{sales_log.id}&referrer=interruption_screen")
end
@@ -431,7 +436,8 @@ RSpec.describe DuplicateLogsController, type: :request do
expect(page).to have_content("- Buyer 1’s gender identity", count: 1)
expect(page).to have_content("- Buyer 1’s working situation", count: 1)
expect(page).to have_content("- Postcode", count: 1)
- expect(page).to have_link("Change", count: 6)
+ expect(page).to have_content("- Address line 1", count: 1)
+ expect(page).to have_link("Change", count: 7)
expect(page).to have_link("Change", href: "/sales-logs/#{sales_log.id}/purchaser-code?original_log_id=#{sales_log.id}&referrer=interruption_screen")
end
diff --git a/spec/services/bulk_upload/sales/validator_spec.rb b/spec/services/bulk_upload/sales/validator_spec.rb
index 263bb92f8..9d4458a95 100644
--- a/spec/services/bulk_upload/sales/validator_spec.rb
+++ b/spec/services/bulk_upload/sales/validator_spec.rb
@@ -225,7 +225,7 @@ RSpec.describe BulkUpload::Sales::Validator do
end
it "creates errors" do
- expect { validator.call }.to change(BulkUploadError.where(category: :setup, error: "This is a duplicate of a log in your file."), :count).by(20)
+ expect { validator.call }.to change(BulkUploadError.where(category: :setup, error: "This is a duplicate of a log in your file."), :count).by(24)
end
end
end
diff --git a/spec/services/bulk_upload/sales/year2023/row_parser_spec.rb b/spec/services/bulk_upload/sales/year2023/row_parser_spec.rb
index 55146e22e..874bc05f0 100644
--- a/spec/services/bulk_upload/sales/year2023/row_parser_spec.rb
+++ b/spec/services/bulk_upload/sales/year2023/row_parser_spec.rb
@@ -1136,17 +1136,6 @@ RSpec.describe BulkUpload::Sales::Year2023::RowParser do
end
end
end
-
- describe "#field_128" do
- let(:attributes) { valid_attributes.merge({ field_7: "3", field_10: "10", field_128: "3", field_12: "2" }) }
-
- it "does not allow 3 (don't know) as an option for outright sale" do
- expect(parser.errors[:field_128]).to include("Enter a valid value for was a mortgage used for the purchase of this property?")
- parser.log.blank_invalid_non_setup_fields!
- parser.log.save!
- expect(parser.log.mortgageused).to be_nil
- end
- end
end
describe "#log" do
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 523e55fbd..d9c6032b5 100644
--- a/spec/services/bulk_upload/sales/year2025/row_parser_spec.rb
+++ b/spec/services/bulk_upload/sales/year2025/row_parser_spec.rb
@@ -800,6 +800,8 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
:field_1, # Sale completion date
:field_2, # Sale completion date
:field_3, # Sale completion date
+ :field_16, # UPRN
+ :field_17, # Address line 1
:field_21, # Postcode
:field_22, # Postcode
:field_28, # Buyer 1 age
@@ -830,6 +832,8 @@ RSpec.describe BulkUpload::Sales::Year2025::RowParser do
:field_1, # Sale completion date
:field_2, # Sale completion date
:field_3, # Sale completion date
+ :field_16, # UPRN
+ :field_17, # Address line 1
:field_21, # Postcode
:field_22, # Postcode
:field_28, # Buyer 1 age
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 7874cd4c5..e80d9980a 100644
--- a/spec/services/bulk_upload/sales/year2026/row_parser_spec.rb
+++ b/spec/services/bulk_upload/sales/year2026/row_parser_spec.rb
@@ -67,7 +67,7 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
field_38: "28",
field_39: "2",
field_40: "1",
- field_41: "0",
+ field_41: "1",
field_58: "1",
field_59: "1",
field_60: "A1",
@@ -116,6 +116,8 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
field_123: "1",
field_125: "2",
field_126: "Non-binary",
+ field_135: "1",
+ field_136: "150",
}
end
@@ -804,6 +806,8 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
:field_1, # Sale completion date
:field_2, # Sale completion date
:field_3, # Sale completion date
+ :field_16, # UPRN
+ :field_17, # Address line 1
:field_21, # Postcode
:field_22, # Postcode
:field_28, # Buyer 1 age
@@ -834,6 +838,8 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
:field_1, # Sale completion date
:field_2, # Sale completion date
:field_3, # Sale completion date
+ :field_16, # UPRN
+ :field_17, # Address line 1
:field_21, # Postcode
:field_22, # Postcode
:field_28, # Buyer 1 age
@@ -1112,7 +1118,7 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
describe "##{known} and ##{age}" do
context "when #{field} is blank" do
context "and person details are blank" do
- let(:attributes) { setup_section_params.merge({ field.to_s => nil, relationship.to_sym => nil, gender.to_sym => nil, field_15: "1", field_41: "5" }) }
+ let(:attributes) { setup_section_params.merge({ field.to_s => nil, relationship.to_sym => nil, gender.to_sym => nil, field_15: "1", field_41: "6" }) }
it "does not set ##{known}" do
unless known == "age1_known"
@@ -1132,7 +1138,7 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
end
context "and person details are given" do
- let(:attributes) { setup_section_params.merge({ field.to_sym => nil, relationship.to_sym => "C", gender.to_sym => "X", field_15: "1", field_41: "5" }) }
+ let(:attributes) { setup_section_params.merge({ field.to_sym => nil, relationship.to_sym => "C", gender.to_sym => "X", field_15: "1", field_41: "6" }) }
it "does not set ##{age}" do
parser.valid?
@@ -1142,7 +1148,7 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
end
context "when #{field} is R" do
- let(:attributes) { setup_section_params.merge({ field.to_s => "R", field_14: "1", field_41: "5", field_15: "1" }) }
+ let(:attributes) { setup_section_params.merge({ field.to_s => "R", field_14: "1", field_41: "6", field_15: "1" }) }
it "sets ##{known} 1" do
expect(parser.log.public_send(known)).to be(1)
@@ -1154,7 +1160,7 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
end
context "when #{field} is a number" do
- let(:attributes) { setup_section_params.merge({ field.to_s => "50", field_14: "1", field_41: "5", field_15: "1" }) }
+ let(:attributes) { setup_section_params.merge({ field.to_s => "50", field_14: "1", field_41: "6", field_15: "1" }) }
it "sets ##{known} to 0" do
expect(parser.log.public_send(known)).to be(0)
@@ -1166,7 +1172,7 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
end
context "when #{field} is a non-sensical value" do
- let(:attributes) { setup_section_params.merge({ field.to_s => "A", field_14: "1", field_41: "5", field_15: "1" }) }
+ let(:attributes) { setup_section_params.merge({ field.to_s => "A", field_14: "1", field_41: "6", field_15: "1" }) }
it "sets ##{known} to 0" do
expect(parser.log.public_send(known)).to be(0)
@@ -1189,7 +1195,7 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
].each do |input_field, relationship_attribute, person_num|
describe input_field.to_s do
context "when #{input_field} is 1" do
- let(:attributes) { setup_section_params.merge({ input_field.to_sym => "1", field_41: "5" }) }
+ let(:attributes) { setup_section_params.merge({ input_field.to_sym => "1", field_41: "6" }) }
it "sets relationship to P" do
expect(parser.log.public_send(relationship_attribute)).to eq("P")
@@ -1197,7 +1203,7 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
end
context "when #{input_field} is 2" do
- let(:attributes) { setup_section_params.merge({ input_field.to_sym => "2", field_41: "5" }) }
+ let(:attributes) { setup_section_params.merge({ input_field.to_sym => "2", field_41: "6" }) }
it "sets relationship to X" do
expect(parser.log.public_send(relationship_attribute)).to eq("X")
@@ -1205,7 +1211,7 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
end
context "when #{input_field} is 3" do
- let(:attributes) { setup_section_params.merge({ input_field.to_sym => "3", field_41: "5" }) }
+ let(:attributes) { setup_section_params.merge({ input_field.to_sym => "3", field_41: "6" }) }
it "sets relationship to R" do
expect(parser.log.public_send(relationship_attribute)).to eq("R")
@@ -1213,7 +1219,7 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
end
context "when #{input_field} is 4" do
- let(:attributes) { setup_section_params.merge({ input_field.to_sym => "4", field_41: "5" }) }
+ let(:attributes) { setup_section_params.merge({ input_field.to_sym => "4", field_41: "6" }) }
it "gives a validation error" do
parser.valid?
@@ -1331,13 +1337,9 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
context "when value is 3 and stairowned is not 100" do
let(:attributes) { setup_section_params.merge(field_109: "3", field_10: "1", field_96: "50", field_97: "99", field_120: nil) }
- it "returns correct errors" do
+ it "does not add errors" do
parser.valid?
- expect(parser.errors[:field_109]).to include("The percentage owned has to be 100% if the mortgage used is 'Don’t know'")
-
- parser.log.blank_invalid_non_setup_fields!
- parser.log.save!
- expect(parser.log.mortgageused).to be_nil
+ expect(parser.errors[:field_109]).to be_empty
end
end
@@ -1381,13 +1383,9 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
context "when value is 3 and stairowned is not answered" do
let(:attributes) { setup_section_params.merge(field_88: "3", field_10: "2", field_96: "50", field_97: nil, field_120: nil) }
- it "returns correct errors" do
+ it "does not add errors" do
parser.valid?
- expect(parser.errors[:field_88]).to include(I18n.t("validations.invalid_option", question: "was a mortgage used for the purchase of this property?"))
-
- parser.log.blank_invalid_non_setup_fields!
- parser.log.save!
- expect(parser.log.mortgageused).to be_nil
+ expect(parser.errors[:field_88]).to be_empty
end
end
@@ -1423,13 +1421,9 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
describe "#field_116" do
let(:attributes) { valid_attributes.merge({ field_8: "2", field_11: "9", field_116: "3" }) }
- it "does not allow 3 (don't know) as an option for discounted ownership" do
+ it "allows 3 (don't know) as an option for discounted ownership" do
parser.valid?
- expect(parser.errors[:field_116]).to include(I18n.t("validations.invalid_option", question: "was a mortgage used for the purchase of this property?"))
-
- parser.log.blank_invalid_non_setup_fields!
- parser.log.save!
- expect(parser.log.mortgageused).to be_nil
+ expect(parser.errors[:field_116]).to be_empty
end
context "when validate_discounted_ownership_value is triggered" do
diff --git a/spec/services/csv/sales_log_csv_service_spec.rb b/spec/services/csv/sales_log_csv_service_spec.rb
index 84d4267df..9b73d0c6d 100644
--- a/spec/services/csv/sales_log_csv_service_spec.rb
+++ b/spec/services/csv/sales_log_csv_service_spec.rb
@@ -253,7 +253,21 @@ RSpec.describe Csv::SalesLogCsvService do
let(:fixed_time) { collection_start_date_for_year(2026) }
before do
- log.update!(nationality_all: 36, manual_address_entry_selected: false, uprn: "1", uprn_known: 1)
+ log.update!(
+ nationality_all: 36,
+ manual_address_entry_selected: false,
+ uprn: "1",
+ uprn_known: 1,
+ hholdcount: 5,
+ details_known_4: 1,
+ ecstat4: 3,
+ age4_known: 1,
+ sexrab4: "R",
+ gender_same_as_sex4: 2,
+ sex4: "X",
+ relat4: "X",
+ details_known_5: 2,
+ )
end
it "exports the CSV with the 2026 ordering and all values correct" do
@@ -366,7 +380,18 @@ RSpec.describe Csv::SalesLogCsvService do
let(:year) { 2026 }
before do
- log.update!(manual_address_entry_selected: false, uprn: "1", uprn_known: 1)
+ log.update!(manual_address_entry_selected: false,
+ uprn: "1",
+ uprn_known: 1,
+ hholdcount: 5,
+ details_known_4: 1,
+ ecstat4: 3,
+ age4_known: 1,
+ sexrab4: "R",
+ gender_same_as_sex4: 2,
+ sex4: "X",
+ relat4: "X",
+ details_known_5: 2)
end
it "exports the CSV with all values correct" do
@@ -454,7 +479,20 @@ RSpec.describe Csv::SalesLogCsvService do
let(:fixed_time) { collection_start_date_for_year(2026) }
before do
- log.update!(nationality_all: 36, manual_address_entry_selected: false, uprn: "1", uprn_known: 1, buildheightclass: 2)
+ log.update!(nationality_all: 36,
+ manual_address_entry_selected: false,
+ uprn: "1",
+ uprn_known: 1,
+ buildheightclass: 2,
+ hholdcount: 5,
+ details_known_4: 1,
+ ecstat4: 3,
+ age4_known: 1,
+ sexrab4: "R",
+ gender_same_as_sex4: 2,
+ sex4: "X",
+ relat4: "X",
+ details_known_5: 2)
end
context "and exporting with labels" do
diff --git a/spec/services/exports/sales_log_export_service_spec.rb b/spec/services/exports/sales_log_export_service_spec.rb
index 25709fdb8..5c1796ff9 100644
--- a/spec/services/exports/sales_log_export_service_spec.rb
+++ b/spec/services/exports/sales_log_export_service_spec.rb
@@ -411,7 +411,7 @@ RSpec.describe Exports::SalesLogExportService do
end
context "and one sales log is available for export" do
- let!(:sales_log) { FactoryBot.create(:sales_log, :export) }
+ let!(:sales_log) { FactoryBot.create(:sales_log, :export, hholdcount: 6) }
let(:expected_zip_filename) { "core_sales_2026_2027_apr_mar_f0001_inc0001.zip" }
let(:expected_data_filename) { "core_sales_2026_2027_apr_mar_f0001_inc0001_pt001.xml" }
let(:xml_export_file) { File.open("spec/fixtures/exports/sales_log_26_27.xml", "r:UTF-8") }
@@ -451,18 +451,12 @@ RSpec.describe Exports::SalesLogExportService do
end
context "with shared ownership and mscharge" do
- let!(:sales_log) { FactoryBot.create(:sales_log, :export, ownershipsch: 1, staircase: 2, type: 30, mscharge: 321, has_management_fee: 1, management_fee: 222) }
-
- def replace_mscharge_and_shared_ownership_values(export_file)
+ def replace_shared_ownership_values(export_file)
export_file.sub!("", "1")
export_file.sub!("", "321.0")
- export_file.sub!("", "1")
- export_file.sub!("", "222.0")
export_file.sub!("100.0", "")
export_file.sub!("1", "")
- export_file.sub!("8", "30")
- export_file.sub!("", "2")
export_file.sub!("10000.0", "")
export_file.sub!("0", "1")
export_file.sub!("SW1A", "")
@@ -474,16 +468,93 @@ RSpec.describe Exports::SalesLogExportService do
export_file.sub!("Westminster", "")
end
- it "exports mscharge fields as hasmscharge and mscharge" do
- expected_content = replace_entity_ids(sales_log, xml_export_file.read)
- expected_content = replace_mscharge_and_shared_ownership_values(expected_content)
- expect(storage_service).to receive(:write_file).with(expected_zip_filename, any_args) do |_, content|
- entry = Zip::File.open_buffer(content).find_entry(expected_data_filename)
- expect(entry).not_to be_nil
- expect(entry.get_input_stream.read).to have_same_xml_contents_as(expected_content)
+ context "when not staircasing" do
+ let!(:sales_log) { FactoryBot.create(:sales_log, :export, ownershipsch: 1, staircase: 2, type: 30, mscharge: 321, has_management_fee: 1, management_fee: 222) }
+
+ def replace_non_staircasing_values(export_file)
+ export_file.sub!("", "1")
+ export_file.sub!("", "222.0")
+ export_file.sub!("8", "30")
+ export_file.sub!("", "2")
end
- export_service.export_xml_sales_logs
+ it "exports mscharge fields as hasmscharge and mscharge" do
+ expected_content = replace_entity_ids(sales_log, xml_export_file.read)
+ replace_shared_ownership_values(expected_content)
+ replace_non_staircasing_values(expected_content)
+ expect(storage_service).to receive(:write_file).with(expected_zip_filename, any_args) do |_, content|
+ entry = Zip::File.open_buffer(content).find_entry(expected_data_filename)
+ expect(entry).not_to be_nil
+ expect(entry.get_input_stream.read).to have_same_xml_contents_as(expected_content)
+ end
+
+ export_service.export_xml_sales_logs
+ end
+ end
+
+ context "when staircasing" do
+ context "when exporting only 26/27 collection period", metadata: { year: 26 } do
+ let(:start_time) { collection_start_date_for_year(2026) }
+ let(:expected_zip_filename) { "core_sales_2026_2027_apr_mar_f0001_inc0001.zip" }
+ let(:expected_data_filename) { "core_sales_2026_2027_apr_mar_f0001_inc0001_pt001.xml" }
+ let(:xml_export_file) { File.open("spec/fixtures/exports/sales_log_26_27.xml", "r:UTF-8") }
+ let!(:sales_log) { FactoryBot.create(:sales_log, :export, ownershipsch: 1, staircase: 1, type: 2, mscharge: 321, has_management_fee: 1, management_fee: 222, hasservicechargeschanged: 1, newservicecharges: 150, hholdcount: 6) }
+
+ def replace_staircasing_values(export_file)
+ export_file.sub!("", "1")
+ export_file.sub!("", "222.0")
+ export_file.sub!("8", "2")
+ export_file.sub!("", "1")
+ export_file.sub!("5", "")
+ export_file.sub!("1", "")
+ export_file.sub!("3", "")
+ export_file.sub!("80000.0", "")
+ export_file.sub!("1", "")
+ export_file.sub!("1", "")
+ export_file.sub!("1", "")
+ export_file.sub!("222.0", "")
+ export_file.sub!("17", "")
+ export_file.sub!("17", "")
+ export_file.sub!("17", "")
+ export_file.sub!("1", "")
+ export_file.sub!("4", "")
+ export_file.sub!("6", "")
+ export_file.sub!("7", "")
+ export_file.sub!("1", "")
+ export_file.sub!("0", "")
+ export_file.sub!("1", "")
+ export_file.sub!("0", "")
+ export_file.sub!("10000", "")
+ export_file.sub!("10000", "")
+ export_file.sub!("1", "")
+ export_file.sub!("1", "")
+ export_file.sub!("20000.0", "")
+ export_file.sub!("10", "")
+ export_file.sub!("826", "")
+ export_file.sub!("826", "")
+ export_file.sub!("1", "")
+ export_file.sub!("2", "")
+ export_file.sub!("1", "")
+ export_file.sub!("1", "")
+ export_file.sub!("1", "")
+ export_file.sub!("1", "")
+ export_file.sub!("", "1")
+ export_file.sub!("", "150.0")
+ end
+
+ it "exports mscharge fields and hasservicechargeschanged and newservicecharges" do
+ expected_content = replace_entity_ids(sales_log, xml_export_file.read)
+ replace_shared_ownership_values(expected_content)
+ replace_staircasing_values(expected_content)
+ expect(storage_service).to receive(:write_file).with(expected_zip_filename, any_args) do |_, content|
+ entry = Zip::File.open_buffer(content).find_entry(expected_data_filename)
+ expect(entry).not_to be_nil
+ expect(entry.get_input_stream.read).to have_same_xml_contents_as(expected_content)
+ end
+
+ export_service.export_xml_sales_logs(full_update: true, collection_year: 2026)
+ end
+ end
end
end
end