From 57463f993b0079b035c67546e16c8bec3ca8d009 Mon Sep 17 00:00:00 2001 From: Davide Grilli Date: Wed, 9 Sep 2026 10:24:43 +0200 Subject: [PATCH] Bonifica una tantum le righe orfane da eventi cancellati prima di M14 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit M14 (DD-029) pulisce a cascata i dati collegati solo per le cancellazioni future; questa migration ripulisce lo storico. Per risposte_presenze, cacche_partita, turni_palloni, scout_sessioni, scout_live e scout_partite elimina ogni riga il cui evento_id non esiste più in eventi_app. Per mvp_voti, pagelle_voti e badge_social_voti serve più cautela: prima del passaggio all'id evento CrAPP, match_id conteneva id Scout (prefisso "s") o CSI (numerico o data-based), voti storici legittimi mai collegati a un evento CrAPP. Il filtro si applica solo ai match_id nel formato di nuovoIdEvento() ("e" + timestamp base36), così i vecchi voti Scout/CSI restano intatti. Verificato manualmente sul database locale prima dell'applicazione. Co-Authored-By: Claude Sonnet 5 --- docs/CHANGELOG.md | 6 +- docs/DATABASE.md | 2 +- docs/DESIGN_DECISIONS.md | 17 +++++- ...130000_m15_bonifica_dati_evento_orfani.sql | 55 +++++++++++++++++++ 4 files changed, 74 insertions(+), 6 deletions(-) create mode 100644 supabase/migrations/20260909130000_m15_bonifica_dati_evento_orfani.sql diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index 5daf001..21cae1a 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -82,8 +82,10 @@ Prima versione, pre-release. Alcuni conteggi `mvp` già mostrati possono scendere per effetto della nuova regola. - Cancellare un evento pulisce ora a cascata, tramite trigger database, tutte le tabelle collegate (presenze, pagelle, MVP, badge social, turni palloni, scout) invece di lasciarle - come righe orfane (migration `m14_pulizia_dati_evento_cancellato`, DD-029). Le righe orfane - generate da cancellazioni precedenti a questa migration non vengono bonificate. + come righe orfane (migration `m14_pulizia_dati_evento_cancellato`, DD-029). +- Bonificate una tantum le righe orfane lasciate da cancellazioni precedenti a M14 (migration + `m15_bonifica_dati_evento_orfani`), senza toccare i vecchi voti MVP/pagelle/badge social + legati a id Scout o CSI, che restano dati storici legittimi (DD-029). ### Sicurezza diff --git a/docs/DATABASE.md b/docs/DATABASE.md index a86e21c..8239575 100644 --- a/docs/DATABASE.md +++ b/docs/DATABASE.md @@ -46,7 +46,7 @@ La tabella è verificata da `test/integration/permessi.test.ts` contro il databa | Tabella | Scopo | Note | | ------------------- | ---------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `eventi_app` | Eventi gestionali utilizzati dall'app. | Modello in uso dal codice attuale. Cancellare un evento pulisce a cascata, tramite trigger, tutte le tabelle collegate elencate in questa pagina (`risposte_presenze`, `cacche_partita`, `mvp_voti`, `pagelle_voti`, `badge_social_voti`, `turni_palloni`, `scout_sessioni`, `scout_live`, `scout_partite`) — migration `m14_pulizia_dati_evento_cancellato`, DD-029. | +| `eventi_app` | Eventi gestionali utilizzati dall'app. | Modello in uso dal codice attuale. Cancellare un evento pulisce a cascata, tramite trigger, tutte le tabelle collegate elencate in questa pagina (`risposte_presenze`, `cacche_partita`, `mvp_voti`, `pagelle_voti`, `badge_social_voti`, `turni_palloni`, `scout_sessioni`, `scout_live`, `scout_partite`) — migration `m14_pulizia_dati_evento_cancellato`, DD-029. Le righe orfane da cancellazioni precedenti sono state bonificate una tantum da `m15_bonifica_dati_evento_orfani`, senza toccare i vecchi voti MVP/pagelle/badge social legati a id Scout o CSI. | | `risposte_presenze` | Risposte dei giocatori agli eventi. | Modello in uso dal codice attuale. `risposto_il` è l'istante della **prima** risposta (migration `m9_risposte_presenze_risposto_il`): confrontato con `eventi_app.creato_il` dà la serie "Conferme 24h". Un trigger lo rende immutabile, così un ripensamento non fa risultare rapida una risposta lenta — `aggiornato_il` resta l'ultima modifica. | | `eventi` | Calendario generale: allenamenti, partite, eventi della squadra. | Modello "nuovo" con autenticazione e vincoli, non ancora adottato (DD-014). | | `presenze` | Presenze agli eventi. | Come sopra (DD-014). | diff --git a/docs/DESIGN_DECISIONS.md b/docs/DESIGN_DECISIONS.md index 3673578..2942a4b 100644 --- a/docs/DESIGN_DECISIONS.md +++ b/docs/DESIGN_DECISIONS.md @@ -1130,7 +1130,18 @@ PostgREST, non solo chi passa dal bottone dell'app. scrive una riga in ciascuna delle otto tabelle, cancella l'evento e verifica che spariscano tutte. +**Aggiornamento (9 settembre 2026, stesso giorno)** — la bonifica dello storico prevista sopra +come "riesame" è stata fatta subito dopo, migration `m15_bonifica_dati_evento_orfani`: righe +orfane in `risposte_presenze`, `cacche_partita`, `turni_palloni`, `scout_sessioni`, +`scout_live`, `scout_partite` identificate confrontando `evento_id` con `eventi_app`. Per +`mvp_voti`/`pagelle_voti`/`badge_social_voti` il confronto si applica **solo** ai `match_id` +nel formato id evento CrAPP (`^e[0-9a-z]+$`, quello di `nuovoIdEvento()`): i vecchi voti su id +Scout (prefisso `s` + timestamp decimale) o CSI (numerico o `data-squadra-squadra`) non sono +orfani, sono dati storici legittimi mai collegati a un evento CrAPP (vedi contesto sopra), e la +migration non li tocca. Verificato manualmente sul database locale prima di applicarla: un voto +di test su id Scout è sopravvissuto alla bonifica, un voto di test su id evento CrAPP orfano è +stato rimosso. + **Riesame** -Se in futuro si vuole bonificare anche lo storico di righe orfane già esistenti, o se una -nuova tabella collegata a un evento non viene aggiunta al trigger quando creata (va aggiornata -a mano, non c'è un meccanismo che lo forzi). +Se una nuova tabella collegata a un evento non viene aggiunta al trigger quando creata (va +aggiornata a mano, non c'è un meccanismo che lo forzi). diff --git a/supabase/migrations/20260909130000_m15_bonifica_dati_evento_orfani.sql b/supabase/migrations/20260909130000_m15_bonifica_dati_evento_orfani.sql new file mode 100644 index 0000000..f6a30d7 --- /dev/null +++ b/supabase/migrations/20260909130000_m15_bonifica_dati_evento_orfani.sql @@ -0,0 +1,55 @@ +-- M15 — Bonifica delle righe orfane lasciate da eventi cancellati prima di M14 +-- +-- M14 ha aggiunto un trigger che pulisce a cascata i dati collegati quando un evento viene +-- cancellato (DD-029), ma agisce solo sulle cancellazioni da quel momento in avanti. Questa +-- migration ripulisce una tantum le righe orfane lasciate da cancellazioni PRECEDENTI a M14. +-- +-- Per `risposte_presenze`, `cacche_partita`, `turni_palloni`, `scout_sessioni`, `scout_live` e +-- `scout_partite`, `evento_id` ha sempre e solo indicato un id evento CrAPP (mai un altro +-- schema): qualsiasi riga il cui `evento_id` non esiste più in `eventi_app` è, senza ambiguità, +-- un orfano da una cancellazione passata (per `scout_partite`, `evento_id` può anche essere +-- legittimamente NULL — una partita scoutata mai collegata a un evento — e quelle righe non +-- vengono toccate). +-- +-- `mvp_voti`, `pagelle_voti` e `badge_social_voti` sono diverse: PRIMA che `match_id` +-- diventasse l'id evento CrAPP, contenevano l'id di una sessione Scout (formato `s` + timestamp +-- in base 10, es. "s1717426810123") o la chiave di un referto CSI (id numerico del portale, o +-- fallback "data-squadra-squadra"). Quei voti sono dati storici legittimi, mai stati collegati +-- a un evento CrAPP: docs/modules/mvp.md li descrive come "non più letti da nessuna schermata", +-- non come dati da eliminare. Cancellarli qui sarebbe un bug, non una bonifica. +-- +-- Il filtro `match_id ~ '^e[0-9a-z]+$'` isola solo i match_id nel formato di +-- `nuovoIdEvento()` (`"e" + Date.now().toString(36)`, src/lib/eventi.ts): nessun id Scout (che +-- inizia per "s") o CSI (numerico o con trattini) può rientrarci, quindi solo i veri orfani da +-- evento CrAPP cancellato vengono rimossi, mai un voto storico su id scout/CSI. + +DELETE FROM public.risposte_presenze +WHERE evento_id NOT IN (SELECT id FROM public.eventi_app); + +DELETE FROM public.cacche_partita +WHERE evento_id NOT IN (SELECT id FROM public.eventi_app); + +DELETE FROM public.turni_palloni +WHERE evento_id NOT IN (SELECT id FROM public.eventi_app); + +DELETE FROM public.scout_sessioni +WHERE evento_id NOT IN (SELECT id FROM public.eventi_app); + +DELETE FROM public.scout_live +WHERE evento_id NOT IN (SELECT id FROM public.eventi_app); + +DELETE FROM public.scout_partite +WHERE evento_id IS NOT NULL + AND evento_id NOT IN (SELECT id FROM public.eventi_app); + +DELETE FROM public.mvp_voti +WHERE match_id ~ '^e[0-9a-z]+$' + AND match_id NOT IN (SELECT id FROM public.eventi_app); + +DELETE FROM public.pagelle_voti +WHERE match_id ~ '^e[0-9a-z]+$' + AND match_id NOT IN (SELECT id FROM public.eventi_app); + +DELETE FROM public.badge_social_voti +WHERE match_id ~ '^e[0-9a-z]+$' + AND match_id NOT IN (SELECT id FROM public.eventi_app);