Files
CRAPP/docs/decisions/DD-047.md
T
davideandClaude Sonnet 5.5 985fc2fcc1 Notifica di compleanno: auguri al festeggiato, avviso agli altri (DD-047)
Ogni giorno, dalle 8:00 (Europe/Rome), un job pg_cron orario manda a chi compie
gli anni «Buon compleanno, <Nome>! 🎂» e a tutti gli altri membri attivi,
allenatori compresi, «Oggi è il compleanno di <Nome>» (con più compleanni lo
stesso giorno un solo messaggio a testa, nomi in ordine alfabetico). Solo
titolo, senza corpo né età. Canali: push, centro notifiche ed email.

- migration m31: tipi `compleanno` e `compleanno_auguri`, registro
  `compleanni_notificati` (una sola volta per destinatario e giorno, anche se la
  notifica viene eliminata), funzione `genera_avvisi_compleanno()` e job
  `avvisi-compleanno`, trigger push esteso ai nuovi tipi. Non ancora applicata
  in produzione.
- 29 febbraio non gestito: chi è nato quel giorno è avvisato solo negli anni
  bisestili (limite noto, documentato).
- test: integrazione `notifiche-compleanno` (ora e ora legale, destinatari,
  più compleanni, registro, coda push/email, 29 febbraio, job pianificato);
  unit sui nuovi tipi e sul corpo vuoto del service worker.
- documentazione: DD-047, catalogo e testi delle notifiche, DATABASE, CHANGELOG,
  ROADMAP, PROJECT_STATE.

Chiude la issue #11.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-06 10:18:22 +02:00

4.5 KiB

DD-047 — Notifica di compleanno

Data: 6 ottobre 2026
Stato: Accettata (migration m31, non ancora applicata in produzione; nasce dalla issue #11 «notifica»)

Contesto
I compleanni si vedono solo aprendo il Calendario, dove compleanniEventi() li calcola dalla data di nascita pubblica (giocatori_squadra.nascita, DD-031). Nessun avviso arriva ad app chiusa. La issue #11 chiede una notifica del tipo «oggi è il compleanno di tizio».

Decisione

  1. Una notifica vera, automatica, su tutti e tre i canali (DD-038): push, centro notifiche in-app ed email. Nasce nel database come le altre notifiche automatiche (DD-040): un job pg_cron scrive in notifiche_utente, il worker mailer/ manda push ed email.
  2. Quando: una volta al giorno, dalle 8:00 (fuso Europe/Rome). Il job gira ogni ora e agisce solo dalle 8 in poi; un registro ricorda a chi l'avviso del giorno è già stato generato, quindi un giro mancato si recupera all'ora dopo e non si genera mai due volte.
  3. Chi compie gli anni è chi ha nascita con lo stesso giorno e mese di oggi tra i membri attivi della squadra (giocatori_squadra.attivo), allenatori compresi. Senza data di nascita o non attivo: nessun avviso.
  4. Destinatari: tutti i membri attivi, allenatori compresi (il compleanno è un fatto della squadra, non una notifica di gioco: DD-039 non si applica). Due messaggi diversi, entrambi senza l'età:
    • il festeggiato riceve solo gli auguri: titolo Buon compleanno, <Nome>! 🎂, senza corpo;
    • tutti gli altri ricevono solo l'avviso: titolo Oggi è il compleanno di <Nome>, senza corpo.
  5. Più compleanni lo stesso giorno: un solo messaggio per destinatario. Chi non compie gli anni riceve un unico avviso con tutti i nomi: titolo Oggi è il compleanno di <A> e <B> (con tre o più: A, B e C, in ordine alfabetico per nome), sempre senza corpo. Ogni festeggiato riceve solo i propri auguri, senza i nomi degli altri.
  6. Registro. Nuova tabella compleanni_notificati (giocatore_id, giorno): una riga per destinatario e giorno. Il registro, e non notifiche_utente, impedisce il doppione anche se il giocatore elimina la notifica (stessa logica di DD-037). Il registro non è legato a un evento: i compleanni non sono eventi_app.
  7. Tipi (CHECK di notifiche_utente): compleanno (l'avviso agli altri) e compleanno_auguri (gli auguri). Nessun pulsante manuale: la notifica parte solo dal job. Il trigger delle push accoda entrambi; quello delle email li lascia passare, quindi arrivano anche per email.
  8. 29 febbraio: per ora non gestito. Chi è nato il 29 febbraio viene avvisato solo negli anni bisestili, perché il confronto è tra giorno e mese. Negli altri anni non parte nulla (né il 28 febbraio né il 1° marzo). È un limite noto, accettato: oggi non interessa nessuno in squadra.

Alternative scartate

  • Card in Home, senza push né migration → più semplice, ma non avvisa chi non apre l'app: non è ciò che chiede la issue.
  • Un messaggio per festeggiato anche a chi lo riceve da altri → con due compleanni lo stesso giorno sarebbero due notifiche e due mail al giorno per lo stesso destinatario.
  • Registro per (destinatario, festeggiato, giorno) → serve solo a chi vuole due avvisi separati, che abbiamo scartato; la chiave (destinatario, giorno) basta.
  • Allenatori esclusi → scartata su indicazione esplicita: «tutti».
  • Gestire il 29 febbraio il 28 febbraio → rimandato (punto 8).

Conseguenze

  • Ogni giorno con un compleanno ogni membro attivo riceve una notifica e, se ha account, email e le email accese, una mail. Con molti compleanni nello stesso periodo il tetto giornaliero di invio del worker (mailer/) può farsi sentire: il compleanno non ha priorità sulle altre mail.
  • Chi inserisce la propria data di nascita il giorno stesso del compleanno, dopo le 8 e dopo che gli altri sono già stati avvisati, non genera un secondo avviso (il registro ha già il giorno per i destinatari). Chi la inserisce prima delle 8 viene incluso.
  • Un nuovo membro che si aggiunge dopo l'avviso della giornata non riceve quello del giorno.
  • Il compleanno resta anche in Calendario, invariato.

Riesame
Se le mail di compleanno risultano troppe, spegnerle e tenere solo push e centro notifiche (come il turno palloni, DD-040). Se in squadra arriva qualcuno nato il 29 febbraio, gestire quel caso (punto 8).