Browse Source

CLDC-4178: Add gender same as sex question for sales (#3188)

* CLDC-4173: add new buildheightclass db changes

* CLDC-4173: add new buildheightclass page and question

* CLDC-4173: add new buildheightclass bu and export updates

* CLDC-4173: update tests

* CLDC-4173: update var defs

* CLDC-4173: add sales csv export tests for 26 including buildheightclass

* CLDC-4173: add sales csv export tests for 25 and 26 including buildheightclass

* CLDC-4173: update sales export spec

* CLDC-4173: update sales export spec and make sales log csv service future-proof

* CLDC-4178: add gender same as sex question for sales db changes

* CLDC-4178: add gender same as sex question for sales questions and pages

* CLDC-4178: add gender same as sex question for sales questions and pages

* CLDC-4178: add gender same as sex question for sales copy

* CLDC-4178: add gender same as sex question for sales person known page

* CLDC-4178: add gender same as sex question for sales service updates

* CLDC-4178: add gender same as sex question for sales test updates

* CLDC-4140: update sales log to csv

* CLDC-4140: revert typo

* CLDC-4140: update factory

* CLDC-4140: update factory

* CLDC-4140: filename linting

* CLDC-4178: update parser tests

* CLDC-4178: update fixtures

* CLDC-4173: add missing sales log export fixtures and tests

* CLDC-4178: add missing sales log export fixtures and tests

* CLDC-4178: update log var defs count

* CLDC-4178: fix tests

* CLDC-4237: Use each over for_each in sidekiq init (#3196)

linter incorrectly assumes it is an activerecord relation

* CLDC-4173: date refactoring in tests

* CLDC-4173: date refactoring in tests

* CLDC-4173: schema updates

* CLDC-4173: cleanup and test improvements

* CLDC-4173: remove deduplicated code

* CLDC-4173: update dates in tests

* CLDC-4178: more test date updates

* CLDC-4173: test date updates

* CLDC-4178: test date updates

* CLDC-4178: unused copy cleanup

* CLDC-4178: use shared person subsection block from CLDC-4176

* CLDC-4178: comment refactoring

* CLDC-4178: person_n_present? updates

* CLDC-4178: copy main csv fixtures

* CLDC-4178: update csv fixtures

* CLDC-4178: factory updates

* CLDC-4178: export updates

* CLDC-4178: refactoring for consistency with lettings

* CLDC-4178: add copy key to gender same as sex

* CLDC-4178: fix typo in export test

* CLDC-4178: fix typo in locale copy

---------

Co-authored-by: Samuel Young <samuel.young@softwire.com>
pull/3217/head
Nat Dean-Lewis 2 weeks ago committed by GitHub
parent
commit
34664bde2d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 15
      app/helpers/bulk_upload/sales_log_to_csv.rb
  2. 12
      app/models/derived_variables/lettings_log_variables.rb
  3. 2
      app/models/derived_variables/sales_log_variables.rb
  4. 21
      app/models/form/sales/pages/buyer1_gender_same_as_sex.rb
  5. 23
      app/models/form/sales/pages/buyer2_gender_same_as_sex.rb
  6. 16
      app/models/form/sales/pages/person_gender_same_as_sex.rb
  7. 16
      app/models/form/sales/questions/gender_description.rb
  8. 33
      app/models/form/sales/questions/gender_same_as_sex.rb
  9. 3
      app/models/form/sales/subsections/household_characteristics.rb
  10. 13
      app/models/log.rb
  11. 4
      app/services/bulk_upload/sales/year2026/csv_parser.rb
  12. 61
      app/services/bulk_upload/sales/year2026/row_parser.rb
  13. 1
      app/services/csv/sales_log_csv_service.rb
  14. 2
      app/services/exports/sales_log_export_constants.rb
  15. 16
      config/locales/forms/2026/lettings/household_characteristics.en.yml
  16. 91
      config/locales/forms/2026/sales/household_characteristics.en.yml
  17. 18
      db/migrate/20260220141000_add_gender_same_as_sex_fields_to_sales_logs.rb
  18. 12
      db/schema.rb
  19. 12
      spec/factories/sales_log.rb
  20. 12
      spec/fixtures/exports/sales_log_26_27.xml
  21. 18
      spec/fixtures/files/2026_27_sales_bulk_upload.csv
  22. 6
      spec/fixtures/files/sales_logs_csv_export_codes_26.csv
  23. 6
      spec/fixtures/files/sales_logs_csv_export_labels_26.csv
  24. 6
      spec/fixtures/files/sales_logs_csv_export_non_support_codes_26.csv
  25. 6
      spec/fixtures/files/sales_logs_csv_export_non_support_labels_26.csv
  26. 12
      spec/fixtures/variable_definitions/sales_download_26_27.csv
  27. 2
      spec/lib/tasks/log_variable_definitions_spec.rb
  28. 31
      spec/models/form/sales/pages/buyer1_gender_same_as_sex_spec.rb
  29. 40
      spec/models/form/sales/pages/buyer2_gender_same_as_sex_spec.rb
  30. 105
      spec/models/form/sales/pages/person_gender_same_as_sex_spec.rb
  31. 163
      spec/models/form/sales/questions/gender_description_spec.rb
  32. 189
      spec/models/form/sales/questions/gender_same_as_sex_spec.rb
  33. 7
      spec/models/form/sales/subsections/household_characteristics_spec.rb
  34. 3
      spec/services/bulk_upload/sales/year2026/row_parser_spec.rb
  35. 8
      spec/services/csv/sales_log_csv_service_spec.rb

15
app/helpers/bulk_upload/sales_log_to_csv.rb

@ -664,8 +664,21 @@ class BulkUpload::SalesLogToCsv
log.mortlen,
log.extrabor,
log.deposit, # 120
log.mscharge,
log.buildheightclass, # 122
log.buildheightclass,
log.gender_same_as_sex1,
log.gender_description1,
log.gender_same_as_sex2,
log.gender_description2,
log.gender_same_as_sex3,
log.gender_description3,
log.gender_same_as_sex4,
log.gender_description4, # 130
log.gender_same_as_sex5,
log.gender_description5,
log.gender_same_as_sex6,
log.gender_description6, # 134
]
end

12
app/models/derived_variables/lettings_log_variables.rb

@ -450,18 +450,6 @@ private
3 if rent_type == 5
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
(1..8).each do |person_index|
gender_same_as_sex = public_send("gender_same_as_sex#{person_index}")
if gender_same_as_sex.present? && gender_same_as_sex != 2
self["gender_description#{person_index}"] = nil
end
end
end
def set_checkbox_values!
form.questions.select { |q| q.type == "checkbox" }.each do |question|
options = question.answer_keys_without_dividers

2
app/models/derived_variables/sales_log_variables.rb

@ -102,6 +102,8 @@ module DerivedVariables::SalesLogVariables
self.mortlen_known = 0
end
clear_gender_description_unless_gender_not_same_as_sex! if form.start_year_2026_or_later?
set_encoded_derived_values!(DEPENDENCIES)
end

21
app/models/form/sales/pages/buyer1_gender_same_as_sex.rb

@ -0,0 +1,21 @@
class Form::Sales::Pages::Buyer1GenderSameAsSex < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "buyer_1_gender_same_as_sex"
@depends_on = [
{
"buyer_has_seen_privacy_notice?" => true,
},
{
"buyer_not_interviewed?" => true,
},
]
end
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),
]
end
end

