From b09dde3e17dc7ceb0b48fe098b8b7650df825869 Mon Sep 17 00:00:00 2001 From: oscric Date: Tue, 21 Jul 2026 09:52:08 +0100 Subject: [PATCH] Hide address questions for schemes marked 'sensitive' --- .../lettings_log_variables.rb | 14 +++ .../pages/property_local_authority.rb | 1 + app/models/lettings_log.rb | 6 + spec/factories/scheme.rb | 2 +- .../pages/property_local_authority_spec.rb | 14 +++ .../lettings_log_derived_fields_spec.rb | 103 ++++++++++++++++++ spec/models/lettings_log_spec.rb | 19 ++++ 7 files changed, 158 insertions(+), 1 deletion(-) diff --git a/app/models/derived_variables/lettings_log_variables.rb b/app/models/derived_variables/lettings_log_variables.rb index f0f4ff279..33068b0a5 100644 --- a/app/models/derived_variables/lettings_log_variables.rb +++ b/app/models/derived_variables/lettings_log_variables.rb @@ -183,6 +183,20 @@ module DerivedVariables::LettingsLogVariables clear_gender_description_unless_gender_not_same_as_sex! if form.start_year_2026_or_later? + if scheme_has_confidential_information? + reset_address_fields! + self.uprn_selection = nil + self.postcode_known = nil + self.manual_address_entry_selected = nil + location_la = location&.linked_local_authorities&.active(form.start_date)&.first&.code || location&.location_code + if location_la.present? + self.la = location_la + self.is_la_inferred = true + else + self.is_la_inferred = false + end + end + set_checkbox_values! end diff --git a/app/models/form/lettings/pages/property_local_authority.rb b/app/models/form/lettings/pages/property_local_authority.rb index 5656ec2d9..99683b0da 100644 --- a/app/models/form/lettings/pages/property_local_authority.rb +++ b/app/models/form/lettings/pages/property_local_authority.rb @@ -5,6 +5,7 @@ class Form::Lettings::Pages::PropertyLocalAuthority < ::Form::Page @depends_on = [ { "is_la_inferred" => false, "is_general_needs?" => true, "form.start_year_2025_or_later?" => false, "address_search_given?" => true }, { "is_la_inferred" => false, "is_general_needs?" => true, "form.start_year_2025_or_later?" => true }, + { "is_la_inferred" => false, "scheme_has_confidential_information?" => true }, ] end diff --git a/app/models/lettings_log.rb b/app/models/lettings_log.rb index 5a11da38a..df7ee4581 100644 --- a/app/models/lettings_log.rb +++ b/app/models/lettings_log.rb @@ -822,9 +822,15 @@ class LettingsLog < Log end def is_address_asked? + return false if scheme_has_confidential_information? + form.start_year_2026_or_later? || !is_supported_housing? end + def scheme_has_confidential_information? + scheme&.sensitive == "Yes" + end + def referral_is_from_local_authority_housing_register? referral_register == 6 end diff --git a/spec/factories/scheme.rb b/spec/factories/scheme.rb index a882fd9ea..3860bdcf2 100644 --- a/spec/factories/scheme.rb +++ b/spec/factories/scheme.rb @@ -1,7 +1,7 @@ FactoryBot.define do factory :scheme do service_name { "#{Faker::Name.name}'s Housing & Co." } - sensitive { Faker::Number.within(range: 0..1) } + sensitive { 0 } registered_under_care_act { 1 } support_type { [0, 2, 3, 4].sample } scheme_type { 4 } diff --git a/spec/models/form/lettings/pages/property_local_authority_spec.rb b/spec/models/form/lettings/pages/property_local_authority_spec.rb index 5e29424e3..e78521de2 100644 --- a/spec/models/form/lettings/pages/property_local_authority_spec.rb +++ b/spec/models/form/lettings/pages/property_local_authority_spec.rb @@ -56,5 +56,19 @@ RSpec.describe Form::Lettings::Pages::PropertyLocalAuthority, type: :model do log.is_la_inferred = false expect(page).not_to be_routed_to(log, nil) end + + context "when the scheme is confidential" do + let(:log) { build(:lettings_log, needstype: 2, scheme: build(:scheme, sensitive: 1)) } + + it "is routed to when the LA could not be inferred, even for supported housing" do + log.is_la_inferred = false + expect(page).to be_routed_to(log, nil) + end + + it "is not routed to when the LA was inferred from the location" do + log.is_la_inferred = true + expect(page).not_to be_routed_to(log, nil) + end + end end end diff --git a/spec/models/lettings_log_derived_fields_spec.rb b/spec/models/lettings_log_derived_fields_spec.rb index 95a25fe08..fb9ad1369 100644 --- a/spec/models/lettings_log_derived_fields_spec.rb +++ b/spec/models/lettings_log_derived_fields_spec.rb @@ -1585,6 +1585,109 @@ RSpec.describe LettingsLog, type: :model do end end + describe "deriving address fields and LA for a confidential scheme", metadata: { year: 26 } do + let(:startdate) { collection_start_date_for_year(2026) } + let(:confidential_scheme) { create(:scheme, sensitive: 1) } + let(:location) { create(:location, scheme: confidential_scheme) } + + let(:uprn) { "123456789" } + let(:uprn_known) { 1 } + let(:uprn_confirmed) { 1 } + let(:address_line1) { "1 Test Street" } + let(:address_line2) { "Testville" } + let(:town_or_city) { "Testford" } + let(:county) { "Testshire" } + let(:postcode_full) { "SW1 1AA" } + let(:la) { "E07000105" } + + around do |example| + Timecop.freeze(collection_start_date_for_year(2026)) do + Singleton.__init__(FormHandler) + example.run + end + end + + before do + log.needstype = 2 + log.scheme = confidential_scheme + log.location = location + log.assign_attributes(uprn:, uprn_known:, uprn_confirmed:, address_line1:, address_line2:, town_or_city:, county:, postcode_full:, la:) + end + + it "does not ask the address or UPRN question" do + expect(log.is_address_asked?).to be false + end + + it "still asks the address question when the scheme is not confidential" do + log.scheme = create(:scheme, sensitive: 0) + expect(log.is_address_asked?).to be true + end + + it "resets all the address and UPRN fields to nil" do + expect { log.set_derived_fields! } + .to change { log.read_attribute(:uprn) }.from(uprn).to(nil) + .and change { log.read_attribute(:uprn_known) }.from(uprn_known).to(nil) + .and change { log.read_attribute(:uprn_confirmed) }.from(uprn_confirmed).to(nil) + .and change { log.read_attribute(:address_line1) }.from(address_line1).to(nil) + .and change { log.read_attribute(:address_line2) }.from(address_line2).to(nil) + .and change { log.read_attribute(:town_or_city) }.from(town_or_city).to(nil) + .and change { log.read_attribute(:county) }.from(county).to(nil) + .and change { log.read_attribute(:postcode_full) }.from(postcode_full).to(nil) + end + + context "when the location postcode resolves to a local authority" do + it "derives the LA from the location and marks it as inferred" do + log.set_derived_fields! + + expect(log.read_attribute(:la)).to eq(location.location_code) + expect(log.is_la_inferred).to be true + end + end + + context "when the location postcode does not resolve to a local authority" do + before do + location.update_column(:location_code, nil) + end + + it "does not infer an LA, so the user is routed to the LA drop-down" do + log.la = nil + log.set_derived_fields! + + expect(log.read_attribute(:la)).to be_nil + expect(log.is_la_inferred).to be false + end + + it "keeps a manually chosen LA when one has been provided" do + # In the real edit flow the log is persisted, so the location/startdate have not + # "changed" and the earlier LA-reset branches do not fire. Stub those guards to + # isolate the confidential handling, which must not clobber the drop-down answer. + allow(log).to receive_messages(startdate_changed?: false, location_changed?: false) + log.la = "E07000105" + log.set_derived_fields! + + expect(log.read_attribute(:la)).to eq("E07000105") + expect(log.is_la_inferred).to be false + end + end + + context "when the log is also a new-build first let" do + before do + log.rsnvac = 15 + end + + it "still does not ask the address or UPRN question (confidential overrides new-build)" do + expect(log.is_address_asked?).to be false + end + + it "resets the address and UPRN fields to nil" do + expect { log.set_derived_fields! } + .to change { log.read_attribute(:uprn) }.from(uprn).to(nil) + .and change { log.read_attribute(:address_line1) }.from(address_line1).to(nil) + .and(change { log.read_attribute(:postcode_full) }.from(postcode_full).to(nil)) + end + end + end + describe "#infer_at_most_one_relationship!" do context "when 2025", metadata: { year: 25 } do before do diff --git a/spec/models/lettings_log_spec.rb b/spec/models/lettings_log_spec.rb index 9f2f7c675..cf1823dc6 100644 --- a/spec/models/lettings_log_spec.rb +++ b/spec/models/lettings_log_spec.rb @@ -2373,5 +2373,24 @@ RSpec.describe LettingsLog do end end end + + describe "#scheme_has_confidential_information?" do + let(:log) { build(:lettings_log) } + + it "returns false when there is no scheme" do + log.scheme = nil + expect(log.scheme_has_confidential_information?).to be false + end + + it "returns false when the scheme is not confidential" do + log.scheme = build(:scheme, sensitive: 0) + expect(log.scheme_has_confidential_information?).to be false + end + + it "returns true when the scheme is confidential" do + log.scheme = build(:scheme, sensitive: 1) + expect(log.scheme_has_confidential_information?).to be true + end + end end # rubocop:enable RSpec/MessageChain