diff --git a/app/services/mailings/hourly_throughput.rb b/app/services/mailings/hourly_throughput.rb index 94040d9..f9aa9ca 100644 --- a/app/services/mailings/hourly_throughput.rb +++ b/app/services/mailings/hourly_throughput.rb @@ -1,6 +1,7 @@ class Mailings::HourlyThroughput HOUR = 1.hour RECENT = 15.minutes + HISTORY_HOURS = 12 def initialize(project, now: Time.current) @project = project @@ -23,6 +24,31 @@ class Mailings::HourlyThroughput sent + failed end + def hourly_history + @hourly_history ||= begin + from = (@now - (HISTORY_HOURS - 1).hours).beginning_of_hour + keyed = recipients.sent + .where(sent_at: from..@now) + .pluck(:sent_at) + .each_with_object(Hash.new(0)) do |sent_at, counts| + counts[sent_at.in_time_zone.beginning_of_hour] += 1 + end + + HISTORY_HOURS.times.map do |index| + at = from + index.hours + { at: at, count: keyed[at] || 0 } + end + end + end + + def history_total + hourly_history.sum { |bucket| bucket[:count] } + end + + def history_max + [hourly_history.map { |bucket| bucket[:count] }.max, 1].max + end + private def sent_since(window) diff --git a/app/views/mailings/dashboard.html.erb b/app/views/mailings/dashboard.html.erb index 977465e..9438549 100644 --- a/app/views/mailings/dashboard.html.erb +++ b/app/views/mailings/dashboard.html.erb @@ -26,7 +26,7 @@ <% end %> -
+
In corso
<%= @active_mailings.size %>
@@ -41,6 +41,18 @@ <% end %>
+
+
Storico invio
+ +
<%= @hourly_throughput.history_total %> inviate · ultime 12 ore
+
In pausa (fascia)
<%= @paused_mailings.size %>
diff --git a/test/controllers/mailings_controller_test.rb b/test/controllers/mailings_controller_test.rb index 9b5bfcc..a46e75f 100644 --- a/test/controllers/mailings_controller_test.rb +++ b/test/controllers/mailings_controller_test.rb @@ -34,6 +34,8 @@ class MailingsControllerTest < ActionDispatch::IntegrationTest assert_response :success assert_select "div", text: "Mail / ora" assert_match(/1 ultimi 15 min/, response.body) + assert_select "div", text: "Storico invio" + assert_match(/1 inviate · ultime 12 ore/, response.body) end test "creates a draft and opens audience filters" do diff --git a/test/services/mailings/hourly_throughput_test.rb b/test/services/mailings/hourly_throughput_test.rb index a086254..1d6312b 100644 --- a/test/services/mailings/hourly_throughput_test.rb +++ b/test/services/mailings/hourly_throughput_test.rb @@ -46,6 +46,26 @@ class Mailings::HourlyThroughputTest < ActiveSupport::TestCase assert_equal 1, stats.recent_sent end + test "builds twelve hourly buckets of confirmed sends" do + now = Time.zone.parse("2026-09-07 12:40") + travel_to now do + add_recipient status: "sent", sent_at: now - 20.minutes + add_recipient status: "sent", sent_at: now - 70.minutes, mailing: extra_mailing("Ore 11") + add_recipient status: "sent", sent_at: now - 80.minutes, mailing: extra_mailing("Ore 11 bis") + add_recipient status: "sent", sent_at: now - 13.hours, mailing: extra_mailing("Fuori finestra") + + stats = Mailings::HourlyThroughput.new(@project, now: now) + history = stats.hourly_history + + assert_equal 12, history.size + assert_equal now.beginning_of_hour, history.last[:at] + assert_equal 1, history.last[:count] + assert_equal 2, history[-2][:count] + assert_equal 0, history.first[:count] + assert_equal 3, stats.history_total + end + end + private def extra_mailing(name = "Altra campagna")