Importa i prospect Calcio a 5 senza toccare la Pallavolo e filtra le organizzazioni per sport.
CI / scan_ruby (push) Failing after 15m50s
CI / scan_js (push) Successful in 18m7s
CI / lint (push) Failing after 12m1s

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-09-05 11:07:43 +02:00
co-authored by Cursor
parent b5737a7ee7
commit e492c43bf8
7 changed files with 320 additions and 9 deletions
@@ -3,8 +3,9 @@ require "csv"
class CampaignImport::MatchlivetvLaunch
CAMPAIGN_NAME = "Campagna lancio 01".freeze
SPORT = "Pallavolo".freeze
LEGAL_PREFIXES = /\b(ssdarl|ssd arl|a\.?s\.?d\.?|asd|s\.?s\.?d\.?|ssd|s\.?s\.?|a\.?f\.?|a\.?p\.?|c\.?s\.?|polisportiva)\b/i
Result = Struct.new(:wiped_organizations, :imported, :errors, keyword_init: true)
Result = Struct.new(:wiped_organizations, :imported, :skipped, :errors, keyword_init: true)
STREAMING_MAP = {
"NON RILEVATO" => "not_detected",
@@ -27,11 +28,13 @@ class CampaignImport::MatchlivetvLaunch
"NON INVIARE" => "no_send"
}.freeze
def initialize(path:, user: nil, project: nil, wipe: true)
def initialize(path:, user: nil, project: nil, wipe: true, sport: SPORT, campaign_name: CAMPAIGN_NAME)
@path = Pathname.new(path)
@user = user
@project = project
@wipe = wipe
@sport = sport
@campaign_name = campaign_name
end
def call
@@ -43,17 +46,27 @@ class CampaignImport::MatchlivetvLaunch
Current.project = @project
wiped = @wipe ? wipe_project! : 0
index_existing_names!
imported = 0
skipped = 0
errors = []
rows.each_with_index do |row, idx|
name = cell(row, "Società")
if duplicate_name?(name)
skipped += 1
next
end
import_row!(row)
remember_name!(name)
imported += 1
rescue StandardError => e
errors << { line: idx + 2, name: row["Società"], message: e.message }
message = e.is_a?(ActiveRecord::RecordInvalid) ? e.record.errors.full_messages.to_sentence : e.message
errors << { line: idx + 2, name: row["Società"], message: message }
end
Result.new(wiped_organizations: wiped, imported: imported, errors: errors)
Result.new(wiped_organizations: wiped, imported: imported, skipped: skipped, errors: errors)
ensure
Current.user = nil
Current.project = nil
@@ -88,11 +101,11 @@ class CampaignImport::MatchlivetvLaunch
org = Organization.new(
name: name,
organization_type: "societa_sportiva",
sport: SPORT,
sport: @sport,
country: "Italia",
region: cell(row, "Regione"),
province: cell(row, "Prov."),
email: cell(row, "Email verificata")&.downcase,
email: normalize_email(cell(row, "Email verificata")),
website: cell(row, "Sito / profilo"),
source_url: cell(row, "Fonte contatto / ricerca"),
commercial_fit: cell(row, "Evidenza / fit commerciale"),
@@ -129,10 +142,10 @@ class CampaignImport::MatchlivetvLaunch
end
org.opportunities.create!(
name: CAMPAIGN_NAME,
name: @campaign_name,
project: @project,
pipeline_stage: stage,
product: cell(row, "Piano"),
product: blank_if_no(cell(row, "Piano")),
assigned_user: @user,
ab_variant: cell(row, "Test A/B").to_s.upcase.presence,
send_status: SEND_MAP.fetch(normalize_key(cell(row, "Stato invio")), "to_send"),
@@ -144,6 +157,43 @@ class CampaignImport::MatchlivetvLaunch
)
end
def index_existing_names!
@existing_names = {}
Organization.find_each { |org| remember_name!(org.name) }
end
def remember_name!(name)
key = normalize_org_name(name)
@existing_names[key] = true if key.present?
end
def duplicate_name?(name)
key = normalize_org_name(name)
key.blank? || @existing_names[key]
end
def normalize_org_name(name)
I18n.transliterate(name.to_s)
.downcase
.gsub("'", " ")
.gsub(LEGAL_PREFIXES, " ")
.gsub(/[^a-z0-9]+/, " ")
.squeeze(" ")
.strip
end
def blank_if_no(value)
return if value.blank?
return if %w[NO N/A].include?(normalize_key(value))
value
end
def normalize_email(value)
email = value.to_s.strip.downcase.gsub(/\s+/, "")
email.presence
end
def cell(row, header)
value = row[header].to_s.strip
value.presence