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