+
Mail / ora
+
<%= @hourly_throughput.sent %>
+
+ <%= @hourly_throughput.recent_sent %> ultimi 15 min
+ <% if @hourly_throughput.failed.positive? %>
+ ยท <%= @hourly_throughput.failed %> scodate in errore
+ <% end %>
+
+
In pausa (fascia)
<%= @paused_mailings.size %>
diff --git a/test/controllers/mailings_controller_test.rb b/test/controllers/mailings_controller_test.rb
index 3f569c3..9b5bfcc 100644
--- a/test/controllers/mailings_controller_test.rb
+++ b/test/controllers/mailings_controller_test.rb
@@ -16,6 +16,26 @@ class MailingsControllerTest < ActionDispatch::IntegrationTest
assert_match(/Invii email/, response.body)
end
+ test "dashboard shows hourly send throughput" do
+ login_as users(:admin)
+ follow_redirect! if response.redirect?
+
+ mailing = create_mailing(identity: @identity, audience: "to_send")
+ org = organizations(:acme)
+ mailing.mailing_recipients.create!(
+ organization: org,
+ contact: org.contacts.first,
+ email: org.email,
+ status: "sent",
+ sent_at: 8.minutes.ago
+ )
+
+ get dashboard_mailings_path(project_code: @project.code)
+ assert_response :success
+ assert_select "div", text: "Mail / ora"
+ assert_match(/1 ultimi 15 min/, response.body)
+ end
+
test "creates a draft and opens audience filters" do
login_as users(:admin)
follow_redirect! if response.redirect?
diff --git a/test/services/mailings/hourly_throughput_test.rb b/test/services/mailings/hourly_throughput_test.rb
new file mode 100644
index 0000000..a086254
--- /dev/null
+++ b/test/services/mailings/hourly_throughput_test.rb
@@ -0,0 +1,65 @@
+require "test_helper"
+
+class Mailings::HourlyThroughputTest < ActiveSupport::TestCase
+ setup do
+ @project = projects(:matchlivetv)
+ @identity = create_mail_identity
+ @mailing = create_mailing(identity: @identity, audience: "all")
+ end
+
+ test "counts confirmed sends in the last hour and last 15 minutes" do
+ add_recipient status: "sent", sent_at: 10.minutes.ago
+ add_recipient status: "sent", sent_at: 40.minutes.ago, mailing: extra_mailing
+ add_recipient status: "sent", sent_at: 2.hours.ago, mailing: extra_mailing("Vecchia")
+ add_recipient status: "queued", mailing: extra_mailing("In coda")
+
+ stats = Mailings::HourlyThroughput.new(@project)
+
+ assert_equal 2, stats.sent
+ assert_equal 1, stats.recent_sent
+ assert_equal 0, stats.failed
+ assert_equal 2, stats.drained
+ end
+
+ test "counts failed recipients that left the queue in the last hour" do
+ recipient = add_recipient(status: "failed")
+ recipient.update_columns(updated_at: 5.minutes.ago)
+
+ stale = add_recipient(status: "failed", mailing: extra_mailing)
+ stale.update_columns(updated_at: 2.hours.ago)
+
+ stats = Mailings::HourlyThroughput.new(@project)
+
+ assert_equal 0, stats.sent
+ assert_equal 1, stats.failed
+ assert_equal 1, stats.drained
+ end
+
+ test "ignores sends from other projects" do
+ other = create_mailing(project: projects(:riskmeter), identity: @identity, audience: "all")
+ add_recipient status: "sent", sent_at: 5.minutes.ago, mailing: other
+ add_recipient status: "sent", sent_at: 5.minutes.ago
+
+ stats = Mailings::HourlyThroughput.new(@project)
+
+ assert_equal 1, stats.sent
+ assert_equal 1, stats.recent_sent
+ end
+
+ private
+
+ def extra_mailing(name = "Altra campagna")
+ create_mailing(identity: @identity, audience: "all", name: name)
+ end
+
+ def add_recipient(status:, sent_at: nil, mailing: @mailing)
+ org = organizations(:acme)
+ mailing.mailing_recipients.create!(
+ organization: org,
+ contact: org.contacts.first,
+ email: org.email,
+ status: status,
+ sent_at: sent_at
+ )
+ end
+end