Browse Source

Merge branch 'main' into CLDC-4270-fix-text-being-coerced-to-0-on-integer-fields

pull/3230/head
samyou-softwire 2 weeks ago
parent
commit
1044bf8163
  1. 1
      .github/workflows/production_pipeline.yml
  2. 23
      .github/workflows/review_app_hint.yml
  3. 30
      .github/workflows/review_deploy.yml
  4. 3
      .github/workflows/review_deploy_image_only.yml
  5. 3
      .github/workflows/review_teardown_pipeline.yml
  6. 45
      Gemfile.lock
  7. 23
      app/models/derived_variables/lettings_log_variables.rb
  8. 10
      app/models/form.rb
  9. 5
      app/models/form/lettings/pages/person_lead_partner.rb
  10. 6
      app/models/form/lettings/questions/person_partner.rb
  11. 6
      app/models/form/lettings/subsections/household_characteristics.rb
  12. 4
      app/models/form/question.rb
  13. 10
      app/models/lettings_log.rb
  14. 21
      app/models/sales_log.rb
  15. 6
      app/services/bulk_upload/sales/year2025/row_parser.rb
  16. 6
      app/services/bulk_upload/sales/year2026/row_parser.rb
  17. 16
      config/locales/forms/2025/lettings/tenancy_information.en.yml
  18. 16
      config/locales/forms/2026/lettings/tenancy_information.en.yml
  19. 1
      spec/factories/sales_log.rb
  20. 72
      spec/features/form/page_routing_spec.rb
  21. 10
      spec/features/sales_log_spec.rb
  22. 6
      spec/fixtures/files/lettings_log_csv_export_codes_26.csv
  23. 6
      spec/fixtures/files/lettings_log_csv_export_labels_26.csv
  24. 6
      spec/models/form/lettings/pages/person_lead_partner_spec.rb
  25. 86
      spec/models/form/lettings/questions/person_partner_spec.rb
  26. 7
      spec/models/form/lettings/subsections/household_characteristics_spec.rb
  27. 37
      spec/models/form_spec.rb
  28. 319
      spec/models/lettings_log_derived_fields_spec.rb
  29. 18
      spec/models/lettings_log_spec.rb
  30. 18
      spec/requests/duplicate_logs_controller_spec.rb
  31. 2
      spec/services/bulk_upload/sales/validator_spec.rb
  32. 4
      spec/services/bulk_upload/sales/year2025/row_parser_spec.rb
  33. 4
      spec/services/bulk_upload/sales/year2026/row_parser_spec.rb

1
.github/workflows/production_pipeline.yml

@ -3,7 +3,6 @@ name: Production CI/CD Pipeline
on:
release:
types: [released]
workflow_dispatch:
defaults:
run:

23
.github/workflows/review_app_hint.yml

@ -0,0 +1,23 @@
name: "Review App: PR Hint Comment"
on:
pull_request:
types: [opened]
jobs:
hint:
name: Add review app hint
runs-on: ubuntu-latest
permissions:
pull-requests: write
steps:
- name: Comment on PR
uses: actions/github-script@v7
with:
script: |
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: context.issue.number,
body: 'To deploy a review app for this PR, add the `review-app` label.',
});

30
.github/workflows/review_pipeline.yml → .github/workflows/review_deploy.yml

@ -1,4 +1,4 @@
name: Review app pipeline
name: "Review App: Deploy"
concurrency:
group: review-${{ github.event.pull_request.number }}
@ -6,9 +6,9 @@ concurrency:
on:
pull_request:
types:
- opened
- synchronize
- reopened
- labeled
workflow_dispatch:
defaults:
@ -18,6 +18,7 @@ defaults:
jobs:
infra:
name: Deploy review app infrastructure
if: contains(github.event.pull_request.labels.*.name, 'review-app')
uses: communitiesuk/submit-social-housing-lettings-and-sales-data-infrastructure/.github/workflows/create_review_app_infra.yml@main
with:
key: ${{ github.event.pull_request.number }}
@ -27,6 +28,7 @@ jobs:
code:
name: Deploy review app code
if: contains(github.event.pull_request.labels.*.name, 'review-app')
needs: [infra]
uses: ./.github/workflows/aws_deploy.yml
with:
@ -40,6 +42,7 @@ jobs:
comment:
name: Add link to PR
if: contains(github.event.pull_request.labels.*.name, 'review-app')
needs: [code]
runs-on: ubuntu-latest
permissions:
@ -48,10 +51,21 @@ jobs:
steps:
- name: Comment on PR with URL
uses: unsplash/comment-on-pr@v1.3.0
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
uses: actions/github-script@v7
with:
msg: "Created review app at https://review.submit-social-housing-data.communities.gov.uk/${{ github.event.pull_request.number }}. Note that the review app will be automatically deprovisioned after 30 days and will need the review app pipeline running again."
check_for_duplicate_msg: true
duplicate_msg_pattern: Created review app at*
script: |
const prNumber = context.issue.number;
const msg = `Created review app at https://review.submit-social-housing-data.communities.gov.uk/${prNumber}. Note that the review app will be automatically deprovisioned after 30 days and will need the review app pipeline running again.`;
const { data: comments } = await github.rest.issues.listComments({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
});
if (!comments.find(c => c.body.startsWith('Created review app at'))) {
await github.rest.issues.createComment({
owner: context.repo.owner,
repo: context.repo.repo,
issue_number: prNumber,
body: msg,
});
}

3
.github/workflows/manual_review_code_pipeline.yml → .github/workflows/review_deploy_image_only.yml

@ -1,4 +1,5 @@
name: Manual review app code pipeline
# Pushes the Docker image to a review app, for use when the ECS image has expired.
name: "Review App: Deploy (ECS Image only)"
concurrency:
group: review-${{ inputs.review_app_key }}