23
app/models/form/sales/pages/buyer2_gender_same_as_sex.rb

@ -0,0 +1,23 @@
class Form::Sales::Pages::Buyer2GenderSameAsSex < ::Form::Page
def initialize(id, hsh, subsection)
super
@id = "buyer_2_gender_same_as_sex"
@depends_on = [
{
"joint_purchase?" => true,
"buyer_has_seen_privacy_notice?" => true,
},
{
"joint_purchase?" => true,
"buyer_not_interviewed?" => true,
},
]
end
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),
]
end
end

16
app/models/form/sales/pages/person_gender_same_as_sex.rb

@ -0,0 +1,16 @@
class Form::Sales::Pages::PersonGenderSameAsSex < ::Form::Page
def initialize(id, hsh, subsection, person_index:)
super(id, hsh, subsection)
@person_index = person_index
@depends_on = [
{ "details_known_#{person_index}" => 1 },
]
end
def questions
@questions ||= [
Form::Sales::Questions::GenderSameAsSex.new(nil, nil, self, person_index: @person_index),
Form::Sales::Questions::GenderDescription.new(nil, nil, self, person_index: @person_index),
]
end
end

16
app/models/form/sales/questions/gender_description.rb

@ -0,0 +1,16 @@
class Form::Sales::Questions::GenderDescription < ::Form::Question
def initialize(id, hsh, page, person_index:)
super(id, hsh, page)
@id = "gender_description#{person_index}"
@type = "text"
@check_answers_card_number = person_index
@person_index = person_index
@question_number = QUESTION_NUMBER_FROM_YEAR[form.start_date.year] || QUESTION_NUMBER_FROM_YEAR[QUESTION_NUMBER_FROM_YEAR.keys.max]
end
QUESTION_NUMBER_FROM_YEAR = { 2026 => 0 }.freeze
def derived?(log)
log.public_send("gender_same_as_sex#{@person_index}") != 2
end
end

33
app/models/form/sales/questions/gender_same_as_sex.rb

@ -0,0 +1,33 @@
class Form::Sales::Questions::GenderSameAsSex < ::Form::Question
def initialize(id, hsh, page, person_index:, buyer: false)
super(id, hsh, page)
@id = "gender_same_as_sex#{person_index}"
@type = "radio"
@check_answers_card_number = person_index
@conditional_for = { "gender_description#{person_index}" => [2] }
@inferred_check_answers_value = [{ "condition" => { "gender_same_as_sex#{person_index}" => 2 }, "value" => "No" }]
@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]
end
QUESTION_NUMBER_FROM_YEAR = { 2026 => 0 }.freeze
def answer_options
{
"1" => { "value" => "Yes" },
"2" => { "value" => "No, enter gender identity" },
"divider" => { "value" => true },
"3" => { "value" => "#{@buyer ? 'Buyer' : 'Person'} prefers not to say" },
}.freeze
end
def label_from_value(value, _log = nil, _user = nil)
return unless value
return "Prefers not to say" if value == 3
super
end
end

3
app/models/form/sales/subsections/household_characteristics.rb

@ -25,6 +25,7 @@ class Form::Sales::Subsections::HouseholdCharacteristics < ::Form::Subsection
Form::Sales::Pages::OldPersonsSharedOwnershipValueCheck.new("age_1_old_persons_shared_ownership_joint_purchase_value_check", nil, self, joint_purchase: true),
Form::Sales::Pages::OldPersonsSharedOwnershipValueCheck.new("age_1_old_persons_shared_ownership_value_check", nil, self, joint_purchase: false),
(Form::Sales::Pages::SexRegisteredAtBirth1.new(nil, nil, self) if form.start_year_2026_or_later?),
(Form::Sales::Pages::Buyer1GenderSameAsSex.new(nil, nil, self) if form.start_year_2026_or_later?),
(Form::Sales::Pages::GenderIdentity1.new(nil, nil, self) unless form.start_year_2026_or_later?),
Form::Sales::Pages::Buyer1EthnicGroup.new(nil, nil, self),
Form::Sales::Pages::Buyer1EthnicBackgroundBlack.new(nil, nil, self),
@ -48,6 +49,7 @@ class Form::Sales::Subsections::HouseholdCharacteristics < ::Form::Subsection
(Form::Sales::Pages::NotRetiredValueCheck.new("age_2_buyer_not_retired_value_check", nil, self, person_index: 2) if form.start_year_2024_or_later?),
(Form::Sales::Pages::PersonStudentNotChildValueCheck.new("buyer_2_age_student_not_child_value_check", nil, self, person_index: 2) unless form.start_year_2025_or_later?),
(Form::Sales::Pages::SexRegisteredAtBirth2.new(nil, nil, self) if form.start_year_2026_or_later?),
(Form::Sales::Pages::Buyer2GenderSameAsSex.new(nil, nil, self) if form.start_year_2026_or_later?),
(Form::Sales::Pages::GenderIdentity2.new(nil, nil, self) unless form.start_year_2026_or_later?),
buyer_2_ethnicity_nationality_pages,
Form::Sales::Pages::Buyer2WorkingSituation.new(nil, nil, self),
@ -77,6 +79,7 @@ class Form::Sales::Subsections::HouseholdCharacteristics < ::Form::Subsection
(Form::Sales::Pages::PartnerUnder16ValueCheck.new("age_#{person_index}_partner_under_16_value_check", nil, self, person_index:) if form.start_year_2024_or_later?),
(Form::Sales::Pages::PersonGenderIdentity.new("person_#{person_index}_gender_identity", nil, self, person_index:) unless form.start_year_2026_or_later?),
(Form::Sales::Pages::PersonSexRegisteredAtBirth.new("person_#{person_index}_sex_registered_at_birth", nil, self, person_index:) if form.start_year_2026_or_later?),
(Form::Sales::Pages::PersonGenderSameAsSex.new("person_#{person_index}_gender_same_as_sex", nil, self, person_index:) if form.start_year_2026_or_later?),
Form::Sales::Pages::PersonWorkingSituation.new("person_#{person_index}_working_situation", nil, self, person_index:),
Form::Sales::Pages::RetirementValueCheck.new("working_situation_#{person_index}_retirement_value_check", nil, self, person_index:),
(Form::Sales::Pages::NotRetiredValueCheck.new("working_situation_#{person_index}_not_retired_value_check", nil, self, person_index:) if form.start_year_2024_or_later?),

