Browse Source

Merge 5b7d00e1d5 into 8620594d07

pull/3378/merge
Nat Dean-Lewis 1 day ago committed by GitHub
parent
commit
cf2fe7e1f7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 10
      app/models/derived_variables/lettings_log_variables.rb
  2. 1
      app/models/form/lettings/pages/property_local_authority.rb
  3. 6
      app/models/lettings_log.rb
  4. 75
      lib/tasks/clear_confidential_address_data.rake
  5. 141
      spec/lib/tasks/clear_confidential_address_data_spec.rb

10
app/models/derived_variables/lettings_log_variables.rb

@ -176,9 +176,13 @@ module DerivedVariables::LettingsLogVariables
if !form.start_year_2026_or_later? && is_supported_housing?
reset_address_fields!
elsif form.start_year_2026_or_later? && location_changed?
reset_address_fields!
self.la = nil
elsif form.start_year_2026_or_later?
if location_changed?
reset_address_fields!
self.la = nil
end
self.is_la_inferred = la.present? if is_supported_housing? && location && self[:la].blank?
end
if scheme_has_confidential_information?

1
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, "is_supported_housing?" => true, "form.start_year_2026_or_later?" => true },
]
end

6
app/models/lettings_log.rb

@ -31,7 +31,7 @@ class LettingsLog < Log
before_validation :process_postcode_changes!, if: :postcode_full_changed?
before_validation :process_previous_postcode_changes!, if: :ppostcode_full_changed?
before_validation :reset_invalidated_dependent_fields!
before_validation :reset_location_fields!, unless: :postcode_known?
before_validation :reset_location_fields!, unless: :postcode_known_or_la_derived_from_scheme_location?
before_validation :reset_previous_location_fields!, unless: :previous_postcode_known?
before_validation :set_derived_fields!
before_validation :process_uprn_change!, if: :should_process_uprn_change?
@ -375,6 +375,10 @@ class LettingsLog < Log
postcode_known == 1
end
def postcode_known_or_la_derived_from_scheme_location?
postcode_known? || (form&.start_year_2026_or_later? && is_supported_housing? && location.present?)
end
def previous_postcode_known?
# 0: Yes
ppcodenk&.zero?

75
lib/tasks/clear_confidential_address_data.rake

@ -0,0 +1,75 @@
desc "Clears already-collected address/UPRN data for 2026/27 lettings logs in confidential (sensitive) schemes"
task clear_confidential_address_data: :environment do
year = 2026
fields_present_scope = %w[
uprn
uprn_known
uprn_confirmed
uprn_selection
address_line1
address_line2
town_or_city
county
postcode_full
postcode_known
address_line1_input
postcode_full_input
address_line1_as_entered
address_line2_as_entered
town_or_city_as_entered
county_as_entered
postcode_full_as_entered
la_as_entered
address_search_value_check
la
]
scope = LettingsLog
.filter_by_year(year)
.joins(:scheme)
.where(schemes: { sensitive: "Yes" })
.where(fields_present_scope.map { |field| "#{LettingsLog.table_name}.#{field} IS NOT NULL" }.join(" OR "))
puts "Found #{scope.count} confidential-scheme lettings logs in #{year}/#{year + 1} with address data to clear"
scope.find_each do |log|
puts "log_id=#{log.id} scheme_id=#{log.scheme_id} location_id=#{log.location_id} status=#{log.status} la=#{log.la} postcode_full=#{log.postcode_full}"
end
updated = 0
scope.find_each do |log|
original_status = log.status
log.uprn = nil
log.uprn_known = nil
log.uprn_confirmed = nil
log.uprn_selection = nil
log.address_line1 = nil
log.address_line2 = nil
log.town_or_city = nil
log.county = nil
log.postcode_full = nil
log.postcode_known = nil
log.address_line1_input = nil
log.postcode_full_input = nil
log.address_line1_as_entered = nil
log.address_line2_as_entered = nil
log.town_or_city_as_entered = nil
log.county_as_entered = nil
log.postcode_full_as_entered = nil
log.la_as_entered = nil
log.address_search_value_check = nil
log.la = nil
log.is_la_inferred = log.la.present?
if log.save(validate: false)
updated += 1
puts "log_id=#{log.id} status changed: #{original_status} -> #{log.status}" if log.status != original_status
else
Rails.logger.error "CLDC-4462: failed to clear address data for log #{log.id}: #{log.errors.full_messages.join(', ')}"
end
end
puts "#{updated} logs updated"
end