3
.github/workflows/review_teardown_pipeline.yml

@ -1,4 +1,4 @@
name: Review app teardown pipeline
name: "Review App: Teardown"
concurrency:
group: review-${{ github.event.pull_request.number }}
@ -7,7 +7,6 @@ on:
pull_request:
types:
- closed
workflow_dispatch:
env:
app_repo_role: arn:aws:iam::815624722760:role/core-application-repo

45
Gemfile.lock

@ -112,7 +112,7 @@ GEM
ice_nine (~> 0.11.0)
thread_safe (~> 0.3, >= 0.3.1)
base64 (0.3.0)
bcrypt (3.1.20)
bcrypt (3.1.21)
benchmark (0.5.0)
better_html (2.2.0)
actionview (>= 7.0)
@ -160,13 +160,13 @@ GEM
cssbundling-rails (1.4.0)
railties (>= 6.0.0)
csv (3.3.2)
date (3.4.1)
date (3.5.1)
descendants_tracker (0.0.4)
thread_safe (~> 0.3, >= 0.3.1)
devise (4.9.3)
devise (5.0.3)
bcrypt (~> 3.0)
orm_adapter (~> 0.1)
railties (>= 4.1.0)
railties (>= 7.0)
responders
warden (~> 1.2.3)
devise_two_factor_authentication (3.0.0)
@ -184,6 +184,7 @@ GEM
drb (2.2.3)
dumb_delegator (1.0.0)
encryptor (3.0.0)
erb (6.0.2)
erb_lint (0.9.0)
activesupport
better_html (>= 2.0.1)
@ -236,9 +237,10 @@ GEM
concurrent-ruby (~> 1.0)
ice_nine (0.11.2)
iniparse (1.5.0)
io-console (0.8.0)
irb (1.15.1)
io-console (0.8.2)
irb (1.17.0)
pp (>= 0.6.0)
prism (>= 1.3.0)
rdoc (>= 4.0.0)
reline (>= 0.4.2)
jmespath (1.6.2)
@ -269,7 +271,7 @@ GEM
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
logger (1.7.0)
loofah (2.25.0)
loofah (2.25.1)
crass (~> 1.0.2)
nokogiri (>= 1.12.0)
mail (2.8.1)
@ -329,7 +331,7 @@ GEM
racc
pg (1.5.5)
possessive (1.0.1)
pp (0.6.2)
pp (0.6.3)
prettyprint
prettyprint (0.2.0)
prism (1.9.0)
@ -344,7 +346,7 @@ GEM
pry-byebug (3.10.1)
byebug (~> 11.0)
pry (>= 0.13, < 0.15)
psych (5.2.3)
psych (5.3.1)
date
stringio
public_suffix (5.0.4)
@ -364,7 +366,7 @@ GEM
rack (>= 3.0.0)
rack-test (2.2.0)
rack (>= 1.3)
rackup (2.2.1)
rackup (2.3.1)
rack (>= 3)
rails (7.2.2.2)
actioncable (= 7.2.2.2)
@ -384,8 +386,8 @@ GEM
activesupport (>= 5.0.0)
minitest
nokogiri (>= 1.6)
rails-html-sanitizer (1.6.2)
loofah (~> 2.21)
rails-html-sanitizer (1.7.0)
loofah (~> 2.25)
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
rails_admin (3.3.0)
activemodel-serializers-xml (>= 1.0)
@ -403,25 +405,27 @@ GEM
thor (~> 1.0, >= 1.2.2)
zeitwerk (~> 2.6)
rainbow (3.1.1)
rake (13.2.1)
rake (13.3.1)
randexp (0.1.7)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
rdoc (6.12.0)
rdoc (7.2.0)
erb
psych (>= 4.0.0)
tsort
redcarpet (3.6.0)
redis (4.8.1)
redis-client (0.22.1)
connection_pool
regexp_parser (2.11.3)
reline (0.6.0)
reline (0.6.3)
io-console (~> 0.5)
request_store (1.7.0)
rack (>= 1.4)
responders (3.1.1)
actionpack (>= 5.2)
railties (>= 5.2)
responders (3.2.0)
actionpack (>= 7.0)
railties (>= 7.0)
rexml (3.4.4)
roo (2.10.1)
nokogiri (~> 1)
@ -519,11 +523,12 @@ GEM
smart_properties (1.17.0)
stimulus-rails (1.3.3)
railties (>= 6.0.0)
stringio (3.1.5)
stringio (3.2.0)
thor (1.4.0)
thread_safe (0.3.6)
timecop (0.9.8)
timeout (0.4.3)
tsort (0.2.0)
turbo-rails (2.0.13)
actionpack (>= 7.1.0)
railties (>= 7.1.0)
@ -563,7 +568,7 @@ GEM
websocket-extensions (0.1.5)
xpath (3.2.0)
nokogiri (~> 1.8)
zeitwerk (2.6.18)
zeitwerk (2.7.5)
PLATFORMS
arm64-darwin

23
app/models/derived_variables/lettings_log_variables.rb

@ -75,6 +75,10 @@ module DerivedVariables::LettingsLogVariables
self.beds = nil
end
if form.start_year_2026_or_later?
infer_at_most_one_relationship!
end
clear_child_constraints_for_age_changes!
child_under_16_constraints!
@ -325,6 +329,25 @@ private
end
end
def infer_at_most_one_relationship!
new_partner_numbers = partner_numbers.select { |i| public_send("relat#{i}_changed?") }
return unless new_partner_numbers.any?
infer_only_partner!(new_partner_numbers.first)
end
def infer_only_partner!(partner_number)
return unless hhmemb
(2..hhmemb).each do |i|
next if i == partner_number
if ["P", nil].include?(public_send("relat#{i}"))
self["relat#{i}"] = "X"
end
end
end
def household_type
return unless totelder && totadult && totchild

