From 74b1f01fa8337b205569393d6caccd7067a61bfa Mon Sep 17 00:00:00 2001 From: Thomas Leese Date: Wed, 15 Nov 2023 11:14:18 +0000 Subject: [PATCH] Send reminder reference emails --- app/models/application_form.rb | 60 ++++++++-- spec/services/send_reminder_email_spec.rb | 127 ++++++++++++++++----- spec/support/shared_examples/remindable.rb | 4 +- 3 files changed, 149 insertions(+), 42 deletions(-) diff --git a/app/models/application_form.rb b/app/models/application_form.rb index abfbb60d1c..1f52837f1b 100644 --- a/app/models/application_form.rb +++ b/app/models/application_form.rb @@ -220,7 +220,12 @@ class ApplicationForm < ApplicationRecord .or(withdrawn.where("withdrawn_at < ?", 5.years.ago)) end - scope :remindable, -> { draft.where("created_at < ?", 5.months.ago) } + scope :remindable, + -> do + verification_stage.or( + draft_stage.where("created_at < ?", 5.months.ago), + ) + end def to_param reference @@ -262,18 +267,46 @@ def created_under_new_regulations? created_at >= Date.parse(ENV.fetch("NEW_REGS_DATE", "2023-02-01")) end - def should_send_reminder_email?(_name, number_of_reminders_sent) - return false if days_until_expired.nil? || teacher.application_form != self + def reminder_email_names + %w[expiration references] + end - (days_until_expired <= 14 && number_of_reminders_sent.zero?) || - (days_until_expired <= 7 && number_of_reminders_sent == 1) + def should_send_reminder_email?(name, number_of_reminders_sent) + return false if teacher.application_form != self + + case name + when "expiration" + return false if days_until_expired.nil? + + (days_until_expired <= 14 && number_of_reminders_sent.zero?) || + (days_until_expired <= 7 && number_of_reminders_sent == 1) + when "references" + unreviewed_reference_requests.any? do |reference_request| + reference_request.should_send_reminder_email?( + "expiration", + number_of_reminders_sent, + ) + end + end end - def send_reminder_email(_name, number_of_reminders_sent) - TeacherMailer - .with(teacher:, number_of_reminders_sent:) - .application_not_submitted - .deliver_later + def send_reminder_email(name, number_of_reminders_sent) + case name + when "expiration" + TeacherMailer + .with(teacher:, number_of_reminders_sent:) + .application_not_submitted + .deliver_later + when "references" + TeacherMailer + .with( + teacher:, + number_of_reminders_sent:, + reference_requests: unreviewed_reference_requests.to_a, + ) + .references_reminder + .deliver_later + end end def expires_after @@ -293,4 +326,11 @@ def build_documents documents.build(document_type: :english_language_proficiency) documents.build(document_type: :written_statement) end + + def unreviewed_reference_requests + ReferenceRequest + .joins(:work_history) + .where(work_histories: { application_form_id: id }) + .where(received_at: nil, expired_at: nil) + end end diff --git a/spec/services/send_reminder_email_spec.rb b/spec/services/send_reminder_email_spec.rb index e0939ef779..8b6082172b 100644 --- a/spec/services/send_reminder_email_spec.rb +++ b/spec/services/send_reminder_email_spec.rb @@ -16,16 +16,16 @@ end end - shared_examples "sends an email" do + shared_examples "sends an email" do |name| it "logs an email" do expect { call }.to change { - ReminderEmail.where(remindable:, name: "expiration").count + ReminderEmail.where(remindable:, name:).count }.by(1) end end shared_examples "sends a further information reminder email" do - include_examples "sends an email" + include_examples "sends an email", "expiration" it "sends an email" do expect { call }.to have_enqueued_mail( @@ -42,7 +42,7 @@ end shared_examples "sends a reference reminder email" do - include_examples "sends an email" + include_examples "sends an email", "expiration" it "sends an email" do expect { subject }.to have_enqueued_mail( @@ -53,7 +53,7 @@ end shared_examples "sends an application not submitted email" do - include_examples "sends an email" + include_examples "sends an email", "expiration" it "sends an email" do expect { subject }.to have_enqueued_mail( @@ -69,56 +69,68 @@ end end - shared_examples "first reminder email" do |shared_example| + shared_examples "sends an application references reminder email" do + include_examples "sends an email", "references" + + it "sends an email" do + expect { subject }.to have_enqueued_mail( + TeacherMailer, + :references_reminder, + ).with( + params: { + teacher: remindable.teacher, + number_of_reminders_sent: a_kind_of(Integer), + reference_requests: [reference_request], + }, + args: [], + ) + end + end + + shared_examples "first reminder email" do |shared_example, name| context "when no previous reminder has been sent" do include_examples shared_example end context "when a previous reminder has been sent" do - before { remindable.reminder_emails.create!(name: "expiration") } + before { remindable.reminder_emails.create!(name:) } include_examples "doesn't send an email" end context "when two previous reminders have been sent" do - before do - 2.times { remindable.reminder_emails.create!(name: "expiration") } - end + before { 2.times { remindable.reminder_emails.create!(name:) } } include_examples "doesn't send an email" end end - shared_examples "second reminder email" do |shared_example| + shared_examples "second reminder email" do |shared_example, name| context "when no previous reminder has been sent" do include_examples shared_example end context "when one previous reminder has been sent" do - before { remindable.reminder_emails.create!(name: "expiration") } + before { remindable.reminder_emails.create!(name:) } include_examples shared_example end context "when two previous reminders have been sent" do - before do - 2.times { remindable.reminder_emails.create!(name: "expiration") } - end + before { 2.times { remindable.reminder_emails.create!(name:) } } include_examples "doesn't send an email" end end - shared_examples "third reminder email" do |shared_example| + shared_examples "third reminder email" do |shared_example, name| context "when no previous reminder has been sent" do include_examples shared_example end context "when one previous reminder has been sent" do - before { remindable.reminder_emails.create!(name: "expiration") } + before { remindable.reminder_emails.create!(name:) } include_examples shared_example end context "when two previous reminders have been sent" do - before do - 2.times { remindable.reminder_emails.create!(name: "expiration") } - end + before { 2.times { remindable.reminder_emails.create!(name:) } } include_examples shared_example end end @@ -131,13 +143,15 @@ context "with less than two weeks remaining" do let(:application_created_at) { (6.months - 13.days).ago } include_examples "first reminder email", - "sends an application not submitted email" + "sends an application not submitted email", + "expiration" end context "with less than one week remaining" do let(:application_created_at) { (6.months - 1.day).ago } include_examples "second reminder email", - "sends an application not submitted email" + "sends an application not submitted email", + "expiration" end end @@ -150,19 +164,22 @@ context "with less than two weeks remaining" do let(:further_information_requested_at) { (6.weeks - 13.days).ago } include_examples "first reminder email", - "sends a further information reminder email" + "sends a further information reminder email", + "expiration" end context "with less than one week remaining" do let(:further_information_requested_at) { (6.weeks - 5.days).ago } include_examples "second reminder email", - "sends a further information reminder email" + "sends a further information reminder email", + "expiration" end context "with one day remaining" do let(:further_information_requested_at) { (6.weeks - 47.hours).ago } include_examples "third reminder email", - "sends a further information reminder email" + "sends a further information reminder email", + "expiration" end end @@ -170,19 +187,22 @@ context "with less than two weeks remaining" do let(:further_information_requested_at) { (4.weeks - 13.days).ago } include_examples "first reminder email", - "sends a further information reminder email" + "sends a further information reminder email", + "expiration" end context "with less than one week remaining" do let(:further_information_requested_at) { (4.weeks - 5.days).ago } include_examples "second reminder email", - "sends a further information reminder email" + "sends a further information reminder email", + "expiration" end context "with one day remaining" do let(:further_information_requested_at) { (4.weeks - 47.hours).ago } include_examples "third reminder email", - "sends a further information reminder email" + "sends a further information reminder email", + "expiration" end end @@ -276,13 +296,15 @@ context "with less than four weeks remaining" do let(:reference_requested_at) { (6.weeks - 27.days).ago } include_examples "first reminder email", - "sends a reference reminder email" + "sends a reference reminder email", + "expiration" end context "with less than two weeks remaining" do let(:reference_requested_at) { (6.weeks - 13.days).ago } include_examples "second reminder email", - "sends a reference reminder email" + "sends a reference reminder email", + "expiration" end end @@ -299,5 +321,50 @@ end include_examples "doesn't send an email" end + + context "with a teacher with an remindable reference request" do + let(:remindable) { create(:application_form, :submitted) } + let(:assessment) { create(:assessment, application_form: remindable) } + let!(:reference_request) do + create( + :reference_request, + requested_at: reference_requested_at, + assessment:, + ) + end + + context "with less than four weeks remaining" do + let(:reference_requested_at) { (6.weeks - 27.days).ago } + include_examples "first reminder email", + "sends an application references reminder email", + "references" + end + + context "with less than two weeks remaining" do + let(:reference_requested_at) { (6.weeks - 13.days).ago } + include_examples "second reminder email", + "sends an application references reminder email", + "references" + end + + context "with more than four weeks remaining" do + let(:reference_requested_at) { 2.days.ago } + include_examples "doesn't send an email" + end + + context "with a received reference request" do + let!(:reference_request) do + create(:reference_request, :received, requested_at: Time.zone.now) + end + include_examples "doesn't send an email" + end + + context "with an expired reference request" do + let!(:reference_request) do + create(:reference_request, :expired, requested_at: Time.zone.now) + end + include_examples "doesn't send an email" + end + end end end diff --git a/spec/support/shared_examples/remindable.rb b/spec/support/shared_examples/remindable.rb index 0b2398d7c2..97a9d9bbfd 100644 --- a/spec/support/shared_examples/remindable.rb +++ b/spec/support/shared_examples/remindable.rb @@ -14,7 +14,7 @@ describe "#should_send_reminder_email?" do let(:should_send_reminder_email?) do - subject.should_send_reminder_email?("type", 0) + subject.should_send_reminder_email?("expiration", 0) end it "returns a boolean" do @@ -23,7 +23,7 @@ end describe "#send_reminder_email" do - let(:send_reminder_email) { subject.send_reminder_email("type", 0) } + let(:send_reminder_email) { subject.send_reminder_email("expiration", 0) } it "enqueues an email" do expect { send_reminder_email }.to have_enqueued_mail