Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions app/jobs/schedule_bounce_notifications_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ def perform
CurrentJobLoggingAttributes.job_class = self.class.name
CurrentJobLoggingAttributes.job_id = job_id

SendBounceNotificationsJob.perform_later(bounced_on_date: 1.day.ago.to_date, user_role: :group_admin)
SendBounceNotificationsJob.perform_later(bounced_on_date: 8.days.ago.to_date, user_role: :organisation_admin)
SendBounceNotificationsJob.perform_later(bounced_on_date: 1.day.ago.to_date, is_escalation: false)
SendBounceNotificationsJob.perform_later(bounced_on_date: 8.days.ago.to_date, is_escalation: true)
end
end
12 changes: 9 additions & 3 deletions app/jobs/send_bounce_notifications_job.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class SendBounceNotificationsJob < ApplicationJob
queue_as :bounce_notifications

def perform(bounced_on_date:, user_role:)
def perform(bounced_on_date:, is_escalation:)
Comment thread
stephencdaly marked this conversation as resolved.
CloudWatchService.record_job_started_metric(self.class.name)
CurrentJobLoggingAttributes.job_class = self.class.name
CurrentJobLoggingAttributes.job_id = job_id
Expand All @@ -15,11 +15,17 @@ def perform(bounced_on_date:, user_role:)

group = Api::V2::GroupResource.find(form_id)

users = user_role == :organisation_admin ? group.organisation.organisation_admin_users : group.group_admin_users
if !is_escalation && group.group_admin_users.any?
users = group.group_admin_users
user_role = :group_admin
else
users = group.organisation.organisation_admin_users
user_role = :organisation_admin
end

users.each do |user|
BounceNotificationMailer.bounce_notification_email(
form:, group_name: group.name, user:, user_role:, deliveries:, bounced_on_date:,
form:, group_name: group.name, user:, user_role:, deliveries:,
).deliver_now
end

Expand Down
9 changes: 4 additions & 5 deletions app/mailers/bounce_notification_mailer.rb
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
class BounceNotificationMailer < GovukNotifyRails::Mailer
include NotifyUtils

def bounce_notification_email(form:, group_name:, user:, user_role:, deliveries:, bounced_on_date:)
def bounce_notification_email(form:, group_name:, user:, user_role:, deliveries:)
set_template(Settings.govuk_notify.bounce_notification_to_group_admins_template_id)
set_email_reply_to(Settings.govuk_notify.zendesk_reply_to_id)

Expand All @@ -24,7 +24,7 @@ def bounce_notification_email(form:, group_name:, user:, user_role:, deliveries:
deadline_date: deadline_date(deliveries),
is_organisation_admin: make_notify_boolean(user_role == :organisation_admin),
is_group_admin: make_notify_boolean(user_role == :group_admin),
contacted_group_admins_paragraph: contacted_group_admins_paragraph(user_role:, group_name:, bounced_on_date:),
contacted_group_admins_paragraph: contacted_group_admins_paragraph(user_role:, group_name:),
)

mail(to: user.email)
Expand Down Expand Up @@ -69,10 +69,9 @@ def deadline_date(deliveries)
deadline_date_time.strftime("%-d %B %Y")
end

def contacted_group_admins_paragraph(user_role:, group_name:, bounced_on_date:)
def contacted_group_admins_paragraph(user_role:, group_name:)
return "" if user_role == :group_admin

contacted_date = (bounced_on_date + 1.day).strftime("%-d %B %Y")
I18n.t("mailer.bounce_notification.contacted_group_admins_paragraph", group_name:, contacted_date:)
I18n.t("mailer.bounce_notification.contacted_group_admins_paragraph", group_name:)
end
end
2 changes: 1 addition & 1 deletion config/locales/cy.yml
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ cy:
bounced_daily_batch: Daily batch sent at %{sent_at_time} on %{sent_at_date}
bounced_submission: "%{submission_reference} at %{sent_at_time} on %{sent_at_date}"
bounced_weekly_batch: Weekly batch sent at %{sent_at_time} on %{sent_at_date}
contacted_group_admins_paragraph: We emailed the group admins of the group the form is in, “%{group_name}”, on %{contacted_date}. We have not received a response.
contacted_group_admins_paragraph: The form is in the group “%{group_name}”, which has no group admins or whose group admins have not responded.
cannot_reply:
contact_form_filler_html: "<p>If you need to contact the person who completed this form, you’ll need to contact them directly.</p>"
contact_form_filler_plain: If you need to contact the person who completed this form, you’ll need to contact them directly.
Expand Down
2 changes: 1 addition & 1 deletion config/locales/en.yml
Original file line number Diff line number Diff line change
Expand Up @@ -472,7 +472,7 @@ en:
bounced_daily_batch: Daily batch sent at %{sent_at_time} on %{sent_at_date}
bounced_submission: "%{submission_reference} at %{sent_at_time} on %{sent_at_date}"
bounced_weekly_batch: Weekly batch sent at %{sent_at_time} on %{sent_at_date}
contacted_group_admins_paragraph: We emailed the group admins of the group the form is in, “%{group_name}”, on %{contacted_date}. We have not received a response.
contacted_group_admins_paragraph: The form is in the group “%{group_name}”, which has no group admins or whose group admins have not responded.
cannot_reply:
contact_form_filler_html: "<p>If you need to contact the person who completed this form, you’ll need to contact them directly.</p>"
contact_form_filler_plain: If you need to contact the person who completed this form, you’ll need to contact them directly.
Expand Down
8 changes: 4 additions & 4 deletions spec/jobs/schedule_bounce_notifications_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
end
end

