
Smart Event Ticketing
Eventix
Gestisci eventi, accrediti e richieste.
Un unico spazio operativo.
Area riservata

Smart Event Ticketing
Gestisci eventi, accrediti e richieste.
Un unico spazio operativo.
Area riservata



Sviluppo: Simone Grandi
Un prodotto Tecnodream.
# Changelog
Tutte le modifiche rilevanti a questo progetto saranno documentate in questo file.
## [Unreleased]
### Added
- Elenco e gestione biglietti (solo admin): nuova voce **Biglietti** nel menu con tutti i nominativi tracciati — evento e data, richiedente, stato richiesta, stati biglietto/pass e zona, badge allegato, registrazione e il contatore "N richieste" sotto al nominativo — con filtro live e scheda **Dettaglio** con link a *Gestisci richiesta*; dalla scheda si aggiornano **link PDF** e **codice biglietto** (il caricamento file PDF è predisposto ma al momento disabilitato) e la tipologia di invio dell'evento è mostrata come riferimento. Il riallineamento con la richiesta ora conserva gli allegati: risalvare non azzera più PDF e codici inseriti.
- Nuova richiesta senza nominativi: i **nomi dei partecipanti sono facoltativi** all'inserimento (e nella modifica completa admin). La richiesta viene salvata anche senza nominativi con un avviso giallo; admin ed editor ricevono una notifica interna "Richiesta senza nominativi" (messaggio **URGENTE** se all'evento mancano meno di 5 giorni). Le richieste senza nominativi e con evento a **meno di 5 giorni** sono evidenziate con un alert rosso in dashboard, *Gestisci richiesta* e *Modifica richiesta*, con badge di richiamo negli elenchi.
- Creazione rapida "in overlay" di Luogo e Organizzatore dal form evento (nuovo e modifica): i pulsanti **+** aprono una modale che salva **senza ricaricare la pagina** tramite i nuovi endpoint JSON `POST /api/locations` e `POST /api/organizers`; il record creato viene aggiunto e selezionato automaticamente nella tendina e i dati già inseriti nell'evento restano compilati.
- **Prompt di impegno sui nominativi (ruolo utente)**: inviando una nuova richiesta senza nominativi l'utente vede la finestra *Nominativi da comunicare* con la scadenza (5 giorni prima dell'evento) e deve spuntare *Accetto l'impegno* per procedere (l'invio è bloccato anche lato server); l'impegno è registrato sulla richiesta. Il richiedente riceve l'email di conferma con la scadenza e lo staff viene avvisato dell'impegno preso. Admin ed editor inviano senza prompt.
- **Promemoria automatici per i nominativi mancanti**: avvicinandosi la scadenza, richiedente e staff ricevono una email di promemoria e una notifica in campanella per le richieste ancora prive di nominativi; l'invio è idempotente (una sola volta per richiesta).
- **Richiesta presa in carico e completamento nominativi**: una richiesta è "presa in carico" quando almeno un biglietto/pass è *Emesso* oppure lo staff ha portato lo stato oltre *Ricevuta*. Da allora il richiedente non può più modificarla né eliminarla (403/404) e la pagina diventa **Richiedi una modifica**; può solo completare le schede senza nome o cognome (sezione *Completa i nominativi mancanti*, con telefono/email) oppure inviare una richiesta di modifica dal diario note.
- **Avviso "Nomi Modificati"**: il completamento dei nominativi attiva il nuovo flag `requests.names_modified`, mostra badge negli elenchi e alert in *Gestisci richiesta*/*Modifica richiesta* e riallinea i biglietti in `tickets` dei nominativi toccati, conservando gli allegati dei nomi invariati. L'avviso si azzera salvando la richiesta dalla gestione.
- **Eliminazione richiesta**: nuovo pulsante *Elimina* (con conferma) nella pagina di modifica e negli elenchi dashboard/evento. Gli admin eliminano qualsiasi richiesta, gli utenti solo le proprie non ancora prese in carico; la cancellazione rimuove a cascata partecipanti, diario note e biglietti. Il redirect accetta solo un `return_to` interno (anti-open-redirect).
### Changed
- **Debug Flask sicuro per default**: `FLASK_DEBUG` ha default `false` e l'avvio diretto con debug attivo e `HOST` non locale (es. `0.0.0.0`) viene rifiutato con un errore esplicito, per non esporre in rete il debugger Werkzeug; `python app.py` usa `HOST` con default `127.0.0.1` e `PORT` invariato. Variabili documentate in `README.md` e `.env.example`.
- Recapiti del referente esterno riusati senza doppio inserimento: se il referente/richiedente esterno coincide (confronto normalizzato di nome e cognome) con un partecipante, i recapiti già indicati vengono copiati automaticamente sui campi vuoti della scheda partecipante, sia lato server sia in tempo reale nei form.
### Fixed
- Richieste senza nominativi: `add_request` e `update_request_full_admin` non bloccano più il salvataggio quando nome o cognome dei partecipanti non sono compilati; il referente scelto fra i partecipanti continua a richiedere nome, cognome e un recapito valido.
### Security
- **Protezione CSRF su tutte le azioni di modifica**: ogni richiesta `POST`/`PUT`/`PATCH`/`DELETE` deve inviare un token legato alla sessione — campo nascosto in tutti i form, header `X-CSRF-Token` per le richieste in background, campo `csrf_token` nel body JSON. Senza token valido la richiesta viene respinta prima di toccare il database o inviare email: `400 {"ok": false}` per gli endpoint `/api/*`, avviso e ritorno a una pagina sicura per le pagine normali. Il token è stabile per la durata della sessione, quindi i form aperti a lungo restano validi; accesso (`/login`) e primo inserimento password restano esenti in questa fase.
- **Cookie di sessione più protetti**: `SESSION_COOKIE_HTTPONLY=True` e `SESSION_COOKIE_SAMESITE="Lax"`; `SESSION_COOKIE_SECURE` non viene attivato automaticamente perché richiede HTTPS.
## [0.4.4] - 2026-10-05
### Changed
- Eventi con più contatti organizzatore: selettori ripetibili e ricercabili, senza duplicati, filtrati per organizzatore. Il cambio organizzatore azzera le selezioni; modifica e duplicazione conservano l'ordine. Elenco e dettaglio mostrano tutti i contatti (con recapiti nel dettaglio).
- Etichette evento uniformate a **Nome — Città** in elenchi, dashboard, richieste e suggerimenti di ricerca; senza città rimane il solo nome.
- Inizializzazione database: tabella `event_organizer_contacts` e recupero idempotente dei contatti legacy validi, mantenendo il primo contatto in `events.organizer_contact_id` per compatibilità.
### Fixed
- Notifiche (alert) rivisti: risolto il bug `psycopg2.InterfaceError: cursor already closed` in gestione richiesta (il controllo "evento passato" riusava il cursore dopo `cur.close()`, quindi la notifica di emissione non partiva mai e scattavano retry/500); confronto date unificato su `datetime.now()`; anti-duplicato interno (stessa notifica allo stesso utente entro 10 minuti, un solo inserimento per utente anche se i ruoli si sovrappongono) e anti-toast-doppio nel frontend (stessa pagina + altre tab via `localStorage`): niente più "4 notifiche uguali".
- Alert visivi coerenti: giorni rimanenti calcolati a giorno (`event.date - oggi`), non a ore — "Domani" resta domani fino a mezzanotte, "Oggi" solo il giorno stesso, evento passato marchiato **Scaduto** (mai "Oggi"/giorni negativi); richieste da gestire con badge graduato (grigio da 1 g, giallo da 3 g) e riga `table-warning` da 1 g; elenco eventi con badge **Scaduto · data** anche nel filtro "Tutti".
### Added
- Tracciamento nomi richiesti (visibile **solo agli admin**): nuova tabella `tickets` che registra ogni nominativo per cui vengono chiesti biglietti/pass (una riga per richiesta e nome normalizzato, con i campi riservati `pdf_url`/`ticket_code` predisposti ma non ancora usati per allegare PDF o codice). Se un admin immette un nome già presente riceve un **avviso giallo** ("Nome già richiesto in precedenza…") con il numero di richieste precedenti e il contatore viene incrementato; in *Gestisci richiesta* e nella *Modifica richiesta completa* sotto al nome compare in piccolo **quante richieste di biglietti/pass sono state fatte** per quella persona. Mentre digiti nome e cognome nei form compaiono avvisi a comparsa con i nomi già richiesti o simili (`GET /api/tickets/check`, solo admin); i flash ora distinguono il colore per categoria (giallo per gli avvisi, rosso per gli errori).
- Ricerca globale nell'header (`GET /api/search?q=`): campo centrale con risultati live raggruppati (Eventi, Richieste, Luoghi, Organizzatori, Utenti) e link diretti; lo scope rispetta il ruolo (gli user vedono solo eventi attivi futuri e proprie richieste). I risultati di eventi e richieste mostrano anche la data dell'evento (gg/mm/aaaa hh:mm) per distinguere gli omonimi.
- Filtro dinamico in tempo reale in ogni vista di gestione (richieste in dashboard e dettaglio evento, eventi, luoghi, organizzatori, utenti): campo al centro della barra titolo, conteggio “N totali” aggiornato al volo e messaggio di nessun risultato; i link globali a luoghi/organizzatori/utenti precompilano il filtro via `?q=`.
- Gestione richiesta: il blocco di aggiornamento in massa è ora **"Applica a selezione"**: ogni partecipante ha un flag di selezione con casella **"Tutti"** nell'intestazione della tabella; gli stati biglietti/pass (e la nuova **zona biglietto**) si applicano solo ai selezionati, con avviso se nessuno è spuntato.
- Gestione richiesta: quando un biglietto viene messo in stato **Emesso** compare la scelta della **tipologia di posto** (zona, es. Platea, Tribuna numerata) presa dalla scheda evento, con posti disponibili indicati; la zona è salvata per partecipante (`request_participants.ticket_zone`, conservata anche nelle modifiche complete admin e azzerata se il biglietto non è più emesso). Applicabile anche in massa ai selezionati.
- Dettaglio evento (admin/editor): **overview sempre visibile** con biglietti totali, disponibilità residua (colorata a semaforo), richieste da evadere e numero di zone ripartite.
- Eventi: **Zone e biglietti multipli** (`events.ticket_zones`, es. Posto unico, Platea, Tribuna numerata): nel form nuovo/modifica evento ogni riga è *zona + posti*; scegli una zona e compare automaticamente una nuova riga, senza duplicati. Il default è **"Posto unico"**. La **somma dei posti delle zone deve coincidere con i posti totali** (che fanno fede per semaforo e disponibilità): in caso di scostamento compare un avviso con le azioni **"Aggiorna totale"** (allinea il totale alla somma) e **"Rivedi posti"** (resta da correggere, l'invio è bloccato finché non coincidono); il server valida di nuovo e avvisa con un flash. La **capienza del luogo è solo un riferimento visualizzato, mai compilata in automatico**. Zone e posti sono mostrati nel dettaglio evento; la duplicazione evento li copia. Elenco zone e **sinonimi** (righe `Canonico = alias1, alias2`, usati per normalizzare i nomi in fase di importazione) configurabili in *Impostazioni* (`ticket_zones_list`, `ticket_zone_synonyms`).
- Gestione utenti: il form "Nuovo utente" (solo admin) include i campi **Telefono** e il flag **Richiesta pass** (gli admin sono sempre abilitati e l'elenco mostra telefono e permesso pass di ogni utente); **solo gli admin gestiscono i pass**: nella gestione richiesta gli altri ruoli vedono categoria e stato pass in sola lettura (niente flag, selettori o applicazione in massa) e il server ignora comunque i campi pass eventualmente inviati dal form.
- Gestione utenti rifatta: l'elenco `/users` è ora una tabella di sola lettura (anagrafica, contatti, ruolo, permesso pass) e ogni persona ha una pagina di modifica dedicata `/users/<id>/edit`; gli admin gestiscono username, ruolo, permesso pass e possono **reimpostare la password**, gli editor modificano solo anagrafica e contatti.
- Profilo personale `/profilo` per tutti i ruoli (raggiungibile dal menu del proprio nome): dati personali e avatar, cambio password con verifica della password attuale e **preferenze di notifica individuali** (nuove colonne `users.notify_email` e `users.notify_browser`): disattivando le email non si ricevono più le notifiche di sistema, disattivando gli avvisi a comparsa non compaiono più i toast (campanella e contatore restano attivi).
- Eventi: campo **Piattaforme di vendita** (`events.sales_platform`, es. Botteghino, Sito Web Ufficiale, TicketOne, Vivaticket), **una o più per evento**: alla creazione e in modifica evento una nuova riga di selezione compare automaticamente dopo la scelta, senza duplicati. Elenco configurabile `sales_channels_list` nelle Impostazioni; mostrato nel dettaglio evento e nella pagina di modifica richiesta.
- Modifica richiesta (admin): il richiedente registrato si seleziona con un combobox ricercabile con voce "Esterno"; se il richiedente e indicato come referente, i recapiti (telefono/email) vengono compilati automaticamente dai dati utente, con fallback lato server.
- Impostazioni: nuovo elenco "Piattaforme di vendita" (`sales_channels_list`) modificabile dagli admin.
- Eventi: **Artista**, **Città** e **Luogo** (testo libero di fallback) funzionano come gli altri campi di ricerca: mentre digiti propongono gli artisti già usati negli altri eventi, le città già usate e i nomi dei luoghi esistenti, per evitare doppioni e varianti dello stesso nome; resta possibile inserire un valore nuovo.
- Eventi: gli admin possono **duplicare** un evento dal pulsante "Duplica" in `/events` (`POST /events/<id>/duplicate`): copia senza richieste (nome + " (copia)", luogo, organizzatore, consegna, piattaforme e responsabili); la copia nasce non attiva da verificare/attivare.
## [0.4.3] - 2026-09-15
### Fixed
- Gestione richiesta: sistemato il layout della tabella partecipanti — niente più campi sovrapposti o tagliati: la pagina usa tutta la larghezza disponibile, ogni colonna ha una larghezza minima (Partecipante, Contatti, Biglietto, Pass), i contatti sono impilati senza schiacciare la riga, i select ricercabili compatti non vengono più coperti dalle icone di freccia e di reset e la tabella scorre in orizzontale sui display stretti. Il blocco "Applica a selezione" non comprime più select e pulsante (vanno a capo) e passa a tre colonne solo da schermi `lg`.
### Added
- Gestione richiesta (admin/editor): **disponibilità residua visibile** durante la selezione e l'assegnazione del posto. In cima alla pagina i badge posti totali / richiesti / disponibili (a semaforo come nel dettaglio evento) e, per gli eventi con più zone, i **posti liberi per zona** con la zona esaurita evidenziata. In ogni riga la tendina della tipologia di posto mostra i posti liberi della zona e, sotto la scelta, compare l'avviso "Posti liberi in …: N su M" (oppure "Zona esaurita"), aggiornato al volo quando si cambia stato biglietto o zona; anche il selettore in massa "Zona biglietto dei selezionati" riporta i posti liberi di ogni zona.
## [0.4.2] - 2026-09-14
### Fixed
- Login: il nome utente non è più sensibile alle maiuscole/minuscole — accetta ad esempio `Admin`, `ADMIN` o `aDmin` per l'utente registrato come `admin` (la password resta sensibile alle maiuscole).
- Homepage e filtro richieste: corretto il filtro "Archiviate", che passava `status=Archiviate` invece del valore realmente salvato nel database (`Archiviata`), quindi la selezione non mostrava alcuna richiesta anche quando una richiesta archiviata esisteva.
- Homepage (admin/editor): aggiunto il pulsante **Archivia** accanto alle richieste concluse (evento già passato o già archiviate) per portarle direttamente a stato `Archiviata`.
- Gestione richiesta: l'archiviazione (o l'aggiornamento) di una richiesta per un evento **già passato** non invia più nessuna notifica (né email né notifica interna di emissione biglietti/pass).
- Nuova richiesta (admin): selezionando un richiedente dall'elenco utenti, il nominativo e i recapiti (telefono/email) del referente (se il destinatario è il richiedente) vengono compilati automaticamente; inoltre il form non richiede più il reinserimento dei recapiti del richiedente esterno quando questi sono già indicati nella sezione Richiedente.
- Nuova richiesta (admin): corretto il salvataggio del richiedente selezionato dall'elenco utenti: prima il nome veniva copiato nel campo del richiedente esterno e il server lo trattava come esterno perdendo il collegamento all'utente; ora `requested_by` ha priorità sul nome, quindi il richiedente registrato viene associato correttamente all'utente e i recapiti del referente sono presi dal suo profilo.
- Nuova richiesta (admin): corretta la compilazione/ripristino dei dati del primo partecipante quando la validazione del form riporta di nuovo i campi partecipanti dopo un errore.
- Homepage e elenco eventi: precisato che la home mostra gli eventi futuri; un evento futuro prossimo (es. "Ligabue - Jesolo" del 12/09/2026) appare normale e non grigio perché non ancora scaduto; lo sfondo grigio/evidenziazione per scaduti vale sugli elenchi completi o quando filtrati per eventi passati.
- Gestione eventi e modifica evento: risolto l'errore `psycopg2.InterfaceError: cursor already closed` (le impostazioni venivano lette dopo la chiusura del cursore).
- Modifica richiesta: rimosso l'`id` duplicato del campo Note nel form completo.
- Notifiche: corrette le regole di invio — l'emissione di biglietti/pass notifica l'utente richiedente (o il referente invio per richiedenti esterni), le nuove note notificano anche l'utente richiedente oltre ad admin/editor, l'autore non riceve la notifica della propria azione e le richieste di modifica su biglietti emessi avvisano admin/editor.
- Gestione luoghi: corretto il disallineamento tra query e template — la tabella mostrava città/capienza/contatti nei campi sbagliati e i pulsanti "Sito web", "Mappa" e "Planimetria" puntavano a campi diversi; nei form di creazione e modifica manca la **Città** (che veniva azzerata a ogni salvataggio) e la tipologia selezionata non risultava mai corretta: ora campi e indici sono allineati e l'ordine è Nome, Indirizzo, Città, Tipologia, Capienza, Sito web, Mappa, Planimetria, Contatto, Email, Telefono.
- Dashboard: le richieste concluse (evento già passato o archiviate) sono spostate in fondo all'elenco ed evidenziate con sfondo grigio, come per gli eventi passati.
- Elenco eventi: con il filtro "Tutti" gli eventi già terminati (data passata) sono spostati in fondo all'elenco ed evidenziati con sfondo grigio, in linea con le richieste concluse in dashboard.
## [0.4.1] - 2026-09-09
### Added
- Eventi: tipologia di invio biglietti (`events.delivery_type`: invio digitale, invio cartaceo, ritiro in cassa accrediti, codice, altro) con note aggiuntive libere (`events.delivery_notes`), selezionabile alla creazione e modificabile dagli admin; mostrata nel dettaglio evento e nella creazione richiesta quando si seleziona l'evento.
- Gestione eventi: il form di creazione evento non è più sempre visibile in alto ma si apre da un pulsante "Nuovo evento" in una finestra modale.
- Gestione richiesta: aggiornamento in massa degli stati dei biglietti (e dei pass) di tutti i partecipanti con un solo clic.
- Ottimizzazione layout mobile: page-heading impilabile, tabelle e form più compatti su smartphone.
## [0.4.0] - 2026-09-09
### Added
- Richieste: scelta del destinatario di biglietti e pass (richiedente o uno dei partecipanti referente). Il referente deve avere nome, cognome e almeno un recapito validato (telefono o email). Possibile scegliere come richiedente anche utenti admin/editor, non solo user.
- Note delle richieste salvate come diario/log (`request_notes`): ogni inserimento viene aggiunto con autore, ruolo e data. Gli utenti modificano le richieste non emesse; dopo l'emissione inviano una richiesta di modifica agli amministratori.
- Modifica completa della richiesta riservata agli admin: richiedente (anche esterno), radio/cliente, quantita, partecipanti, destinatario invio.
- Eliminazione eventi e luoghi (solo admin, con conferma): la cancellazione e bloccata se esistono richieste/collegamenti.
- Luoghi: campi edit/delete ripristinati con piano di modifica completo (anche link mappa dedicato).
- PWA: `manifest.webmanifest`, icone dedicate e meta tag; il titolo delle pagine ora e `Eventix | pagina`.
### Fixed
- Pulsanti modifica/elimina uniformati (dimensioni identiche) su organizzatori, eventi e luoghi.
- "Apri mappa" dell'evento usa il link mappa del luogo oppure Google Maps dall'indirizzo (prima inviava al sito web).
- Impaginazione lista eventi e form richiesta su smartphone (layout non piu sovrapposto).
## [0.3.2] - 2026-09-09
### Fixed
- Sistemata la ricerca dinamica: i campi ricerca/combo non visualizzano più tutti i record sovrapposti, ma si comportano con una ricerca dinamica con autocomplete (ricerca per sottostringa, anche parte di una parola all'interno della frase). Aggiunto pulsante freccia per visualizzare tutte le opzioni disponibili. Applicato a tutti i campi di questo tipo nell'app.
## [0.3.1] - 2026-09-02
### Fixed
- Risolto il conflitto nell'uso contemporaneo dello stesso file di versione/changelog e verificata la correttezza complessiva delle funzionalità e dei test.
## [0.3.0] - 2026-09-02
### Fixed
- Corretta la gestione dei contatti dell'organizzatore nella creazione e modifica degli eventi, garantendo che vengano mostrati e associati correttamente solo se l'organizzatore è selezionato.
### Added
- Gestione anagrafiche organizzatori e contatti associabili agli eventi.
- Aggiornamento dei luoghi registrati con il link al sito web in sostituzione del link mappa.
## [0.2.0] - 2026-09-01
### Added
- Menu operativo permanente per ogni ruolo.
- Gestione eventi, partecipanti, disponibilita e impostazioni.
- Impersonificazione utenti riservata agli amministratori.
- Credits con dati sviluppatore e cronologia delle versioni.
- Anagrafiche organizzatori, relativi contatti e aggiornamento gestione luoghi con sito web.
## [0.1.0] - 2026-09-01
### Added
- Gestione ruoli, eventi e richieste.
- Area amministrativa per utenti ed eventi.