diff --git a/app/interactions/domains/force_delete/post_set_process.rb b/app/interactions/domains/force_delete/post_set_process.rb
index a4b24eb817..0c7ae061c4 100644
--- a/app/interactions/domains/force_delete/post_set_process.rb
+++ b/app/interactions/domains/force_delete/post_set_process.rb
@@ -12,7 +12,6 @@ def execute
# Allow deletion
statuses.delete(DomainStatus::CLIENT_DELETE_PROHIBITED)
- puts "Try to save domain: #{domain.name} with statuses: #{statuses}"
domain.save(validate: false)
end
end
diff --git a/app/jobs/force_delete_daily_admin_notifier_job.rb b/app/jobs/force_delete_daily_admin_notifier_job.rb
new file mode 100644
index 0000000000..88a59c606f
--- /dev/null
+++ b/app/jobs/force_delete_daily_admin_notifier_job.rb
@@ -0,0 +1,41 @@
+class ForceDeleteDailyAdminNotifierJob < ApplicationJob
+ queue_as :default
+
+ def perform
+ domains = Domain.where("'#{DomainStatus::FORCE_DELETE}' = ANY (statuses)")
+ .where("force_delete_start = ?", Time.zone.now)
+
+ return if domains.empty?
+
+ notify_admins(domains)
+ end
+
+ private
+
+ def notify_admins(domains)
+ summary = generate_summary(domains)
+ AdminMailer.force_delete_daily_summary(summary).deliver_now
+ end
+
+ def generate_summary(domains)
+ domains.map do |domain|
+ {
+ name: domain.name,
+ reason: determine_reason(domain),
+ force_delete_type: domain.force_delete_type,
+ force_delete_start: domain.force_delete_start,
+ force_delete_date: domain.force_delete_date
+ }
+ end
+ end
+
+ def determine_reason(domain)
+ if domain.template_name.present?
+ domain.template_name
+ elsif domain.status_notes[DomainStatus::FORCE_DELETE].present?
+ "Manual force delete: #{domain.status_notes[DomainStatus::FORCE_DELETE]}"
+ else
+ 'Unknown reason'
+ end
+ end
+end
diff --git a/app/mailers/admin_mailer.rb b/app/mailers/admin_mailer.rb
new file mode 100644
index 0000000000..b76db8a677
--- /dev/null
+++ b/app/mailers/admin_mailer.rb
@@ -0,0 +1,9 @@
+class AdminMailer < ApplicationMailer
+ def force_delete_daily_summary(domains_summary)
+ @domains = domains_summary
+ mail(
+ to: ENV['admin_notification_email'] || 'admin@registry.test',
+ subject: "Force Delete Daily Summary - #{Date.current}"
+ )
+ end
+end
\ No newline at end of file
diff --git a/app/views/admin_mailer/force_delete_daily_summary.html.erb b/app/views/admin_mailer/force_delete_daily_summary.html.erb
new file mode 100644
index 0000000000..33f2bdea5e
--- /dev/null
+++ b/app/views/admin_mailer/force_delete_daily_summary.html.erb
@@ -0,0 +1,24 @@
+
Force Delete Daily Summary - <%= Date.current %>
+
+
+
+
+ Domain |
+ Reason |
+ Type |
+ Start Date |
+ Delete Date |
+
+
+
+ <% @domains.each do |domain| %>
+
+ <%= domain[:name] %> |
+ <%= domain[:reason] %> |
+ <%= domain[:force_delete_type] %> |
+ <%= domain[:force_delete_start]&.to_date %> |
+ <%= domain[:force_delete_date]&.to_date %> |
+
+ <% end %>
+
+
\ No newline at end of file
diff --git a/test/jobs/force_delete_daily_admin_notifier_job_test.rb b/test/jobs/force_delete_daily_admin_notifier_job_test.rb
new file mode 100644
index 0000000000..ebfa3f5d85
--- /dev/null
+++ b/test/jobs/force_delete_daily_admin_notifier_job_test.rb
@@ -0,0 +1,81 @@
+require 'test_helper'
+
+class ForceDeleteDailyAdminNotifierJobTest < ActiveSupport::TestCase
+ include ActionMailer::TestHelper
+
+ setup do
+ @domain = domains(:shop)
+ travel_to Time.zone.parse('2010-07-05')
+ ActionMailer::Base.deliveries.clear
+ end
+
+ def test_sends_notification_for_domains_with_force_delete_today
+ @domain.schedule_force_delete(type: :soft)
+ @domain.update!(force_delete_start: Time.zone.now.to_date)
+ @domain.reload
+
+ assert_emails 1 do
+ ForceDeleteDailyAdminNotifierJob.perform_now
+ end
+
+ email = ActionMailer::Base.deliveries.last
+ assert_includes email.body.to_s, @domain.name
+ assert_includes email.body.to_s, @domain.force_delete_type
+ end
+
+ def test_does_not_send_notification_when_no_force_delete_domains_today
+ travel_to Time.zone.parse('2010-07-06')
+ @domain.schedule_force_delete(type: :soft)
+ @domain.reload
+
+ assert_no_emails do
+ ForceDeleteDailyAdminNotifierJob.perform_now
+ end
+ end
+
+ def test_includes_multiple_domains_in_notification
+ @domain.schedule_force_delete(type: :soft)
+ @domain.update!(force_delete_start: Time.zone.now.to_date)
+
+ domain2 = domains(:airport)
+ domain2.schedule_force_delete(type: :fast_track)
+ domain2.update!(force_delete_start: Time.zone.now.to_date)
+
+ assert_emails 1 do
+ ForceDeleteDailyAdminNotifierJob.perform_now
+ end
+
+ email = ActionMailer::Base.deliveries.last
+ assert_includes email.body.to_s, @domain.name
+ assert_includes email.body.to_s, domain2.name
+ end
+
+ def test_includes_correct_reason_for_invalid_email_template
+ @domain.update!(template_name: 'invalid_email')
+ @domain.schedule_force_delete(type: :soft)
+ @domain.update!(force_delete_start: Time.zone.now.to_date)
+ @domain.reload
+
+ assert_emails 1 do
+ ForceDeleteDailyAdminNotifierJob.perform_now
+ end
+
+ email = ActionMailer::Base.deliveries.last
+ assert_includes email.body.to_s, 'invalid_email'
+ end
+
+ def test_includes_correct_reason_for_manual_force_delete
+ manual_reason = "Manual deletion requested"
+ @domain.status_notes = { DomainStatus::FORCE_DELETE => manual_reason }
+ @domain.schedule_force_delete(type: :fast_track)
+ @domain.update!(force_delete_start: Time.zone.now.to_date)
+ @domain.reload
+
+ assert_emails 1 do
+ ForceDeleteDailyAdminNotifierJob.perform_now
+ end
+
+ email = ActionMailer::Base.deliveries.last
+ assert_includes email.body.to_s, "Manual force delete: #{manual_reason}"
+ end
+end
\ No newline at end of file