it "schedules a SendBounceNotifications job to send to group admins with yesterday's date" do
it "schedules a SendBounceNotifications job to send the initial notifications with yesterday's date" do
expect(SendBounceNotificationsJob).to have_received(:perform_later)
.with({ bounced_on_date: Date.new(2026, 5, 11), user_role: :group_admin })
.with({ bounced_on_date: Date.new(2026, 5, 11), is_escalation: false })
.once
end

it "schedules a SendBounceNotifications job to send to organisation admins with a date of 8 days ago" do
it "schedules a SendBounceNotifications job to send the escalation notifications with a date of 8 days ago" do
expect(SendBounceNotificationsJob).to have_received(:perform_later)
.with({ bounced_on_date: Date.new(2026, 5, 4), user_role: :organisation_admin })
.with({ bounced_on_date: Date.new(2026, 5, 4), is_escalation: true })
.once
end
end
71 changes: 48 additions & 23 deletions spec/jobs/send_bounce_notifications_job_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
include ActiveJob::TestHelper

let(:bounced_on_date) { Date.new(2026, 5, 6) }
let(:user_role) { :group_admin }
let(:is_escalation) { false }

let(:form_with_bounces) { build :form }
let(:other_form_with_bounces) { build :form }
Expand All @@ -28,7 +28,7 @@
context "when there are multiple forms with bounces on the date" do
before do
create_list :delivery, 2, :bounced, :daily_scheduled_delivery, form_id: other_form_with_bounces.id, failed_at: Time.zone.local(2026, 5, 6, 22, 59, 0)
described_class.perform_now(bounced_on_date:, user_role:)
described_class.perform_now(bounced_on_date:, is_escalation:)
end

it "sends an email per form with bounced submissions" do
Expand All @@ -55,39 +55,64 @@
end
end

context "when notifying the group admins" do
let(:user_role) { :group_admin }
let(:group) { build :group, group_admin_users_count: 2 }
context "when sending the initial bounce notification" do
let(:is_escalation) { false }

before do
described_class.perform_now(bounced_on_date:, user_role:)
described_class.perform_now(bounced_on_date:, is_escalation:)
end

it "sends an email to each group admin" do
expect(ActionMailer::Base.deliveries.size).to eq 2
expect(ActionMailer::Base.deliveries.map(&:to).flatten).to contain_exactly(
group.group_admin_users.first.email,
group.group_admin_users.second.email,
)
context "when the group has group admin users" do
let(:group) { build :group, group_admin_users_count: 2 }

it "sends an email to each group admin" do
expect(ActionMailer::Base.deliveries.size).to eq 2
expect(ActionMailer::Base.deliveries.map(&:to).flatten).to contain_exactly(
group.group_admin_users.first.email,
group.group_admin_users.second.email,
)
end

it "logs that it sent the notifications to the group admins" do
expect(log_lines).to include(
hash_including(
"level" => "INFO",
"form_id" => form_with_bounces.form_id,
"message" => "Sent bounce notifications to 2 group admin users for bounced deliveries on 6 May 2026 for form #{form_with_bounces.form_id}",
),
)
end
end

it "logs that it sent the notifications to the group admins" do
expect(log_lines).to include(
hash_including(
"level" => "INFO",
"form_id" => form_with_bounces.form_id,
"message" => "Sent bounce notifications to 2 group admin users for bounced deliveries on 6 May 2026 for form #{form_with_bounces.form_id}",
),
)
context "when the group does not have group admin users" do
let(:group) { build :group, group_admin_users_count: 0, organisation_admin_users_count: 2 }

it "sends an email to the organisation admins" do
expect(ActionMailer::Base.deliveries.size).to eq 2
expect(ActionMailer::Base.deliveries.map(&:to).flatten).to contain_exactly(
group.organisation.organisation_admin_users.first.email,
group.organisation.organisation_admin_users.second.email,
)
end

it "logs that it sent the notifications to the organisation admins" do
expect(log_lines).to include(
hash_including(
"level" => "INFO",
"form_id" => form_with_bounces.form_id,
"message" => "Sent bounce notifications to 2 organisation admin users for bounced deliveries on 6 May 2026 for form #{form_with_bounces.form_id}",
),
)
end
end
end

context "when notifying the organisation admins" do
let(:user_role) { :organisation_admin }
context "when sending the escalation notification" do
let(:is_escalation) { true }
let(:group) { build :group, group_admin_users_count: 1, organisation_admin_users_count: 2 }

before do
described_class.perform_now(bounced_on_date:, user_role:)
described_class.perform_now(bounced_on_date:, is_escalation:)
end

it "sends an email to each organisation admin" do
Expand Down
6 changes: 2 additions & 4 deletions spec/mailers/bounce_notification_mailer_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
RSpec.describe BounceNotificationMailer do
describe "#bounce_notification_to_group_admins_email" do
subject(:mail) do
described_class.bounce_notification_email(form:, group_name:, user:, user_role:, deliveries:, bounced_on_date:)
described_class.bounce_notification_email(form:, group_name:, user:, user_role:, deliveries:)
end

let(:deliveries) { create_list :delivery, 3, :bounced, :immediate }
Expand Down Expand Up @@ -52,9 +52,7 @@
end

it "sets the personalisation for the contacted_group_admins_paragraph" do
expected_paragraph = I18n.t("mailer.bounce_notification.contacted_group_admins_paragraph",
group_name:,
contacted_date: "8 May 2026")
expected_paragraph = I18n.t("mailer.bounce_notification.contacted_group_admins_paragraph", group_name:)
expect(mail.govuk_notify_personalisation[:contacted_group_admins_paragraph]).to eq expected_paragraph
end
end
Expand Down