Aggiunge il rilevamento di invio e apertura delle email di campagna.
Ogni destinatario mostra se la mail è partita e se è stata aperta, con conteggi in dashboard. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
@@ -5,12 +5,16 @@ class MailingRecipient < ApplicationRecord
|
||||
|
||||
validates :status, inclusion: { in: Catalog::MAILING_RECIPIENT_STATUSES.keys }
|
||||
validates :ab_variant, inclusion: { in: Catalog::AB_VARIANTS.keys }, allow_blank: true
|
||||
validates :tracking_token, presence: true, uniqueness: true
|
||||
|
||||
before_validation :assign_tracking_token, on: :create
|
||||
|
||||
scope :pending, -> { where(status: "pending") }
|
||||
scope :skipped, -> { where(status: "skipped") }
|
||||
scope :sent, -> { where(status: "sent") }
|
||||
scope :failed, -> { where(status: "failed") }
|
||||
scope :queued, -> { where(status: "queued") }
|
||||
scope :opened, -> { where.not(opened_at: nil) }
|
||||
scope :ordered, -> { joins(:organization).order("organizations.list_position ASC NULLS LAST", "organizations.name ASC") }
|
||||
|
||||
def status_label
|
||||
@@ -21,10 +25,33 @@ class MailingRecipient < ApplicationRecord
|
||||
status == "pending"
|
||||
end
|
||||
|
||||
def sent?
|
||||
status == "sent"
|
||||
end
|
||||
|
||||
def email_ok?
|
||||
email.present? && email.match?(URI::MailTo::EMAIL_REGEXP)
|
||||
end
|
||||
|
||||
def opened?
|
||||
opened_at.present?
|
||||
end
|
||||
|
||||
def record_open!(at: Time.current)
|
||||
return unless sent?
|
||||
|
||||
first_open = false
|
||||
with_lock do
|
||||
return unless sent?
|
||||
|
||||
first_open = opened_at.blank?
|
||||
attrs = { last_opened_at: at, open_count: open_count + 1 }
|
||||
attrs[:opened_at] = at if first_open
|
||||
update!(attrs)
|
||||
end
|
||||
log_open_activity! if first_open
|
||||
end
|
||||
|
||||
def merge_context
|
||||
opportunity = organization.campaign_opportunity(mailing.project)
|
||||
{
|
||||
@@ -90,6 +117,29 @@ class MailingRecipient < ApplicationRecord
|
||||
opportunity.update!(attrs) if attrs.any?
|
||||
end
|
||||
|
||||
def assign_tracking_token
|
||||
self.tracking_token ||= self.class.generate_tracking_token
|
||||
end
|
||||
|
||||
def self.generate_tracking_token
|
||||
loop do
|
||||
token = SecureRandom.urlsafe_base64(24)
|
||||
break token unless exists?(tracking_token: token)
|
||||
end
|
||||
end
|
||||
|
||||
def log_open_activity!
|
||||
organization.activities.create!(
|
||||
activity_type: "email_opened",
|
||||
subject: rendered_subject.presence || mailing.subject_for(ab_variant),
|
||||
description: "Apertura rilevata · campagna #{mailing.name}",
|
||||
happened_at: opened_at || Time.current,
|
||||
user: mailing.created_by,
|
||||
contact: contact,
|
||||
opportunity: organization.campaign_opportunity(mailing.project)
|
||||
)
|
||||
end
|
||||
|
||||
def log_activity!(subject_line)
|
||||
variant_note = "variante #{ab_variant}" if mailing.ab_test? && ab_variant.present?
|
||||
organization.activities.create!(
|
||||
|
||||
Reference in New Issue
Block a user