Browse Source

Merge branch 'main' into IncomeErrorMessages

pull/2270/head
Rachael Booth 2 years ago committed by GitHub
parent
commit
ebff983fae
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 2
      app/models/form/lettings/questions/homeless.rb
  2. 1
      app/models/lettings_log.rb
  3. 183
      app/services/bulk_update_from_csv/update_locations_from_csv_service.rb
  4. 121
      app/services/bulk_update_from_csv/update_schemes_from_csv_service.rb
  5. 21
      lib/tasks/update_schemes_and_locations_from_csv.rake
  6. 2
      spec/factories/lettings_log.rb
  7. 5
      spec/fixtures/files/original_locations.csv
  8. 6
      spec/fixtures/files/original_schemes.csv
  9. 6
      spec/fixtures/files/updated_locations.csv
  10. 6
      spec/fixtures/files/updated_schemes.csv
  11. 651
      spec/lib/tasks/update_schemes_and_locations_from_csv_spec.rb
  12. 46
      spec/models/form/lettings/questions/homeless_spec.rb

2
app/models/form/lettings/questions/homeless.rb

@ -12,7 +12,7 @@ class Form::Lettings::Questions::Homeless < ::Form::Question
end
ANSWER_OPTIONS = {
"11" => { "value" => "Assessed by a local authority as homeless" },
"11" => { "value" => "Yes - assessed by a local authority as homeless" },
"1" => { "value" => "No" },
}.freeze
end

1
app/models/lettings_log.rb

@ -65,6 +65,7 @@ class LettingsLog < Log
.or(filter_by_id(param))
}
scope :after_date, ->(date) { where("lettings_logs.startdate >= ?", date) }
scope :before_date, ->(date) { where("lettings_logs.startdate < ?", date) }
scope :unresolved, -> { where(unresolved: true) }
scope :age1_answered, -> { where.not(age1: nil).or(where(age1_known: 1)) }
scope :tcharge_answered, -> { where.not(tcharge: nil).or(where(household_charge: 1)).or(where(is_carehome: 1)) }

183
app/services/bulk_update_from_csv/update_locations_from_csv_service.rb

@ -0,0 +1,183 @@
class BulkUpdateFromCsv::UpdateLocationsFromCsvService
def initialize(original_file_name:, updated_file_name:)
@original_file_name = original_file_name
@updated_file_name = updated_file_name
end
def call
s3_service = Storage::S3Service.new(Configuration::EnvConfigurationService.new, ENV["CSV_DOWNLOAD_PAAS_INSTANCE"])
original_locations_csv = csv_from_path(@original_file_name, s3_service)
updated_locations_csv = csv_from_path(@updated_file_name, s3_service)
updated_locations_csv.each do |row|
updated_attributes = attributes_from_row(row)
original_row = original_locations_csv.find { |original_locations_row| original_locations_row[1] == updated_attributes["location_code"] }
if original_row.blank? || original_row["location_code"].nil?
Rails.logger.info("Location with id #{updated_attributes['location_code']} is not in the original location csv")
next
end
original_attributes = attributes_from_row(original_row)
location = Location.find_by(id: original_attributes["location_code"])
if location.blank?
Rails.logger.info("Location with id #{original_attributes['location_code']} is not in the database")
next
end
updated_attributes.each do |key, value|
next unless value != original_attributes[key] && value.present?
case key
when "location_admin_district"
update_location_admin_district(location, original_attributes, value)
when "postcode"
update_postcode(location, original_attributes, value)
when "scheme_code"
update_scheme(location, original_attributes, value)
when "name", "units", "type_of_unit", "mobility_type"
begin
location[key] = value
Rails.logger.info("Updating location #{original_attributes['location_code']} with #{key}: #{value}")
rescue ArgumentError => e
Rails.logger.info("Cannot update location #{original_attributes['location_code']} with #{key}: #{value}. #{e.message}")
end
when "location_code", "status", "active_dates"
Rails.logger.info("Cannot update location #{original_attributes['location_code']} with #{key} as it it not a permitted field")
end
end
unless location.changed?
Rails.logger.info("No changes to location #{original_attributes['location_code']}.")
next
end
save_location(location, original_attributes)
end
end
private
def csv_from_path(path, s3_service)
original_file_io = s3_service.get_file_io(path)
original_file_io.set_encoding_by_bom
CSV.parse(original_file_io, headers: true)
end
def attributes_from_row(row)
attributes = {}
attributes["scheme_code"] = row[0]
attributes["location_code"] = row[1]
attributes["postcode"] = row[2]
attributes["name"] = row[3]
attributes["status"] = row[4]
attributes["location_admin_district"] = row[5]
attributes["units"] = row[6]
attributes["type_of_unit"] = row[7]
attributes["mobility_type"] = row[8]
attributes["active_dates"] = row[9]
attributes
end
def update_location_admin_district(location, original_attributes, value)
location_code = Location.local_authorities_for_current_year.key(value)
if location_code.present?
location.location_code = location_code
location.location_admin_district = value
Rails.logger.info("Updating location #{original_attributes['location_code']} with location_code: #{location_code}")
else
Rails.logger.info("Cannot update location #{original_attributes['location_code']} with location_admin_district: #{value}. Location admin distrint #{value} is not a valid option")
end
end
def update_postcode(location, original_attributes, value)
if !value&.match(POSTCODE_REGEXP)
Rails.logger.info("Cannot update location #{original_attributes['location_code']} with postcode: #{value}. #{I18n.t('validations.postcode')}")
else
location.postcode = PostcodeService.clean(value)
Rails.logger.info("Updating location #{original_attributes['location_code']} with postcode: #{value}")
end
end
def update_scheme(location, original_attributes, value)
scheme = Scheme.find_by(id: value.delete("S"))
if scheme.present?
original_scheme = Scheme.find_by(id: original_attributes["scheme_code"].delete("S"))
if original_scheme.nil? || !([original_scheme.owning_organisation] + original_scheme.owning_organisation.parent_organisations + original_scheme.owning_organisation.child_organisations).include?(scheme.owning_organisation)
Rails.logger.info("Cannot update location #{original_attributes['location_code']} with scheme_code: #{value}. Scheme with id #{value} is not in organisation that does not have relationship with the original organisation")
else
location["scheme_id"] = scheme.id
Rails.logger.info("Updating location #{original_attributes['location_code']} with scheme: S#{scheme.id}")
editable_from_date = FormHandler.instance.earliest_open_for_editing_collection_start_date
editable_logs = LettingsLog.where(location_id: location.id).after_date(editable_from_date)
Rails.logger.info("Clearing location and scheme for logs with startdate and location #{location.id}. Log IDs: #{editable_logs.map(&:id).join(', ')}")
editable_logs.update!(location: nil, scheme: nil, values_updated_at: Time.zone.now)
logs_without_start_date = LettingsLog.where(scheme_id: scheme.id).where(startdate: nil)
Rails.logger.info("Clearing location and scheme for logs without startdate and location #{location.id}. Log IDs: #{logs_without_start_date.map(&:id).join(', ')}")
logs_without_start_date.update!(location: nil, scheme: nil, values_updated_at: Time.zone.now)
exportable_from_date = FormHandler.instance.previous_collection_start_date
remaining_logs_to_export = LettingsLog.where(location_id: location.id).after_date(exportable_from_date)
Rails.logger.info("Clearing location and scheme for non editable logs with location #{location.id}. Log IDs: #{remaining_logs_to_export.map(&:id).join(', ')}")
remaining_logs_to_export.update_all(location_id: nil, scheme_id: nil, values_updated_at: Time.zone.now)
end
else
Rails.logger.info("Cannot update location #{original_attributes['location_code']} with scheme_code: #{value}. Scheme with id #{value} is not in the database")
end
end
def save_location(location, original_attributes)
location.save!
Rails.logger.info("Saved location #{original_attributes['location_code']}.")
exportable_from_date = FormHandler.instance.previous_collection_start_date
logs_to_export = LettingsLog.where(location_id: location.id).after_date(exportable_from_date)
if original_attributes["location_admin_district"] != location.location_admin_district
clear_invalid_rent_fields(logs_to_export)
else
logs_to_export.update_all(values_updated_at: Time.zone.now)
end
logs_not_to_export = LettingsLog.where(location_id: location.id).before_date(exportable_from_date)
Rails.logger.info("Will not export log #{logs_not_to_export.map(&:id).join(',')} as it is before the exportable date") if logs_not_to_export.any?
rescue ActiveRecord::RecordInvalid => e
Rails.logger.error("Cannot update location #{original_attributes['location_code']}. #{e.message}")
end
def clear_invalid_rent_fields(logs)
logs.each do |log|
if log.rent_in_soft_min_range? || log.rent_in_soft_max_range?
complete_or_log_soft_invalidated_log(log)
else
log.validate
if log.errors["brent"].any?
Rails.logger.info("Log #{log.id} went from completed to in progress.") if log.status == "completed"
log.brent = nil
log.scharge = nil
log.pscharge = nil
log.supcharg = nil
end
log.values_updated_at = Time.zone.now
log.save!(validate: false)
end
end
end
def complete_or_log_soft_invalidated_log(log)
return if log.rent_value_check.present?
editable_from_date = FormHandler.instance.earliest_open_for_editing_collection_start_date
if log.startdate < editable_from_date
log.rent_value_check = 0
Rails.logger.info("Confirmed rent value check for log #{log.id}.")
elsif log.status == "completed"
Rails.logger.info("Log #{log.id} went from completed to in progress.")
else
Rails.logger.info("Log #{log.id} stayed in progress, triggering soft rent value check.")
end
log.values_updated_at = Time.zone.now
log.save!(validate: false)
end
end

