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