10
app/models/form.rb

@ -108,7 +108,8 @@ class Form
return :check_answers if next_page.nil?
return next_page.id if next_page.routed_to?(log, current_user) &&
(!ignore_answered || next_page.has_unanswered_questions?(log))
(!ignore_answered || next_page.has_unanswered_questions?(log)) &&
next_page.questions.any? { |question| !question.skip_question_in_form_flow?(log) }
next_page_id(next_page, log, current_user, ignore_answered:)
end
@ -323,7 +324,12 @@ class Form
if value.is_a?(Hash) && value.key?("operator")
operator = value["operator"]
operand = value["operand"]
log[question]&.send(operator, operand)
if operator == "!=" # This branch is needed as `nil` does not behave as expected with the default logic (`nil&.send("!=", nil)` => `nil` i.e., `false`).
log[question] != operand
else
log[question]&.send(operator, operand)
end
else
parts = question.split(".")
log_value = send_chain(parts, log)

5
app/models/form/lettings/pages/person_lead_partner.rb

@ -19,7 +19,10 @@ class Form::Lettings::Pages::PersonLeadPartner < ::Form::Page
"operand" => 16,
},
},
{ "details_known_#{@person_index}" => 0, "age#{@person_index}" => nil },
{
"details_known_#{@person_index}" => 0,
"age#{@person_index}" => nil,
},
]
else
[{ "details_known_#{@person_index}" => 0 }]

6
app/models/form/lettings/questions/person_partner.rb

@ -35,6 +35,10 @@ class Form::Lettings::Questions::PersonPartner < ::Form::Question
end
def derived?(log)
form.start_year_2026_or_later? && log.is_partner_inferred?(@person_index)
form.start_year_2026_or_later? && log.is_person_under_16?(@person_index)
end
def skip_question_in_form_flow?(log)
form.start_year_2026_or_later? && log.is_any_person_partner?
end
end

6
app/models/form/lettings/subsections/household_characteristics.rb

@ -52,15 +52,15 @@ class Form::Lettings::Subsections::HouseholdCharacteristics < ::Form::Subsection
Form::Lettings::Pages::PersonKnown.new(nil, nil, self, person_index:),
(Form::Lettings::Pages::PersonAge.new(nil, nil, self, person_index:) if form.start_year_2026_or_later?),
relationship_question(person_index:),
(Form::Lettings::Pages::PartnerUnder16ValueCheck.new("relationship_#{person_index}_partner_under_16_value_check", nil, self, person_index:) if form.start_year_2024_or_later? && !form.start_year_2026_or_later?),
(Form::Lettings::Pages::MultiplePartnersValueCheck.new("relationship_#{person_index}_multiple_partners_value_check", nil, self, person_index:) if form.start_year_2024_or_later?),
(Form::Lettings::Pages::PartnerUnder16ValueCheck.new("relationship_#{person_index}_partner_under_16_value_check", nil, self, person_index:) unless form.start_year_2026_or_later?),
(Form::Lettings::Pages::MultiplePartnersValueCheck.new("relationship_#{person_index}_multiple_partners_value_check", nil, self, person_index:) unless form.start_year_2026_or_later?),
(Form::Lettings::Pages::PersonAge.new(nil, nil, self, person_index:) unless form.start_year_2026_or_later?),
(Form::Lettings::Pages::NoFemalesPregnantHouseholdPersonAgeValueCheck.new(nil, nil, self, person_index:) unless form.start_year_2026_or_later?),
(Form::Lettings::Pages::FemalesInSoftAgeRangeInPregnantHouseholdPersonAgeValueCheck.new(nil, nil, self, person_index:) unless form.start_year_2026_or_later?),
(Form::Lettings::Pages::NoHouseholdMemberLikelyToBePregnantCheck.new("no_household_member_likely_to_be_pregnant_person_age_#{person_index}_check", nil, self, person_index:) if form.start_year_2026_or_later?),
Form::Lettings::Pages::PersonUnderRetirementValueCheck.new("age_#{person_index}_under_retirement_value_check", nil, self, person_index:),
Form::Lettings::Pages::PersonOverRetirementValueCheck.new("age_#{person_index}_over_retirement_value_check", nil, self, person_index:),
(Form::Lettings::Pages::PartnerUnder16ValueCheck.new("age_#{person_index}_partner_under_16_value_check", nil, self, person_index:) if form.start_year_2024_or_later? && !form.start_year_2026_or_later?),
(Form::Lettings::Pages::PartnerUnder16ValueCheck.new("age_#{person_index}_partner_under_16_value_check", nil, self, person_index:) unless form.start_year_2026_or_later?),
(Form::Lettings::Pages::PersonSexRegisteredAtBirth.new(nil, nil, self, person_index:) if form.start_year_2026_or_later?),
(Form::Lettings::Pages::PersonGenderSameAsSex.new(nil, nil, self, person_index:) if form.start_year_2026_or_later?),
(Form::Lettings::Pages::PersonGenderIdentity.new(nil, nil, self, person_index:) unless form.start_year_2026_or_later?),

4
app/models/form/question.rb

@ -304,6 +304,10 @@ class Form::Question
nil
end
def skip_question_in_form_flow?(_log)
false
end
private
def selected_answer_option_is_derived?(log)

10
app/models/lettings_log.rb

