# DD-040 — Promemoria con «oggi» o «domani», turno palloni e solleciti automatici **Data:** 30 settembre 2026 **Stato:** Accettata (implementata: migration `m26`, applicata in produzione il 30 settembre 2026, job, route e test). Il turno palloni è poi passato a un solo avviso a 3 ore da [DD-042](DD-042.md). **Contesto** Quattro notifiche su sei partivano da un pulsante premuto da un admin (DD-025 per i palloni): se nessuno lo premeva, nessuno veniva avvisato. I testi erano inoltre brevi e informali, e i promemoria non dicevano quando e dove. Si vuole che turno palloni e sollecito presenze partano anche da soli, a orari fissi prima dell'evento, e che i testi siano più formali e completi. I testi nuovi sono nel [catalogo](../modules/notifiche.md#testi-delle-notifiche). **Decisione** 1. **Promemoria a 24 e 3 ore:** nuovo testo con data, ora e luogo. La parola nel titolo e nella riga «Data» è **«domani»** se la data dell'evento è quella di domani (fuso `Europe/Rome`), **«oggi»** altrimenti. Vale per entrambi i promemoria, quindi anche quello a 3 ore di un evento dopo la mezzanotte dice «domani». La parola la calcola la funzione SQL quando genera la notifica. 2. **Turno palloni automatico.** Un job `pg_cron` ogni 15 minuti avvisa per gli eventi di tipo allenamento o partita, in tre tempi con finestre che non si sovrappongono: **12 ore** (tra 12 e 6 ore prima dell'inizio), **6 ore** (tra 6 e 3) e **3 ore** (meno di 3). Parte **solo se per l'evento c'è un incaricato confermato** in `turni_palloni`: le proposte automatiche di `completaTurni()` non salvate non contano. Gli avvisi sono due, con lo stesso testo nei tre tempi: «incarico assegnato» all'incaricato e «riconsegna» a chi aveva i palloni all'evento precedente, se è un'altra persona. - **Pulsante manuale.** «Avvisa chi è di turno» e la route `promemoria-palloni` **restano**: tipo `turno_palloni`, testo nuovo, push mandata dalla route e non dalla coda. È una notifica in più; riceverne due (automatica e manuale) va bene. - **Incaricato cambiato dopo un avviso.** Il nuovo incaricato riceve il suo avviso al giro successivo, con il tipo della finestra in cui cade. Chi aveva già ricevuto un avviso e non è più destinatario riceve **una sola volta** «Turno palloni: incarico revocato» (`turno_palloni_revocato`), se l'evento non è iniziato. Il job lo scopre confrontando i destinatari attuali con il **registro** degli avvisi automatici già generati (non con le notifiche, che il giocatore può aver eliminato), senza trigger su `turni_palloni`. Gli avvisi del pulsante non contano: possono riguardare una proposta non confermata. - **Niente email.** Gli avvisi palloni (automatici, revoca e pulsante) arrivano come push e nel centro notifiche, **non per email**: il trigger `notifiche_utente_accoda_email` salta i tipi `turno_palloni`, `turno_palloni_12h`, `_6h`, `_3h` e `turno_palloni_revocato`. È un'eccezione a DD-038 («ogni notifica ha tre canali») solo per questi tipi; l'interruttore «Email» non cambia. 3. **Sollecito presenze automatico in tre tempi.** Lo stesso job manda il sollecito **24 ore** (tra 24 e 12 ore prima), **12 ore** (tra 12 e 6) e **6 ore** (meno di 6) prima, al massimo una notifica per giocatore e per tipo. Lo riceve solo chi in quel momento non ha risposto o ha risposto «forse» ed è destinatario dell'evento: i convocati, o tutta la rosa attiva se `convocati` è vuoto, mai l'allenatore. Chi risponde presente, assente o in ritardo smette di riceverli; chi resta su «forse» li riceve tutti e tre. Un evento creato a meno di 12 ore dall'inizio riceve solo il sollecito della sua finestra. - **Pulsante manuale.** «Sollecita» e la route `sollecita-presenze` **restano**, anche per l'allenatore: tipo `sollecita_presenze`, push mandata dalla route, testo nuovo con in più la riga «Richiesta di: _Nome_». I destinatari sono **gli stessi dell'automatico** (convocati senza risposta o con «forse»); oggi la route guarda invece tutti i giocatori attivi. 4. **Stessa infrastruttura dei promemoria** (DD-037, DD-038): le notifiche automatiche nascono nel database, il registro `promemoria_eventi_generati` impedisce i doppioni anche se il giocatore le elimina, la push la manda il worker dalla coda `notifiche_push_coda`, l'email (quando c'è) nasce dal trigger su `notifiche_utente`. Tipi nuovi: `sollecita_presenze_24h`, `_12h`, `_6h`; `turno_palloni_12h`, `_6h`, `_3h` e `turno_palloni_revocato`. Il `turno_palloni` del pulsante resta. 5. **Migration `m26`:** estende i `CHECK` sui tipi di `notifiche_utente` e del registro, il trigger della coda push, il trigger della coda email (che salta i tipi dei palloni) e ridefinisce la funzione dei promemoria. Le funzioni nuove riusano `giocatori_destinatari_evento()`. **Alternative scartate** - Togliere i pulsanti manuali (turno palloni e sollecito) una volta arrivati gli automatici → scartata su indicazione esplicita: servono all'admin per rimandare un avviso o sollecitare fuori dagli orari fissi. - Mandare tutti i solleciti (o gli avvisi palloni) a un evento creato tardi → scartata: più messaggi nel giro di pochi minuti sono rumore. - «Domani» e «oggi» fissi nei due testi → scartata: il job delle 24 ore scatta anche per eventi che iniziano oggi, e quello delle 3 ore attraversa la mezzanotte. - Calcolare il testo nell'app invece che nel database → scartata: le notifiche nascono nei job `pg_cron`, che non chiamano l'app (DD-038). - Spostare nel worker il calcolo di evento precedente e successivo dei palloni → scartata: un secondo punto che scrive in `notifiche_utente`, per un vantaggio piccolo. - Ritirare l'avviso già consegnato al vecchio incaricato → scartata: per la push non si può, e in-app confonde. Si manda la revoca. **Conseguenze** - Cambia la regola «quattro notifiche su sei dipendono da un gesto manuale»: restano solo manuali il messaggio dello staff e il sondaggio pre-partita; per turno palloni e sollecito gli automatici si aggiungono ai pulsanti, e un giocatore può ricevere lo stesso avviso due volte. - **Logica duplicata:** «evento precedente» e «evento successivo» per i palloni, in `palloni-core.ts` (usato dal pulsante e dalla schermata), sono riscritti in SQL per i job (`genera_avvisi_palloni_fascia`). Ordine comune: data, ora, id. Se si cambia una regola in una sola delle due versioni, pulsante e job danno risposte diverse: `notifiche-automatiche.test.ts` confronta testi e destinatari sugli stessi dati, anche a parità di data e ora. - `destinatariSollecito()` riceve anche i convocati e serve al sollecito manuale; un giocatore non convocato non è più sollecitato. `avvisiPalloniEvento()` resta come riferimento per i test finché il SQL non la sostituisce del tutto. - Se un incaricato revocato viene poi riassegnato non riceve un secondo avviso, perché il registro lo ha già generato per quella finestra: la revoca resta l'ultima notifica che ha letto. - Le mail automatiche per evento e giocatore sono al massimo **cinque** (due promemoria, tre solleciti), più quelle dei pulsanti (sollecito, sondaggio). Il turno palloni non ne manda. - Il testo dei promemoria già generati non cambia (il registro impedisce di rigenerarli). **Riesame** Dopo la prima stagione di uso: se i solleciti o gli avvisi palloni risultano troppi, ridurre le finestre o escludere chi ha risposto «forse» più di una volta.