121
app/services/bulk_update_from_csv/update_schemes_from_csv_service.rb

@ -0,0 +1,121 @@
class BulkUpdateFromCsv::UpdateSchemesFromCsvService
def initialize(original_file_name:, updated_file_name:)
@original_file_name = original_file_name
@updated_file_name = updated_file_name
end
def call
s3_service = Storage::S3Service.new(Configuration::EnvConfigurationService.new, ENV["CSV_DOWNLOAD_PAAS_INSTANCE"])
original_schemes_csv = csv_from_path(@original_file_name, s3_service)
updated_schemes_csv = csv_from_path(@updated_file_name, s3_service)
updated_schemes_csv.each do |row|
updated_attributes = attributes_from_row(row)
original_row = original_schemes_csv.find { |original_schemes_row| original_schemes_row[0] == updated_attributes["scheme_code"] }
if original_row.blank? || original_row["scheme_code"].nil?
Rails.logger.info("Scheme with id #{updated_attributes['scheme_code']} is not in the original scheme csv")
next
end
original_attributes = attributes_from_row(original_row)
scheme = Scheme.find_by(id: original_attributes["scheme_code"].delete("S"))
if scheme.blank?
Rails.logger.info("Scheme with id #{original_attributes['scheme_code']} is not in the database")
next
end
updated_attributes.each do |key, value|
next unless value != original_attributes[key] && value.present?
case key
when "owning_organisation"
update_owning_organisation(scheme, original_attributes, value)
when "service_name", "sensitive", "scheme_type", "registered_under_care_act", "arrangement_type", "primary_client_group", "has_other_client_group", "secondary_client_group", "support_type", "intended_stay"
begin
scheme[key] = value
Rails.logger.info("Updating scheme #{original_attributes['scheme_code']} with #{key}: #{value}")
rescue ArgumentError => e
Rails.logger.info("Cannot update scheme #{original_attributes['scheme_code']} with #{key}: #{value}. #{e.message}")
end
when "scheme_code", "status", "created_at", "active_dates"
Rails.logger.info("Cannot update scheme #{original_attributes['scheme_code']} with #{key} as it it not a permitted field")
end
end
unless scheme.changed?
Rails.logger.info("No changes to scheme #{original_attributes['scheme_code']}.")
next
end
save_scheme(scheme, original_attributes)
end
end
private
def csv_from_path(path, s3_service)
original_file_io = s3_service.get_file_io(path)
original_file_io.set_encoding_by_bom
CSV.parse(original_file_io, headers: true)
end
def attributes_from_row(row)
attributes = {}
attributes["scheme_code"] = row[0]
attributes["service_name"] = row[1]
attributes["status"] = row[2]
attributes["sensitive"] = row[3]
attributes["scheme_type"] = row[4]
attributes["registered_under_care_act"] = row[5]
attributes["owning_organisation"] = row[6]
attributes["arrangement_type"] = row[7]
attributes["primary_client_group"] = row[8]
attributes["has_other_client_group"] = row[9]
attributes["secondary_client_group"] = row[10]
attributes["support_type"] = row[11]
attributes["intended_stay"] = row[12]
attributes["created_at"] = row[13]
attributes["active_dates"] = row[14]
attributes
end
def update_owning_organisation(scheme, original_attributes, value)
current_organisation = scheme.owning_organisation
organisation = Organisation.find_by(name: value)
if organisation.present? && (organisation.child_organisations.include?(current_organisation) || organisation.parent_organisations.include?(current_organisation))
if LettingsLog.where(scheme_id: scheme.id).before_date(FormHandler.instance.lettings_earliest_open_for_editing_collection_start_date).any?
Rails.logger.info("Cannot update scheme #{original_attributes['scheme_code']} with owning_organisation: #{value}. There are lettings logs from closed collection period using this scheme")
else
scheme["owning_organisation_id"] = organisation.id
Rails.logger.info("Updating scheme #{original_attributes['scheme_code']} with owning_organisation: #{organisation.name}")
editable_from_date = FormHandler.instance.earliest_open_for_editing_collection_start_date
editable_logs_with_startdate = LettingsLog.where(scheme_id: scheme.id).after_date(editable_from_date)
Rails.logger.info("Clearing location and scheme for logs with startdate and scheme S#{scheme.id}. Log IDs: #{editable_logs_with_startdate.map(&:id).join(', ')}")
editable_logs_with_startdate.update!(location: nil, scheme: nil)
logs_without_start_date = LettingsLog.where(scheme_id: scheme.id).where(startdate: nil)
Rails.logger.info("Clearing location and scheme for logs without startdate and scheme S#{scheme.id}. Log IDs: #{logs_without_start_date.map(&:id).join(', ')}")
logs_without_start_date.update!(location: nil, scheme: nil)
end
else
Rails.logger.info("Cannot update scheme #{original_attributes['scheme_code']} with owning_organisation: #{value}. Organisation with name #{value} is not in the database or is not related to current organisation")
end
end
def save_scheme(scheme, original_attributes)
scheme.save!
Rails.logger.info("Saved scheme #{original_attributes['scheme_code']}.")
exportable_from_date = FormHandler.instance.previous_collection_start_date
LettingsLog.where(scheme_id: scheme.id).after_date(exportable_from_date).update_all(values_updated_at: Time.zone.now)
LettingsLog.where(scheme_id: scheme.id).where(startdate: nil).update_all(values_updated_at: Time.zone.now)
logs_not_to_export = LettingsLog.where(scheme_id: scheme.id).before_date(exportable_from_date)
Rails.logger.info("Will not export log #{logs_not_to_export.map(&:id).join(',')} as it is before the exportable date") if logs_not_to_export.any?
rescue ActiveRecord::RecordInvalid => e
Rails.logger.error("Cannot update scheme #{original_attributes['scheme_code']}. #{e.message}")
end
end