13
app/models/log.rb

@ -345,6 +345,19 @@ class Log < ApplicationRecord
end
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
max_person = lettings? ? 8 : 6
(1..max_person).each do |person_index|
gender_same_as_sex = public_send("gender_same_as_sex#{person_index}")
if gender_same_as_sex.present? && gender_same_as_sex != 2
self["gender_description#{person_index}"] = nil
end
end
end
private
# Handle logs that are older than previous collection start date

4
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 = 122
FIELDS = 134
FORM_YEAR = 2026
attr_reader :path
@ -27,7 +27,7 @@ class BulkUpload::Sales::Year2026::CsvParser
def cols
# TODO: CLDC-4162: Update when 2026 format is known
@cols ||= ("A".."DP").to_a
@cols ||= ("A".."ED").to_a
end
def row_parsers

61
app/services/bulk_upload/sales/year2026/row_parser.rb

@ -137,6 +137,18 @@ class BulkUpload::Sales::Year2026::RowParser
field_121: "What are the total monthly leasehold charges for the property?",
field_122: "What is the building height classification?",
field_123: "Is the gender buyer 1 identifies with the same as their sex registered at birth?",
field_124: "If 'No', enter buyer 1's gender identity",
field_125: "Is the gender buyer/person 2 identifies with the same as their sex registered at birth?",
field_126: "If 'No', enter buyer/person 2's gender identity",
field_127: "Is the gender person 3 identifies with the same as their sex registered at birth?",
field_128: "If 'No', enter person 3's gender identity",
field_129: "Is the gender person 4 identifies with the same as their sex registered at birth?",
field_130: "If 'No', enter person 4's gender identity",
field_131: "Is the gender person 5 identifies with the same as their sex registered at birth?",
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",
}.freeze
ERROR_BASE_KEY = "validations.sales.2026.bulk_upload".freeze
@ -303,6 +315,19 @@ class BulkUpload::Sales::Year2026::RowParser
attribute :field_121, :decimal
attribute :field_122, :integer
attribute :field_123, :integer
attribute :field_124, :string
attribute :field_125, :integer
attribute :field_126, :string
attribute :field_127, :integer
attribute :field_128, :string
attribute :field_129, :integer
attribute :field_130, :string
attribute :field_131, :integer
attribute :field_132, :string
attribute :field_133, :integer
attribute :field_134, :string
validates :field_1,
presence: {
message: I18n.t("#{ERROR_BASE_KEY}.not_answered", question: "sale completion date (day)."),
@ -839,6 +864,19 @@ private
sexrab5: %i[field_52],
sexrab6: %i[field_56],
buildheightclass: %i[field_122],
gender_same_as_sex1: %i[field_123],
gender_description1: %i[field_124],
gender_same_as_sex2: %i[field_125],
gender_description2: %i[field_126],
gender_same_as_sex3: %i[field_127],
gender_description3: %i[field_128],
gender_same_as_sex4: %i[field_129],
gender_description4: %i[field_130],
gender_same_as_sex5: %i[field_131],
gender_description5: %i[field_132],
gender_same_as_sex6: %i[field_133],
gender_description6: %i[field_134],
}
end
@ -875,6 +913,19 @@ private
attributes["sexrab6"] = field_56
attributes["buildheightclass"] = field_122
attributes["gender_same_as_sex1"] = field_123
attributes["gender_description1"] = field_124
attributes["gender_same_as_sex2"] = field_125
attributes["gender_description2"] = field_126
attributes["gender_same_as_sex3"] = field_127
attributes["gender_description3"] = field_128
attributes["gender_same_as_sex4"] = field_129
attributes["gender_description4"] = field_130
attributes["gender_same_as_sex5"] = field_131
attributes["gender_description5"] = field_132
attributes["gender_same_as_sex6"] = field_133
attributes["gender_description6"] = field_134
attributes["relat2"] = relationship_from_is_partner(field_34)
attributes["relat3"] = relationship_from_is_partner(field_42)
attributes["relat4"] = relationship_from_is_partner(field_46)
@ -1075,23 +1126,23 @@ private
end
def person_2_present?
field_35.present? || field_36.present? || field_34.present?
field_35.present? || field_36.present? || field_34.present? || field_125.present? || field_126.present?
end
def person_3_present?
field_43.present? || field_44.present? || field_42.present?
field_43.present? || field_44.present? || field_42.present? || field_127.present? || field_128.present?
end
def person_4_present?
field_47.present? || field_48.present? || field_46.present?
field_47.present? || field_48.present? || field_46.present? || field_129.present? || field_130.present?
end
def person_5_present?
field_51.present? || field_52.present? || field_50.present?
field_51.present? || field_52.present? || field_50.present? || field_131.present? || field_132.present?
end
def person_6_present?
field_55.present? || field_56.present? || field_54.present?
field_55.present? || field_56.present? || field_54.present? || field_133.present? || field_134.present?
end
def relationship_from_is_partner(is_partner)

1
app/services/csv/sales_log_csv_service.rb