@ -445,10 +445,14 @@ class LettingsLog < Log
unittype_gn_changed? && unittype_gn_was == 2
end
def is_partner_inferred?(person_index)
def is_person_under_16?(person_index)
public_send("age#{person_index}") && public_send("age#{person_index}") < 16
end
def is_any_person_partner?
!partner_numbers.empty?
end
def age_changed_from_below_16(person_index)
public_send("age#{person_index}_was") && public_send("age#{person_index}_was") < 16
end
@ -943,6 +947,10 @@ private
end
end
def partner_numbers
(2..8).select { |i| public_send("relat#{i}") == "P" }
end
def age_refused?
[age1_known, age2_known, age3_known, age4_known, age5_known, age6_known, age7_known, age8_known].any?(1)
end

21
app/models/sales_log.rb

@ -18,7 +18,6 @@ class SalesLog < Log
include Validations::Sales::SoftValidations
include Validations::SoftValidations
include MoneyFormattingHelper
include CollectionTimeHelper
self.inheritance_column = :_type_disabled
@ -38,8 +37,6 @@ 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)
@ -72,14 +69,12 @@ 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)
.sex1_answered
.address_answered
.where.not(sex1: nil)
.where.not(postcode_full: nil)
.ecstat1_answered
.age1_answered
}
@ -89,8 +84,8 @@ class SalesLog < Log
scope = visible
.group(*DUPLICATE_LOG_ATTRIBUTES)
.where.not(saledate: nil)
.sex1_answered
.address_answered
.where.not(sex1: nil)
.where.not(postcode_full: nil)
.age1_answered
.ecstat1_answered
.having("COUNT(*) > 1")
@ -103,7 +98,7 @@ class SalesLog < Log
}
OPTIONAL_FIELDS = %w[purchid othtype buyers_organisations].freeze
DUPLICATE_LOG_ATTRIBUTES = %w[owning_organisation_id purchid saledate age1_known age1 sex1 sexrab1 ecstat1 postcode_full uprn address_line1].freeze
DUPLICATE_LOG_ATTRIBUTES = %w[owning_organisation_id purchid saledate age1_known age1 sex1 ecstat1 postcode_full].freeze
def lettings?
false
@ -543,12 +538,10 @@ class SalesLog < Log
["owning_organisation_id",
"saledate",
"purchid",
"address_line1",
"postcode_full",
"uprn",
"age1",
"sex1",
"ecstat1",
form.start_year_2026_or_later? ? "sexrab1" : "sex1"].compact
uprn.blank? ? "postcode_full" : "uprn"].compact
end
def soctenant_is_inferred?

6
app/services/bulk_upload/sales/year2025/row_parser.rb

@ -535,8 +535,6 @@ 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
@ -1306,8 +1304,6 @@ private
ecstat1
owning_organisation
postcode_full
uprn
address_line1
purchid
]
end
@ -1478,8 +1474,6 @@ 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

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

@ -584,8 +584,6 @@ 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_29", # age1
@ -1405,8 +1403,6 @@ private
ecstat1
owning_organisation
postcode_full
uprn
address_line1
purchid
]
end
@ -1577,8 +1573,6 @@ 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_29, error_message) # Buyer 1 age

16
config/locales/forms/2025/lettings/tenancy_information.en.yml

@ -21,27 +21,27 @@ en:
tenancy_type:
page_header: ""
tenancy:
check_answer_label: "Type of tenancy"
check_answer_label: "Type of main tenancy"
check_answer_prompt: ""
hint_text: ""
question_text: "What is the type of tenancy?"
tenancyother:
check_answer_label: "Type of tenancy (other)"
check_answer_label: ""
check_answer_prompt: ""
hint_text: ""
question_text: "Please state the type of tenancy"
question_text: "Please state the tenancy type"
starter_tenancy_type:
page_header: ""
tenancy:
check_answer_label: "Type of tenancy"
check_answer_label: "Type of main tenancy after the starter or introductory period has ended"
check_answer_prompt: ""
hint_text: "This is for the main tenancy after any starter or introductory period."
question_text: "What is the type of tenancy?"
hint_text: ""
question_text: "What is the type of tenancy after the starter or introductory period has ended?"
tenancyother:
check_answer_label: "Type of tenancy (other)"
check_answer_label: ""
check_answer_prompt: ""
hint_text: ""
question_text: "Please state the type of tenancy"
question_text: "Please state the tenancy type"
tenancylength:
tenancy_length:

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

@ -21,27 +21,27 @@ en:
tenancy_type:
page_header: ""
tenancy:
check_answer_label: "Type of tenancy"
check_answer_label: "Type of main tenancy"
check_answer_prompt: ""
hint_text: ""
question_text: "What is the type of tenancy?"
tenancyother:
check_answer_label: "Type of tenancy (other)"
check_answer_label: ""
check_answer_prompt: ""
hint_text: ""
question_text: "Please state the type of tenancy"
question_text: "Please state the tenancy type"
starter_tenancy_type:
page_header: ""
tenancy:
check_answer_label: "Type of tenancy"
check_answer_label: "Type of main tenancy after the starter or introductory period has ended"
check_answer_prompt: ""
hint_text: "This is for the main tenancy after any starter or introductory period."
question_text: "What is the type of tenancy?"
hint_text: ""
question_text: "What is the type of tenancy after the starter or introductory period has ended?"
tenancyother:
check_answer_label: "Type of tenancy (other)"
check_answer_label: ""
check_answer_prompt: ""
hint_text: ""
question_text: "Please state the type of tenancy"
question_text: "Please state the tenancy type"
tenancylength:
tenancy_length:

1
spec/factories/sales_log.rb

@ -67,7 +67,6 @@ FactoryBot.define do
sexrab1 { "F" }
sex1 { "F" }
ecstat1 { 1 }
address_line1 { "same address line 1" }
postcode_full { "A1 1AA" }
noint { 2 }
uprn_known { 0 }

