Files
eminuxCRM/app/services/mailings/audience_query.rb
T
eminux 3f7794959e
CI / scan_ruby (push) Failing after 12m46s
CI / scan_js (push) Successful in 12m35s
CI / lint (push) Failing after 12m46s
corretti bug sull'invio email
2026-09-10 17:08:50 +02:00

159 lines
6.1 KiB
Ruby

module Mailings
class AudienceQuery
def initialize(project, filters = {}, mailing: nil)
@project = project
@filters = filters.is_a?(AudienceFilters) ? filters : AudienceFilters.new(filters)
@mailing = mailing
end
def relation
scope = Organization.for_project(@project)
scope = apply_preset(scope)
scope = apply_organization_filters(scope)
scope = apply_opportunity_filters(scope)
scope = apply_history_filters(scope)
scope = apply_exclusions(scope)
scope.distinct
end
def counts
{
total: relation.unscope(:order).distinct.count("organizations.id"),
with_email: with_email_scope(relation).unscope(:order).distinct.count("organizations.id")
}
end
def preview(limit = 15)
relation.includes(:primary_contact).reorder(Arel.sql("organizations.list_position ASC NULLS LAST"), "organizations.name ASC").limit(limit)
end
private
def apply_preset(scope)
case @filters.preset
when "to_send"
scope.where(id: opportunity_scope.where(send_status: "to_send").select(:organization_id))
when "test_a"
scope.where(id: opportunity_scope.where(ab_variant: "A").select(:organization_id))
when "test_b"
scope.where(id: opportunity_scope.where(ab_variant: "B").select(:organization_id))
else
scope
end
end
def apply_organization_filters(scope)
scope = scope.where(sport: @filters["sports"]) if @filters["sports"].present?
scope = scope.where(country: @filters["countries"]) if @filters["countries"].present?
scope = scope.where(team_gender: @filters["team_genders"]) if @filters["team_genders"].present?
scope = scope.where(region: @filters["regions"]) if @filters["regions"].present?
scope = scope.where(province: @filters["provinces"]) if @filters["provinces"].present?
scope = scope.where(streaming_status: @filters["streaming_statuses"]) if @filters["streaming_statuses"].present?
scope = scope.where(status: @filters["statuses"]) if @filters["statuses"].present?
scope = scope.where("organizations.list_position >= ?", @filters["list_min"]) if @filters["list_min"].present?
scope = scope.where("organizations.list_position <= ?", @filters["list_max"]) if @filters["list_max"].present?
scope
end
def apply_opportunity_filters(scope)
extra = opportunity_scope
filtered = false
if @filters["send_statuses"].present?
extra = extra.where(send_status: @filters["send_statuses"])
filtered = true
end
if @filters["ab_variants"].present?
extra = extra.where(ab_variant: @filters["ab_variants"])
filtered = true
end
if @filters["pipeline_stages"].present?
extra = extra.where(pipeline_stage: @filters["pipeline_stages"])
filtered = true
end
case @filters["estimated_value"]
when "present"
extra = extra.where("opportunities.estimated_value IS NOT NULL AND opportunities.estimated_value > 0")
filtered = true
when "blank"
extra = extra.where("opportunities.estimated_value IS NULL OR opportunities.estimated_value = 0")
filtered = true
end
filtered ? scope.where(id: extra.select(:organization_id)) : scope
end
def apply_history_filters(scope)
case @filters.history_kind
when "never"
scope.where.not(id: sent_org_ids).where.not(id: emailed_activity_org_ids)
when "received"
scope.where(id: sent_org_ids(mailing_id: @filters.history_mailing_id))
when "not_received"
scope.where.not(id: sent_org_ids(mailing_id: @filters.history_mailing_id))
when "opened"
scope.where(id: opened_org_ids(mailing_id: @filters.history_mailing_id))
when "not_opened"
sent = sent_org_ids(mailing_id: @filters.history_mailing_id)
opened = opened_org_ids(mailing_id: @filters.history_mailing_id)
scope.where(id: sent).where.not(id: opened)
when "recent"
days = @filters.history_days.presence || 30
scope.where(id: sent_org_ids(since: days.days.ago))
else
scope
end
end
def apply_exclusions(scope)
scope = scope.where.not(status: %w[active_customer inactive_customer]) if @filters["exclude_customers"]
if @filters["exclude_received_mailing_ids"].present?
scope = scope.where.not(id: sent_org_ids(mailing_id: project_mailing_ids(@filters["exclude_received_mailing_ids"])))
end
if @filters["exclude_opened_mailing_ids"].present?
scope = scope.where.not(id: opened_org_ids(mailing_id: project_mailing_ids(@filters["exclude_opened_mailing_ids"])))
end
if @filters["exclude_mailed_within_days"].present?
scope = scope.where.not(id: sent_org_ids(since: @filters["exclude_mailed_within_days"].days.ago))
end
scope
end
def with_email_scope(scope)
scope.left_joins(:contacts).where(
"NULLIF(BTRIM(organizations.email), '') IS NOT NULL OR NULLIF(BTRIM(contacts.email), '') IS NOT NULL"
)
end
def opportunity_scope
Opportunity.where(project_id: @project.id)
end
def emailed_activity_org_ids
Activity.where(activity_type: "email_sent", organization_id: Organization.for_project(@project).select(:id)).select(:organization_id)
end
def sent_org_ids(mailing_id: nil, since: nil)
recips = history_recipients.where(status: "sent")
recips = recips.where(mailing_id: mailing_id) if mailing_id.present?
recips = recips.where("mailing_recipients.sent_at >= ?", since) if since.present?
recips.select(:organization_id)
end
def opened_org_ids(mailing_id: nil)
recips = history_recipients.where.not(opened_at: nil)
recips = recips.where(mailing_id: mailing_id) if mailing_id.present?
recips.select(:organization_id)
end
def history_recipients
recips = MailingRecipient.joins(:mailing).where(mailings: { project_id: @project.id })
recips = recips.where.not(mailing_id: @mailing.id) if @mailing&.persisted?
recips
end
def project_mailing_ids(ids)
Mailing.for_project(@project).where(id: ids).select(:id)
end
end
end