Primo commit

This commit is contained in:
Francesco Picone
2026-04-05 19:26:04 +02:00
commit 701f479b7f
135 changed files with 21445 additions and 0 deletions

640
TerManager2_v2.md Normal file
View File

@@ -0,0 +1,640 @@
# TerManager2 — Specifiche funzionali + istruzioni per container (Laravel)
> Documento operativo per realizzare **TerManager2**, applicazione Laravel per la gestione dellassegnazione/rientro di cartoline territorio, statistiche di percorrenza e campagne speciali.
>
> **Obiettivo del documento**: chiarire requisiti, proporre unarchitettura “container-ready”, definire modello dati e regole di calcolo, e fornire una **scomposizione in sottotask** con checklist di controllo a fine attività.
---
## 1) Visione dinsieme
**TerManager2** gestisce:
- **Territori** (cartoline) con PDF, stato (in reparto / assegnato / da rientrare / prioritario / inattivo) e proprietà (Zona, Tipologia, ecc.).
- **Proclamatori** (assegnatari) con dati **illeggibili in DB** (cifratura applicativa a livello di colonna) e gestione **GDPR**.
- **Assegnazioni** con data assegnazione/rientro, teocratic year, opzionale “conteggio campagna”.
- **Campagne** (periodi speciali) con percentuali di percorrenza e dashboard.
- **Statistiche** (media mensile di percorrenza nellanno teocratico, indicatori di giacenza e “smarriti”).
**Ruoli (RBAC)**:
- **Amministratore**: tutto (impostazioni, territori, proclamatori, campagne, registro, proprietà territorio, assegnazione/rientro).
- **Assistente**: proclamatori, campagne, assegnazione/rientro.
- **Operatore**: assegnazione/rientro.
---
## 2) Requisiti non funzionali (sicurezza, GDPR, UX)
### 2.1 Sicurezza e dati illeggibili in DB
Requisito: i dati dei proclamatori devono risultare **illeggibili** se si accede direttamente al database.
**Scelta consigliata (Laravel)**:
- Password utente: **hash** (bcrypt/argon2id) (standard Laravel).
- Dati sensibili (nome, cognome, eventuali note): **cifratura applicativa per colonna**.
- Usare **Laravel Eloquent encrypted casts** (es. `protected $casts = ['nome' => 'encrypted', ...];`) oppure un **Custom Cast** che cifri/decifri con AES-256-GCM.
- La chiave di cifratura è `APP_KEY` (gestita come secret in ambiente). **Mai** versionarla.
**Nota importante**: la cifratura applicativa protegge “a riposo” nel DB. Per un livello ulteriore:
- cifrare anche **backup**;
- considerare cifratura volume/disco a livello host.
### 2.2 GDPR — criteri base da rispettare
Implementare almeno:
- **Minimizzazione**: salvare solo ciò che serve (nome/cognome e stato attivo).
- **Ruoli e autorizzazioni**: accesso ai dati solo per chi ha permessi.
- **Audit trail**: log di operazioni critiche (creazione/modifica/eliminazione, assegnazione/rientro, cambio stato territorio).
- **Retention**: definire policy su conservazione storici (es. registro assegnazioni conservato per X anni — parametro impostazioni).
- **Diritto alloblio**: possibilità di **disattivare/anonimizzare** un proclamatore (senza rompere lo storico).
- **Esportazione**: esportazione dati (CSV/PDF) su richiesta (opzionale ma consigliato).
- **Consenso e informativa**: pagina “Privacy / Informativa” e log di accettazione (se necessario al contesto).
### 2.3 UI/UX
- Responsive “mobile-first” (smartphone/tablet), grafica minimale e moderna.
- Layout con:
- header con logo + congregazione;
- menu laterale (collassabile su mobile);
- contenuti centrali con card e tabelle filtrabili.
Tecnologie UI consigliate:
- **TailwindCSS** + **Livewire** (rapido, server-driven) **oppure** Inertia + Vue/React.
- Componenti: ricerca veloce, paginazione, badge di stato, drawer per dettagli.
---
## 3) Architettura applicativa (Laravel)
### 3.1 Componenti
- Laravel (>=10) con:
- Auth (Breeze/Jetstream o Fortify) + **RBAC** (Spatie Laravel Permission consigliato).
- DB: MySQL/MariaDB o PostgreSQL.
- Storage: `storage/app` per PDF (in dev) + volume Docker; in produzione valutare S3/MinIO.
- Queue: Redis (opzionale ma utile per report/esportazioni).
- Scheduler: `artisan schedule:work` per job (es. calcoli, pulizie, report).
### 3.2 Concetti chiave di dominio
- **Anno teocratico**: da **Settembre** (anno precedente) ad **Agosto** (anno corrente).
- **Percorrenza**: giorni tra assegnazione e rientro (nellanno teocratico corrente) aggregati e convertiti in media mensile.
- **Campagna**: periodo con start/end; a ogni rientro si chiede se quel rientro conta per la campagna (anche retroattivo se assegnato durante il periodo ma rientrato dopo).
---
## 4) Modello dati (proposta)
> I nomi campi sono indicativi; adeguare naming (snake_case) e indici.
### 4.1 Tabelle
#### `users`
- auth utenti app (admin/assistente/operatore)
- campi standard Laravel (`email`, `password`, `name`, ecc.).
#### `roles`, `permissions`, `model_has_roles`, ...
- se si usa Spatie Permission.
#### `settings`
- configurazioni globali:
- `congregazione_nome`
- soglia `giorni_giacenza_da_assegnare`
- soglia `giorni_giacenza_prioritari`
- soglia `giorni_per_smarrito`
- `home_limit_list` (default 10)
- altre.
#### `proclamatori`
- `id`
- `nome` **encrypted**
- `cognome` **encrypted**
- `attivo` boolean
- timestamps
> (Opzionale) `display_name_hash` per ricerche rapide senza decifrare tutto (hash normalizzato di nome+cognome). Attenzione: lhash può comunque essere dato personale; trattarlo come tale.
#### `territori`
- `id`
- `numero` (string/int) **univoco**
- `zona_id`
- `tipologia_id`
- `note` (text)
- `confini` (text)
- `pdf_path` (string)
- `attivo` boolean
- `prioritario` boolean
- timestamps
#### `zone` e `tipologie`
- `id`, `nome`, `attivo`.
#### `anni_teocratici`
- `id`
- `label` (es. `2025-2026`)
- `start_date` (1 settembre)
- `end_date` (31 agosto)
- univoco per `label`.
#### `campagne`
- `id`
- `start_date`
- `end_date`
- `descrizione`
- `attiva` (derivabile da date, ma può essere utile una view/flag)
- timestamps
#### `assegnazioni`
- `id`
- `territorio_id`
- `proclamatore_id`
- `anno_teocratico_id`
- `assigned_at`
- `returned_at` (nullable)
- `counted_in_campaign` boolean nullable (null = non chiesto/non applicabile)
- `campaign_id` nullable (se conteggiata)
- `note` nullable
- `created_by` (user_id)
- `returned_by` (user_id) nullable
- timestamps
#### `audit_logs` (o `activity_log`) — per pagina Log attività
- tabella dedicata a tracciare azioni utenti (vedi §6.7)
- se si usa un pacchetto, mantenere naming/colonne del pacchetto; altrimenti creare tabella custom.
### 4.2 Vincoli e indici (essenziali)
- `territori.numero` unique
- `assegnazioni`:
- indice su (`territorio_id`, `returned_at`)
- indice su (`proclamatore_id`, `returned_at`)
- indice su (`anno_teocratico_id`)
- integrità referenziale con `ON DELETE CASCADE` dove sensato.
- **Attenzione**: requisito: eliminazione territorio => eliminazione su tutto il registro assegnazioni. Quindi `assegnazioni.territorio_id` con cascade.
---
## 5) Regole di business e calcoli
### 5.1 Anno teocratico (creazione automatica)
- Allavvio Home o in fase di assegnazione/rientro:
1. determinare data odierna;
2. se mese >= 9 (settembre) -> anno teocratico = `anno_corrente-anno_corrente+1`;
3. se mese <= 8 -> anno teocratico = `anno_corrente-1-anno_corrente`;
4. se non esiste in DB, crearlo con start_date=1/09 e end_date=31/08.
### 5.2 Stato territorio
- **In reparto**: nessuna assegnazione aperta (ultima assegnazione `returned_at` non null) e attivo.
- **Assegnato a X**: esiste assegnazione aperta (`returned_at` null).
- **Smarrito / da rientrare**: assegnazione aperta da più giorni rispetto a `settings.giorni_per_smarrito`.
- **Prioritario**: flag `prioritario=true` oppure giacenza in reparto > soglia `giorni_giacenza_prioritari`.
- **Inattivo**: `attivo=false` (non assegnabile).
### 5.3 “Territori da assegnare” (Home)
- Territori **in reparto** con giacenza > `giorni_giacenza_da_assegnare`.
- Mostrare primi N (`home_limit_list`).
- Azione: assegnazione rapida a proclamatore.
### 5.4 “Territori prioritari” (Home)
- Territori in reparto con giacenza > `giorni_giacenza_prioritari` **oppure** `prioritario=true`.
- Azione: assegnazione rapida.
### 5.5 “Territori da rientrare” (Home)
- Territori con assegnazione aperta da più giorni di `giorni_per_smarrito`.
- Azione: rientro rapido (sullattuale assegnatario).
### 5.6 Media mensile di percorrenza (Home)
Definizione richiesta: media mensile di percorrenza di tutti i territori nellanno teocratico corrente.
Interpretazione operativa (coerente con testo):
- Per ogni **assegnazione chiusa** (returned_at valorizzato) nellanno teocratico corrente:
- `giorni = returned_at - assigned_at` (in giorni, >=0)
- Sommare tutti i `giorni` e normalizzare su base mensile.
Proposta formula (trasparente e verificabile):
- `giorni_totali = Σ giorni` per tutte le assegnazioni chiuse dellanno teocratico corrente
- `mesi_trascorsi = numero mesi dallinizio anno teocratico a oggi (min 1)`
- `media_mensile = giorni_totali / mesi_trascorsi`
> Alternativa: media per territorio o per assegnazione; scegliere una e documentarla in impostazioni. Limportante è che sia consistente e testata.
### 5.7 Campagne (Home + Tab Campagne)
- Campagna attiva se `today` tra `start_date` e `end_date`.
- Percentuale percorrenza campagna:
- `territori_percorsi_in_campagna / territori_totali_pertinenti`.
Chiarimento necessario per “totali pertinenti”: suggerito:
- denominatore = numero di territori rientrati **conteggiati campagna** durante il periodo **+** territori assegnati nel periodo ma non ancora rientrati? (da definire).
Per evitare ambiguità e mantenere semplice:
- **Proposta**: percentuale = (numero assegnazioni chiuse conteggiate campagna) / (numero assegnazioni chiuse totali che hanno `assigned_at` nel range campagna) * 100.
#### Avviso rientro “con o senza campagna” (retroattivo)
Alla chiusura di unassegnazione:
- se esiste campagna tale che `assigned_at` è compreso nel range campagna **(anche se oggi è dopo end_date)**, mostrare prompt:
- “Questo rientro conta per la campagna X?”
- se sì: `counted_in_campaign=true` e `campaign_id`.
- se no: `counted_in_campaign=false`.
- se non applicabile: lasciare null.
#### Vista “territori percorsi e in quanto tempo”
Per campagna selezionata:
- lista assegnazioni conteggiate in campagna con:
- territorio, proclamatore (mostrato in chiaro solo in UI), assigned_at, returned_at, giorni.
---
## 6) Pagine e funzionalità (corrette/riordinate)
### 6.1 Wizard iniziale (primo avvio)
Se mancano impostazioni base (`settings` vuoto):
- Step 1: Nome congregazione + logo (upload).
- Step 2: soglie (giacenza, prioritari, smarrito) + limite liste Home.
- Step 3: conferma e creazione admin (se necessario).
### 6.2 Home
Header:
- sinistra: logo + nome congregazione
- destra: nome utente + ruolo + logout
Sidebar:
- voci variabili in base ai permessi.
Contenuto centrale:
1) **Anno teocratico in corso** (auto-creazione se non esiste)
2) **Media mensile di percorrenza** (anno teocratico corrente)
3) **Campagna in corso** (se attiva): descrizione + percentuale + pulsante “Dettagli in tempo reale”
4) **Assegnazione rapida** (3 colonne/zone):
- Territori da assegnare
- Territori prioritari
- Territori da rientrare
Ogni lista:
- mostra top N
- ricerca veloce
- pulsante “Vedi tutti” (pagina completa con filtri)
### 6.3 Gestione Territori
Lista filtrabile con colonne:
- Numero
- Zona / Tipologia
- Stato (badge)
- Ultimo rientro
- Azioni: Visualizza / Modifica / Elimina / Attiva-Disattiva
Dettaglio territorio (“Visualizza”):
- dati completi + PDF viewer
- storico assegnazioni raggruppato per anno teocratico
Regole:
- Eliminazione territorio => rimuove anche tutte le assegnazioni (cascade).
- Territorio inattivo non è assegnabile e non appare nelle liste “da assegnare/prioritari” (a meno di filtro admin).
### 6.4 Gestione Proclamatori
Lista filtrabile:
- Proclamatore (nome/cognome decifrati in UI)
- Attivo
- Territori attualmente in assegnazione (conteggio + link)
- Azioni: Visualizza / Modifica / Elimina / Disattiva
Regole consigliate:
- Eliminazione fisica solo se nessuno storico (oppure prevedere “anonimizza”).
### 6.5 Gestione Campagne
- Form creazione campagna (start, end, descrizione)
- Evidenza campagna attiva
- Elenco campagne completate (indipendente dallanno teocratico)
- Dettaglio: elenco assegnazioni conteggiate, tempi, export.
### 6.6 Registro assegnazioni
Lista filtrabile per:
- anno teocratico
- territorio
- zona
- tipologia
- proclamatore
Output:
- tabella con assegnazioni (assegnato, rientrato, giorni, campagna sì/no)
- export CSV/PDF (opzionale)
### 6.7 Log attività (Audit trail) — **REQUISITO OBBLIGATORIO**
> Deve essere disponibile una **pagina di log** che riporti **tutte le azioni degli utenti** (Amministratore, Assistente, Operatore) e in particolare le operazioni di:
> - **Assegnazione** territorio
> - **Rientro** territorio (con/senza campagna)
> - **Creazione / modifica / cancellazione** di: Territori, Proclamatori, Campagne, Zone, Tipologie, Impostazioni
> - **Attiva/Disattiva** territorio o proclamatore
> - **Upload / sostituzione / eliminazione** PDF territorio
> - (Consigliato) **Login/Logout**, tentativi falliti, export dati
#### 6.7.1 Scopo
- Tracciabilità e accountability (chi ha fatto cosa e quando).
- Supporto a sicurezza e requisiti GDPR (audit delle operazioni sui dati).
#### 6.7.2 Permessi di accesso alla pagina log
- **Visualizzazione log**: `audit.view` (almeno Amministratore).
- Opzionale: consentire anche ad Assistente una vista “limitata” (solo eventi di assegnazione/rientro e senza IP/user-agent).
- **Esportazione log**: `audit.export` (solo Amministratore).
#### 6.7.3 Dati minimi da registrare per ogni evento
Registrare per ogni azione:
- `id`
- `created_at` (data/ora evento)
- `causer_user_id` (utente che ha eseguito)
- `causer_role_snapshot` (ruolo al momento dellazione)
- `event` (es. `created`, `updated`, `deleted`, `assigned`, `returned`, `activated`, `deactivated`, `uploaded_pdf`)
- `subject_type` + `subject_id` (entità coinvolta: Territorio/Proclamatore/Campagna/Assegnazione/Setting...)
- `description` (testo leggibile)
- `properties` (JSON) con dettagli evento:
- **prima/dopo** per update (diff campi)
- motivazioni/flag (es. `counted_in_campaign=true`)
- valori di soglia usati in calcoli/decisioni (se rilevanti)
- (Consigliato) `ip_address` e `user_agent` (dato personale → retention e minimizzazione)
> Nota GDPR: retention configurabile (es. 365/730 giorni). Evitare di salvare nei log dati sensibili in chiaro non necessari: per Proclamatori salvare `proclamatore_id` e non nome/cognome.
#### 6.7.4 Implementazione consigliata (senza vincoli)
- È possibile implementare il log con tabella custom (`audit_logs`) oppure usare un pacchetto dedicato.
- Scelta spesso adottata in Laravel: **spatie/laravel-activitylog** per logging automatico su modelli + logging manuale per eventi “di flusso” (assegnazione/rientro).
#### 6.7.5 UI pagina Log
Funzioni minime:
- Tabella: Data/Ora, Utente, Ruolo, Azione, Oggetto, Esito, Dettagli.
- Filtri: date, utente, ruolo, tipo evento, entità.
- Dettaglio evento (drawer/modal): diff before/after + metadati.
- Paginazione + ricerca veloce.
---
## 7) Containerizzazione (Docker) — sviluppo e produzione
### 7.1 Struttura consigliata repository
```
termanager2/
docker/
nginx/
default.conf
php/
Dockerfile
php.ini
.env.example
docker-compose.yml
composer.json
package.json
...
```
> In dev si può usare `npm run dev` in un container separato o sul host.
### 7.6 Produzione (note rapide)
- Impostare `APP_ENV=production`, `APP_DEBUG=false`.
- Usare immagini “buildate” senza montare volume codice.
- Gestire segreti con Docker secrets o secret manager.
- Abilitare HTTPS con reverse proxy (Traefik/Nginx) e HSTS.
- Backup cifrati e rotazione.
---
## 8) RBAC: permessi e gating UI
Definire permessi granulari (anche se i ruoli sono solo 3):
- `settings.manage`
- `proclamatori.manage`
- `territori.manage`
- `campagne.manage`
- `registro.view`
- `territori.assign`
- `territori.return`
- `audit.view`
- `audit.export` (opzionale)
Mappatura ruoli:
- Admin: tutti (incluso `audit.view` e opzionale `audit.export`)
- Assistente: proclamatori.manage, campagne.manage, territori.assign, territori.return
- Operatore: territori.assign, territori.return
Applicare:
- Middleware route (`can:` / `role:` / `permission:`)
- Condizionali menu sidebar
## 8-bis) API routes / schermate (URL, metodi, middleware)
> Nota: di seguito sono indicate **route Web** (UI) e (opzionalmente) **route API**. Anche se lapp nasce “web”, formalizzare le route aiuta a:
> - applicare correttamente `auth` + permessi,
> - mantenere coerenza tra schermate e controller,
> - facilitare test e manutenzione.
### 8-bis.1 Convenzioni middleware
- `auth` su tutte le rotte applicative.
- `permission:<permesso>` (o `can:<permesso>`) per schermate/azioni.
- `throttle` (consigliato) su login e su endpoint di export.
### 8-bis.2 Mappa schermate principali
- **Home/Dashboard**: `/` (GET)
- **Wizard iniziale**: `/setup/*` (GET/POST)
- **Territori**: `/territori` (lista), `/territori/create`, `/territori/{id}` (dettaglio), `/territori/{id}/edit`
- **Proclamatori**: `/proclamatori` + CRUD
- **Campagne**: `/campagne` + CRUD + dettaglio
- **Registro**: `/registro` (filtri)
- **Audit log**: `/audit` (lista) + `/audit/{id}` (dettaglio)
### 8-bis.3 Route Web (UI) — dettaglio
#### Autenticazione
- `GET /login` → form login | middleware: `guest`
- `POST /login` → login | middleware: `guest`, `throttle:login`
- `POST /logout` → logout | middleware: `auth`
#### Wizard iniziale (primo avvio)
- `GET /setup` → step 1 | middleware: `setup.required`
- `POST /setup/step-1` → salva congregazione | middleware: `setup.required`
- `POST /setup/step-2` → salva soglie | middleware: `setup.required`
- `POST /setup/finish` → completa setup | middleware: `setup.required`
> `setup.required` è un middleware custom che intercetta lassenza di settings e forza il wizard.
#### Home
- `GET /` → dashboard | middleware: `auth`
#### Territori
- `GET /territori` → lista | middleware: `auth`, `permission:territori.manage`
- `GET /territori/create` → form create | middleware: `auth`, `permission:territori.manage`
- `POST /territori` → store | middleware: `auth`, `permission:territori.manage`
- `GET /territori/{territorio}` → dettaglio | middleware: `auth`, `permission:territori.manage`
- `GET /territori/{territorio}/edit` → form edit | middleware: `auth`, `permission:territori.manage`
- `PUT /territori/{territorio}` → update | middleware: `auth`, `permission:territori.manage`
- `DELETE /territori/{territorio}` → delete (cascade assegnazioni) | middleware: `auth`, `permission:territori.manage`
- `PATCH /territori/{territorio}/toggle-active` → attiva/disattiva | middleware: `auth`, `permission:territori.manage`
- `PATCH /territori/{territorio}/toggle-priority` → prioritario sì/no | middleware: `auth`, `permission:territori.manage`
- `POST /territori/{territorio}/pdf` → upload/sostituzione PDF | middleware: `auth`, `permission:territori.manage`
- `DELETE /territori/{territorio}/pdf` → rimuovi PDF | middleware: `auth`, `permission:territori.manage`
#### Proclamatori
- `GET /proclamatori` → lista | middleware: `auth`, `permission:proclamatori.manage`
- `GET /proclamatori/create` → form create | middleware: `auth`, `permission:proclamatori.manage`
- `POST /proclamatori` → store | middleware: `auth`, `permission:proclamatori.manage`
- `GET /proclamatori/{proclamatore}` → dettaglio | middleware: `auth`, `permission:proclamatori.manage`
- `GET /proclamatori/{proclamatore}/edit` → form edit | middleware: `auth`, `permission:proclamatori.manage`
- `PUT /proclamatori/{proclamatore}` → update | middleware: `auth`, `permission:proclamatori.manage`
- `DELETE /proclamatori/{proclamatore}` → delete/anonimizza (policy) | middleware: `auth`, `permission:proclamatori.manage`
- `PATCH /proclamatori/{proclamatore}/toggle-active` → attiva/disattiva | middleware: `auth`, `permission:proclamatori.manage`
#### Campagne
- `GET /campagne` → lista + campagna attiva | middleware: `auth`, `permission:campagne.manage`
- `GET /campagne/create` → form create | middleware: `auth`, `permission:campagne.manage`
- `POST /campagne` → store | middleware: `auth`, `permission:campagne.manage`
- `GET /campagne/{campagna}` → dettaglio + tempi real-time | middleware: `auth`, `permission:campagne.manage`
- `GET /campagne/{campagna}/edit` → form edit | middleware: `auth`, `permission:campagne.manage`
- `PUT /campagne/{campagna}` → update | middleware: `auth`, `permission:campagne.manage`
- `DELETE /campagne/{campagna}` → delete | middleware: `auth`, `permission:campagne.manage`
#### Assegnazioni (azioni core)
- `POST /assegnazioni/assign` → assegna territorio a proclamatore | middleware: `auth`, `permission:territori.assign`
- `POST /assegnazioni/{assegnazione}/return` → rientro territorio | middleware: `auth`, `permission:territori.return`
> Nota: `assign` e `return` devono sempre scrivere su **audit log**.
#### Registro
- `GET /registro` → lista filtrabile | middleware: `auth`, `permission:registro.view`
- (Opzionale) `GET /registro/export` → export | middleware: `auth`, `permission:registro.export`
#### Audit log
- `GET /audit` → lista log | middleware: `auth`, `permission:audit.view`
- `GET /audit/{log}` → dettaglio log | middleware: `auth`, `permission:audit.view`
- (Opzionale) `GET /audit/export` → export | middleware: `auth`, `permission:audit.export`
### 8-bis.4 Route API (opzionali, se si usa UI “dinamica”)
> Se si adotta Livewire spesso bastano le Web route. Se si usa SPA (Inertia/Vue/React) o si vuole un frontend più interattivo, prevedere API JSON:
- `GET /api/territori?filters=...` | `auth:sanctum`, `permission:territori.manage`
- `GET /api/home/quicklists` | `auth:sanctum`
- `POST /api/assegnazioni/assign` | `auth:sanctum`, `permission:territori.assign`
- `POST /api/assegnazioni/{id}/return` | `auth:sanctum`, `permission:territori.return`
- `GET /api/campagne/{id}/realtime` | `auth:sanctum`, `permission:campagne.manage`
---
## 9) Checklist di funzionalità (con sottotask e ricontrollo)
> Regola di lavoro: **ogni funzionalità va spezzata in sottotask**, ognuno con test + verifica UI. A completamento, ricontrollare lintera funzionalità end-to-end.
### EPIC A — Setup progetto e base security
**Sottotask**
1. Creazione progetto Laravel + repo + CI base (lint/test).
2. Setup Auth (login/logout) + password policy.
3. Setup RBAC (ruoli/permessi) + seed iniziale admin.
4. Setup cifratura colonne proclamatori + test round-trip.
5. Logging audit (azioni critiche) + retention log.
**Ricontrollo (DoD)**
- Login funziona, utenti e ruoli corretti.
- Dati proclamatori illeggibili in DB (verifica diretta tabella).
- Rotte protette da permessi.
### EPIC B — Wizard iniziale + Settings
**Sottotask**
1. Model/settings + migrazione.
2. Wizard UI 3 step + validazione.
3. Blocco app finché wizard non completato (redirect).
**Ricontrollo**
- Primo avvio porta al wizard.
- Home mostra logo/nome congregazione.
### EPIC C — Gestione Territori
**Sottotask**
1. Tabelle territori/zone/tipologie + seed.
2. CRUD territori + upload PDF.
3. Lista filtrabile + badge di stato.
4. Dettaglio con PDF viewer + storico per anno teocratico.
5. Attiva/disattiva + prioritario.
6. Delete con cascade su assegnazioni.
**Ricontrollo**
- Stati corretti e coerenti.
- PDF visibile e scaricabile.
- Eliminazione rimuove storico come richiesto.
### EPIC D — Gestione Proclamatori
**Sottotask**
1. CRUD proclamatori (encrypted fields).
2. Lista con filtro + indicazione territori assegnati.
3. Disattivazione / (opzionale) anonimizzazione.
**Ricontrollo**
- Dati illeggibili in DB.
- Non assegnabile se attivo=false.
### EPIC E — Assegnazione e rientro (core)
**Sottotask**
1. Flusso assegnazione: selezione territorio + proclamatore + conferma.
2. Prevenire doppia assegnazione (vincolo logico).
3. Flusso rientro: chiusura assegnazione + calcolo giorni.
4. Prompt campagna (retroattivo) al rientro.
5. Audit: created_by/returned_by.
**Ricontrollo**
- Un territorio non può avere due assegnazioni aperte.
- Prompt campagna compare quando dovuto.
### EPIC F — Home Dashboard
**Sottotask**
1. Calcolo anno teocratico corrente + autocreazione.
2. Calcolo media mensile percorrenza.
3. Liste rapide (da assegnare/prioritari/da rientrare) con filtri e “vedi tutti”.
4. UI responsive.
**Ricontrollo**
- Numeri coerenti con registro.
- Liste mostrano gli stessi risultati delle pagine complete.
### EPIC G — Campagne
**Sottotask**
1. CRUD campagne.
2. Indicazione campagna attiva.
3. Percentuale e dettaglio “in tempo reale”.
4. Lista campagne completate.
**Ricontrollo**
- Retroattività corretta.
- Dettaglio mostra tempi e territori.
### EPIC H — Registro e statistiche
**Sottotask**
1. Vista registro per territorio con filtri richiesti.
2. Export (opzionale).
3. Test prestazioni su query con indici.
**Ricontrollo**
- Filtri corretti.
- Dati coerenti con assegnazioni.
### EPIC I — Audit Log (pagina log e tracciamento eventi)
**Sottotask**
1. Definizione eventi da loggare (CRUD + flussi assegnazione/rientro + login/logout opzionale).
2. Implementazione persistenza log (tabella custom o activity log) + migrazioni.
3. Hook automatici su modelli (created/updated/deleted) e log manuali per `assign/return`.
4. Pagina `/audit` con filtri, paginazione, dettaglio evento (before/after).
5. RBAC: `audit.view` e (opzionale) `audit.export`.
6. Retention configurabile + job scheduler (opzionale) per pulizia log.
**Ricontrollo**
- Ogni operazione critica genera un record log.
- Il log non espone dati sensibili non necessari (es. nomi proclamatori in chiaro nei properties).
- Filtri e dettaglio mostrano correttamente chi/cosa/quando e diff.
---
## 10) Test consigliati
- **Unit test**: calcolo anno teocratico, stati territorio, logica campagne.
- **Feature test**: RBAC per pagina, assegnazione/rientro, wizard.
- **Security test**: accesso non autorizzato, CSRF, rate limit login.
- **UX test**: mobile viewport, tabelle filtrabili, azioni rapide.
- **Audit test**: ogni create/update/delete e assign/return produce log con subject/causer corretti.
---
## 11) “Done” globale (criteri di completamento)
- Tutte le funzionalità richieste presenti e testate.
- Responsività verificata su smartphone/tablet.
- Dati proclamatori cifrati e illeggibili in DB.
- Log operazioni critiche + policy di retention.
- Backup e gestione segreti definiti (per produzione).
---
### Allegato — Note di chiarezza (minime)
- La formula di “media mensile” e la definizione di denominatore percentuale campagna vanno **documentate** e rese consistenti con i test.
- La cancellazione territorio con cascade è conforme al requisito, ma valutare impatto GDPR/contabile: in alternativa soft-delete + “nascondi dallo storico”.