@ -115,6 +115,7 @@ module Csv
(2..6).each do |i|
hash["age#{i}"] = { "refused_code" => "-9", "refused_label" => "Not known", "details_known_field" => "details_known_#{i}", "age_known_field" => "age#{i}_known" }
hash["sexrab#{i}"] = { "refused_code" => "R", "refused_label" => "Prefers not to say", "details_known_field" => "details_known_#{i}" }
hash["gender_same_as_sex#{i}"] = { "refused_code" => "3", "refused_label" => "Prefers not to say", "details_known_field" => "details_known_#{i}" }
hash["sex#{i}"] = { "refused_code" => "R", "refused_label" => "Prefers not to say", "details_known_field" => "details_known_#{i}" }
hash["relat#{i}"] = { "refused_code" => "R", "refused_label" => "Prefers not to say", "details_known_field" => "details_known_#{i}" }
hash["ecstat#{i}"] = { "refused_code" => "10", "refused_label" => "Prefers not to say", "details_known_field" => "details_known_#{i}" }

2
app/services/exports/sales_log_export_constants.rb

@ -161,5 +161,7 @@ module Exports::SalesLogExportConstants
(1..6).each do |index|
YEAR_2026_EXPORT_FIELDS << "SEXRAB#{index}"
YEAR_2026_EXPORT_FIELDS << "GENDER_SAME_AS_SEX#{index}"
YEAR_2026_EXPORT_FIELDS << "GENDER_DESCRIPTION#{index}"
end
end

16
config/locales/forms/2026/lettings/household_characteristics.en.yml

@ -32,7 +32,7 @@ en:
gender_same_as_sex1:
page_header: ""
check_answer_label: "Lead tenant’s gender identity same as registered at birth"
check_answer_label: "Lead tenant’s gender identity same as sex registered at birth"
check_answer_prompt: ""
hint_text: ""
question_text: "Is the gender the lead tenant identifies with the same as their sex registered at birth?"
@ -139,7 +139,7 @@ en:
gender_same_as_sex2:
page_header: ""
check_answer_label: "Person 2’s gender identity same as registered at birth"
check_answer_label: "Person 2’s gender identity same as sex registered at birth"
check_answer_prompt: ""
hint_text: ""
question_text: "Is the gender person 2 identifies with the same as their sex registered at birth?"
@ -194,7 +194,7 @@ en:
gender_same_as_sex3:
page_header: ""
check_answer_label: "Person 3’s gender identity same as registered at birth"
check_answer_label: "Person 3’s gender identity same as sex registered at birth"
check_answer_prompt: ""
hint_text: ""
question_text: "Is the gender person 3 identifies with the same as their sex registered at birth?"
@ -249,7 +249,7 @@ en:
gender_same_as_sex4:
page_header: ""
check_answer_label: "Person 4’s gender identity same as registered at birth"
check_answer_label: "Person 4’s gender identity same as sex registered at birth"
check_answer_prompt: ""
hint_text: ""
question_text: "Is the gender person 4 identifies with the same as their sex registered at birth?"
@ -304,7 +304,7 @@ en:
gender_same_as_sex5:
page_header: ""
check_answer_label: "Person 5’s gender identity same as registered at birth"
check_answer_label: "Person 5’s gender identity same as sex registered at birth"
check_answer_prompt: ""
hint_text: ""
question_text: "Is the gender person 5 identifies with the same as their sex registered at birth?"
@ -359,7 +359,7 @@ en:
gender_same_as_sex6:
page_header: ""
check_answer_label: "Person 6’s gender identity same as registered at birth"
check_answer_label: "Person 6’s gender identity same as sex registered at birth"
check_answer_prompt: ""
hint_text: ""
question_text: "Is the gender person 6 identifies with the same as their sex registered at birth?"
@ -414,7 +414,7 @@ en:
gender_same_as_sex7:
page_header: ""
check_answer_label: "Person 7’s gender identity same as registered at birth"
check_answer_label: "Person 7’s gender identity same as sex registered at birth"
check_answer_prompt: ""
hint_text: ""
question_text: "Is the gender person 7 identifies with the same as their sex registered at birth?"
@ -469,7 +469,7 @@ en:
gender_same_as_sex8:
page_header: ""
check_answer_label: "Person 8’s gender identity same as registered at birth"
check_answer_label: "Person 8’s gender identity same as sex registered at birth"
check_answer_prompt: ""
hint_text: ""
question_text: "Is the gender person 8 identifies with the same as their sex registered at birth?"

91
config/locales/forms/2026/sales/household_characteristics.en.yml

