Class: SesDashboard::StatsAggregator
- Inherits:
-
Object
- Object
- SesDashboard::StatsAggregator
- Defined in:
- lib/ses_dashboard/stats_aggregator.rb
Overview
Aggregates email statistics for the dashboard.
Usage:
agg = StatsAggregator.new(project_id: project.id, from: 14.days.ago, to: Time.current)
agg.counters # => { sent: 100, delivered: 90, bounced: 3, ... }
agg.time_series # => { labels: ["2024-01-01", ...], data: [5, 12, ...] }
agg.total_opens # => 45
agg.total_clicks # => 12
Instance Method Summary collapse
-
#counters ⇒ Object
Returns counts grouped by status.
-
#initialize(project_id: nil, from: nil, to: nil) ⇒ StatsAggregator
constructor
A new instance of StatsAggregator.
-
#time_series ⇒ Object
Returns a Chart.js-compatible hash: { labels: […], data: […] } Groups by calendar day over the from..to range, filling gaps with zero.
- #total_clicks ⇒ Object
- #total_opens ⇒ Object
Constructor Details
#initialize(project_id: nil, from: nil, to: nil) ⇒ StatsAggregator
Returns a new instance of StatsAggregator.
12 13 14 15 16 |
# File 'lib/ses_dashboard/stats_aggregator.rb', line 12 def initialize(project_id: nil, from: nil, to: nil) @project_id = project_id @from = from @to = to end |
Instance Method Details
#counters ⇒ Object
Returns counts grouped by status. “not_delivered” is derived as the sum of bounced + complained + rejected.
20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
# File 'lib/ses_dashboard/stats_aggregator.rb', line 20 def counters scope = base_scope counts = scope.group(:status).count not_delivered = (counts["bounced"] || 0) + (counts["complained"] || 0) + (counts["rejected"] || 0) { total: scope.count, sent: counts["sent"] || 0, delivered: counts["delivered"] || 0, bounced: counts["bounced"] || 0, complained: counts["complained"] || 0, rejected: counts["rejected"] || 0, failed: counts["failed"] || 0, not_delivered: not_delivered } end |
#time_series ⇒ Object
Returns a Chart.js-compatible hash: { labels: […], data: […] } Groups by calendar day over the from..to range, filling gaps with zero.
50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
# File 'lib/ses_dashboard/stats_aggregator.rb', line 50 def time_series from = effective_from to = effective_to expr = Arel.sql(date_group_expr) raw = base_scope .where(sent_at: from..to) .group(expr) .order(expr) .count all_days = date_range_days(from, to) labels = all_days.map { |d| d.strftime("%Y-%m-%d") } data = all_days.map { |d| raw[d.strftime("%Y-%m-%d")] || 0 } { labels: labels, data: data } end |
#total_clicks ⇒ Object
44 45 46 |
# File 'lib/ses_dashboard/stats_aggregator.rb', line 44 def total_clicks base_scope.sum(:clicks) end |
#total_opens ⇒ Object
40 41 42 |
# File 'lib/ses_dashboard/stats_aggregator.rb', line 40 def total_opens base_scope.sum(:opens) end |