Class: EmailTemplateDataPoint
- Inherits:
-
ApplicationRecord
- Object
- ActiveRecord::Base
- ApplicationRecord
- EmailTemplateDataPoint
- Includes:
- Models::DataPointMetrics
- Defined in:
- app/models/email_template_data_point.rb
Overview
Daily time-series of email engagement per EmailTemplate, written by
EmailEngagementRollupWorker.
Exists because webhook_events retains only ~3 months. Counts (sends,
delivered, opened, clicked) can always be recomputed from the durable
terminal state on communication_recipients, but anything derived from event
TIMING cannot — once the events age out it is gone. median_hours_to_open
and opened_within_24h are the metrics that showed Saturday quote-expiration
notices sat ~50h before being read against 6-8h on weekdays; that analysis
was only possible inside the retention window.
The generic time-series machinery (scopes, trend/comparison API, period
helpers, idempotent upsert) lives in Models::DataPointMetrics — same shape
as SiteMapDataPoint and CatalogDataPoint.
Constant Summary collapse
- DURABLE_METRICS =
Recomputable from communication_recipients at any time.
%w[sends delivered opened clicked bounced dropped unsubscribed spammed machine_opened].freeze
- PERISHABLE_METRICS =
Derived from webhook_events — unrecoverable once those age out.
%w[total_opens total_clicks median_hours_to_open opened_within_24h].freeze
- INVERTED_METRICS =
Lower is better: a slow open is a worse outcome, so trend arrows must
read a falling median as an improvement. %w[bounced dropped unsubscribed spammed median_hours_to_open].freeze
Constants included from Models::Schedulable
Models::Schedulable::SIMPLE_FORM_OPTIONS
Instance Attribute Summary
Attributes included from Models::DataPointMetrics
Belongs to collapse
-
#email_template ⇒ EmailTemplate
The template these metrics describe.
Class Method Summary collapse
-
.bulk_record!(email_template:, period_start:, period_end:, metrics:, reference: nil, source_batch_id: nil) ⇒ void
Upserts a day's metrics for one template.
Methods included from Models::DataPointMetrics
by_period_start, by_recorded, containing_date, for_metric, for_reference, #inverted_metric?, inverted_metrics, latest, latest_values, overlapping, period_comparison, #period_days, #period_end, #period_start, recent, trend, trend_direction, upsert_data_points!
Methods inherited from ApplicationRecord
ransackable_associations, ransackable_attributes, ransackable_scopes, ransortable_attributes, #to_relation
Methods included from Models::Schedulable
Methods included from Models::AfterCommittable
Methods included from Models::EventPublishable
Class Method Details
.bulk_record!(email_template:, period_start:, period_end:, metrics:, reference: nil, source_batch_id: nil) ⇒ void
This method returns an undefined value.
Upserts a day's metrics for one template.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
# File 'app/models/email_template_data_point.rb', line 46 def self.bulk_record!(email_template:, period_start:, period_end:, metrics:, reference: nil, source_batch_id: nil) # Inclusive daterange literal — the column is `daterange`, so a Ruby Range # would stringify into something Postgres rejects. period = "[#{period_start},#{period_end}]" rows = metrics.filter_map do |metric_type, value| next if value.nil? { email_template_id: email_template.id, metric_type: metric_type.to_s, value:, period:, reference:, source_batch_id:, recorded_at: Time.current } end upsert_data_points!(foreign_key: :email_template_id, rows:) end |
Instance Method Details
#email_template ⇒ EmailTemplate
The template these metrics describe.
22 |
# File 'app/models/email_template_data_point.rb', line 22 belongs_to :email_template |