21
lib/tasks/update_schemes_and_locations_from_csv.rake

@ -0,0 +1,21 @@
namespace :bulk_update do
desc "Bulk update scheme data from a csv file"
task :update_schemes_from_csv, %i[original_file_name updated_file_name] => :environment do |_task, args|
original_file_name = args[:original_file_name]
updated_file_name = args[:updated_file_name]
raise "Usage: rake bulk_update:update_schemes_from_csv['original_file_name','updated_file_name']" if original_file_name.blank? || updated_file_name.blank?
BulkUpdateFromCsv::UpdateSchemesFromCsvService.new(original_file_name:, updated_file_name:).call
end
desc "Bulk update location data from a csv file"
task :update_locations_from_csv, %i[original_file_name updated_file_name] => :environment do |_task, args|
original_file_name = args[:original_file_name]
updated_file_name = args[:updated_file_name]
raise "Usage: rake bulk_update:update_locations_from_csv['original_file_name','updated_file_name']" if original_file_name.blank? || updated_file_name.blank?
BulkUpdateFromCsv::UpdateLocationsFromCsvService.new(original_file_name:, updated_file_name:).call
end
end

2
spec/factories/lettings_log.rb

@ -178,7 +178,7 @@ FactoryBot.define do
end
trait :sh do
needstype { 2 }
sheltered { 0 }
sheltered { 3 }
household_charge { 0 }
end
trait :sheltered_housing do

5
spec/fixtures/files/original_locations.csv vendored

@ -0,0 +1,5 @@
scheme_code,location_code,location_postcode,location_name,location_status,location_local_authority,location_units,location_type_of_unit,location_mobility_type,location_active_dates
{scheme_id1},{id1},SW1A 2AA,Downing Street,active,Wigan,20,Self-contained house,Fitted with equipment and adaptations,"Active from 1 April 2022"
{scheme_id2},{id2},SW1A 2AA,Downing Street,active,Wigan,20,Self-contained house,Fitted with equipment and adaptations,"Active from 1 April 2022"
{scheme_id3},{id3},SW1A 2AA,Downing Street,active,Wigan,20,Self-contained house,Fitted with equipment and adaptations,"Active from 1 April 2022"
1,SWrong_id,SW1A 2AA,Downing Street,active,Wigan,20,Self-contained house,Fitted with equipment and adaptations,"Active from 1 April 2022"
1 scheme_code location_code location_postcode location_name location_status location_local_authority location_units location_type_of_unit location_mobility_type location_active_dates
2 {scheme_id1} {id1} SW1A 2AA Downing Street active Wigan 20 Self-contained house Fitted with equipment and adaptations Active from 1 April 2022
3 {scheme_id2} {id2} SW1A 2AA Downing Street active Wigan 20 Self-contained house Fitted with equipment and adaptations Active from 1 April 2022
4 {scheme_id3} {id3} SW1A 2AA Downing Street active Wigan 20 Self-contained house Fitted with equipment and adaptations Active from 1 April 2022
5 1 SWrong_id SW1A 2AA Downing Street active Wigan 20 Self-contained house Fitted with equipment and adaptations Active from 1 April 2022

6
spec/fixtures/files/original_schemes.csv vendored

@ -0,0 +1,6 @@
scheme_code,scheme_service_name,scheme_status,scheme_sensitive,scheme_type,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_support_services_provided_by,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,scheme_active_dates
{id1},Test name,active,Yes,Housing for older people,Yes – registered care home providing nursing care,DLUHC,The same organisation that owns the housing stock,People with alcohol problems,Yes,Older people with support needs,High level,Medium stay,2021-04-01T00:00:00+01:00,"Active from 1 April 2020"
{id2},Test name,active,Yes,Housing for older people,Yes – registered care home providing nursing care,DLUHC,The same organisation that owns the housing stock,People with alcohol problems,Yes,Older people with support needs,High level,Medium stay,2021-04-01T00:00:00+01:00,"Active from 1 April 2020"
{id3},Test name,active,Yes,Housing for older people,Yes – registered care home providing nursing care,DLUHC,The same organisation that owns the housing stock,People with alcohol problems,Yes,Older people with support needs,High level,Medium stay,2021-04-01T00:00:00+01:00,"Active from 1 April 2020"
{id4},Incomplete scheme,incomplete,Yes,Housing for older people,Yes – registered care home providing nursing care,DLUHC,The same organisation that owns the housing stock,People with alcohol problems,,,,,2021-04-01T00:00:00+01:00,"Active from 1 April 2020"
SWrong_id,Incomplete scheme,incomplete,Yes,Housing for older people,Yes – registered care home providing nursing care,DLUHC,The same organisation that owns the housing stock,People with alcohol problems,,,,,2021-04-01T00:00:00+01:00,"Active from 1 April 2020"
1 scheme_code scheme_service_name scheme_status scheme_sensitive scheme_type scheme_registered_under_care_act scheme_owning_organisation_name scheme_support_services_provided_by scheme_primary_client_group scheme_has_other_client_group scheme_secondary_client_group scheme_support_type scheme_intended_stay scheme_created_at scheme_active_dates
2 {id1} Test name active Yes Housing for older people Yes – registered care home providing nursing care DLUHC The same organisation that owns the housing stock People with alcohol problems Yes Older people with support needs High level Medium stay 2021-04-01T00:00:00+01:00 Active from 1 April 2020
3 {id2} Test name active Yes Housing for older people Yes – registered care home providing nursing care DLUHC The same organisation that owns the housing stock People with alcohol problems Yes Older people with support needs High level Medium stay 2021-04-01T00:00:00+01:00 Active from 1 April 2020
4 {id3} Test name active Yes Housing for older people Yes – registered care home providing nursing care DLUHC The same organisation that owns the housing stock People with alcohol problems Yes Older people with support needs High level Medium stay 2021-04-01T00:00:00+01:00 Active from 1 April 2020
5 {id4} Incomplete scheme incomplete Yes Housing for older people Yes – registered care home providing nursing care DLUHC The same organisation that owns the housing stock People with alcohol problems 2021-04-01T00:00:00+01:00 Active from 1 April 2020
6 SWrong_id Incomplete scheme incomplete Yes Housing for older people Yes – registered care home providing nursing care DLUHC The same organisation that owns the housing stock People with alcohol problems 2021-04-01T00:00:00+01:00 Active from 1 April 2020

6
spec/fixtures/files/updated_locations.csv vendored

