Commit iniziale di eminuxCRM: CRM Rails con pipeline, campagne email e Docker.
CI / scan_ruby (push) Failing after 11m20s
CI / scan_js (push) Successful in 10m35s
CI / lint (push) Has been cancelled

Include autenticazione, progetti isolati, mail marketing HTML con SMTP, test A/B e editor WYSIWYG.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-08-17 23:01:48 +02:00
co-authored by Cursor
commit c4e5f289cf
258 changed files with 11293 additions and 0 deletions
+193
View File
@@ -0,0 +1,193 @@
module Catalog
ORGANIZATION_STATUSES = {
"prospect" => "Prospect",
"active_customer" => "Cliente attivo",
"inactive_customer" => "Cliente inattivo",
"partner" => "Partner",
"lost" => "Perso"
}.freeze
ORGANIZATION_TYPES = {
"societa_sportiva" => "Società sportiva",
"organizzatore_evento" => "Organizzatore evento",
"federazione" => "Federazione",
"comitato" => "Comitato",
"azienda" => "Azienda",
"altro" => "Altro"
}.freeze
TEAM_GENDERS = {
"female" => "Femminile",
"male" => "Maschile",
"mixed" => "Maschile e femminile"
}.freeze
STREAMING_STATUSES = {
"not_detected" => "Non rilevato",
"limited" => "Limitato",
"yes_partial" => "Sì / parziale",
"yes" => "",
"yes_sportcam" => " SportCam"
}.freeze
SEND_STATUSES = {
"to_send" => "Da inviare",
"sent" => "Inviato",
"no_send" => "Non inviare"
}.freeze
AB_VARIANTS = {
"A" => "Test A",
"B" => "Test B"
}.freeze
MAIL_ENCRYPTIONS = {
"starttls" => "STARTTLS (porta 587)",
"tls" => "SSL/TLS (porta 465)",
"none" => "Nessuna"
}.freeze
MAIL_AUTH_METHODS = {
"plain" => "PLAIN",
"login" => "LOGIN",
"cram_md5" => "CRAM-MD5"
}.freeze
MAILING_AUDIENCES = {
"to_send" => "Da inviare (campagna)",
"test_a" => "Solo chi è già Test A in scheda",
"test_b" => "Solo chi è già Test B in scheda",
"all" => "Tutte le organizzazioni del progetto"
}.freeze
MAILING_AB_ASSIGNMENTS = {
"from_record" => "Usa il Test A/B già in scheda",
"split" => "Suddividi a metà (A / B)"
}.freeze
MAILING_STATUSES = {
"draft" => "Bozza",
"sending" => "Invio in corso",
"sent" => "Inviata",
"cancelled" => "Annullata"
}.freeze
MAILING_RECIPIENT_STATUSES = {
"pending" => "Da inviare",
"skipped" => "Escluso",
"queued" => "In coda",
"sent" => "Inviata",
"failed" => "Errore"
}.freeze
PIPELINE_STAGES = {
"to_contact" => "Da contattare",
"contacted" => "Contattato",
"replied" => "Ha risposto",
"interested" => "Interessato",
"demo_trial" => "Demo / Trial",
"first_use" => "Primo utilizzo",
"proposal" => "Proposta",
"won" => "Cliente",
"lost" => "Perso"
}.freeze
PIPELINE_ORDER = PIPELINE_STAGES.keys.freeze
OPEN_PIPELINE_STAGES = %w[to_contact contacted replied interested demo_trial first_use proposal].freeze
LEAD_SOURCES = {
"outbound" => "Contatto diretto",
"campaign" => "Campagna lancio",
"referral" => "Referral",
"federation" => "Federazione/comitato",
"event" => "Evento",
"website" => "Sito",
"organic" => "Organico",
"partner" => "Partner",
"social" => "Social",
"other" => "Altro"
}.freeze
LOST_REASONS = {
"no_response" => "Nessuna risposta",
"not_interested" => "Non interessato",
"price" => "Prezzo",
"competitor" => "Usa già altra soluzione",
"no_streaming" => "Non fa streaming",
"timing" => "Timing",
"technical" => "Problema tecnico",
"deferred" => "Decisione rimandata",
"other" => "Altro"
}.freeze
ACTIVITY_TYPES = {
"note" => "Nota",
"email_sent" => "Email inviata",
"email_received" => "Email ricevuta",
"call" => "Telefonata",
"meeting" => "Meeting",
"demo" => "Demo",
"trial_started" => "Trial attivato",
"follow_up" => "Follow-up",
"first_use" => "Primo utilizzo",
"proposal_sent" => "Proposta inviata",
"won" => "Vinto",
"lost" => "Perso",
"other" => "Altro"
}.freeze
TASK_TYPES = {
"follow_up" => "Follow-up",
"call" => "Chiamata",
"email" => "Email",
"meeting" => "Meeting",
"demo" => "Demo",
"proposal" => "Proposta",
"generic" => "Generico"
}.freeze
TASK_PRIORITIES = {
"low" => "Bassa",
"normal" => "Normale",
"high" => "Alta",
"urgent" => "Urgente"
}.freeze
TASK_STATUSES = {
"pending" => "In corso",
"completed" => "Completato",
"cancelled" => "Annullato"
}.freeze
CONTACT_METHODS = {
"email" => "Email",
"phone" => "Telefono",
"mobile" => "Cellulare",
"whatsapp" => "WhatsApp",
"meeting" => "Incontro"
}.freeze
GOAL_METRICS = {
"customers_acquired" => "Clienti acquisiti",
"won_value" => "Valore opportunità vinte",
"trials" => "Numero trial",
"first_uses" => "Numero primi utilizzi"
}.freeze
STAGE_PROBABILITIES = {
"to_contact" => 5,
"contacted" => 10,
"replied" => 20,
"interested" => 40,
"demo_trial" => 55,
"first_use" => 70,
"proposal" => 80,
"won" => 100,
"lost" => 0
}.freeze
def self.label_for(hash, key)
hash[key.to_s] || key.to_s.humanize
end
end