Browse Source

CLDC-3087 Bulk update schemes and locations (#2144)

* Update schemes from csv

* Handle validation errors

* update locations from csv

* Export logs using updated schemes and locations

* Refactor

* Only update owning org to related ort

* Update logs

* Log and not update old logs

* do not update the org with closed collection logs

* Do not export old logs with changed location

* Rename logs and refactor tests

* Handle rent ranges for open collection periods

* Log ids for logs that turn in progress

* Allow changing scheme to the one from related org

* log updates logs and don't mark them unesolved

* Clear scheme/location if location scheme changes

* Check soft rent validation for closed collection

* Clear location/scheme in remaining exportable logs

* Log updates before clearing locations and schemes
pull/2270/head^2
kosiakkatrina 10 months ago committed by GitHub
parent
commit
07cf4e6fc9
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 1
      app/models/lettings_log.rb
  2. 183
      app/services/bulk_update_from_csv/update_locations_from_csv_service.rb
  3. 121
      app/services/bulk_update_from_csv/update_schemes_from_csv_service.rb
  4. 21
      lib/tasks/update_schemes_and_locations_from_csv.rake
  5. 2
      spec/factories/lettings_log.rb
  6. 5
      spec/fixtures/files/original_locations.csv
  7. 6
      spec/fixtures/files/original_schemes.csv
  8. 6
      spec/fixtures/files/updated_locations.csv
  9. 6
      spec/fixtures/files/updated_schemes.csv
  10. 651
      spec/lib/tasks/update_schemes_and_locations_from_csv_spec.rb

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
Loading…
Cancel
Save