Browse Source

CLDC-4166: How many live in property updates (#3194)

* CLDC-4166: question updaets

* CLDC-4166: question updates

* CLDC-4166: test updates

* CLDC-4166: test updates

* CLDC-4166: test updates

* CLDC-4226: Index logs by org and ID (#3199)

* CLDC-4226: index logs by org and id

* CLDC-4226: include teamwide non-functional schema change

* CLDC-4226: schema update

* CLDC-4176: fix failing tests

* CLDC-4176: renumber case insensitive fields test

* CLDC-4166: update csv export spec

* CLDC-4166: linting

* CLDC-4166: copy updates in fixtures

* CLDC-4166: copy updates in fixtures

* CLDC-4166: copy updates in fixtures

* CLDC-4166: var defs count update

* CLDC-4166: fixtures tweak for hhtype

* CLDC-4166: fixtures tweak for hhtype

* CLDC-4166: fixtures tweak for hhtype

* CLDC-4166: export update

* CLDC-4166: whitespace linting

* CLDC-4166: update number_of_others_in_property_spec.rb

* CLDC-4166: update log_variable_definitions_spec.rb

* CLDC-4166: update sales_log_csv_service_spec.rb

* CLDC-4166: update tests

* CLDC-4166: update tests
pull/3208/head
Nat Dean-Lewis 6 days ago committed by GitHub
parent
commit
cd51f7c2c4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 8
      app/models/derived_variables/sales_log_variables.rb
  2. 6
      app/models/form/sales/pages/person_known.rb
  3. 2
      app/models/form/sales/questions/number_of_others_in_property.rb
  4. 2
      app/services/bulk_upload/sales/year2026/row_parser.rb
  5. 12
      config/locales/forms/2026/sales/household_characteristics.en.yml
  6. 2
      spec/fixtures/exports/sales_log_26_27.xml
  7. 2
      spec/fixtures/files/2026_27_sales_bulk_upload.csv
  8. 4
      spec/fixtures/files/sales_logs_csv_export_codes_26.csv
  9. 4
      spec/fixtures/files/sales_logs_csv_export_labels_26.csv
  10. 4
      spec/fixtures/files/sales_logs_csv_export_non_support_codes_26.csv
  11. 4
      spec/fixtures/files/sales_logs_csv_export_non_support_labels_26.csv
  12. 1
      spec/fixtures/variable_definitions/sales_download_26_27.csv
  13. 2
      spec/lib/tasks/log_variable_definitions_spec.rb
  14. 50
      spec/models/form/sales/pages/number_of_others_in_property_spec.rb
  15. 152
      spec/models/form/sales/pages/person_known_spec.rb
  16. 49
      spec/models/form/sales/questions/number_of_others_in_property_spec.rb
  17. 20
      spec/services/bulk_upload/sales/year2026/row_parser_spec.rb
  18. 44
      spec/services/csv/sales_log_csv_service_spec.rb
  19. 6
      spec/services/exports/sales_log_export_service_spec.rb

8
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

6
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

2
app/models/form/sales/questions/number_of_others_in_property.rb

@ -5,7 +5,7 @@ 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 = get_question_number_from_hash(QUESTION_NUMBER_FROM_YEAR)

2
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",

12
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: ""

2
spec/fixtures/exports/sales_log_26_27.xml vendored

@ -20,7 +20,7 @@
<PRIVACYNOTICE>1</PRIVACYNOTICE>
<ECSTAT1>1</ECSTAT1>
<WHEEL>1</WHEEL>
<HHOLDCOUNT>4</HHOLDCOUNT>
<HHOLDCOUNT>6</HHOLDCOUNT>
<AGE3>14</AGE3>
<LA>E09000033</LA>
<INCOME1>10000</INCOME1>

2
spec/fixtures/files/2026_27_sales_bulk_upload.csv vendored

@ -1,5 +1,5 @@
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?
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.

Can't render this file because it has a wrong number of fields in line 15.

4
spec/fixtures/files/sales_logs_csv_export_codes_26.csv vendored

File diff suppressed because one or more lines are too long

4
spec/fixtures/files/sales_logs_csv_export_labels_26.csv vendored

File diff suppressed because one or more lines are too long

4
spec/fixtures/files/sales_logs_csv_export_non_support_codes_26.csv vendored

File diff suppressed because one or more lines are too long

4
spec/fixtures/files/sales_logs_csv_export_non_support_labels_26.csv vendored

File diff suppressed because one or more lines are too long

1
spec/fixtures/variable_definitions/sales_download_26_27.csv vendored

@ -19,3 +19,4 @@ gender_same_as_sex6,Is the gender person 6 identifies with the same as their sex
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?

1 sexrab1,What was buyer 1's sex at birth?
19 gender_description6,If 'No', enter person 6's gender identity
20 hasservicechargeschanged,Will the service charge change after this staircasing transaction takes place?
21 newservicecharges,What are the new total monthly service charges for the property?
22 hholdcount,In total, how many people live in the property?

2
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) { 465 }
let(:total_variable_definitions_count) { 466 }
before do
Rake.application.rake_require("tasks/log_variable_definitions")

50
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

152
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

49
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

20
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",
@ -1102,7 +1102,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"
@ -1122,7 +1122,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?
@ -1132,7 +1132,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)
@ -1144,7 +1144,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)
@ -1156,7 +1156,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)
@ -1179,7 +1179,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")
@ -1187,7 +1187,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")
@ -1195,7 +1195,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")
@ -1203,7 +1203,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?

44
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

6
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") }
@ -498,7 +498,7 @@ RSpec.describe Exports::SalesLogExportService do
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) }
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!("<HASESTATEFEE/>", "<HASESTATEFEE>1</HASESTATEFEE>")
@ -518,7 +518,7 @@ RSpec.describe Exports::SalesLogExportService do
export_file.sub!("<ETHNICGROUP2>17</ETHNICGROUP2>", "<ETHNICGROUP2/>")
export_file.sub!("<HASESTATEFEE>1</HASESTATEFEE>", "<HASESTATEFEE/>")
export_file.sub!("<HB>4</HB>", "<HB/>")
export_file.sub!("<HHOLDCOUNT>4</HHOLDCOUNT>", "<HHOLDCOUNT/>")
export_file.sub!("<HHOLDCOUNT>6</HHOLDCOUNT>", "<HHOLDCOUNT/>")
export_file.sub!("<HHREGRES>7</HHREGRES>", "<HHREGRES/>")
export_file.sub!("<INC1MORT>1</INC1MORT>", "<INC1MORT/>")
export_file.sub!("<INC1NK>0</INC1NK>", "<INC1NK/>")

Loading…
Cancel
Save