@ -23,6 +23,20 @@ en:
hint_text: "This is the sex that was registered at birth. The next question will ask about the buyer's gender identity."
question_text: "What was buyer 1's sex at birth?"
gender_same_as_sex1:
page_header: ""
check_answer_label: "Buyer 1's gender identity same as sex registered at birth"
check_answer_prompt: ""
hint_text: ""
question_text: "Is the gender buyer 1 identifies with the same as their sex registered at birth?"
gender_description1:
page_header: ""
check_answer_label: "Gender identity description"
check_answer_prompt: ""
hint_text: ""
question_text: "Enter gender identity"
ethnic_group:
page_header: ""
check_answer_label: "Buyer 1’s ethnic group"
@ -144,6 +158,27 @@ en:
hint_text: "This is the sex that was registered at birth. The next question will ask about the person's gender identity."
question_text: "What was person 2's sex at birth?"
gender_same_as_sex2:
buyer:
page_header: ""
check_answer_label: "Buyer 2's gender identity same as sex registered at birth"
check_answer_prompt: ""
hint_text: ""
question_text: "Is the gender buyer 2 identifies with the same as their sex registered at birth?"
person:
page_header: ""
check_answer_label: "Person 2's gender identity same as sex registered at birth"
check_answer_prompt: ""
hint_text: ""
question_text: "Is the gender person 2 identifies with the same as their sex registered at birth?"
gender_description2:
page_header: ""
check_answer_label: "Gender identity description"
check_answer_prompt: ""
hint_text: ""
question_text: "Enter gender identity"
ethnic_group2:
page_header: ""
check_answer_label: "Buyer 2’s ethnic group"
@ -273,6 +308,20 @@ en:
hint_text: "This is the sex that was registered at birth. The next question will ask about the person's gender identity."
question_text: "What was person 3's sex at birth?"
gender_same_as_sex3:
page_header: ""
check_answer_label: "Person 3's gender identity same as sex registered at birth"
check_answer_prompt: ""
hint_text: ""
question_text: "Is the gender person 3 identifies with the same as their sex registered at birth?"
gender_description3:
page_header: ""
check_answer_label: "Gender identity description"
check_answer_prompt: ""
hint_text: ""
question_text: "Enter gender identity"
ecstat3:
page_header: ""
check_answer_label: "Person 3’s working situation"
@ -314,6 +363,20 @@ en:
hint_text: "This is the sex that was registered at birth. The next question will ask about the person's gender identity."
question_text: "What was person 4's sex at birth?"
gender_same_as_sex4:
page_header: ""
check_answer_label: "Person 4's gender identity same as sex registered at birth"
check_answer_prompt: ""
hint_text: ""
question_text: "Is the gender person 4 identifies with the same as their sex registered at birth?"
gender_description4:
page_header: ""
check_answer_label: "Gender identity description"
check_answer_prompt: ""
hint_text: ""
question_text: "Enter gender identity"
ecstat4:
page_header: ""
check_answer_label: "Person 4’s working situation"
@ -355,6 +418,20 @@ en:
hint_text: "This is the sex that was registered at birth. The next question will ask about the person's gender identity."
question_text: "What was person 5's sex at birth?"
gender_same_as_sex5:
page_header: ""
check_answer_label: "Person 5's gender identity same as sex registered at birth"
check_answer_prompt: ""
hint_text: ""
question_text: "Is the gender person 5 identifies with the same as their sex registered at birth?"
gender_description5:
page_header: ""
check_answer_label: "Gender identity description"
check_answer_prompt: ""
hint_text: ""
question_text: "Enter gender identity"
ecstat5:
page_header: ""
check_answer_label: "Person 5’s working situation"
@ -396,6 +473,20 @@ en:
hint_text: "This is the sex that was registered at birth. The next question will ask about the person's gender identity."
question_text: "What was person 6's sex at birth?"
gender_same_as_sex6:
page_header: ""
check_answer_label: "Person 6's gender identity same as sex registered at birth"
check_answer_prompt: ""
hint_text: ""
question_text: "Is the gender person 6 identifies with the same as their sex registered at birth?"
gender_description6:
page_header: ""
check_answer_label: "Gender identity description"
check_answer_prompt: ""
hint_text: ""
question_text: "Enter gender identity"
ecstat6:
page_header: ""
check_answer_label: "Person 6’s working situation"

18
db/migrate/20260220141000_add_gender_same_as_sex_fields_to_sales_logs.rb

@ -0,0 +1,18 @@
class AddGenderSameAsSexFieldsToSalesLogs < ActiveRecord::Migration[7.0]
def change
change_table :sales_logs, bulk: true do |t|
t.integer :gender_same_as_sex1
t.integer :gender_same_as_sex2
t.integer :gender_same_as_sex3
t.integer :gender_same_as_sex4
t.integer :gender_same_as_sex5
t.integer :gender_same_as_sex6
t.string :gender_description1
t.string :gender_description2
t.string :gender_description3
t.string :gender_description4
t.string :gender_description5
t.string :gender_description6
end
end
end

12
db/schema.rb

@ -826,6 +826,18 @@ ActiveRecord::Schema[7.2].define(version: 2026_02_25_135309) do
t.string "sexrab6"
t.integer "mortlen_known"
t.integer "buildheightclass"
t.integer "gender_same_as_sex1"
t.integer "gender_same_as_sex2"
t.integer "gender_same_as_sex3"
t.integer "gender_same_as_sex4"
t.integer "gender_same_as_sex5"
t.integer "gender_same_as_sex6"
t.string "gender_description1"
t.string "gender_description2"
t.string "gender_description3"
t.string "gender_description4"
t.string "gender_description5"
t.string "gender_description6"
t.index ["assigned_to_id"], name: "index_sales_logs_on_assigned_to_id"
t.index ["bulk_upload_id"], name: "index_sales_logs_on_bulk_upload_id"
t.index ["created_by_id"], name: "index_sales_logs_on_created_by_id"

12
spec/factories/sales_log.rb

@ -86,6 +86,7 @@ FactoryBot.define do
age1 { Faker::Number.within(range: 27..45) }
sexrab1 { %w[F M R].sample }
sex1 { %w[F M X R].sample }
gender_same_as_sex1 { 1 }
national { 18 }
buy1livein { 1 }
relat2 { "P" }
@ -98,6 +99,8 @@ FactoryBot.define do
ethnic_group { 17 }
sexrab2 { %w[F M R].sample }
sex2 { "X" }
gender_same_as_sex2 { 2 }
gender_description2 { Faker::Gender.type }
buy2livein { "1" }
ecstat1 { "1" }
ecstat2 { "1" }
@ -131,12 +134,17 @@ FactoryBot.define do
prevshared { 2 }
sexrab3 { %w[F M R].sample }
sex3 { %w[F M X R].sample }
gender_same_as_sex3 { 1 }
sexrab4 { %w[F M R].sample }
sex4 { %w[F M X R].sample }
gender_same_as_sex4 { 2 }
gender_description4 { Faker::Gender.type }
sexrab5 { %w[F M R].sample }
sex5 { %w[F M X R].sample }
gender_same_as_sex5 { 3 }
sexrab6 { %w[F M R].sample }
sex6 { %w[F M X R].sample }
gender_same_as_sex6 { 3 }
mortgage { 20_000 }
ecstat3 { 9 }
ecstat4 { 3 }
@ -291,6 +299,7 @@ FactoryBot.define do
age1 { 27 }
sexrab1 { "F" }
sex1 { "F" }
gender_same_as_sex1 { 1 }
national { 18 }
buy1livein { 1 }
relat2 { "P" }
@ -303,6 +312,8 @@ FactoryBot.define do
ethnic_group { 17 }
sexrab2 { "R" }
sex2 { "X" }
gender_same_as_sex2 { 2 }
gender_description2 { "Non-binary" }
buy2livein { "1" }
ecstat1 { "1" }
ecstat2 { "1" }
@ -311,6 +322,7 @@ FactoryBot.define do
details_known_3 { 1 }
age3_known { 0 }
age3 { 14 }
gender_same_as_sex3 { 3 }
details_known_4 { 1 }
age4_known { 0 }
age4 { 18 }

12
spec/fixtures/exports/sales_log_26_27.xml vendored