@ -0,0 +1,6 @@
scheme_code,location_code,location_postcode,location_name,location_status,location_local_authority,location_units,location_type_of_unit,location_mobility_type,location_active_dates
{scheme_id1},{id1},B11BB,Updated name,deactivating_soon,Westminster,10,Bungalow,Wheelchair-user standard,"Active from 1 April 2028"
{scheme_id2},{id2},SW1A 2AA,Downing Street,active,Wigan,20,Self-contained house,Fitted with equipment and adaptations,"Active from 1 April 2022"
{scheme_id3},{id3},SWAAA,,deactivating_soon,Westminst,,elf-contained house,55,"Active from 1 April 2022"
x,Wrong_id,SWAAA,,deactivating_soon,Westminst,,elf-contained house,55,"Active from 1 April 2022"
x,SWrong_id,SWAAA,,deactivating_soon,Westminst,,elf-contained house,55,"Active from 1 April 2022"
1 scheme_code location_code location_postcode location_name location_status location_local_authority location_units location_type_of_unit location_mobility_type location_active_dates
2 {scheme_id1} {id1} B11BB Updated name deactivating_soon Westminster 10 Bungalow Wheelchair-user standard Active from 1 April 2028
3 {scheme_id2} {id2} SW1A 2AA Downing Street active Wigan 20 Self-contained house Fitted with equipment and adaptations Active from 1 April 2022
4 {scheme_id3} {id3} SWAAA deactivating_soon Westminst elf-contained house 55 Active from 1 April 2022
5 x Wrong_id SWAAA deactivating_soon Westminst elf-contained house 55 Active from 1 April 2022
6 x SWrong_id SWAAA deactivating_soon Westminst elf-contained house 55 Active from 1 April 2022

6
spec/fixtures/files/updated_schemes.csv vendored

@ -0,0 +1,6 @@
scheme_code,scheme_service_name,scheme_status,scheme_sensitive,scheme_type,scheme_registered_under_care_act,scheme_owning_organisation_name,scheme_support_services_provided_by,scheme_primary_client_group,scheme_has_other_client_group,scheme_secondary_client_group,scheme_support_type,scheme_intended_stay,scheme_created_at,scheme_active_dates
{id1},Updated test name,incomplete,No,Direct Access Hostel,No,Different organisation,Another registered stock owner,People with drug problems,No,Older people with support needs,Low level,Permanent,2022-04-01T00:00:00+01:00,"Active from 2 April 2020"
{id2},Test name,active,Yes,Housing for older people,Yes – registered care home providing nursing care,DLUHC,The same organisation that owns the housing stock,People with alcohol problems,Yes,Older people with support needs,High level,Medium stay,2021-04-01T00:00:00+01:00,"Active from 1 April 2020"
{id3}, ,active,Yse,Direct access Hostel,Yes – registered care home providing nursing care,non existing org,wrong answer,FD,no,lder people with support needs,high,Permanent ,2021-04-01T00:00:00+01:00,"Active from 1 April 2020"
Wrong_id,Incomplete scheme,incomplete,Yes,Housing for older people,No,DLUHC,The same organisation that owns the housing stock,People with alcohol problems,,,,,2021-04-01T00:00:00+01:00,"Active from 1 April 2020"
SWrong_id,Incomplete scheme,incomplete,Yes,Housing for older people,No,DLUHC,The same organisation that owns the housing stock,People with alcohol problems,,,,,2021-04-01T00:00:00+01:00,"Active from 1 April 2020"
1 scheme_code scheme_service_name scheme_status scheme_sensitive scheme_type scheme_registered_under_care_act scheme_owning_organisation_name scheme_support_services_provided_by scheme_primary_client_group scheme_has_other_client_group scheme_secondary_client_group scheme_support_type scheme_intended_stay scheme_created_at scheme_active_dates
2 {id1} Updated test name incomplete No Direct Access Hostel No Different organisation Another registered stock owner People with drug problems No Older people with support needs Low level Permanent 2022-04-01T00:00:00+01:00 Active from 2 April 2020
3 {id2} Test name active Yes Housing for older people Yes – registered care home providing nursing care DLUHC The same organisation that owns the housing stock People with alcohol problems Yes Older people with support needs High level Medium stay 2021-04-01T00:00:00+01:00 Active from 1 April 2020
4 {id3} active Yse Direct access Hostel Yes – registered care home providing nursing care non existing org wrong answer FD no lder people with support needs high Permanent 2021-04-01T00:00:00+01:00 Active from 1 April 2020
5 Wrong_id Incomplete scheme incomplete Yes Housing for older people No DLUHC The same organisation that owns the housing stock People with alcohol problems 2021-04-01T00:00:00+01:00 Active from 1 April 2020
6 SWrong_id Incomplete scheme incomplete Yes Housing for older people No DLUHC The same organisation that owns the housing stock People with alcohol problems 2021-04-01T00:00:00+01:00 Active from 1 April 2020

651
spec/lib/tasks/update_schemes_and_locations_from_csv_spec.rb

