From 00abcf471397dfde8cabbb3323089065af44350d Mon Sep 17 00:00:00 2001 From: Kat Date: Mon, 2 Oct 2023 15:24:01 +0100 Subject: [PATCH] Add sales csv rake task --- lib/tasks/send_missing_addresses_csv.rake | 42 +++- spec/factories/sales_log.rb | 3 + .../tasks/send_missing_addresses_csv_spec.rb | 237 +++++++++++++++++- 3 files changed, 270 insertions(+), 12 deletions(-) diff --git a/lib/tasks/send_missing_addresses_csv.rake b/lib/tasks/send_missing_addresses_csv.rake index dbadf8463..beddc4995 100644 --- a/lib/tasks/send_missing_addresses_csv.rake +++ b/lib/tasks/send_missing_addresses_csv.rake @@ -3,8 +3,8 @@ namespace :correct_addresses do MISSING_ADDRESSES_THRESHOLD = 50 # rubocop:enable Lint/ConstantDefinitionInBlock - desc "Send missing addresses csv" - task :send_missing_addresses_csv, %i[] => :environment do |_task, _args| + desc "Send missing lettings addresses csv" + task :send_missing_addresses_lettings_csv, %i[] => :environment do |_task, _args| Organisation.all.each do |organisation| logs_impacted_by_missing_address = organisation.managed_lettings_logs .imported @@ -33,7 +33,43 @@ namespace :correct_addresses do data_coordinators = organisation.users.where(role: 2).filter_by_active users_to_contact = data_coordinators.any? ? data_coordinators : organisation.users.filter_by_active EmailMissingAddressesCsvJob.perform_later(users_to_contact.map(&:id), organisation, "lettings") - Rails.logger.info("Sending missing addresses CSV for #{organisation.name} to #{users_to_contact.map(&:email).join(', ')}") + Rails.logger.info("Sending missing lettings addresses CSV for #{organisation.name} to #{users_to_contact.map(&:email).join(', ')}") + else + Rails.logger.info("Missing addresses below threshold for #{organisation.name}") + end + end + end + + desc "Send missing sales addresses csv" + task :send_missing_addresses_sales_csv, %i[] => :environment do |_task, _args| + Organisation.all.each do |organisation| + logs_impacted_by_missing_address = organisation.sales_logs + .imported + .filter_by_year(2023) + .where(address_line1: nil, town_or_city: nil, uprn_known: [0, nil]) + .where.not(old_form_id: nil).count + + logs_impacted_by_missing_town_or_city = organisation.sales_logs + .imported + .filter_by_year(2023) + .where(town_or_city: nil, uprn_known: [0, nil]) + .where.not(old_form_id: nil) + .where.not(address_line1: nil).count + + logs_impacted_by_uprn_issue = if JSON.parse(ENV["SKIP_UPRN_ISSUE_ORG_IDS"]).include?(organisation.id) + [] + else + organisation.sales_logs + .imported + .filter_by_year(2023) + .where.not(uprn: nil) + .where("uprn = purchid or town_or_city = 'Bristol'") + end + if logs_impacted_by_missing_address >= MISSING_ADDRESSES_THRESHOLD || logs_impacted_by_missing_town_or_city >= MISSING_ADDRESSES_THRESHOLD || logs_impacted_by_uprn_issue.any? + data_coordinators = organisation.users.where(role: 2).filter_by_active + users_to_contact = data_coordinators.any? ? data_coordinators : organisation.users.filter_by_active + EmailMissingAddressesCsvJob.perform_later(users_to_contact.map(&:id), organisation, "sales") + Rails.logger.info("Sending missing sales addresses CSV for #{organisation.name} to #{users_to_contact.map(&:email).join(', ')}") else Rails.logger.info("Missing addresses below threshold for #{organisation.name}") end diff --git a/spec/factories/sales_log.rb b/spec/factories/sales_log.rb index 177ed600c..4835d738e 100644 --- a/spec/factories/sales_log.rb +++ b/spec/factories/sales_log.rb @@ -155,5 +155,8 @@ FactoryBot.define do status { 4 } discarded_at { Time.zone.now } end + trait :imported do + old_id { rand(1...99_999) } + end end end diff --git a/spec/lib/tasks/send_missing_addresses_csv_spec.rb b/spec/lib/tasks/send_missing_addresses_csv_spec.rb index 9181c1036..54afab054 100644 --- a/spec/lib/tasks/send_missing_addresses_csv_spec.rb +++ b/spec/lib/tasks/send_missing_addresses_csv_spec.rb @@ -2,8 +2,8 @@ require "rails_helper" require "rake" RSpec.describe "correct_addresses" do - describe ":send_missing_addresses_csv", type: :task do - subject(:task) { Rake::Task["correct_addresses:send_missing_addresses_csv"] } + describe ":send_missing_addresses_lettings_csv", type: :task do + subject(:task) { Rake::Task["correct_addresses:send_missing_addresses_lettings_csv"] } before do organisation.users.destroy_all @@ -64,7 +64,7 @@ RSpec.describe "correct_addresses" do it "prints out the jobs enqueued" do expect(Rails.logger).to receive(:info).with(nil) - expect(Rails.logger).to receive(:info).with("Sending missing addresses CSV for test organisation to data_coordinator1@example.com, data_coordinator2@example.com") + expect(Rails.logger).to receive(:info).with("Sending missing lettings addresses CSV for test organisation to data_coordinator1@example.com, data_coordinator2@example.com") task.invoke end end @@ -83,7 +83,7 @@ RSpec.describe "correct_addresses" do it "prints out the jobs enqueued" do expect(Rails.logger).to receive(:info).with(nil) - expect(Rails.logger).to receive(:info).with("Sending missing addresses CSV for test organisation to data_provider3@example.com, data_provider4@example.com") + expect(Rails.logger).to receive(:info).with("Sending missing lettings addresses CSV for test organisation to data_provider3@example.com, data_provider4@example.com") task.invoke end end @@ -114,7 +114,7 @@ RSpec.describe "correct_addresses" do it "prints out the jobs enqueued" do expect(Rails.logger).to receive(:info).with(nil) - expect(Rails.logger).to receive(:info).with("Sending missing addresses CSV for test organisation to data_coordinator1@example.com, data_coordinator2@example.com") + expect(Rails.logger).to receive(:info).with("Sending missing lettings addresses CSV for test organisation to data_coordinator1@example.com, data_coordinator2@example.com") task.invoke end end @@ -133,7 +133,7 @@ RSpec.describe "correct_addresses" do it "prints out the jobs enqueued" do expect(Rails.logger).to receive(:info).with(nil) - expect(Rails.logger).to receive(:info).with("Sending missing addresses CSV for test organisation to data_provider3@example.com, data_provider4@example.com") + expect(Rails.logger).to receive(:info).with("Sending missing lettings addresses CSV for test organisation to data_provider3@example.com, data_provider4@example.com") task.invoke end end @@ -164,7 +164,7 @@ RSpec.describe "correct_addresses" do it "prints out the jobs enqueued" do expect(Rails.logger).to receive(:info).with(nil) - expect(Rails.logger).to receive(:info).with("Sending missing addresses CSV for test organisation to data_coordinator1@example.com, data_coordinator2@example.com") + expect(Rails.logger).to receive(:info).with("Sending missing lettings addresses CSV for test organisation to data_coordinator1@example.com, data_coordinator2@example.com") task.invoke end end @@ -183,7 +183,7 @@ RSpec.describe "correct_addresses" do it "prints out the jobs enqueued" do expect(Rails.logger).to receive(:info).with(nil) - expect(Rails.logger).to receive(:info).with("Sending missing addresses CSV for test organisation to data_provider3@example.com, data_provider4@example.com") + expect(Rails.logger).to receive(:info).with("Sending missing lettings addresses CSV for test organisation to data_provider3@example.com, data_provider4@example.com") task.invoke end end @@ -203,7 +203,7 @@ RSpec.describe "correct_addresses" do it "prints out the jobs enqueued" do expect(Rails.logger).to receive(:info).with(nil) - expect(Rails.logger).to receive(:info).with("Sending missing addresses CSV for test organisation to data_provider3@example.com, data_provider4@example.com") + expect(Rails.logger).to receive(:info).with("Sending missing lettings addresses CSV for test organisation to data_provider3@example.com, data_provider4@example.com") task.invoke end end @@ -220,4 +220,223 @@ RSpec.describe "correct_addresses" do end end end + + describe ":send_missing_addresses_sales_csv", type: :task do + subject(:task) { Rake::Task["correct_addresses:send_missing_addresses_sales_csv"] } + + before do + organisation.users.destroy_all + Rake.application.rake_require("tasks/send_missing_addresses_csv") + Rake::Task.define_task(:environment) + task.reenable + + body_1 = { + results: [ + { + DPA: { + "POSTCODE": "BS1 1AD", + "POST_TOWN": "Bristol", + "ORGANISATION_NAME": "Some place", + }, + }, + ], + }.to_json + + body_2 = { + results: [ + { + DPA: { + "POSTCODE": "EC1N 2TD", + "POST_TOWN": "Newcastle", + "ORGANISATION_NAME": "Some place", + }, + }, + ], + }.to_json + + stub_request(:get, "https://api.os.uk/search/places/v1/uprn?key=OS_DATA_KEY&uprn=123") + .to_return(status: 200, body: body_1, headers: {}) + + stub_request(:get, "https://api.os.uk/search/places/v1/uprn?key=OS_DATA_KEY&uprn=12") + .to_return(status: 200, body: body_2, headers: {}) + end + + context "when the rake task is run" do + let(:organisation) { create(:organisation, name: "test organisation") } + + before do + stub_const("MISSING_ADDRESSES_THRESHOLD", 5) + end + + context "when org has more than 5 missing addresses and data coordinators" do + let!(:data_coordinator) { create(:user, :data_coordinator, organisation:, email: "data_coordinator1@example.com") } + let!(:data_coordinator2) { create(:user, :data_coordinator, organisation:, email: "data_coordinator2@example.com") } + + before do + create(:user, :data_provider, organisation:, email: "data_provider1@example.com") + create_list(:sales_log, 7, :completed, :imported, saledate: Time.zone.local(2023, 9, 9), address_line1: nil, town_or_city: nil, old_form_id: "form_1", owning_organisation: organisation, created_by: organisation.users.first) + end + + it "enqueues the job with correct organisations" do + expect { task.invoke }.to enqueue_job(EmailMissingAddressesCsvJob).with(include(data_coordinator.id, data_coordinator2.id), organisation, "sales") + end + + it "prints out the jobs enqueued" do + expect(Rails.logger).to receive(:info).with(nil) + expect(Rails.logger).to receive(:info).with("Sending missing sales addresses CSV for test organisation to data_coordinator1@example.com, data_coordinator2@example.com") + task.invoke + end + end + + context "when org has 5 missing addresses and data providers only" do + let!(:data_provider) { create(:user, :data_provider, organisation:, email: "data_provider3@example.com") } + let!(:data_provider2) { create(:user, :data_provider, organisation:, email: "data_provider4@example.com") } + + before do + create_list(:sales_log, 5, :completed, :imported, saledate: Time.zone.local(2023, 9, 9), address_line1: nil, town_or_city: nil, old_form_id: "form_2", owning_organisation: organisation, created_by: organisation.users.first) + end + + it "enqueues the job with correct organisations" do + expect { task.invoke }.to enqueue_job(EmailMissingAddressesCsvJob).with(include(data_provider.id, data_provider2.id), organisation, "sales") + end + + it "prints out the jobs enqueued" do + expect(Rails.logger).to receive(:info).with(nil) + expect(Rails.logger).to receive(:info).with("Sending missing sales addresses CSV for test organisation to data_provider3@example.com, data_provider4@example.com") + task.invoke + end + end + + context "when org has less than 5 missing addresses" do + before do + create_list(:sales_log, 3, :completed, :imported, saledate: Time.zone.local(2023, 9, 9), address_line1: nil, town_or_city: nil, old_form_id: "form_2", owning_organisation: organisation, created_by: organisation.users.first) + create_list(:sales_log, 2, :completed, :imported, saledate: Time.zone.local(2023, 9, 9), address_line1: nil, owning_organisation: organisation, created_by: organisation.users.first) + end + + it "does not enqueue the job with organisations that is missing less addresses than threshold amount" do + expect { task.invoke }.not_to enqueue_job(EmailMissingAddressesCsvJob) + end + end + + context "when org has more than 5 missing town_or_city and data coordinators" do + let!(:data_coordinator) { create(:user, :data_coordinator, organisation:, email: "data_coordinator1@example.com") } + let!(:data_coordinator2) { create(:user, :data_coordinator, organisation:, email: "data_coordinator2@example.com") } + + before do + create(:user, :data_provider, organisation:, email: "data_provider1@example.com") + create_list(:sales_log, 7, :completed, :imported, saledate: Time.zone.local(2023, 9, 9), address_line1: "exists", town_or_city: nil, old_form_id: "form_1", owning_organisation: organisation, created_by: organisation.users.first) + end + + it "enqueues the job with correct organisations" do + expect { task.invoke }.to enqueue_job(EmailMissingAddressesCsvJob).with(include(data_coordinator.id, data_coordinator2.id), organisation, "sales") + end + + it "prints out the jobs enqueued" do + expect(Rails.logger).to receive(:info).with(nil) + expect(Rails.logger).to receive(:info).with("Sending missing sales addresses CSV for test organisation to data_coordinator1@example.com, data_coordinator2@example.com") + task.invoke + end + end + + context "when org has 5 missing town or city and data providers only" do + let!(:data_provider) { create(:user, :data_provider, organisation:, email: "data_provider3@example.com") } + let!(:data_provider2) { create(:user, :data_provider, organisation:, email: "data_provider4@example.com") } + + before do + create_list(:sales_log, 5, :completed, :imported, saledate: Time.zone.local(2023, 9, 9), address_line1: "exists", town_or_city: nil, old_form_id: "form_2", owning_organisation: organisation, created_by: organisation.users.first) + end + + it "enqueues the job with correct organisations" do + expect { task.invoke }.to enqueue_job(EmailMissingAddressesCsvJob).with(include(data_provider.id, data_provider2.id), organisation, "sales") + end + + it "prints out the jobs enqueued" do + expect(Rails.logger).to receive(:info).with(nil) + expect(Rails.logger).to receive(:info).with("Sending missing sales addresses CSV for test organisation to data_provider3@example.com, data_provider4@example.com") + task.invoke + end + end + + context "when org has less than 5 missing town or city" do + before do + create_list(:sales_log, 3, :completed, :imported, saledate: Time.zone.local(2023, 9, 9), address_line1: "address", town_or_city: nil, old_form_id: "form_2", owning_organisation: organisation, created_by: organisation.users.first) + create_list(:sales_log, 2, :completed, :imported, saledate: Time.zone.local(2023, 9, 9), address_line1: "address", owning_organisation: organisation, created_by: organisation.users.first) + end + + it "does not enqueue the job with organisations that is missing less town or city data than threshold amount" do + expect { task.invoke }.not_to enqueue_job(EmailMissingAddressesCsvJob) + end + end + + context "when org has more than 5 wrong uprn and data coordinators" do + let!(:data_coordinator) { create(:user, :data_coordinator, organisation:, email: "data_coordinator1@example.com") } + let!(:data_coordinator2) { create(:user, :data_coordinator, organisation:, email: "data_coordinator2@example.com") } + + before do + create(:user, :data_provider, organisation:, email: "data_provider1@example.com") + create_list(:sales_log, 7, :completed, :imported, saledate: Time.zone.local(2023, 9, 9), uprn_known: 1, uprn: "123", town_or_city: "Bristol", owning_organisation: organisation, created_by: organisation.users.first) + end + + it "enqueues the job with correct organisations" do + expect { task.invoke }.to enqueue_job(EmailMissingAddressesCsvJob).with(include(data_coordinator.id, data_coordinator2.id), organisation, "sales") + end + + it "prints out the jobs enqueued" do + expect(Rails.logger).to receive(:info).with(nil) + expect(Rails.logger).to receive(:info).with("Sending missing sales addresses CSV for test organisation to data_coordinator1@example.com, data_coordinator2@example.com") + task.invoke + end + end + + context "when org has 5 wrong uprn and data providers only" do + let!(:data_provider) { create(:user, :data_provider, organisation:, email: "data_provider3@example.com") } + let!(:data_provider2) { create(:user, :data_provider, organisation:, email: "data_provider4@example.com") } + + before do + create_list(:sales_log, 5, :completed, :imported, saledate: Time.zone.local(2023, 9, 9), uprn_known: 1, uprn: "12", purchid: "12", owning_organisation: organisation, created_by: organisation.users.first) + end + + it "enqueues the job with correct organisations" do + expect { task.invoke }.to enqueue_job(EmailMissingAddressesCsvJob).with(include(data_provider.id, data_provider2.id), organisation, "sales") + end + + it "prints out the jobs enqueued" do + expect(Rails.logger).to receive(:info).with(nil) + expect(Rails.logger).to receive(:info).with("Sending missing sales addresses CSV for test organisation to data_provider3@example.com, data_provider4@example.com") + task.invoke + end + end + + context "when org has less than 5 wrong uprn" do + let!(:data_provider) { create(:user, :data_provider, organisation:, email: "data_provider3@example.com") } + let!(:data_provider2) { create(:user, :data_provider, organisation:, email: "data_provider4@example.com") } + + before do + create_list(:sales_log, 3, :completed, :imported, saledate: Time.zone.local(2023, 9, 9), uprn_known: 1, uprn: "123", town_or_city: "Bristol", owning_organisation: organisation, created_by: organisation.users.first) + create_list(:sales_log, 2, :completed, :imported, saledate: Time.zone.local(2023, 9, 9), uprn_known: 1, uprn: "12", purchid: "12", owning_organisation: organisation, created_by: organisation.users.first) + end + + it "enqueues the job with correct organisations" do + expect { task.invoke }.to enqueue_job(EmailMissingAddressesCsvJob).with(include(data_provider.id, data_provider2.id), organisation, "sales") + end + + it "prints out the jobs enqueued" do + expect(Rails.logger).to receive(:info).with(nil) + expect(Rails.logger).to receive(:info).with("Sending missing sales addresses CSV for test organisation to data_provider3@example.com, data_provider4@example.com") + task.invoke + end + end + + context "when org is included in SKIP_UPRN_ISSUE_ORG_IDS list" do + before do + create_list(:sales_log, 5, :completed, :imported, saledate: Time.zone.local(2023, 9, 9), uprn_known: 1, uprn: "12", purchid: "12", owning_organisation: organisation, created_by: organisation.users.first) + allow(ENV).to receive(:[]).with("SKIP_UPRN_ISSUE_ORG_IDS").and_return([organisation.id].to_json) + end + + it "does not enqueue the job" do + expect { task.invoke }.not_to enqueue_job(EmailMissingAddressesCsvJob) + end + end + end + end end