# TerManager2 — Specifiche funzionali + istruzioni per container (Laravel) > Documento operativo per realizzare **TerManager2**, applicazione Laravel per la gestione dell’assegnazione/rientro di cartoline territorio, statistiche di percorrenza e campagne speciali. > > **Obiettivo del documento**: chiarire requisiti, proporre un’architettura “container-ready”, definire modello dati e regole di calcolo, e fornire una **scomposizione in sottotask** con checklist di controllo a fine attività. --- ## 1) Visione d’insieme **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 nell’anno 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 all’oblio**: 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 (nell’anno 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: l’hash 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) - All’avvio 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 (sull’attuale assegnatario). ### 5.6 Media mensile di percorrenza (Home) Definizione richiesta: media mensile di percorrenza di tutti i territori nell’anno teocratico corrente. Interpretazione operativa (coerente con testo): - Per ogni **assegnazione chiusa** (returned_at valorizzato) nell’anno 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 dell’anno teocratico corrente - `mesi_trascorsi = numero mesi dall’inizio 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. L’importante è 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 un’assegnazione: - 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 dall’anno 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 dell’azione) - `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 l’app 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:` (o `can:`) 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 l’assenza 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 l’intera 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”.