141
spec/lib/tasks/clear_confidential_address_data_spec.rb

@ -0,0 +1,141 @@
require "rails_helper"
require "rake"
RSpec.describe "clear_confidential_address_data" do
describe ":clear_confidential_address_data", type: :task do
subject(:task) { Rake::Task["clear_confidential_address_data"] }
before do
Rake.application.rake_require("tasks/clear_confidential_address_data")
Rake::Task.define_task(:environment)
task.reenable
end
let(:owning_organisation) { create(:organisation) }
let(:scheme) { create(:scheme, sensitive: "Yes", owning_organisation:) }
let(:non_confidential_scheme) { create(:scheme, sensitive: "No", owning_organisation:) }
let(:location) { create(:location, scheme:) }
def create_log_with_address_data(scheme:, location:, startdate:)
log = create(
:lettings_log,
:completed,
:sh,
:ignore_validation_errors,
owning_organisation:,
managing_organisation: owning_organisation,
scheme:,
location:,
startdate:,
)
# Bypass callbacks/validations to simulate a log that already holds property
# address/UPRN data collected before the confidential address feature existed.
log.update_columns(
uprn: "123456789012",
address_line1: "1 Secret Street",
town_or_city: "Secretville",
postcode_known: 1,
la: "E09000003",
)
log
end
context "when a confidential-scheme log in 2026/27 has address data" do
let!(:log) { create_log_with_address_data(scheme:, location:, startdate: Time.zone.local(2026, 5, 1)) }
it "clears the address and UPRN fields" do
task.invoke
log.reload
expect(log.address_line1).to be_nil
expect(log.town_or_city).to be_nil
expect(log.uprn).to be_nil
expect(log.postcode_known).to be_nil
end
it "keeps the log's status unchanged when the location's LA can be inferred" do
task.invoke
expect(log.reload.status).to eq("completed")
end
it "resolves the local authority from the scheme's location without persisting it" do
task.invoke
log.reload
expect(log.la).to eq(location.location_code)
expect(log[:la]).to be_nil
expect(log.is_la_inferred).to be true
end
end
context "when the scheme's location has no resolvable local authority" do
let!(:log) { create_log_with_address_data(scheme:, location:, startdate: Time.zone.local(2026, 5, 1)) }
before { location.update_columns(location_code: nil, location_admin_district: nil, is_la_inferred: false) }
it "clears the address fields and forces the log to in_progress" do
task.invoke
log.reload
expect(log.address_line1).to be_nil
expect(log.la).to be_nil
expect(log.status).to eq("in_progress")
end
end
context "when the confidential-scheme log is outside the 2026/27 collection year" do
let!(:log) { create_log_with_address_data(scheme:, location:, startdate: Time.zone.local(2025, 5, 1)) }
it "does not clear the address fields" do
task.invoke
expect(log.reload.address_line1).to eq("1 Secret Street")
end
end
context "when the log's scheme is not confidential" do
let!(:log) { create_log_with_address_data(scheme: non_confidential_scheme, location:, startdate: Time.zone.local(2026, 5, 1)) }
it "does not clear the address fields" do
task.invoke
expect(log.reload.address_line1).to eq("1 Secret Street")
end
end
context "when a confidential-scheme 2026/27 log has no address data left" do
let!(:log) do
create(
:lettings_log,
:ignore_validation_errors,
needstype: 2,
owning_organisation:,
managing_organisation: owning_organisation,
scheme:,
location:,
startdate: Time.zone.local(2026, 5, 1),
)
end
it "is not touched" do
expect { task.invoke }.not_to(change { log.reload.updated_at })
end
end
it "does not affect the scheme or location associations" do
log = create_log_with_address_data(scheme:, location:, startdate: Time.zone.local(2026, 5, 1))
task.invoke
log.reload
expect(log.scheme_id).to eq(scheme.id)
expect(log.location_id).to eq(location.id)
end
it "is idempotent" do
log = create_log_with_address_data(scheme:, location:, startdate: Time.zone.local(2026, 5, 1))
task.invoke
task.reenable
expect { task.invoke }.not_to(change { log.reload.updated_at })
end
end
end
Loading…
Cancel
Save