72
spec/features/form/page_routing_spec.rb

@ -270,6 +270,78 @@ RSpec.describe "Form Page Routing" do
expect(lettings_log.form.depends_on_met(depends_on, lettings_log)).to be(true)
end
describe "using the 'not equal to' operator" do
it "returns true if both values are non-nil and different" do
depends_on = [
{
"relat2" => {
"operator" => "!=",
"operand" => "P",
},
},
]
lettings_log.relat2 = "X"
expect(lettings_log.form.depends_on_met(depends_on, lettings_log)).to be(true)
end
it "returns false if both values are non-nil and the same" do
depends_on = [
{
"relat2" => {
"operator" => "!=",
"operand" => "P",
},
},
]
lettings_log.relat2 = "P"
expect(lettings_log.form.depends_on_met(depends_on, lettings_log)).to be(false)
end
it "returns true if the being tested is nil and the operand is non-nil" do
depends_on = [
{
"relat2" => {
"operator" => "!=",
"operand" => "P",
},
},
]
lettings_log.relat2 = nil
expect(lettings_log.form.depends_on_met(depends_on, lettings_log)).to be(true)
end
it "returns true if the being tested is non-nil and the operand is nil" do
depends_on = [
{
"relat2" => {
"operator" => "!=",
"operand" => nil,
},
},
]
lettings_log.relat2 = "P"
expect(lettings_log.form.depends_on_met(depends_on, lettings_log)).to be(true)
end
it "returns false if both values are nil" do
depends_on = [
{
"relat2" => {
"operator" => "!=",
"operand" => nil,
},
},
]
lettings_log.relat2 = nil
expect(lettings_log.form.depends_on_met(depends_on, lettings_log)).to be(false)
end
end
end
end

10
spec/features/sales_log_spec.rb

@ -352,6 +352,16 @@ 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) }

6
spec/fixtures/files/lettings_log_csv_export_codes_26.csv vendored

File diff suppressed because one or more lines are too long

6
spec/fixtures/files/lettings_log_csv_export_labels_26.csv vendored

File diff suppressed because one or more lines are too long

6
spec/models/form/lettings/pages/person_lead_partner_spec.rb