@ -89,6 +89,18 @@
<NUMSTAIR/>
<MRENTPRESTAIRCASING/>
<BUILDHEIGHTCLASS>2</BUILDHEIGHTCLASS>
<GENDER_SAME_AS_SEX1>1</GENDER_SAME_AS_SEX1>
<GENDER_DESCRIPTION1/>
<GENDER_SAME_AS_SEX2>2</GENDER_SAME_AS_SEX2>
<GENDER_DESCRIPTION2>Non-binary</GENDER_DESCRIPTION2>
<GENDER_SAME_AS_SEX3>3</GENDER_SAME_AS_SEX3>
<GENDER_DESCRIPTION3/>
<GENDER_SAME_AS_SEX4/>
<GENDER_DESCRIPTION4/>
<GENDER_SAME_AS_SEX5/>
<GENDER_DESCRIPTION5/>
<GENDER_SAME_AS_SEX6/>
<GENDER_DESCRIPTION6/>
<DAY>1</DAY>
<MONTH>4</MONTH>
<YEAR>2026</YEAR>

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

File diff suppressed because one or more lines are too long

6
spec/fixtures/files/sales_logs_csv_export_codes_26.csv vendored

File diff suppressed because one or more lines are too long

6
spec/fixtures/files/sales_logs_csv_export_labels_26.csv vendored

File diff suppressed because one or more lines are too long

6
spec/fixtures/files/sales_logs_csv_export_non_support_codes_26.csv vendored

File diff suppressed because one or more lines are too long

6
spec/fixtures/files/sales_logs_csv_export_non_support_labels_26.csv vendored

File diff suppressed because one or more lines are too long

12
spec/fixtures/variable_definitions/sales_download_26_27.csv vendored

@ -5,3 +5,15 @@ sexrab4,What was person 4's sex at birth?
sexrab5,What was person 5's sex at birth?
sexrab6,What was person 6's sex at birth?
buildheightclass, What is the building height classification?
gender_same_as_sex1,Is the gender buyer 1 identifies with the same as their sex registered at birth?
gender_description1,If 'No', enter buyer 1's gender identity
gender_same_as_sex2,Is the gender buyer/person 2 identifies with the same as their sex registered at birth?
gender_description2,If 'No', enter buyer/person 2's gender identity
gender_same_as_sex3,Is the gender person 3 identifies with the same as their sex registered at birth?
gender_description3,If 'No', enter person 3's gender identity
gender_same_as_sex4,Is the gender person 4 identifies with the same as their sex registered at birth?
gender_description4,If 'No', enter person 4's gender identity
gender_same_as_sex5,Is the gender person 5 identifies with the same as their sex registered at birth?
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

1 sexrab1 sexrab1,What was buyer 1's sex at birth? What was buyer 1's sex at birth?
5 sexrab5 sexrab5,What was person 5's sex at birth? What was person 5's sex at birth?
6 sexrab6 sexrab6,What was person 6's sex at birth? What was person 6's sex at birth?
7 buildheightclass buildheightclass, What is the building height classification? What is the building height classification?
8 gender_same_as_sex1,Is the gender buyer 1 identifies with the same as their sex registered at birth?
9 gender_description1,If 'No', enter buyer 1's gender identity
10 gender_same_as_sex2,Is the gender buyer/person 2 identifies with the same as their sex registered at birth?
11 gender_description2,If 'No', enter buyer/person 2's gender identity
12 gender_same_as_sex3,Is the gender person 3 identifies with the same as their sex registered at birth?
13 gender_description3,If 'No', enter person 3's gender identity
14 gender_same_as_sex4,Is the gender person 4 identifies with the same as their sex registered at birth?
15 gender_description4,If 'No', enter person 4's gender identity
16 gender_same_as_sex5,Is the gender person 5 identifies with the same as their sex registered at birth?
17 gender_description5,If 'No', enter person 5's gender identity
18 gender_same_as_sex6,Is the gender person 6 identifies with the same as their sex registered at birth?
19 gender_description6,If 'No', enter person 6's gender identity

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

31
spec/models/form/sales/pages/buyer1_gender_same_as_sex_spec.rb

@ -0,0 +1,31 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::Buyer1GenderSameAsSex, 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: current_collection_start_date)) }
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[gender_same_as_sex1 gender_description1])
end
it "has the correct id" do
expect(page.id).to eq("buyer_1_gender_same_as_sex")
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 eq([{ "buyer_has_seen_privacy_notice?" => true }, { "buyer_not_interviewed?" => true }])
end
end

40
spec/models/form/sales/pages/buyer2_gender_same_as_sex_spec.rb

@ -0,0 +1,40 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::Buyer2GenderSameAsSex, 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: current_collection_start_date)) }
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[gender_same_as_sex2 gender_description2])
end
it "has the correct id" do
expect(page.id).to eq("buyer_2_gender_same_as_sex")
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 eq([
{
"joint_purchase?" => true,
"buyer_has_seen_privacy_notice?" => true,
},
{
"joint_purchase?" => true,
"buyer_not_interviewed?" => true,
},
])
end
end

105
spec/models/form/sales/pages/person_gender_same_as_sex_spec.rb

@ -0,0 +1,105 @@
require "rails_helper"
RSpec.describe Form::Sales::Pages::PersonGenderSameAsSex, type: :model do
include CollectionTimeHelper
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(:person_index) { 2 }
let(:page_id) { "person_2_gender_same_as_sex" }
it "has correct subsection" do
expect(page.subsection).to eq(subsection)
end
it "has the correct description" do
expect(page.description).to be_nil
end
context "with person 2" do
let(:person_index) { 2 }
let(:page_id) { "person_2_gender_same_as_sex" }
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[gender_same_as_sex2 gender_description2])
end
it "has the correct id" do
expect(page.id).to eq("person_2_gender_same_as_sex")
end
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "details_known_2" => 1 }])
end
end
context "with person 3" do
let(:person_index) { 3 }
let(:page_id) { "person_3_gender_same_as_sex" }
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[gender_same_as_sex3 gender_description3])
end
it "has the correct id" do
expect(page.id).to eq("person_3_gender_same_as_sex")
end
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "details_known_3" => 1 }])
end
end
context "with person 4" do
let(:person_index) { 4 }
let(:page_id) { "person_4_gender_same_as_sex" }
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[gender_same_as_sex4 gender_description4])
end
it "has the correct id" do
expect(page.id).to eq("person_4_gender_same_as_sex")
end
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "details_known_4" => 1 }])
end
end
context "with person 5" do
let(:person_index) { 5 }
let(:page_id) { "person_5_gender_same_as_sex" }
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[gender_same_as_sex5 gender_description5])
end
it "has the correct id" do
expect(page.id).to eq("person_5_gender_same_as_sex")
end
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "details_known_5" => 1 }])
end
end
context "with person 6" do
let(:person_index) { 6 }
let(:page_id) { "person_6_gender_same_as_sex" }
it "has correct questions" do
expect(page.questions.map(&:id)).to eq(%w[gender_same_as_sex6 gender_description6])
end
it "has the correct id" do
expect(page.id).to eq("person_6_gender_same_as_sex")
end
it "has correct depends_on" do
expect(page.depends_on).to eq([{ "details_known_6" => 1 }])
end
end
end

