DD-050: «Presenza modificata» anche agli allenatori (m33)
Fine della fase di prova: la funzione avvisa admin e allenatori attivi. Test aggiornato (l'allenatore ora è tra i destinatari), DD-050, notifiche, allenatore, DATABASE, CHANGELOG, ROADMAP e PROJECT_STATE allineati. m33 non ancora applicata in produzione. Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
274fed93c5
commit
986098d933
10 files changed
+129
-60
No files matched your search
+6
-6
@@ -24,12 +24,12 @@ la consegna effettiva a schermo bloccato richiede un telefono e il servizio push
|
||||
|
||||
## Struttura
|
||||
|
||||
| Cartella | Cosa verifica | Serve rete? |
|
||||
| -------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| `unit/` | Logica di dominio pura: badge, serie, palloni, pagelle, MVP, cacche, scout, obiettivi (calcolo e card di dettaglio), avvisi in Home, notifiche, parsing CSI, dati della rosa. Più le funzioni pure isolabili nei moduli con hook/rete (validazione upload, guardie push, JWT VAPID, cattura errori, avatar, guardia admin delle route, lettura del `.env` ed elenco dei bucket dello script di backup, logica del worker in `mailer/` (email e push dei promemoria), preferenza «Email» e avviso del sondaggio) | No |
|
||||
| `integration/` | Le route `/api/public/*` sul server di sviluppo: risposte, cache, validazione degli input. Più schema e permessi del Profilo Giocatore (`schema-profili`) contro il database configurato; permessi per ruolo, incluse le policy di M11, le deroghe dell'amministratore e le tabelle lasciate aperte di proposito (`permessi`), accesso alle route di notifica (`permessi-route`), semantica degli upsert e vincoli (`scritture`), le letture lato server delle route push (`lettori-server`) e la pulizia a cascata dei dati collegati alla cancellazione di un evento (`pulizia-evento`, M14) la funzione di bonifica delle righe orfane (`bonifica-evento`, M16), il centro notifiche in-app (`notifiche-utente`, M17), la coda delle email e le sue funzioni RPC (`notifiche-email`, M22), i promemoria evento che non ricompaiono se eliminati (`promemoria-eventi`, M23), la coda delle push dei promemoria (`push-promemoria`, M24), i job automatici di turno palloni e sollecito presenze con revoca, finestre e testi identici al codice (`notifiche-automatiche`, M26-M28 e M30, DD-040, DD-042, DD-043 e DD-045: palloni un solo avviso a 3 ore, sollecito uno solo a 24 ore, nessun promemoria evento) la colonna `foto_path` eliminata (`foto-tessera-rimossa`, M29, DD-044) e il sondaggio in-app/email (`sondaggio-notifiche`, M24), i destinatari delle notifiche per ruolo (`destinatari-notifiche`: promemoria, messaggio dello staff, sondaggio, sollecito e turno palloni con allenatore e giocatore), l'avviso «Presenza modificata» agli admin con finestra di 6 ore, stati e nessun avviso a cancellazione dell'evento (`presenza-modificata`, M32, DD-050), gli avvisi di compleanno con ora, più compleanni lo stesso giorno, registro e 29 febbraio (`notifiche-compleanno`, M31, DD-047), la nascita pubblica sincronizzata dal profilo (`nascita-pubblica`, M18) e il suo backfill per i profili preesistenti (`backfill-nascita-esistenti`, M19 — unico test che esegue SQL diretto via `docker exec` nel container Postgres, perché PostgREST non espone quell'update multi-tabella come RPC) sul database locale | Sì |
|
||||
| `e2e/` | Percorsi completi sull'app servita: schermate, dati CSI fino alla pagina, file PWA, 404 | Sì |
|
||||
| `helpers/` | Avvio del server di test e mini-harness condiviso | — |
|
||||
| Cartella | Cosa verifica | Serve rete? |
|
||||
| -------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ----------- |
|
||||
| `unit/` | Logica di dominio pura: badge, serie, palloni, pagelle, MVP, cacche, scout, obiettivi (calcolo e card di dettaglio), avvisi in Home, notifiche, parsing CSI, dati della rosa. Più le funzioni pure isolabili nei moduli con hook/rete (validazione upload, guardie push, JWT VAPID, cattura errori, avatar, guardia admin delle route, lettura del `.env` ed elenco dei bucket dello script di backup, logica del worker in `mailer/` (email e push dei promemoria), preferenza «Email» e avviso del sondaggio) | No |
|
||||
| `integration/` | Le route `/api/public/*` sul server di sviluppo: risposte, cache, validazione degli input. Più schema e permessi del Profilo Giocatore (`schema-profili`) contro il database configurato; permessi per ruolo, incluse le policy di M11, le deroghe dell'amministratore e le tabelle lasciate aperte di proposito (`permessi`), accesso alle route di notifica (`permessi-route`), semantica degli upsert e vincoli (`scritture`), le letture lato server delle route push (`lettori-server`) e la pulizia a cascata dei dati collegati alla cancellazione di un evento (`pulizia-evento`, M14) la funzione di bonifica delle righe orfane (`bonifica-evento`, M16), il centro notifiche in-app (`notifiche-utente`, M17), la coda delle email e le sue funzioni RPC (`notifiche-email`, M22), i promemoria evento che non ricompaiono se eliminati (`promemoria-eventi`, M23), la coda delle push dei promemoria (`push-promemoria`, M24), i job automatici di turno palloni e sollecito presenze con revoca, finestre e testi identici al codice (`notifiche-automatiche`, M26-M28 e M30, DD-040, DD-042, DD-043 e DD-045: palloni un solo avviso a 3 ore, sollecito uno solo a 24 ore, nessun promemoria evento) la colonna `foto_path` eliminata (`foto-tessera-rimossa`, M29, DD-044) e il sondaggio in-app/email (`sondaggio-notifiche`, M24), i destinatari delle notifiche per ruolo (`destinatari-notifiche`: promemoria, messaggio dello staff, sondaggio, sollecito e turno palloni con allenatore e giocatore), l'avviso «Presenza modificata» ad admin e allenatori con finestra di 6 ore, stati e nessun avviso a cancellazione dell'evento (`presenza-modificata`, M32-M33, DD-050), gli avvisi di compleanno con ora, più compleanni lo stesso giorno, registro e 29 febbraio (`notifiche-compleanno`, M31, DD-047), la nascita pubblica sincronizzata dal profilo (`nascita-pubblica`, M18) e il suo backfill per i profili preesistenti (`backfill-nascita-esistenti`, M19 — unico test che esegue SQL diretto via `docker exec` nel container Postgres, perché PostgREST non espone quell'update multi-tabella come RPC) sul database locale | Sì |
|
||||
| `e2e/` | Percorsi completi sull'app servita: schermate, dati CSI fino alla pagina, file PWA, 404 | Sì |
|
||||
| `helpers/` | Avvio del server di test e mini-harness condiviso | — |
|
||||
|
||||
## Server di sviluppo con Node vecchio
|
||||
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
/**
|
||||
* Avviso «Presenza modificata» (M32, DD-050): `bun test/integration/presenza-modificata.test.ts`.
|
||||
* Avviso «Presenza modificata» (M32 e M33, DD-050): `bun test/integration/presenza-modificata.test.ts`.
|
||||
*
|
||||
* Scrive su `risposte_presenze` come farebbe l'app e verifica, sul database vero:
|
||||
*
|
||||
* - una risposta nuova, modificata o ritirata a meno di 6 ore da una partita o da un allenamento
|
||||
* avvisa gli admin attivi, con titolo e corpo del catalogo;
|
||||
* - in fase di prova (DD-050) non riceve nulla un giocatore semplice né un allenatore, e non riceve
|
||||
* avvisa gli admin e gli allenatori attivi, con titolo e corpo del catalogo;
|
||||
* - riceve l'avviso chi ha il ruolo admin o allenatore con uno slot attivo (M33); non riceve nulla un giocatore semplice, e non riceve
|
||||
* nulla l'admin a cui appartiene la presenza;
|
||||
* - nessun avviso se lo stato non cambia, se l'evento è oltre le 6 ore, già iniziato, o di un tipo che
|
||||
* non è partita né allenamento, né quando una risposta sparisce perché l'evento è stato cancellato;
|
||||
@@ -168,7 +168,9 @@ if (!locale) {
|
||||
|
||||
// Il seed può avere altri admin con uno slot attivo: l'elenco atteso lo calcola il test.
|
||||
const attesi = async () => {
|
||||
const ruoli = await leggi<{ user_id: string }>("user_roles?role=eq.admin&select=user_id");
|
||||
const ruoli = await leggi<{ user_id: string }>(
|
||||
"user_roles?role=in.(admin,allenatore)&select=user_id",
|
||||
);
|
||||
const slot = await leggi<{ id: string; auth_user_id: string }>(
|
||||
"giocatori_squadra?attivo=eq.true&auth_user_id=not.is.null&select=id,auth_user_id",
|
||||
);
|
||||
@@ -184,31 +186,34 @@ if (!locale) {
|
||||
idEventi.push(`${PREFISSO}partita`);
|
||||
const dataIt = `${ev.data.slice(8, 10)}/${ev.data.slice(5, 7)}/${ev.data.slice(0, 4)}`;
|
||||
|
||||
await prova("risposta nuova: avvisa gli admin, con il testo del catalogo", async () => {
|
||||
await risposta(`${PREFISSO}partita`, "presente");
|
||||
const righe = await notifiche();
|
||||
assert.deepEqual(righe.map((r) => r.giocatore_id).sort(), await attesi());
|
||||
assert.ok(
|
||||
righe.some((r) => r.giocatore_id === ADMIN),
|
||||
"l'admin di prova è tra i destinatari",
|
||||
);
|
||||
const mia = righe.find((r) => r.giocatore_id === ADMIN)!;
|
||||
assert.equal(mia.titolo, `Presenza modificata: ${nomeCompleto}`);
|
||||
assert.equal(
|
||||
mia.corpo,
|
||||
[
|
||||
`Evento: ${ev.titolo}`,
|
||||
`Data: ${dataIt}, ore ${ev.ora}`,
|
||||
"Da: nessuna risposta",
|
||||
"A: presente",
|
||||
].join("\n"),
|
||||
);
|
||||
});
|
||||
await prova(
|
||||
"risposta nuova: avvisa admin e allenatori, con il testo del catalogo",
|
||||
async () => {
|
||||
await risposta(`${PREFISSO}partita`, "presente");
|
||||
const righe = await notifiche();
|
||||
assert.deepEqual(righe.map((r) => r.giocatore_id).sort(), await attesi());
|
||||
assert.ok(
|
||||
righe.some((r) => r.giocatore_id === ADMIN),
|
||||
"l'admin di prova è tra i destinatari",
|
||||
);
|
||||
const mia = righe.find((r) => r.giocatore_id === ADMIN)!;
|
||||
assert.equal(mia.titolo, `Presenza modificata: ${nomeCompleto}`);
|
||||
assert.equal(
|
||||
mia.corpo,
|
||||
[
|
||||
`Evento: ${ev.titolo}`,
|
||||
`Data: ${dataIt}, ore ${ev.ora}`,
|
||||
"Da: nessuna risposta",
|
||||
"A: presente",
|
||||
].join("\n"),
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
await prova("in prova non ricevono nulla il giocatore semplice e l'allenatore", async () => {
|
||||
await prova("il giocatore semplice non riceve nulla, l'allenatore sì", async () => {
|
||||
const destinatari = (await notifiche()).map((r) => r.giocatore_id);
|
||||
assert.ok(!destinatari.includes(GIOCATORE));
|
||||
assert.ok(!destinatari.includes(ALLENATORE));
|
||||
assert.ok(destinatari.includes(ALLENATORE), "l'allenatore attivo è tra i destinatari");
|
||||
assert.ok(!destinatari.includes(RISPONDE), "chi risponde non avvisa se stesso");
|
||||
});
|
||||
|
||||
|
||||
Reference in new issue
Block a user