@ -28,8 +28,6 @@ RSpec.describe Form::Lettings::Pages::PersonLeadPartner, type: :model do
end
context "with start year < 2026", metadata: { year: 25 } do
let(:person_question_count) { 4 }
it "has correct depends_on" do
expect(page.depends_on).to eq(
[{ "details_known_2" => 0 }],
@ -39,7 +37,6 @@ RSpec.describe Form::Lettings::Pages::PersonLeadPartner, type: :model do
context "with start year >= 2026", metadata: { year: 26 } do
let(:start_year_2026_or_later?) { true }
let(:person_question_count) { 5 }
it "has correct depends_on" do
expect(page.depends_on).to eq(
@ -70,8 +67,6 @@ RSpec.describe Form::Lettings::Pages::PersonLeadPartner, type: :model do
end
context "with start year < 2026", metadata: { year: 25 } do
let(:person_question_count) { 4 }
it "has correct depends_on" do
expect(page.depends_on).to eq(
[{ "details_known_3" => 0 }],
@ -81,7 +76,6 @@ RSpec.describe Form::Lettings::Pages::PersonLeadPartner, type: :model do
context "with start year >= 2026", metadata: { year: 26 } do
let(:start_year_2026_or_later?) { true }
let(:person_question_count) { 5 }
it "has correct depends_on" do
expect(page.depends_on).to eq(

86
spec/models/form/lettings/questions/person_partner_spec.rb

@ -24,6 +24,8 @@ RSpec.describe Form::Lettings::Questions::PersonPartner, type: :model do
)
end
let(:person_index) { 2 }
let(:is_any_person_partner?) { false }
let(:log) { instance_double(LettingsLog, is_any_person_partner?: is_any_person_partner?) }
it "has correct page" do
expect(question.page).to eq(page)
@ -47,6 +49,48 @@ RSpec.describe Form::Lettings::Questions::PersonPartner, type: :model do
expect(question.hidden_in_check_answers).to be_nil
end
describe "#skip_page_in_form_flow?" do
context "with start year < 2026", metadata: { year: 25 } do
let(:year) { 2025 }
context "when no other person is the partner of the lead tenant" do
let(:is_any_person_partner?) { false }
it "returns false" do
expect(question.skip_question_in_form_flow?(log)).to be false
end
end
context "when another person is the partner of the lead tenant" do
let(:is_any_person_partner?) { true }
it "returns false" do
expect(question.skip_question_in_form_flow?(log)).to be false
end
end
end
context "with start year >= 2026", metadata: { year: 26 } do
let(:year) { 2026 }
context "when no other person is the partner of the lead tenant" do
let(:is_any_person_partner?) { false }
it "returns false" do
expect(question.skip_question_in_form_flow?(log)).to be false
end
end
context "when another person is the partner of the lead tenant" do
let(:is_any_person_partner?) { true }
it "returns true" do
expect(question.skip_question_in_form_flow?(log)).to be true
end
end
end
end
context "with person 2" do
it "has the correct id" do
expect(question.id).to eq("relat2")
@ -56,39 +100,49 @@ RSpec.describe Form::Lettings::Questions::PersonPartner, type: :model do
expect(question.check_answers_card_number).to eq(2)
end
context "with person 2 age < 16" do
let(:log) { build(:lettings_log, age2: 10) }
context "and in 2025", metadata: { year: 25 } do
let(:year) { 2025 }
let(:person_question_count) { 4 }
context "and in 2025", metadata: { year: 25 } do
let(:year) { 2025 }
it "has the correct question number" do
expect(question.question_number).to eq(37)
end
context "with person 2 age < 16" do
let(:log) { build(:lettings_log, age2: 10) }
it "is not marked as derived" do
expect(question.derived?(log)).to be false
end
end
context "and in 2026", metadata: { year: 26 } do
let(:year) { 2026 }
context "with person 2 age >= 16" do
let(:log) { build(:lettings_log, age2: 20) }
it "is marked as derived" do
expect(question.derived?(log)).to be true
it "is not marked as derived" do
expect(question.derived?(log)).to be false
end
end
end
context "with person 2 age >= 16" do
let(:log) { build(:lettings_log, age2: 20) }
context "and in 2026", metadata: { year: 26 } do
let(:year) { 2026 }
let(:person_question_count) { 5 }
context "and in 2025", metadata: { year: 25 } do
let(:year) { 2025 }
it "has the correct question number" do
expect(question.question_number).to eq(38)
end
it "is not marked as derived" do
expect(question.derived?(log)).to be false
context "with person 2 age < 16" do
let(:log) { build(:lettings_log, age2: 10) }
it "is marked as derived" do
expect(question.derived?(log)).to be true
end
end
context "and in 2026", metadata: { year: 26 } do
let(:year) { 2026 }
context "with person 2 age >= 16" do
let(:log) { build(:lettings_log, age2: 20) }
it "is not marked as derived" do
expect(question.derived?(log)).to be false

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

@ -357,7 +357,6 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_2_known
person_2_age
person_2_lead_partner
relationship_2_multiple_partners_value_check
no_household_member_likely_to_be_pregnant_person_age_2_check
age_2_under_retirement_value_check
age_2_over_retirement_value_check
@ -372,7 +371,6 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_3_known
person_3_age
person_3_lead_partner
relationship_3_multiple_partners_value_check
no_household_member_likely_to_be_pregnant_person_age_3_check
age_3_under_retirement_value_check
age_3_over_retirement_value_check
@ -387,7 +385,6 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_4_known
person_4_age
person_4_lead_partner
relationship_4_multiple_partners_value_check
no_household_member_likely_to_be_pregnant_person_age_4_check
age_4_under_retirement_value_check
age_4_over_retirement_value_check
@ -402,7 +399,6 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_5_known
person_5_age
person_5_lead_partner
relationship_5_multiple_partners_value_check
no_household_member_likely_to_be_pregnant_person_age_5_check
age_5_under_retirement_value_check
age_5_over_retirement_value_check
@ -417,7 +413,6 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_6_known
person_6_age
person_6_lead_partner
relationship_6_multiple_partners_value_check
no_household_member_likely_to_be_pregnant_person_age_6_check
age_6_under_retirement_value_check
age_6_over_retirement_value_check
@ -432,7 +427,6 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_7_known
person_7_age
person_7_lead_partner
relationship_7_multiple_partners_value_check
no_household_member_likely_to_be_pregnant_person_age_7_check
age_7_under_retirement_value_check
age_7_over_retirement_value_check
@ -447,7 +441,6 @@ RSpec.describe Form::Lettings::Subsections::HouseholdCharacteristics, type: :mod
person_8_known
person_8_age
person_8_lead_partner
relationship_8_multiple_partners_value_check
no_household_member_likely_to_be_pregnant_person_age_8_check
age_8_under_retirement_value_check
age_8_over_retirement_value_check

37
spec/models/form_spec.rb

@ -19,10 +19,45 @@ RSpec.describe Form, type: :model do
let(:previous_page_id) { form.get_page("person_1_age") }
let(:value_check_previous_page) { form.get_page("net_income_value_check") }
it "returns the next page given the previous" do
it "returns the next page, given the previous" do
expect(form.next_page_id(previous_page_id, lettings_log, user)).to eq("person_1_gender")
end
context "when the next page has more than one question" do
let(:previous_page_id) { form.get_page("tenancy_start_date") }
let(:next_page) { form.get_page("rent_type") }
context "when every question on the next page returns `true` from its `skip_question_in_form_flow?` method" do
before do
allow(next_page.questions.first).to receive(:skip_question_in_form_flow?)
.with(lettings_log)
.and_return(true)
allow(next_page.questions.second).to receive(:skip_question_in_form_flow?)
.with(lettings_log)
.and_return(true)
end
it "returns the page after next, given the previous" do
expect(form.next_page_id(previous_page_id, lettings_log, user)).to eq("tenant_code")
end
end
context "when at least question on the next page returns `false` from its `skip_question_in_form_flow?` method" do
before do
allow(next_page.questions.first).to receive(:skip_question_in_form_flow?)
.with(lettings_log)
.and_return(true)
allow(next_page.questions.second).to receive(:skip_question_in_form_flow?)
.with(lettings_log)
.and_return(false)
end
it "returns the next page, given the previous" do
expect(form.next_page_id(previous_page_id, lettings_log, user)).to eq("rent_type")
end
end
end
context "when the current page is a value check page" do
before do
lettings_log.hhmemb = 1

319
spec/models/lettings_log_derived_fields_spec.rb

@ -1588,4 +1588,323 @@ RSpec.describe LettingsLog, type: :model do
end
end
end
describe "#infer_at_most_one_relationship!" do
context "when 2025", metadata: { year: 25 } do
before do
Timecop.freeze(collection_start_date_for_year(2025))
Singleton.__init__(FormHandler)
end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
context "when there are no existing relationships" do
let(:log) { create(:lettings_log, :in_progress, hhmemb: 6, details_known_2: 0, details_known_3: 0, details_known_4: 0, details_known_5: 0, details_known_6: 0, relat2: nil, relat3: "X", relat4: "X", relat5: "R") }
context "when a new relationship is added" do
before do
log.relat4 = "P"
end
it "does not infer no to any relationship answers" do
expect { log.set_derived_fields! }
.to not_change(log, :relat2)
.and not_change(log, :relat3)
.and not_change(log, :relat4)
.and not_change(log, :relat5)
.and not_change(log, :relat6)
.and not_change(log, :relat7)
.and not_change(log, :relat8)
end
end
end
context "when there is an existing relationship" do
let(:log) { create(:lettings_log, :in_progress, hhmemb: 6, details_known_2: 0, details_known_3: 0, details_known_4: 0, details_known_5: 0, details_known_6: 0, relat2: "X", relat3: "P", relat4: "R", relat5: "X") }
context "when a new relationship is added" do
before do
log.relat2 = "P"
end
it "does not infer no to any relationship answers" do
expect { log.set_derived_fields! }
.to not_change(log, :relat2)
.and not_change(log, :relat3)
.and not_change(log, :relat4)
.and not_change(log, :relat5)
.and not_change(log, :relat6)
.and not_change(log, :relat7)
.and not_change(log, :relat8)
end
end
context "when the relationship is removed" do
before do
log.relat3 = "X"
end
it "does not reset any answers" do
expect { log.set_derived_fields! }
.to not_change(log, :relat2)
.and not_change(log, :relat3)
.and not_change(log, :relat4)
.and not_change(log, :relat5)
.and not_change(log, :relat6)
.and not_change(log, :relat7)
.and not_change(log, :relat8)
end
end
end
context "when more than one relationship is set" do
let(:log) { create(:lettings_log, :in_progress, hhmemb: 6, details_known_2: 0, details_known_3: 0, details_known_4: 0, details_known_5: 0, details_known_6: 0, relat2: "X", relat3: "X", relat4: "R", relat5: "X") }
before do
log.relat2 = "P"
log.relat3 = "P"
end
it "does not infer no to any relationship answers" do
expect { log.set_derived_fields! }
.to not_change(log, :relat2)
.and not_change(log, :relat3)
.and not_change(log, :relat4)
.and not_change(log, :relat5)
.and not_change(log, :relat6)
.and not_change(log, :relat7)
.and not_change(log, :relat8)
end
end
end
context "when 2026", metadata: { year: 26 } do
before do
Timecop.freeze(collection_start_date_for_year(2026))
Singleton.__init__(FormHandler)
end
after do
Timecop.return
Singleton.__init__(FormHandler)
end
context "when there are no existing relationships" do
let(:log) { create(:lettings_log, :in_progress, hhmemb: 6, details_known_2: 0, details_known_3: 0, details_known_4: 0, details_known_5: 0, details_known_6: 0, relat3: "X", relat4: "X", relat5: "R") }
context "when a new relationship is added" do
before do
log.relat4 = "P"
end
it "infers no to unanswered questions" do
expect { log.set_derived_fields! }
.to change(log, :relat2).to("X")
.and change(log, :relat6).to("X")
end
it "does not change relationship answers for people not in the household" do
expect { log.set_derived_fields! }
.to not_change(log, :relat7)
.and not_change(log, :relat8)
end
it "does not change relationship answers of no or prefer not to say" do
expect { log.set_derived_fields! }
.to not_change(log, :relat3)
.and not_change(log, :relat5)
end
it "does not change the relationship answer for the newly added relationship" do
expect { log.set_derived_fields! }.to not_change(log, :relat4)
end
end
context "when a 'no' is changed to 'prefers not to say'" do
before do
log.relat4 = "R"
end
it "does not change any relationship answers" do
expect { log.set_derived_fields! }
.to not_change(log, :relat2)
.and not_change(log, :relat3)
.and not_change(log, :relat4)
.and not_change(log, :relat5)
.and not_change(log, :relat6)
.and not_change(log, :relat7)
.and not_change(log, :relat8)
end
end
context "when a 'prefers not to say' is changed to 'no'" do
before do
log.relat5 = "X"
end
it "does not change any relationship answers" do
expect { log.set_derived_fields! }
.to not_change(log, :relat2)
.and not_change(log, :relat3)
.and not_change(log, :relat4)
.and not_change(log, :relat5)
.and not_change(log, :relat6)
.and not_change(log, :relat7)
.and not_change(log, :relat8)
end
end
end
context "when there is an existing relationship" do
let(:log) { create(:lettings_log, :in_progress, hhmemb: 6, details_known_2: 0, details_known_3: 0, details_known_4: 0, details_known_5: 0, details_known_6: 0, relat2: "X", relat3: "P", relat4: "R", relat5: "X") }
context "and a new relationship is added to an earlier person than the existing one" do
before do
log.relat6 = nil # This is necessary because `log.set_derived_fields!` runs when the log is created from the factory, which sets `relat6` to "X".
log.relat2 = "P"
end
it "infers no to the existing relationship" do
expect { log.set_derived_fields! }.to change(log, :relat3).to "X"
end
it "infers no to unanswered questions" do
expect { log.set_derived_fields! }.to change(log, :relat6).to "X"
end
it "does not change relationship answers for people not in the household" do
expect { log.set_derived_fields! }
.to not_change(log, :relat7)
.and not_change(log, :relat8)
end
it "does not change relationship answers of no or prefer not to say" do
expect { log.set_derived_fields! }
.to not_change(log, :relat5)
.and not_change(log, :relat4)
end
it "does not change the relationship answer for the newly added relationship" do
expect { log.set_derived_fields! }.to not_change(log, :relat2)
end
end
context "and a new relationship is added to an later person than the existing one" do
before do
log.relat6 = nil # This is necessary because `log.set_derived_fields!` runs when the log is created from the factory, which sets `relat6` to "X".
log.relat5 = "P"
end
it "infers no to the existing relationship" do
expect { log.set_derived_fields! }.to change(log, :relat3).to "X"
end
it "infers no to unanswered questions" do
expect { log.set_derived_fields! }.to change(log, :relat6).to "X"
end
it "does not change relationship answers for people not in the household" do
expect { log.set_derived_fields! }
.to not_change(log, :relat7)
.and not_change(log, :relat8)
end
it "does not change relationship answers of no or prefer not to say" do
expect { log.set_derived_fields! }
.to not_change(log, :relat2)
.and not_change(log, :relat4)
end
it "does not change the relationship answer for the newly added relationship" do
expect { log.set_derived_fields! }.to not_change(log, :relat5)
end
end
context "when a 'no' is changed to 'prefers not to say'" do
before do
log.relat4 = "R"
end
it "does not change any relationship answers" do
expect { log.set_derived_fields! }
.to not_change(log, :relat2)
.and not_change(log, :relat3)
.and not_change(log, :relat4)
.and not_change(log, :relat5)
.and not_change(log, :relat6)
.and not_change(log, :relat7)
.and not_change(log, :relat8)
end
end
context "when a 'prefers not to say' is changed to 'no'" do
before do
log.relat5 = "X"
end
it "does not change any relationship answers" do
expect { log.set_derived_fields! }
.to not_change(log, :relat2)
.and not_change(log, :relat3)
.and not_change(log, :relat4)
.and not_change(log, :relat5)
.and not_change(log, :relat6)
.and not_change(log, :relat7)
.and not_change(log, :relat8)
end
end
context "and the relationship is removed" do
before do
log.relat3 = "X"
end
it "does not reset any answers" do
expect { log.set_derived_fields! }
.to not_change(log, :relat2)
.and not_change(log, :relat3)
.and not_change(log, :relat4)
.and not_change(log, :relat5)
.and not_change(log, :relat6)
.and not_change(log, :relat7)
.and not_change(log, :relat8)
end
end
end
context "when more than one relationship is set" do
let(:log) { create(:lettings_log, :in_progress, hhmemb: 6, details_known_2: 0, details_known_3: 0, details_known_4: 0, details_known_5: 0, details_known_6: 0, relat2: "X", relat3: "X", relat4: "R", relat5: "X") }
before do
log.relat2 = "P"
log.relat3 = "P"
end
it "keeps the lower numbered relationship and infers the higher numbered one to false" do
expect { log.set_derived_fields! }
.to not_change(log, :relat2)
.and change(log, :relat3).to("X")
end
it "infers no to unanswered questions" do
expect { log.set_derived_fields! }.to change(log, :relat6).to "X"
end
it "does not change relationship answers for people not in the household" do
expect { log.set_derived_fields! }
.to not_change(log, :relat7)
.and not_change(log, :relat8)
end
it "does not change relationship answers of no or prefer not to say" do
expect { log.set_derived_fields! }
.to not_change(log, :relat5)
.and not_change(log, :relat4)
end
end
end
end
end

18
spec/models/lettings_log_spec.rb

@ -2349,5 +2349,23 @@ RSpec.describe LettingsLog do
end
end
end
describe "#is_any_person_partner?" do
context "when no person is the partner of the lead tenant" do
let(:log) { create(:lettings_log, :in_progress, hhmemb: 3, details_known_2: 0, details_known_3: 0, relat2: "X", relat3: "R") }
it "returns false" do
expect(log.is_any_person_partner?).to be false
end
end
context "when a person is the partner of the lead tenant" do
let(:log) { create(:lettings_log, :in_progress, hhmemb: 3, details_known_2: 0, details_known_3: 0, relat2: "X", relat3: "P") }
it "returns true" do
expect(log.is_any_person_partner?).to be true
end
end
end
end
# rubocop:enable RSpec/MessageChain

18
spec/requests/duplicate_logs_controller_spec.rb

@ -170,8 +170,7 @@ 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_content("- Address line 1", count: 3)
expect(page).to have_link("Change", count: 24)
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}&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")
@ -217,8 +216,7 @@ 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_content("- Address line 1", count: 1)
expect(page).to have_link("Change", count: 8)
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
@ -244,8 +242,7 @@ 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_content("- Address line 1", count: 1)
expect(page).to have_link("Change", count: 8)
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
@ -380,8 +377,7 @@ 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_content("- Address line 1", count: 3)
expect(page).to have_link("Change", count: 21)
expect(page).to have_link("Change", count: 18)
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")
@ -409,8 +405,7 @@ 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_content("- Address line 1", count: 1)
expect(page).to have_link("Change", count: 7)
expect(page).to have_link("Change", count: 6)
expect(page).to have_link("Change", href: "/sales-logs/#{sales_log.id}/purchaser-code?original_log_id=#{sales_log.id}&referrer=interruption_screen")
end
@ -436,8 +431,7 @@ 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_content("- Address line 1", count: 1)
expect(page).to have_link("Change", count: 7)
expect(page).to have_link("Change", count: 6)
expect(page).to have_link("Change", href: "/sales-logs/#{sales_log.id}/purchaser-code?original_log_id=#{sales_log.id}&referrer=interruption_screen")
end

2
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(24)
expect { validator.call }.to change(BulkUploadError.where(category: :setup, error: "This is a duplicate of a log in your file."), :count).by(20)
end
end
end

4
spec/services/bulk_upload/sales/year2025/row_parser_spec.rb

@ -800,8 +800,6 @@ 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
@ -832,8 +830,6 @@ 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

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

@ -806,8 +806,6 @@ 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_29, # Buyer 1 age
@ -838,8 +836,6 @@ 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_29, # Buyer 1 age

Loading…
Cancel
Save