Include autenticazione, progetti isolati, mail marketing HTML con SMTP, test A/B e editor WYSIWYG. Co-authored-by: Cursor <cursoragent@cursor.com>
108 lines
2.7 KiB
Ruby
108 lines
2.7 KiB
Ruby
class Mailing < ApplicationRecord
|
|
include Auditable
|
|
include HtmlBlankable
|
|
|
|
belongs_to :project
|
|
belongs_to :mail_identity
|
|
belongs_to :mail_template, optional: true
|
|
belongs_to :mail_template_b, class_name: "MailTemplate", optional: true
|
|
has_many :mailing_recipients, dependent: :destroy
|
|
has_many :organizations, through: :mailing_recipients
|
|
has_many_attached :files
|
|
|
|
validates :name, :subject, :body_html, presence: true
|
|
validates :status, inclusion: { in: Catalog::MAILING_STATUSES.keys }
|
|
validates :audience, inclusion: { in: Catalog::MAILING_AUDIENCES.keys }
|
|
validates :ab_assignment, inclusion: { in: Catalog::MAILING_AB_ASSIGNMENTS.keys }
|
|
validates :interval_seconds, numericality: { greater_than_or_equal_to: 0, less_than_or_equal_to: 86_400 }
|
|
validates :subject_b, :body_html_b, presence: true, if: :ab_test?
|
|
clears_blank_html :body_html, :body_html_b
|
|
|
|
scope :recent, -> { order(created_at: :desc) }
|
|
scope :for_project, ->(project) { where(project_id: project.id) }
|
|
|
|
def status_label
|
|
Catalog.label_for(Catalog::MAILING_STATUSES, status)
|
|
end
|
|
|
|
def audience_label
|
|
Catalog.label_for(Catalog::MAILING_AUDIENCES, audience)
|
|
end
|
|
|
|
def ab_assignment_label
|
|
Catalog.label_for(Catalog::MAILING_AB_ASSIGNMENTS, ab_assignment)
|
|
end
|
|
|
|
def ab_from_record?
|
|
ab_assignment == "from_record"
|
|
end
|
|
|
|
def subject_for(variant)
|
|
ab_test? && variant.to_s.upcase == "B" ? subject_b : subject
|
|
end
|
|
|
|
def body_for(variant)
|
|
ab_test? && variant.to_s.upcase == "B" ? body_html_b : body_html
|
|
end
|
|
|
|
def variant_pending_count(variant)
|
|
mailing_recipients.pending.where(ab_variant: variant).count
|
|
end
|
|
|
|
def variant_sent_count(variant)
|
|
mailing_recipients.sent.where(ab_variant: variant).count
|
|
end
|
|
|
|
def draft?
|
|
status == "draft"
|
|
end
|
|
|
|
def sending?
|
|
status == "sending"
|
|
end
|
|
|
|
def sent?
|
|
status == "sent"
|
|
end
|
|
|
|
def editable?
|
|
draft?
|
|
end
|
|
|
|
def pending_count
|
|
mailing_recipients.pending.count
|
|
end
|
|
|
|
def skipped_count
|
|
mailing_recipients.skipped.count
|
|
end
|
|
|
|
def sent_count
|
|
mailing_recipients.sent.count
|
|
end
|
|
|
|
def failed_count
|
|
mailing_recipients.failed.count
|
|
end
|
|
|
|
def rebuild_recipients!
|
|
mailing_recipients.delete_all
|
|
Mailings::RecipientBuilder.new(self).call
|
|
end
|
|
|
|
def queue_send!
|
|
raise "Nessun destinatario da inviare" if pending_count.zero?
|
|
|
|
update!(status: "sending", queued_at: Time.current)
|
|
first = mailing_recipients.pending.order(:id).first
|
|
SendMailingRecipientJob.perform_later(first.id)
|
|
end
|
|
|
|
def mark_finished_if_done!
|
|
return unless sending?
|
|
return if mailing_recipients.pending.exists? || mailing_recipients.queued.exists?
|
|
|
|
update!(status: "sent", completed_at: Time.current)
|
|
end
|
|
end
|