diff --git a/CHANGELOG.md b/CHANGELOG.md index dc1a7954f..4bb318d2a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -21,6 +21,8 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/). finance team - Added a field to enter the date a grant payment certificate was received to the Conversions Receive grant payment certificate task. +- Script to backfill dates in the Conversions Receive grant payment certificate + task ### Changed diff --git a/app/services/import/grant_certificate_date_importer_service.rb b/app/services/import/grant_certificate_date_importer_service.rb new file mode 100644 index 000000000..e78df8420 --- /dev/null +++ b/app/services/import/grant_certificate_date_importer_service.rb @@ -0,0 +1,27 @@ +require "csv" + +class Import::GrantCertificateDateImporterService + def call(csv_path) + CSV.foreach(csv_path, headers: true, header_converters: :symbol) do |row| + urn = row[:urn] + next unless urn + + project = Project.find_by(academy_urn: urn.to_i) + unless project + puts "Unable to find project with academy_urn: #{urn}" + next + end + + tasks_data = project.tasks_data + next unless tasks_data + + date_string = row[:date].to_s + date = Date.strptime(date_string, "%d/%m/%Y") + tasks_data.receive_grant_payment_certificate_date_received = date + tasks_data.save(validate: false) + puts "Updated grant payment certificate date for project with academy_urn: #{urn}" + rescue Date::Error + puts "Date for URN #{urn} is not valid" + end + end +end diff --git a/config/locales/en.yml b/config/locales/en.yml index ea95a34ea..eac81e763 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -76,6 +76,9 @@ en: director_of_child_services_importer: import: error: You must provide a path, e.g. director_of_child_services:import[path/to/data.csv] + grant_payment_certificate_importer: + import: + error: You must provide a path, e.g. project_data:grant_payment_certificate_dates[path/to/data.csv] assignment: assign_regional_delivery_officer: title: Change regional delivery officer for %{school_name} diff --git a/lib/tasks/project_tasks/project_data_import.rake b/lib/tasks/project_tasks/project_data_import.rake new file mode 100644 index 000000000..6687295b5 --- /dev/null +++ b/lib/tasks/project_tasks/project_data_import.rake @@ -0,0 +1,10 @@ +namespace :project_data do + desc ">> Update dates in the Conversion Grant payment certificate task" + task :grant_payment_certificate_dates, [:csv_path] => :environment do |_task, args| + abort I18n.t("tasks.grant_payment_certificate_importer.import.error") if args[:csv_path].nil? + + csv_path = Rails.root.join(args[:csv_path]) + + Import::GrantCertificateDateImporterService.new.call(csv_path) + end +end diff --git a/spec/lib/tasks/project_tasks/project_data_import_spec.rb b/spec/lib/tasks/project_tasks/project_data_import_spec.rb new file mode 100644 index 000000000..5e4750ea3 --- /dev/null +++ b/spec/lib/tasks/project_tasks/project_data_import_spec.rb @@ -0,0 +1,22 @@ +require "rails_helper" + +RSpec.describe "rake project_data:grant_payment_certificate_dates", type: :task do + subject { Rake::Task["project_data:grant_payment_certificate_dates"] } + + let(:csv_path) { "/csv/grant_payment_certificate_dates.csv" } + + before do + allow_any_instance_of(Import::GrantCertificateDateImporterService).to receive(:call) + end + + it "calls GrantCertificateDateImporterService service with the supplied path" do + expect_any_instance_of(Import::GrantCertificateDateImporterService).to receive(:call).with(Pathname.new(csv_path)).once + + subject.invoke(csv_path) + end + + it "errors if no path is supplied" do + expect { subject.execute } + .to raise_error(SystemExit, I18n.t("tasks.grant_payment_certificate_importer.import.error")) + end +end diff --git a/spec/services/import/grant_certificate_date_importer_service_spec.rb b/spec/services/import/grant_certificate_date_importer_service_spec.rb new file mode 100644 index 000000000..da73f759c --- /dev/null +++ b/spec/services/import/grant_certificate_date_importer_service_spec.rb @@ -0,0 +1,90 @@ +require "rails_helper" + +RSpec.describe Import::GrantCertificateDateImporterService do + let(:csv_path) { "/csv/grant_certificate_dates.csv" } + let(:date_importer) { Import::GrantCertificateDateImporterService.new } + let(:date_csv) do + <<~CSV + URN,Date + 149962,09/12/2023 + 150075,17/10/2023 + CSV + end + + before { allow(File).to receive(:open).with(csv_path, any_args).and_return(date_csv) } + + before do + mock_all_academies_api_responses + end + + describe "#call" do + subject(:call_date_importer) { date_importer.call(csv_path) } + + context "when dates are all valid and URNs are all present" do + let(:tasks_data_1) { create(:conversion_tasks_data, receive_grant_payment_certificate_date_received: nil) } + let(:tasks_data_2) { create(:conversion_tasks_data, receive_grant_payment_certificate_date_received: nil) } + let!(:project_1) { create(:conversion_project, academy_urn: 149962, tasks_data: tasks_data_1) } + let!(:project_2) { create(:conversion_project, academy_urn: 150075, tasks_data: tasks_data_2) } + + it "updates all the project tasks_data" do + call_date_importer + + expect(project_1.tasks_data.reload.receive_grant_payment_certificate_date_received).to eq(Date.new(2023, 12, 9)) + expect(project_2.tasks_data.reload.receive_grant_payment_certificate_date_received).to eq(Date.new(2023, 10, 17)) + end + end + + context "when a URN is not valid" do + let(:tasks_data_1) { create(:conversion_tasks_data, receive_grant_payment_certificate_date_received: nil) } + let!(:project_1) { create(:conversion_project, academy_urn: 149962, tasks_data: tasks_data_1) } + + it "updates all other rows" do + call_date_importer + + expect(project_1.tasks_data.reload.receive_grant_payment_certificate_date_received).to eq(Date.new(2023, 12, 9)) + end + end + + context "when a date is not valid" do + let(:tasks_data_1) { create(:conversion_tasks_data, receive_grant_payment_certificate_date_received: nil) } + let(:tasks_data_2) { create(:conversion_tasks_data, receive_grant_payment_certificate_date_received: nil) } + let!(:project_1) { create(:conversion_project, academy_urn: 149962, tasks_data: tasks_data_1) } + let!(:project_2) { create(:conversion_project, academy_urn: 150075, tasks_data: tasks_data_2) } + let(:date_csv) do + <<~CSV + URN,Date + 149962,09/12/2023 + 150075,17/18/2023 + CSV + end + + it "updates all other rows" do + call_date_importer + + expect(project_1.tasks_data.reload.receive_grant_payment_certificate_date_received).to eq(Date.new(2023, 12, 9)) + expect(project_2.tasks_data.reload.receive_grant_payment_certificate_date_received).to be_nil + end + end + + context "when a date is zero" do + let(:tasks_data_1) { create(:conversion_tasks_data, receive_grant_payment_certificate_date_received: nil) } + let(:tasks_data_2) { create(:conversion_tasks_data, receive_grant_payment_certificate_date_received: nil) } + let!(:project_1) { create(:conversion_project, academy_urn: 149962, tasks_data: tasks_data_1) } + let!(:project_2) { create(:conversion_project, academy_urn: 150075, tasks_data: tasks_data_2) } + let(:date_csv) do + <<~CSV + URN,Date + 149962,09/12/2023 + 150075,0 + CSV + end + + it "updates all other rows" do + call_date_importer + + expect(project_1.tasks_data.reload.receive_grant_payment_certificate_date_received).to eq(Date.new(2023, 12, 9)) + expect(project_2.tasks_data.reload.receive_grant_payment_certificate_date_received).to be_nil + end + end + end +end