Aggiunge filtri avanzati per i destinatari delle campagne email.
CI / scan_ruby (push) Failing after 18m40s
CI / scan_js (push) Successful in 11m46s
CI / lint (push) Failing after 13m8s

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>
This commit is contained in:
2026-08-24 21:00:11 +02:00
co-authored by Cursor
parent 2db7504629
commit 1f946f63ba
19 changed files with 912 additions and 46 deletions
+69 -4
View File
@@ -1,6 +1,6 @@
class MailingsController < ApplicationController
before_action :require_current_project!
before_action :set_mailing, only: %i[show edit update destroy queue cancel test_send test_preview refresh_recipients update_recipients preview]
before_action :set_mailing, only: %i[show edit update destroy queue cancel test_send test_preview refresh_recipients update_recipients preview audience update_audience]
before_action :load_form_collections, only: %i[new create edit update]
def index
@@ -26,6 +26,7 @@ class MailingsController < ApplicationController
mail_template: template,
mail_identity: identity,
audience: "to_send",
audience_filters: Mailings::AudienceFilters.default("to_send").to_h,
interval_seconds: 0,
send_window_start_minutes: 10 * 60,
send_window_end_minutes: 18 * 60,
@@ -41,8 +42,7 @@ class MailingsController < ApplicationController
@mailing.project = current_project
apply_template_if_needed
if @mailing.save
@mailing.rebuild_recipients!
redirect_to @mailing, notice: "Bozza creata. Controlla i destinatari e poi invia."
redirect_to audience_mailing_path(@mailing), notice: "Bozza creata. Ora raffina i destinatari, poi genera la lista."
else
@page_title = "Nuovo invio"
render :new, status: :unprocessable_entity
@@ -95,6 +95,45 @@ class MailingsController < ApplicationController
redirect_to dashboard_mailings_path, notice: "Invio eliminato."
end
def audience
unless @mailing.editable?
redirect_to @mailing, alert: "I destinatari sono bloccati: l'invio è già partito."
return
end
@page_title = "Destinatari · #{@mailing.name}"
load_audience_options
assign_audience_preview
end
def update_audience
unless @mailing.editable?
redirect_to @mailing, alert: "I destinatari sono bloccati: l'invio è già partito."
return
end
filters = Mailings::AudienceFilters.from_params(audience_filter_params)
@mailing.assign_attributes(audience_filters: filters.to_h, audience: filters.preset)
unless @mailing.save
@page_title = "Destinatari · #{@mailing.name}"
load_audience_options
assign_audience_preview
render :audience, status: :unprocessable_entity
return
end
if Array(params[:intent]).include?("apply")
@mailing.rebuild_recipients!
redirect_to @mailing, notice: "Lista generata: #{@mailing.pending_count} da inviare, #{@mailing.skipped_count} esclusi."
else
@page_title = "Destinatari · #{@mailing.name}"
load_audience_options
assign_audience_preview
render :audience
end
end
def refresh_recipients
unless @mailing.editable?
redirect_to @mailing, alert: "Destinatari bloccati: l'invio è già partito."
@@ -224,11 +263,37 @@ class MailingsController < ApplicationController
def rebuild_recipients_if_needed
return unless @mailing.editable?
return unless @mailing.saved_change_to_audience? || @mailing.saved_change_to_ab_test? || @mailing.saved_change_to_ab_assignment?
return unless @mailing.saved_change_to_ab_test? || @mailing.saved_change_to_ab_assignment?
@mailing.rebuild_recipients!
end
def load_audience_options
orgs = Organization.for_project(current_project)
@sport_options = orgs.where.not(sport: [nil, ""]).distinct.order(:sport).pluck(:sport)
@region_options = orgs.where.not(region: [nil, ""]).distinct.order(:region).pluck(:region)
@province_options = orgs.where.not(province: [nil, ""]).distinct.order(:province).pluck(:province)
@history_mailings = Mailing.for_project(current_project).where.not(id: @mailing.id).recent
end
def assign_audience_preview
@filters = @mailing.parsed_audience_filters
query = @mailing.audience_query
@audience_counts = query.counts
@audience_preview = query.preview
@open_sections = Array(params[:open_sections]).map(&:to_s)
end
def audience_filter_params
params.fetch(:filters, ActionController::Parameters.new).permit(
:preset, :list_min, :list_max, :estimated_value, :history_kind, :history_mailing_id, :history_days,
:exclude_customers, :exclude_mailed_within_days,
sports: [], team_genders: [], regions: [], provinces: [], streaming_statuses: [], statuses: [],
send_statuses: [], ab_variants: [], pipeline_stages: [],
exclude_received_mailing_ids: [], exclude_opened_mailing_ids: []
)
end
def preview_recipient
if params[:recipient_id].present?
@mailing.mailing_recipients.find_by(id: params[:recipient_id])