163
spec/models/form/sales/questions/gender_description_spec.rb

@ -0,0 +1,163 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::GenderDescription, type: :model do
include CollectionTimeHelper
subject(:question) { described_class.new(question_id, question_definition, page, person_index:) }
let(:question_id) { nil }
let(:question_definition) { nil }
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) }
before do
allow(page).to receive(:subsection).and_return(subsection)
allow(subsection).to receive(:form).and_return(form)
end
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct type" do
expect(question.type).to eq("text")
end
context "when person 1" do
let(:person_index) { 1 }
it "has the correct id" do
expect(question.id).to eq("gender_description1")
end
it "has expected check answers card number" do
expect(question.check_answers_card_number).to eq(1)
end
it "has the correct inferred_check_answers_value" do
expect(question.inferred_check_answers_value).to be_nil
end
context "when gender_same_as_sex1 is 'Yes'" do
let(:log) { build(:sales_log, gender_same_as_sex1: 1) }
it "is marked as derived" do
expect(question.derived?(log)).to be true
end
end
context "when gender_same_as_sex1 is 'No'" do
let(:log) { build(:sales_log, gender_same_as_sex1: 2) }
it "is not marked as derived" do
expect(question.derived?(log)).to be false
end
end
context "when gender_same_as_sex1 is 'Prefers not to say'" do
let(:log) { build(:sales_log, gender_same_as_sex1: 3) }
it "is marked as derived" do
expect(question.derived?(log)).to be true
end
end
end
context "when person 2" do
let(:person_index) { 2 }
it "has the correct id" do
expect(question.id).to eq("gender_description2")
end
it "has expected check answers card number" do
expect(question.check_answers_card_number).to eq(2)
end
it "has the correct inferred_check_answers_value" do
expect(question.inferred_check_answers_value).to be_nil
end
context "when gender_same_as_sex2 is 'Yes'" do
let(:log) { build(:sales_log, gender_same_as_sex2: 1) }
it "is marked as derived" do
expect(question.derived?(log)).to be true
end
end
context "when gender_same_as_sex2 is 'No'" do
let(:log) { build(:sales_log, gender_same_as_sex2: 2) }
it "is not marked as derived" do
expect(question.derived?(log)).to be false
end
end
end
context "when person 3" do
let(:person_index) { 3 }
it "has the correct id" do
expect(question.id).to eq("gender_description3")
end
it "has expected check answers card number" do
expect(question.check_answers_card_number).to eq(3)
end
it "has the correct inferred_check_answers_value" do
expect(question.inferred_check_answers_value).to be_nil
end
end
context "when person 4" do
let(:person_index) { 4 }
it "has the correct id" do
expect(question.id).to eq("gender_description4")
end
it "has expected check answers card number" do
expect(question.check_answers_card_number).to eq(4)
end
it "has the correct inferred_check_answers_value" do
expect(question.inferred_check_answers_value).to be_nil
end
end
context "when person 5" do
let(:person_index) { 5 }
it "has the correct id" do
expect(question.id).to eq("gender_description5")
end
it "has expected check answers card number" do
expect(question.check_answers_card_number).to eq(5)
end
it "has the correct inferred_check_answers_value" do
expect(question.inferred_check_answers_value).to be_nil
end
end
context "when person 6" do
let(:person_index) { 6 }
it "has the correct id" do
expect(question.id).to eq("gender_description6")
end
it "has expected check answers card number" do
expect(question.check_answers_card_number).to eq(6)
end
it "has the correct inferred_check_answers_value" do
expect(question.inferred_check_answers_value).to be_nil
end
end
end

189
spec/models/form/sales/questions/gender_same_as_sex_spec.rb