@ -0,0 +1,651 @@
require "rails_helper"
require "rake"
RSpec.describe "bulk_update" do
def replace_entity_ids(scheme_1, scheme_2, scheme_3, export_template)
export_template.sub!(/\{id1\}/, "S#{scheme_1.id}")
export_template.sub!(/\{id2\}/, "S#{scheme_2.id}")
export_template.sub!(/\{id3\}/, "S#{scheme_3.id}")
end
def replace_entity_ids_for_locations(location_1, location_2, location_3, scheme_1, scheme_2, scheme_3, export_template)
export_template.sub!(/\{id1\}/, location_1.id.to_s)
export_template.sub!(/\{id2\}/, location_2.id.to_s)
export_template.sub!(/\{id3\}/, location_3.id.to_s)
export_template.sub!(/\{scheme_id1\}/, "S#{scheme_1['id']}")
export_template.sub!(/\{scheme_id2\}/, "S#{scheme_2['id']}")
export_template.sub!(/\{scheme_id3\}/, "S#{scheme_3['id']}")
end
before do
allow(Storage::S3Service).to receive(:new).and_return(storage_service)
allow(Configuration::EnvConfigurationService).to receive(:new).and_return(env_config_service)
allow(ENV).to receive(:[])
allow(ENV).to receive(:[]).with("CSV_DOWNLOAD_PAAS_INSTANCE").and_return(instance_name)
WebMock.stub_request(:get, /api\.postcodes\.io/)
.to_return(status: 200, body: "{\"status\":404,\"error\":\"Postcode not found\"}", headers: {})
WebMock.stub_request(:get, /api\.postcodes\.io\/postcodes\/B11BB/)
.to_return(status: 200, body: '{"status":200,"result":{"admin_district":"Westminster","codes":{"admin_district":"E09000033"}}}', headers: {})
end
describe ":update_schemes_from_csv", type: :task do
subject(:task) { Rake::Task["bulk_update:update_schemes_from_csv"] }
let(:instance_name) { "import_instance" }
let(:storage_service) { instance_double(Storage::S3Service) }
let(:env_config_service) { instance_double(Configuration::EnvConfigurationService) }
before do
Rake.application.rake_require("tasks/update_schemes_and_locations_from_csv")
Rake::Task.define_task(:environment)
task.reenable
end
context "when the rake task is run" do
let(:original_schemes_csv_path) { "original_schemes.csv" }
let(:updated_schemes_csv_path) { "updated_schemes.csv" }
let(:wrong_file_path) { "/test/no_csv_here.csv" }
let!(:different_organisation) { FactoryBot.create(:organisation, name: "Different organisation") }
let(:schemes) do
create_list(:scheme,
3,
service_name: "Test name",
sensitive: 1,
registered_under_care_act: 4,
support_type: 4,
scheme_type: 7,
arrangement_type: "D",
intended_stay: "M",
primary_client_group: "G",
secondary_client_group: "M",
has_other_client_group: 1,
owning_organisation: FactoryBot.create(:organisation),
confirmed: true,
created_at: Time.zone.local(2021, 4, 1),
total_units: 2)
end
let(:location) { FactoryBot.create(:location, scheme: schemes[0]) }
let(:location_2) { FactoryBot.create(:location, scheme: schemes[1]) }
let(:location_3) { FactoryBot.create(:location, scheme: schemes[2]) }
let!(:lettings_log) { FactoryBot.create(:lettings_log, :sh, scheme: schemes[0], location:, values_updated_at: nil, owning_organisation: schemes[0].owning_organisation) }
let!(:lettings_log_2) { FactoryBot.create(:lettings_log, :sh, scheme: schemes[1], location: location_2, values_updated_at: nil, owning_organisation: schemes[1].owning_organisation) }
let!(:lettings_log_3) { FactoryBot.create(:lettings_log, :sh, scheme: schemes[2], location: location_3, values_updated_at: nil, owning_organisation: schemes[2].owning_organisation) }
let!(:lettings_log_4) { FactoryBot.create(:lettings_log, :sh, scheme: schemes[0], location:, values_updated_at: nil, owning_organisation: schemes[0].owning_organisation) }
let!(:lettings_log_5) { FactoryBot.create(:lettings_log, :sh, scheme: schemes[0], location:, values_updated_at: nil, owning_organisation: schemes[0].owning_organisation) }
before do
allow(storage_service).to receive(:get_file_io)
.with("original_schemes.csv")
.and_return(StringIO.new(replace_entity_ids(schemes[0], schemes[1], schemes[2], File.open("./spec/fixtures/files/original_schemes.csv").read)))
allow(storage_service).to receive(:get_file_io)
.with("updated_schemes.csv")
.and_return(StringIO.new(replace_entity_ids(schemes[0], schemes[1], schemes[2], File.open("./spec/fixtures/files/updated_schemes.csv").read)))
end
it "updates the allowed scheme fields if they have changed and doesn't update other fields" do
create(:organisation_relationship, parent_organisation: schemes[0].owning_organisation, child_organisation: different_organisation)
task.invoke(original_schemes_csv_path, updated_schemes_csv_path)
schemes[0].reload
expect(schemes[0].service_name).to eq("Updated test name")
expect(schemes[0].sensitive).to eq("No")
expect(schemes[0].registered_under_care_act).to eq("No")
expect(schemes[0].support_type).to eq("Low level")
expect(schemes[0].scheme_type).to eq("Direct Access Hostel")
expect(schemes[0].arrangement_type).to eq("Another registered stock owner")
expect(schemes[0].intended_stay).to eq("Permanent")
expect(schemes[0].primary_client_group).to eq("People with drug problems")
expect(schemes[0].has_other_client_group).to eq("No")
expect(schemes[0].owning_organisation).to eq(different_organisation)
expect(schemes[0].created_at).to eq(Time.zone.local(2021, 4, 1))
expect(schemes[0].total_units).to eq(2)
end
it "updates the lettings log if scheme has changed owning organisation" do
create(:organisation_relationship, parent_organisation: schemes[0].owning_organisation, child_organisation: different_organisation)
task.invoke(original_schemes_csv_path, updated_schemes_csv_path)
lettings_log.reload
expect(lettings_log.scheme).to be_nil
expect(lettings_log.location).to be_nil
end
it "does not update the scheme if it hasn't changed" do
task.invoke(original_schemes_csv_path, updated_schemes_csv_path)
schemes[1].reload
expect(schemes[1].service_name).to eq("Test name")
expect(schemes[1].sensitive).to eq("Yes")
expect(schemes[1].registered_under_care_act).to eq("Yes – registered care home providing nursing care")
expect(schemes[1].support_type).to eq("High level")
expect(schemes[1].scheme_type).to eq("Housing for older people")
expect(schemes[1].arrangement_type).to eq("The same organisation that owns the housing stock")
expect(schemes[1].intended_stay).to eq("Medium stay")
expect(schemes[1].primary_client_group).to eq("People with alcohol problems")
expect(schemes[1].secondary_client_group).to eq("Older people with support needs")
expect(schemes[1].has_other_client_group).to eq("Yes")
expect(schemes[1].owning_organisation).not_to eq(different_organisation)
expect(schemes[1].created_at).to eq(Time.zone.local(2021, 4, 1))
expect(schemes[1].total_units).to eq(2)
end
it "does not update the scheme with invalid values" do
task.invoke(original_schemes_csv_path, updated_schemes_csv_path)
schemes[2].reload
expect(schemes[2].service_name).to eq("Test name")
expect(schemes[2].sensitive).to eq("Yes")
expect(schemes[2].registered_under_care_act).to eq("Yes – registered care home providing nursing care")
expect(schemes[2].support_type).to eq("High level")
expect(schemes[2].scheme_type).to eq("Housing for older people")
expect(schemes[2].arrangement_type).to eq("The same organisation that owns the housing stock")
expect(schemes[2].intended_stay).to eq("Medium stay")
expect(schemes[2].primary_client_group).to eq("People with alcohol problems")
expect(schemes[2].secondary_client_group).to eq("Older people with support needs")
expect(schemes[2].has_other_client_group).to eq("Yes")
expect(schemes[2].owning_organisation).not_to eq(different_organisation)
expect(schemes[2].created_at).to eq(Time.zone.local(2021, 4, 1))
expect(schemes[2].total_units).to eq(2)
end
it "does not update the owning organisation if the new organisation is not related to current organisation" do
task.invoke(original_schemes_csv_path, updated_schemes_csv_path)
schemes[0].reload
expect(schemes[0].owning_organisation).not_to eq(different_organisation)
end
it "does not update the owning organisation if there are logs from closed collection periods" do
create(:organisation_relationship, parent_organisation: schemes[0].owning_organisation, child_organisation: different_organisation)
lettings_log_4.startdate = Time.zone.local(2022, 4, 1)
lettings_log_4.save!(validate: false)
lettings_log_5.startdate = Time.zone.local(2021, 4, 1)
lettings_log_5.save!(validate: false)
task.invoke(original_schemes_csv_path, updated_schemes_csv_path)
schemes[0].reload
expect(schemes[0].owning_organisation).not_to eq(different_organisation)
end
it "does not update the lettings log if scheme owning organisation didn't change" do
task.invoke(original_schemes_csv_path, updated_schemes_csv_path)
lettings_log.reload
expect(lettings_log.scheme).not_to be_nil
expect(lettings_log.location).not_to be_nil
end
it "only re-exports the logs for the schemes that have been updated" do
lettings_log_4.startdate = Time.zone.local(2022, 4, 1)
lettings_log_4.save!(validate: false)
lettings_log_5.startdate = Time.zone.local(2021, 4, 1)
lettings_log_5.save!(validate: false)
task.invoke(original_schemes_csv_path, updated_schemes_csv_path)
lettings_log.reload
expect(lettings_log.values_updated_at).not_to eq(nil)
lettings_log_2.reload
expect(lettings_log_2.values_updated_at).to eq(nil)
lettings_log_3.reload
expect(lettings_log_3.values_updated_at).to eq(nil)
lettings_log_4.reload
expect(lettings_log_4.values_updated_at).not_to eq(nil)
lettings_log_5.reload
expect(lettings_log_5.values_updated_at).to eq(nil)
end
it "logs the progress of the update" do
create(:organisation_relationship, parent_organisation: schemes[0].owning_organisation, child_organisation: different_organisation)
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with service_name: Updated test name")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with sensitive: No")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with scheme_type: Direct Access Hostel")
expect(Rails.logger).to receive(:info).with("Clearing location and scheme for logs with startdate and scheme S#{schemes[0].id}. Log IDs: ")
expect(Rails.logger).to receive(:info).with("Clearing location and scheme for logs without startdate and scheme S#{schemes[0].id}. Log IDs: #{lettings_log.id}, #{lettings_log_4.id}, #{lettings_log_5.id}")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with arrangement_type: Another registered stock owner")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with primary_client_group: People with drug problems")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with has_other_client_group: No")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with support_type: Low level")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with intended_stay: Permanent")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with registered_under_care_act: No")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with owning_organisation: Different organisation")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[0].id} with status as it it not a permitted field")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[0].id} with created_at as it it not a permitted field")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[0].id} with active_dates as it it not a permitted field")
expect(Rails.logger).to receive(:info).with("Saved scheme S#{schemes[0].id}.")
expect(Rails.logger).to receive(:info).with("No changes to scheme S#{schemes[1].id}.")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with sensitive: Yse. 'Yse' is not a valid sensitive")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with scheme_type: Direct access Hostel. 'Direct access Hostel' is not a valid scheme_type")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with owning_organisation: non existing org. Organisation with name non existing org is not in the database or is not related to current organisation")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with arrangement_type: wrong answer. 'wrong answer' is not a valid arrangement_type")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with primary_client_group: FD. 'FD' is not a valid primary_client_group")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with has_other_client_group: no. 'no' is not a valid has_other_client_group")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with secondary_client_group: lder people with support needs. 'lder people with support needs' is not a valid secondary_client_group")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with support_type: high. 'high' is not a valid support_type")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with intended_stay: Permanent . 'Permanent ' is not a valid intended_stay")
expect(Rails.logger).to receive(:info).with("No changes to scheme S#{schemes[2].id}.")
expect(Rails.logger).to receive(:info).with("Scheme with id Wrong_id is not in the original scheme csv")
expect(Rails.logger).to receive(:info).with("Scheme with id SWrong_id is not in the database")
task.invoke(original_schemes_csv_path, updated_schemes_csv_path)
end
it "raises an error when no paths are given" do
expect { task.invoke(nil) }.to raise_error(RuntimeError, "Usage: rake bulk_update:update_schemes_from_csv['original_file_name','updated_file_name']")
end
it "raises an error when no original path is given" do
expect { task.invoke(nil, updated_schemes_csv_path) }.to raise_error(RuntimeError, "Usage: rake bulk_update:update_schemes_from_csv['original_file_name','updated_file_name']")
end
it "raises an error when no updated path is given" do
expect { task.invoke(original_schemes_csv_path, nil) }.to raise_error(RuntimeError, "Usage: rake bulk_update:update_schemes_from_csv['original_file_name','updated_file_name']")
end
it "logs an error if a validation fails and processes the rest of the rows" do
create(:organisation_relationship, parent_organisation: schemes[0].owning_organisation, child_organisation: different_organisation)
lettings_log_4.startdate = Time.zone.local(2022, 4, 1)
lettings_log_4.save!(validate: false)
lettings_log_5.startdate = Time.zone.local(2021, 4, 1)
lettings_log_5.save!(validate: false)
schemes[1].support_type = nil
schemes[1].save!(validate: false)
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with service_name: Updated test name")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with sensitive: No")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with scheme_type: Direct Access Hostel")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with arrangement_type: Another registered stock owner")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with primary_client_group: People with drug problems")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with has_other_client_group: No")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with support_type: Low level")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with intended_stay: Permanent")
expect(Rails.logger).to receive(:info).with("Updating scheme S#{schemes[0].id} with registered_under_care_act: No")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[0].id} with status as it it not a permitted field")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[0].id} with created_at as it it not a permitted field")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[0].id} with active_dates as it it not a permitted field")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[0].id} with owning_organisation: Different organisation. There are lettings logs from closed collection period using this scheme")
expect(Rails.logger).to receive(:info).with("Saved scheme S#{schemes[0].id}.")
expect(Rails.logger).to receive(:info).with("Will not export log #{lettings_log_5.id} as it is before the exportable date")
expect(Rails.logger).to receive(:info).with("No changes to scheme S#{schemes[1].id}.")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with sensitive: Yse. 'Yse' is not a valid sensitive")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with scheme_type: Direct access Hostel. 'Direct access Hostel' is not a valid scheme_type")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with owning_organisation: non existing org. Organisation with name non existing org is not in the database or is not related to current organisation")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with arrangement_type: wrong answer. 'wrong answer' is not a valid arrangement_type")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with primary_client_group: FD. 'FD' is not a valid primary_client_group")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with has_other_client_group: no. 'no' is not a valid has_other_client_group")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with secondary_client_group: lder people with support needs. 'lder people with support needs' is not a valid secondary_client_group")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with support_type: high. 'high' is not a valid support_type")
expect(Rails.logger).to receive(:info).with("Cannot update scheme S#{schemes[2].id} with intended_stay: Permanent . 'Permanent ' is not a valid intended_stay")
expect(Rails.logger).to receive(:info).with("No changes to scheme S#{schemes[2].id}.")
expect(Rails.logger).to receive(:info).with("Scheme with id Wrong_id is not in the original scheme csv")
expect(Rails.logger).to receive(:info).with("Scheme with id SWrong_id is not in the database")
task.invoke(original_schemes_csv_path, updated_schemes_csv_path)
end
end
end
describe ":update_locations_from_csv", type: :task do
subject(:task) { Rake::Task["bulk_update:update_locations_from_csv"] }
let(:instance_name) { "import_instance" }
let(:storage_service) { instance_double(Storage::S3Service) }
let(:env_config_service) { instance_double(Configuration::EnvConfigurationService) }
before do
Rake.application.rake_require("tasks/update_schemes_and_locations_from_csv")
Rake::Task.define_task(:environment)
task.reenable
end
context "when the rake task is run" do
let(:original_locations_csv_path) { "original_locations.csv" }
let(:updated_locations_csv_path) { "updated_locations.csv" }
let(:wrong_file_path) { "/test/no_csv_here.csv" }
let!(:scheme) { FactoryBot.create(:scheme, service_name: "Scheme 1") }
let!(:different_scheme) { FactoryBot.create(:scheme, service_name: "Different scheme", owning_organisation: scheme.owning_organisation) }
let(:locations) do
create_list(:location,
3,
postcode: "SW1A 2AA",
name: "Downing Street",
type_of_unit: "Self-contained house",
units: 20,
mobility_type: "Fitted with equipment and adaptations",
location_code: "E08000010",
location_admin_district: "Wigan",
startdate: Time.zone.local(2022, 4, 1),
confirmed: true,
updated_at: Time.zone.local(2022, 3, 1),
scheme:)
end
let!(:lettings_log) { FactoryBot.create(:lettings_log, :sh, location: locations[0], scheme:, values_updated_at: nil, startdate: Time.zone.local(2023, 4, 4)) }
let!(:lettings_log_2) { FactoryBot.create(:lettings_log, :sh, location: locations[1], scheme:, values_updated_at: nil, startdate: Time.zone.local(2023, 4, 4)) }
let!(:lettings_log_3) { FactoryBot.create(:lettings_log, :sh, location: locations[2], scheme:, values_updated_at: nil, startdate: Time.zone.local(2023, 4, 4)) }
let!(:lettings_log_4) { FactoryBot.create(:lettings_log, :sh, location: locations[0], scheme:, values_updated_at: nil, startdate: Time.zone.local(2023, 4, 4)) }
let!(:lettings_log_5) { FactoryBot.create(:lettings_log, :sh, location: locations[0], scheme:, values_updated_at: nil, startdate: Time.zone.local(2023, 4, 4)) }
before do
allow(storage_service).to receive(:get_file_io)
.with("original_locations.csv")
.and_return(StringIO.new(replace_entity_ids_for_locations(locations[0], locations[1], locations[2], scheme, scheme, scheme, File.open("./spec/fixtures/files/original_locations.csv").read)))
allow(storage_service).to receive(:get_file_io)
.with("updated_locations.csv")
.and_return(StringIO.new(replace_entity_ids_for_locations(locations[0], locations[1], locations[2], different_scheme, scheme, { id: "non existent scheme id" }, File.open("./spec/fixtures/files/updated_locations.csv").read)))
end
it "updates the allowed location fields if they have changed and doesn't update other fields" do
task.invoke(original_locations_csv_path, updated_locations_csv_path)
locations[0].reload
expect(locations[0].postcode).to eq("B1 1BB")
expect(locations[0].name).to eq("Updated name")
expect(locations[0].type_of_unit).to eq("Bungalow")
expect(locations[0].units).to eq(10)
expect(locations[0].mobility_type).to eq("Wheelchair-user standard")
expect(locations[0].location_code).to eq("E09000033")
expect(locations[0].location_admin_district).to eq("Westminster")
expect(locations[0].scheme).to eq(different_scheme)
end
it "does not update the location if it hasn't changed" do
task.invoke(original_locations_csv_path, updated_locations_csv_path)
locations[1].reload
expect(locations[1].postcode).to eq("SW1A 2AA")
expect(locations[1].name).to eq("Downing Street")
expect(locations[1].type_of_unit).to eq("Self-contained house")
expect(locations[1].units).to eq(20)
expect(locations[1].mobility_type).to eq("Fitted with equipment and adaptations")
expect(locations[1].location_code).to eq("E08000010")
expect(locations[1].location_admin_district).to eq("Wigan")
expect(locations[1].scheme).to eq(scheme)
end
it "does not update the location with invalid values" do
task.invoke(original_locations_csv_path, updated_locations_csv_path)
locations[2].reload
expect(locations[2].postcode).to eq("SW1A 2AA")
expect(locations[2].name).to eq("Downing Street")
expect(locations[2].type_of_unit).to eq("Self-contained house")
expect(locations[2].units).to eq(20)
expect(locations[2].mobility_type).to eq("Fitted with equipment and adaptations")
expect(locations[2].location_code).to eq("E08000010")
expect(locations[2].location_admin_district).to eq("Wigan")
expect(locations[2].scheme).to eq(scheme)
end
it "does not update the scheme id if the new scheme is not in the same or related organisation as the old scheme" do
different_scheme.update!(owning_organisation: FactoryBot.create(:organisation))
task.invoke(original_locations_csv_path, updated_locations_csv_path)
locations[0].reload
expect(locations[0].scheme).not_to eq(different_scheme)
end
it "only re-exports the logs for the locations that have been updated" do
lettings_log_4.startdate = Time.zone.local(2022, 4, 1)
lettings_log_4.save!(validate: false)
lettings_log_5.startdate = Time.zone.local(2021, 4, 1)
lettings_log_5.save!(validate: false)
task.invoke(original_locations_csv_path, updated_locations_csv_path)
lettings_log.reload
expect(lettings_log.values_updated_at).not_to eq(nil)
lettings_log_2.reload
expect(lettings_log_2.values_updated_at).to eq(nil)
lettings_log_3.reload
expect(lettings_log_3.values_updated_at).to eq(nil)
lettings_log_4.reload
expect(lettings_log_4.values_updated_at).not_to eq(nil)
lettings_log_5.reload
expect(lettings_log_5.values_updated_at).to eq(nil)
end
it "logs the progress of the update" do
lettings_log_4.startdate = Time.zone.local(2022, 4, 1)
lettings_log_4.save!(validate: false)
lettings_log_5.startdate = Time.zone.local(2021, 4, 1)
lettings_log_5.save!(validate: false)
expect(Rails.logger).to receive(:info).with("Updating location #{locations[0].id} with scheme: S#{different_scheme.id}")
expect(Rails.logger).to receive(:info).with("Clearing location and scheme for logs with startdate and location #{locations[0].id}. Log IDs: #{lettings_log.id}")
expect(Rails.logger).to receive(:info).with("Clearing location and scheme for logs without startdate and location #{locations[0].id}. Log IDs: ")
expect(Rails.logger).to receive(:info).with("Clearing location and scheme for non editable logs with location #{locations[0].id}. Log IDs: #{lettings_log_4.id}")
expect(Rails.logger).to receive(:info).with("Updating location #{locations[0].id} with postcode: B11BB")
expect(Rails.logger).to receive(:info).with("Updating location #{locations[0].id} with name: Updated name")
expect(Rails.logger).to receive(:info).with("Updating location #{locations[0].id} with location_code: E09000033")
expect(Rails.logger).to receive(:info).with("Updating location #{locations[0].id} with type_of_unit: Bungalow")
expect(Rails.logger).to receive(:info).with("Updating location #{locations[0].id} with units: 10")
expect(Rails.logger).to receive(:info).with("Updating location #{locations[0].id} with mobility_type: Wheelchair-user standard")
expect(Rails.logger).to receive(:info).with("Cannot update location #{locations[0].id} with status as it it not a permitted field")
expect(Rails.logger).to receive(:info).with("Cannot update location #{locations[0].id} with active_dates as it it not a permitted field")
expect(Rails.logger).to receive(:info).with("Saved location #{locations[0].id}.")
expect(Rails.logger).to receive(:info).with("Will not export log #{lettings_log_5.id} as it is before the exportable date")
expect(Rails.logger).to receive(:info).with("No changes to location #{locations[1].id}.")
expect(Rails.logger).to receive(:info).with("Cannot update location #{locations[2].id} with postcode: SWAAA. Enter a postcode in the correct format, for example AA1 1AA")
expect(Rails.logger).to receive(:info).with("Cannot update location #{locations[2].id} with scheme_code: S. Scheme with id S is not in the database")
expect(Rails.logger).to receive(:info).with("Cannot update location #{locations[2].id} with location_admin_district: Westminst. Location admin distrint Westminst is not a valid option")
expect(Rails.logger).to receive(:info).with("Cannot update location #{locations[2].id} with type_of_unit: elf-contained house. 'elf-contained house' is not a valid type_of_unit")
expect(Rails.logger).to receive(:info).with("Cannot update location #{locations[2].id} with mobility_type: 55. '55' is not a valid mobility_type")
expect(Rails.logger).to receive(:info).with("Cannot update location #{locations[2].id} with status as it it not a permitted field")
expect(Rails.logger).to receive(:info).with("No changes to location #{locations[2].id}.")
expect(Rails.logger).to receive(:info).with("Location with id Wrong_id is not in the original location csv")
expect(Rails.logger).to receive(:info).with("Location with id SWrong_id is not in the database")
task.invoke(original_locations_csv_path, updated_locations_csv_path)
end
it "raises an error when no paths are given" do
expect { task.invoke(nil) }.to raise_error(RuntimeError, "Usage: rake bulk_update:update_locations_from_csv['original_file_name','updated_file_name']")
end
it "raises an error when no original path is given" do
expect { task.invoke(nil, updated_locations_csv_path) }.to raise_error(RuntimeError, "Usage: rake bulk_update:update_locations_from_csv['original_file_name','updated_file_name']")
end
it "raises an error when no updated path is given" do
expect { task.invoke(original_locations_csv_path, nil) }.to raise_error(RuntimeError, "Usage: rake bulk_update:update_locations_from_csv['original_file_name','updated_file_name']")
end
context "when updating LA" do
before do
LaRentRange.create!(
ranges_rent_id: "1",
la: "E09000033",
beds: 0,
lettype: 8,
soft_min: 12.41,
soft_max: 89.54,
hard_min: 9.87,
hard_max: 100.99,
start_year: 2023,
)
end
context "when new LA does not trigger hard rent ranges validations" do
let!(:lettings_log) do
FactoryBot.create(:lettings_log,
:completed,
:sh,
location: locations[0],
scheme:,
values_updated_at: nil,
owning_organisation: scheme.owning_organisation,
brent: 80,
scharge: 50,
pscharge: 50,
supcharg: 50,
beds: 4,
lettype: 1,
period: 1)
end
before do
allow(storage_service).to receive(:get_file_io)
.with("updated_locations.csv")
.and_return(StringIO.new(replace_entity_ids_for_locations(locations[0], locations[1], locations[2], scheme, scheme, { id: "non existent scheme id" }, File.open("./spec/fixtures/files/updated_locations.csv").read)))
end
it "does not clear the charges values" do
expect(lettings_log.status).to eq("completed")
task.invoke(original_locations_csv_path, updated_locations_csv_path)
lettings_log.reload
expect(lettings_log.status).to eq("completed")
expect(lettings_log.brent).to eq(80)
expect(lettings_log.scharge).to eq(50)
expect(lettings_log.pscharge).to eq(50)
expect(lettings_log.supcharg).to eq(50)
end
end
context "when new LA triggers hard rent ranges validation" do
let!(:lettings_log) do
FactoryBot.create(:lettings_log,
:completed,
:sh,
location: locations[0],
scheme:,
values_updated_at: nil,
owning_organisation: scheme.owning_organisation,
brent: 200,
scharge: 50,
pscharge: 50,
supcharg: 50,
beds: 4,
lettype: 1,
period: 1)
end
before do
allow(storage_service).to receive(:get_file_io)
.with("updated_locations.csv")
.and_return(StringIO.new(replace_entity_ids_for_locations(locations[0], locations[1], locations[2], scheme, scheme, { id: "non existent scheme id" }, File.open("./spec/fixtures/files/updated_locations.csv").read)))
end
it "clears the charges values" do
expect(lettings_log.status).to eq("completed")
task.invoke(original_locations_csv_path, updated_locations_csv_path)
lettings_log.reload
expect(lettings_log.status).to eq("in_progress")
expect(lettings_log.brent).to be_nil
expect(lettings_log.scharge).to be_nil
expect(lettings_log.pscharge).to be_nil
expect(lettings_log.supcharg).to be_nil
end
end
context "when new LA triggers soft rent ranges validations" do
let!(:lettings_log) do
FactoryBot.create(:lettings_log,
:completed,
:sh,
location: locations[0],
scheme:,
values_updated_at: nil,
owning_organisation: scheme.owning_organisation,
brent: 100,
scharge: 50,
pscharge: 50,
supcharg: 50,
beds: 4,
lettype: 1,
period: 1)
end
before do
allow(storage_service).to receive(:get_file_io)
.with("updated_locations.csv")
.and_return(StringIO.new(replace_entity_ids_for_locations(locations[0], locations[1], locations[2], scheme, scheme, { id: "non existent scheme id" }, File.open("./spec/fixtures/files/updated_locations.csv").read)))
end
it "does not clear the charges values and marks the log in progress" do
expect(lettings_log.status).to eq("completed")
task.invoke(original_locations_csv_path, updated_locations_csv_path)
lettings_log.reload
expect(lettings_log.status).to eq("in_progress")
expect(lettings_log.rent_value_check).to eq(nil)
expect(lettings_log.brent).to eq(100)
expect(lettings_log.scharge).to eq(50)
expect(lettings_log.pscharge).to eq(50)
expect(lettings_log.supcharg).to eq(50)
end
end
context "when new LA triggers soft rent ranges validations for closed collection period" do
let!(:lettings_log) do
FactoryBot.create(:lettings_log,
:completed,
:sh,
location: locations[0],
scheme:,
values_updated_at: nil,
owning_organisation: scheme.owning_organisation,
brent: 100,
scharge: 50,
pscharge: 50,
supcharg: 50,
beds: 4,
lettype: 1,
voiddate: Time.zone.local(2020, 4, 1),
mrcdate: Time.zone.local(2020, 4, 1),
period: 1)
end
before do
LaRentRange.create!(
ranges_rent_id: "1",
la: "E09000033",
beds: 0,
lettype: 8,
soft_min: 12.41,
soft_max: 89.54,
hard_min: 9.87,
hard_max: 100.99,
start_year: 2022,
)
allow(storage_service).to receive(:get_file_io)
.with("updated_locations.csv")
.and_return(StringIO.new(replace_entity_ids_for_locations(locations[0], locations[1], locations[2], scheme, scheme, { id: "non existent scheme id" }, File.open("./spec/fixtures/files/updated_locations.csv").read)))
lettings_log.startdate = Time.zone.local(2022, 4, 1)
lettings_log.owning_organisation = scheme.owning_organisation
lettings_log.save!(validate: false)
end
it "does not clear the charges values and confirms the rent value check" do
expect(lettings_log.status).to eq("completed")
task.invoke(original_locations_csv_path, updated_locations_csv_path)
lettings_log.reload
expect(lettings_log.status).to eq("completed")
expect(lettings_log.rent_value_check).to eq(0)
expect(lettings_log.brent).to eq(100)
expect(lettings_log.scharge).to eq(50)
expect(lettings_log.pscharge).to eq(50)
expect(lettings_log.supcharg).to eq(50)
end
end
end
end
end
end

46
spec/models/form/lettings/questions/homeless_spec.rb

@ -0,0 +1,46 @@
require "rails_helper"
RSpec.describe Form::Lettings::Questions::Homeless, type: :model do
subject(:question) { described_class.new(nil, nil, page) }
let(:page) { instance_double(Form::Page) }
it "has correct page" do
expect(question.page).to eq(page)
end
it "has the correct id" do
expect(question.id).to eq("homeless")
end
it "has the correct header" do
expect(question.header).to eq("Did the household experience homelessness immediately before this letting?")
end
it "has the correct check_answer_label" do
expect(question.check_answer_label).to eq("Household homeless immediately before letting")
end
it "has the correct type" do
expect(question.type).to eq("radio")
end
it "is not marked as derived" do
expect(question.derived?).to be false
end
it "has the correct answer_options" do
expect(question.answer_options).to eq({
"11" => { "value" => "Yes - assessed by a local authority as homeless" },
"1" => { "value" => "No" },
})
end
it "has no hint text" do
expect(question.hint_text).to be_empty
end
it "has the correct check_answers_card_number" do
expect(question.check_answers_card_number).to eq(0)
end
end
Loading…
Cancel
Save