Files
eminuxCRM/app/services/mailings/recipient_builder.rb
T
eminuxandCursor 1f946f63ba
CI / scan_ruby (push) Failing after 18m40s
CI / scan_js (push) Successful in 11m46s
CI / lint (push) Failing after 13m8s
Aggiunge filtri avanzati per i destinatari delle campagne email.
La scelta della lista passa da un wizard a tre passi, con anteprima del conteggio e lista congelata solo dopo la conferma.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-24 21:00:11 +02:00

58 lines
1.6 KiB
Ruby

class Mailings::RecipientBuilder
def initialize(mailing)
@mailing = mailing
end
def call
split_index = 0
ordered_scope.each do |org|
contact = org.primary_contact || org.contacts.min_by(&:id)
email = contact&.email.presence || org.email.presence
attrs = {
organization: org,
contact: contact,
email: email&.downcase
}
if email.blank?
attrs[:status] = "skipped"
attrs[:skip_reason] = "manca email"
elsif !email.match?(URI::MailTo::EMAIL_REGEXP)
attrs[:status] = "skipped"
attrs[:skip_reason] = "email non valida"
else
attrs[:status] = "pending"
end
assign_variant!(attrs, org, split_index)
split_index += 1 if attrs[:status] == "pending"
@mailing.mailing_recipients.create!(attrs)
end
@mailing.mailing_recipients.ordered
end
private
def ordered_scope
scope.reorder(Arel.sql("organizations.list_position ASC NULLS LAST"), "organizations.name ASC")
end
def scope
Mailings::AudienceQuery.new(@mailing.project, @mailing.parsed_audience_filters, mailing: @mailing)
.relation
.includes(:contacts, :opportunities)
end
def assign_variant!(attrs, org, split_index)
return unless @mailing.ab_test?
opportunity = org.campaign_opportunity(@mailing.project)
recorded = opportunity&.ab_variant.to_s.upcase
variant =
if @mailing.ab_from_record? && recorded.in?(%w[A B])
recorded
else
split_index.even? ? "A" : "B"
end
attrs[:ab_variant] = variant
end
end