@ -0,0 +1,189 @@
require "rails_helper"
RSpec.describe Form::Sales::Questions::GenderSameAsSex, type: :model do
include CollectionTimeHelper
subject(:question) { described_class.new(question_id, question_definition, page, person_index:) }
let(:question_id) { nil }
let(:question_definition) { nil }
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) }
before do
allow(page).to receive(:subsection).and_return(subsection)
allow(subsection).to receive(:form).and_return(form)
end
it "has correct page" do
expect(question.page).to eq(page)
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
context "when buyer is false (default)" do
it "has the correct answer_options" do
expect(question.answer_options).to eq({
"1" => { "value" => "Yes" },
"2" => { "value" => "No, enter gender identity" },
"divider" => { "value" => true },
"3" => { "value" => "Person prefers not to say" },
})
end
end
context "when buyer is true" do
subject(:question) { described_class.new(question_id, question_definition, page, person_index:, buyer: true) }
it "has the correct answer_options" do
expect(question.answer_options).to eq({
"1" => { "value" => "Yes" },
"2" => { "value" => "No, enter gender identity" },
"divider" => { "value" => true },
"3" => { "value" => "Buyer prefers not to say" },
})
end
end
it "returns correct label_from_value for 'Prefers not to say'" do
expect(question.label_from_value(3)).to eq("Prefers not to say")
end
it "returns nil label_from_value for nil" do
expect(question.label_from_value(nil)).to be_nil
end
context "when person 1 (buyer)" do
subject(:question) { described_class.new(question_id, question_definition, page, person_index: 1, buyer: true) }
let(:person_index) { 1 }
it "has the correct id" do
expect(question.id).to eq("gender_same_as_sex1")
end
it "has expected check answers card number" do
expect(question.check_answers_card_number).to eq(1)
end
it "has the correct conditional_for" do
expect(question.conditional_for).to eq({ "gender_description1" => [2] })
end
it "has the correct inferred_check_answers_value" do
expect(question.inferred_check_answers_value).to eq([{ "condition" => { "gender_same_as_sex1" => 2 }, "value" => "No" }])
end
it "has the correct answer_options with Buyer label" do
expect(question.answer_options["3"]).to eq({ "value" => "Buyer prefers not to say" })
end
end
context "when person 2" do
let(:person_index) { 2 }
it "has the correct id" do
expect(question.id).to eq("gender_same_as_sex2")
end
it "has expected check answers card number" do
expect(question.check_answers_card_number).to eq(2)
end
it "has the correct conditional_for" do
expect(question.conditional_for).to eq({ "gender_description2" => [2] })
end
it "has the correct inferred_check_answers_value" do
expect(question.inferred_check_answers_value).to eq([{ "condition" => { "gender_same_as_sex2" => 2 }, "value" => "No" }])
end
end
context "when person 3" do
let(:person_index) { 3 }
it "has the correct id" do
expect(question.id).to eq("gender_same_as_sex3")
end
it "has expected check answers card number" do
expect(question.check_answers_card_number).to eq(3)
end
it "has the correct conditional_for" do
expect(question.conditional_for).to eq({ "gender_description3" => [2] })
end
it "has the correct inferred_check_answers_value" do
expect(question.inferred_check_answers_value).to eq([{ "condition" => { "gender_same_as_sex3" => 2 }, "value" => "No" }])
end
end
context "when person 4" do
let(:person_index) { 4 }
it "has the correct id" do
expect(question.id).to eq("gender_same_as_sex4")
end
it "has expected check answers card number" do
expect(question.check_answers_card_number).to eq(4)
end
it "has the correct conditional_for" do
expect(question.conditional_for).to eq({ "gender_description4" => [2] })
end
it "has the correct inferred_check_answers_value" do
expect(question.inferred_check_answers_value).to eq([{ "condition" => { "gender_same_as_sex4" => 2 }, "value" => "No" }])
end
end
context "when person 5" do
let(:person_index) { 5 }
it "has the correct id" do
expect(question.id).to eq("gender_same_as_sex5")
end
it "has expected check answers card number" do
expect(question.check_answers_card_number).to eq(5)
end
it "has the correct conditional_for" do
expect(question.conditional_for).to eq({ "gender_description5" => [2] })
end
it "has the correct inferred_check_answers_value" do
expect(question.inferred_check_answers_value).to eq([{ "condition" => { "gender_same_as_sex5" => 2 }, "value" => "No" }])
end
end
context "when person 6" do
let(:person_index) { 6 }
it "has the correct id" do
expect(question.id).to eq("gender_same_as_sex6")
end
it "has expected check answers card number" do
expect(question.check_answers_card_number).to eq(6)
end
it "has the correct conditional_for" do
expect(question.conditional_for).to eq({ "gender_description6" => [2] })
end
it "has the correct inferred_check_answers_value" do
expect(question.inferred_check_answers_value).to eq([{ "condition" => { "gender_same_as_sex6" => 2 }, "value" => "No" }])
end
end
end

7
spec/models/form/sales/subsections/household_characteristics_spec.rb

@ -407,6 +407,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
age_1_old_persons_shared_ownership_joint_purchase_value_check
age_1_old_persons_shared_ownership_value_check
buyer_1_sex_registered_at_birth
buyer_1_gender_same_as_sex
buyer_1_ethnic_group
buyer_1_ethnic_background_black
buyer_1_ethnic_background_asian
@ -427,6 +428,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
age_2_buyer_retirement_value_check
age_2_buyer_not_retired_value_check
buyer_2_sex_registered_at_birth
buyer_2_gender_same_as_sex
buyer_2_ethnic_group
buyer_2_ethnic_background_black
buyer_2_ethnic_background_asian
@ -451,6 +453,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
age_2_not_retired_value_check
age_2_partner_under_16_value_check
person_2_sex_registered_at_birth
person_2_gender_same_as_sex
person_2_working_situation
working_situation_2_retirement_value_check
working_situation_2_not_retired_value_check
@ -463,6 +466,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
age_3_not_retired_value_check
age_3_partner_under_16_value_check
person_3_sex_registered_at_birth
person_3_gender_same_as_sex
person_3_working_situation
working_situation_3_retirement_value_check
working_situation_3_not_retired_value_check
@ -475,6 +479,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
age_4_not_retired_value_check
age_4_partner_under_16_value_check
person_4_sex_registered_at_birth
person_4_gender_same_as_sex
person_4_working_situation
working_situation_4_retirement_value_check
working_situation_4_not_retired_value_check
@ -487,6 +492,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
age_5_not_retired_value_check
age_5_partner_under_16_value_check
person_5_sex_registered_at_birth
person_5_gender_same_as_sex
person_5_working_situation
working_situation_5_retirement_value_check
working_situation_5_not_retired_value_check
@ -499,6 +505,7 @@ RSpec.describe Form::Sales::Subsections::HouseholdCharacteristics, type: :model
age_6_not_retired_value_check
age_6_partner_under_16_value_check
person_6_sex_registered_at_birth
person_6_gender_same_as_sex
person_6_working_situation
working_situation_6_retirement_value_check
working_situation_6_not_retired_value_check

3
spec/services/bulk_upload/sales/year2026/row_parser_spec.rb

@ -113,6 +113,9 @@ RSpec.describe BulkUpload::Sales::Year2026::RowParser do
field_106: "2023",
field_110: "900",
field_122: "1",
field_123: "1",
field_125: "2",
field_126: "Non-binary",
}
end

8
spec/services/csv/sales_log_csv_service_spec.rb

@ -38,6 +38,14 @@ RSpec.describe Csv::SalesLogCsvService do
age6: nil,
ecstat6: nil,
relat6: nil,
gender_same_as_sex1: 1,
gender_same_as_sex2: 2,
gender_description2: "Nonbinary",
gender_same_as_sex3: 1,
gender_same_as_sex4: 2,
gender_description4: "Genderfluid",
gender_same_as_sex5: 3,
gender_same_as_sex6: nil,
sexrab6: nil,
sex6: nil,
town_or_city: "Town or city",

Loading…
Cancel
Save