# TerManager2 Applicazione web per la **gestione dell'assegnazione e rientro di territori** (cartoline), statistiche di percorrenza e campagne speciali per congregazioni. --- ## Indice - [Panoramica](#panoramica) - [Stack tecnologico](#stack-tecnologico) - [Requisiti di sistema](#requisiti-di-sistema) - [Installazione rapida](#installazione-rapida) - [Configurazione](#configurazione) - [Struttura del progetto](#struttura-del-progetto) - [Funzionalità principali](#funzionalità-principali) - [Ruoli e permessi (RBAC)](#ruoli-e-permessi-rbac) - [Sicurezza e GDPR](#sicurezza-e-gdpr) - [Modello dati](#modello-dati) - [Regole di business](#regole-di-business) - [Pagine dell'applicazione](#pagine-dellapplicazione) - [Comandi utili](#comandi-utili) - [Produzione](#produzione) - [Licenza](#licenza) --- ## Panoramica **TerManager2** gestisce: - **Territori** (cartoline) con PDF allegato, stato dinamico (in reparto / assegnato / da rientrare / prioritario / inattivo), zona e tipologia. - **Proclamatori** (assegnatari) con dati personali **cifrati a livello di colonna** nel database (AES-256-CBC tramite `APP_KEY`). - **Assegnazioni** con data assegnazione/rientro, anno teocratico, conteggio opzionale in campagna. - **Campagne** (periodi speciali) con percentuali di percorrenza in tempo reale. - **Dashboard** con media mensile di percorrenza, campagna attiva, e tre liste rapide (da assegnare, prioritari, da rientrare). - **Registro** delle assegnazioni filtrabile per anno teocratico, zona, stato. - **Audit Log** completo di tutte le azioni utente con diff before/after. --- ## Stack tecnologico | Componente | Tecnologia | |------------------|-----------------------------------------------| | **Framework** | Laravel 11.x | | **PHP** | 8.3-FPM | | **UI** | Livewire 3.5 + TailwindCSS 4.0 + Alpine.js | | **Database** | MariaDB 11 | | **Cache/Session**| Redis 7 (Alpine) | | **Web Server** | Nginx 1.25 (Alpine) | | **Auth** | Laravel Breeze 2.0 | | **RBAC** | spatie/laravel-permission 6.4 | | **Audit Trail** | spatie/laravel-activitylog 4.8 | | **Asset Build** | Vite 6.0 + @tailwindcss/vite | | **Node.js** | 20 LTS (nel container PHP) | | **Mail (dev)** | Mailpit | | **Container** | Docker Compose (5 servizi) | --- ## Requisiti di sistema - **Docker** >= 24.0 e **Docker Compose** >= 2.20 - Oppure, senza Docker: - PHP >= 8.3 con estensioni: pdo_mysql, mbstring, gd, intl, zip, bcmath, redis, opcache - Composer >= 2.7 - Node.js >= 20 LTS + npm - MariaDB >= 11 (o MySQL 8) - Redis >= 7 --- ## Installazione ### Prerequisiti - **Docker** e **Docker Compose** (v2) installati - Porte libere: `8080` (app), `3306` (MariaDB), `6379` (Redis), `8025` (Mailpit) ### Procedura ```bash # 1. Clona il repository git clone termanager2 cd termanager2 # 2. Configura l'ambiente cp .env.example .env # 3. Imposta i permessi dei file (UID 1000 = appuser nel container) chown -R 1000:1000 . mkdir -p storage/app/public storage/framework/{cache/data,sessions,views} storage/logs bootstrap/cache chmod -R 775 storage bootstrap/cache # 4. Avvia i container (build al primo avvio) docker compose up -d --build # 5. Installa le dipendenze PHP docker compose exec app composer install # 6. Installa le dipendenze Node.js docker compose exec app npm install # 7. Pubblica gli asset dei pacchetti Spatie docker compose exec app php artisan vendor:publish --provider="Spatie\Permission\PermissionServiceProvider" docker compose exec app php artisan vendor:publish --provider="Spatie\Activitylog\ActivitylogServiceProvider" --tag="activitylog-migrations" # 8. Esegui le migrazioni e i seeder docker compose exec app php artisan migrate --seed # 9. Crea il symbolic link per lo storage pubblico docker compose exec app php artisan storage:link # 10. Compila gli asset frontend docker compose exec app npm run build ``` > **Nota**: La `APP_KEY` viene generata automaticamente al primo avvio se assente nel `.env`. Al termine l'applicazione sarà disponibile su: **http://localhost:8080** ### Reset completo Per ripartire da zero (elimina database e volumi): ```bash docker compose down -v --remove-orphans docker compose up -d --build # Ripetere i passaggi dal punto 4 in poi ``` --- ## Configurazione ### Variabili d'ambiente principali (`.env`) | Variabile | Default | Descrizione | |-----------------------|----------------------|------------------------------------------| | `APP_KEY` | (generata) | Chiave AES-256 per cifratura. **Mai condividere** | | `APP_PORT` | `8080` | Porta host per l'applicazione | | `SEED_DEV_DATA` | `false` | Se `true`, `php artisan db:seed` include anche i dati demo | | `DB_DATABASE` | `termanager2` | Nome database MariaDB | | `DB_USERNAME` | `termanager2` | Utente database | | `DB_PASSWORD` | `secret` | Password database | | `DB_ROOT_PASSWORD` | `rootsecret` | Password root MariaDB | | `REDIS_PASSWORD` | `redissecret` | Password Redis | | `MAIL_PORT` | `1025` | Porta SMTP Mailpit | | `MAILPIT_UI_PORT` | `8025` | UI Mailpit per debug email | | `USER_ID` / `GROUP_ID`| `1000` | UID/GID container (match con host) | ### Primo avvio — Wizard Al primo accesso l'applicazione forza il **wizard di configurazione** in 3 step: 1. **Nome congregazione** (visualizzato in header) 2. **Soglie**: mesi priorità (default 4), giorni rientro (default 120), retention audit log (default 365 gg) 3. **Creazione utente admin** (email + password) ### Utenti di sviluppo (DevSeeder) | Ruolo | Email | Password | |----------------|-------------------------|------------| | Amministratore | admin@termanager2.local | `password` | | Assistente | assistente@termanager2.local | `password` | | Operatore | operatore@termanager2.local | `password` | > **Attenzione**: cambiare le password prima di qualsiasi uso in produzione. --- ## Struttura del progetto ``` TerManager2/ ├── app/ │ ├── Console/Commands/ # AuditCleanup (pulizia log schedulata) │ ├── Http/Middleware/ # SetupRequired (wizard forzato) │ ├── Livewire/ │ │ ├── Assegnazioni/ # Assegna, Rientra │ │ ├── Auth/ # Login │ │ ├── Campagne/ # Index, Create, Edit, Show │ │ ├── Proclamatori/ # Index, Create, Edit, Show, Cestino │ │ ├── Settings/ # SettingsEdit, ZoneIndex, TipologieIndex │ │ ├── Setup/ # Wizard (3 step) │ │ ├── Territori/ # Index, Create, Edit, Show, Cestino │ │ ├── AuditLog.php # Log attività (filtri, diff) │ │ ├── Home.php # Dashboard │ │ └── Registro.php # Registro assegnazioni │ ├── Models/ # 8 modelli Eloquent │ └── Providers/ # AppServiceProvider (Gate admin) ├── bootstrap/ # app.php (middleware), providers.php ├── config/ # app, auth, database, session ├── database/ │ ├── migrations/ # 10 migrazioni ordinate │ └── seeders/ # Roles, Dev, Database seeders ├── docker/ │ ├── nginx/default.conf # Vhost con security headers │ └── php/ │ ├── Dockerfile # PHP 8.3-FPM + estensioni + Composer + Node 20 │ └── php.ini # 64M upload, opcache, Europe/Rome ├── public/index.php # Entry point Laravel ├── resources/ │ ├── css/app.css # TailwindCSS 4 import │ ├── js/ # app.js, bootstrap.js (Axios) │ └── views/ │ ├── components/layouts/ # app.blade.php (sidebar), guest.blade.php │ └── livewire/ # Tutte le viste dei componenti ├── routes/ │ ├── web.php # Tutte le rotte con permessi │ └── console.php # Schedule audit:cleanup daily ├── .env.example # Template configurazione ├── artisan # CLI Laravel ├── composer.json # Dipendenze PHP ├── docker-compose.yml # 5 servizi (app, nginx, mariadb, redis, mailpit) ├── package.json # Dipendenze Node (Vite, TailwindCSS) └── vite.config.js # Vite + Laravel plugin + TailwindCSS plugin ``` --- ## Funzionalità principali ### Dashboard (Home) - Anno teocratico corrente (auto-creato se mancante, Set→Ago) - Media mensile di percorrenza (territori rientrati / mesi trascorsi) - Campagna attiva con barra di progresso percentuale - Tre liste rapide con azione diretta: - **Da assegnare**: territori in reparto, ordinati per priorità - **Prioritari**: flag manuale O soglia automatica (la soglia vince sempre) - **Da rientrare**: assegnazioni oltre la soglia giorni configurata ### Territori - CRUD completo con upload/sostituzione PDF - Filtri per zona, tipologia, stato (in_reparto, assegnato, da_rientrare, inattivo) - Badge di stato colorati + indicatore priorità (Manuale/Automatico) - Dettaglio con PDF viewer inline e storico assegnazioni per anno teocratico - Toggle attivo/inattivo e prioritario - Soft delete con cestino (ripristino o eliminazione definitiva) ### Proclamatori - CRUD con campi nome/cognome **cifrati nel DB** (AES-256-CBC) - Ricerca in-memory (necessaria per campi cifrati, ottimizzata per < 200 record) - Conteggio territori attualmente assegnati - Toggle attivo/inattivo - **Anonimizzazione GDPR** (sostituzione dati con placeholder irreversibile) - Soft delete con cestino ### Assegnazione / Rientro - Selezione territorio disponibile + proclamatore attivo - Data assegnazione con auto-detection anno teocratico - Validazione: territorio non già assegnato, entrambi attivi - Rientro con calcolo automatico giorni - **Prompt retroattivo campagna**: se l'assegnazione ricade nel range di una campagna, viene chiesto se conteggiare il rientro ### Campagne - CRUD con date inizio/fine e descrizione - Stato automatico (Attiva/Futura/Conclusa) - Percentuale percorrenza in tempo reale (conteggiati / totali assegnati nel range) - Dettaglio con lista territorio-per-territorio dei conteggiati ### Registro Assegnazioni - Filtri: anno teocratico, zona, stato (aperte/chiuse), ricerca testo - Colonne: territorio, proclamatore, date, giorni, campagna ### Audit Log - Log automatico su tutti i modelli (spatie/laravel-activitylog) - Log manuale per eventi di flusso (assign, return, login, logout) - Filtri per utente, tipo evento, ricerca testo - Dettaglio con diff before/after (properties JSON espanso) - Pulizia automatica schedulata (`audit:cleanup` — retention configurabile) ### Impostazioni - Nome congregazione - Soglia mesi priorità automatica - Soglia giorni per "da rientrare" - Retention giorni audit log ### Zone e Tipologie - CRUD inline (aggiungi, rinomina, attiva/disattiva, elimina) - Protezione: non eliminabile se ha territori associati --- ## Ruoli e permessi (RBAC) Tre ruoli con permessi granulari gestiti da **spatie/laravel-permission**: | Permesso | Amministratore | Assistente | Operatore | |---------------------|:--------------:|:----------:|:---------:| | `settings.manage` | ✅ | | | | `territori.manage` | ✅ | | | | `proclamatori.manage`| ✅ | ✅ | | | `campagne.manage` | ✅ | ✅ | | | `territori.assign` | ✅ | ✅ | ✅ | | `territori.return` | ✅ | ✅ | ✅ | | `registro.view` | ✅ | ✅ | | | `registro.export` | ✅ | | | | `audit.view` | ✅ | | | | `audit.export` | ✅ | | | L'amministratore ha un bypass completo via `Gate::before` nel `AppServiceProvider`. Il menu sidebar mostra solo le voci per cui l'utente ha permesso. --- ## Sicurezza e GDPR ### Sicurezza - **Cifratura a riposo**: nome e cognome proclamatori cifrati con `encrypted` cast (AES-256-CBC via `APP_KEY`) - **Password**: hash bcrypt (standard Laravel) - **RBAC**: middleware `permission:` su ogni rotta - **CSRF**: token integrato in tutti i form Livewire - **Rate limiting**: login con throttle configurabile - **Security headers**: X-Frame-Options, X-Content-Type-Options, X-XSS-Protection (via Nginx) - **Sessioni**: Redis con cookie `termanager2_session` (httpOnly, secure in produzione) ### GDPR - **Minimizzazione**: solo nome, cognome e stato attivo per i proclamatori - **Cifratura a riposo**: dati illeggibili con accesso diretto al DB - **Audit trail**: log completo di tutte le operazioni sui dati - **Diritto all'oblio**: metodo `anonimizza()` sul Proclamatore (sostituisce dati con placeholder) - **Retention**: pulizia automatica dei log audit oltre il periodo configurato - **Ruoli e autorizzazioni**: accesso ai dati solo per chi ha permessi specifici - **No log di dati sensibili**: l'audit log registra `proclamatore_id` ma non nome/cognome in chiaro nei `properties` --- ## Modello dati ### Tabelle principali (10 migrazioni) | Tabella | Descrizione | |-------------------|--------------------------------------------------------------| | `users` | Utenti app con auth standard Laravel | | `settings` | Configurazione singleton (congregazione, soglie, retention) | | `zone` | Zone territoriali (id, nome, attivo) | | `tipologie` | Tipologie territorio (id, nome, attivo) | | `proclamatori` | Assegnatari con nome/cognome cifrati, soft delete | | `territori` | Cartoline con zona, tipologia, PDF, soft delete | | `anni_teocratici` | Periodi Set→Ago con label univoca | | `campagne` | Periodi speciali con date e descrizione | | `assegnazioni` | Join territorio↔proclamatore con date, anno, campagna | | `activity_log` | Audit trail (spatie/laravel-activitylog) | ### Indici e vincoli - `territori.numero` — UNIQUE - `anni_teocratici.label` — UNIQUE - `assegnazioni(territorio_id, returned_at)` — INDEX composito - `assegnazioni(proclamatore_id, returned_at)` — INDEX composito - `assegnazioni(anno_teocratico_id)` — INDEX - FK con `RESTRICT` su territorio e proclamatore (protezione integrità) --- ## Regole di business ### Anno teocratico - **Settembre → Agosto**: se mese ≥ 9 → anno = `corrente/corrente+1`; se mese ≤ 8 → anno = `corrente-1/corrente` - Creato automaticamente se non esiste (metodo `AnnoTeocratico::perData()`) - L'assegnazione conta per l'anno determinato dalla **data di assegnazione** ### Stato territorio (calcolato dinamicamente) - **in_reparto**: attivo, nessuna assegnazione aperta - **assegnato**: ha assegnazione con `returned_at = null` - **da_rientrare**: assegnato da più giorni della soglia configurata - **inattivo**: `attivo = false` ### Priorità - **Manuale**: flag `prioritario = true` impostato dall'admin - **Automatica**: nessuna assegnazione negli ultimi N mesi (soglia configurabile) - La soglia automatica **vince sempre** sul flag manuale (l'admin può aggiungere ma non rimuovere se la soglia scatta) ### Campagne — percentuale percorrenza - **Denominatore**: tutti i territori assegnati nel range della campagna - **Numeratore**: assegnazioni conteggiate in campagna (`counted_in_campaign = true`) - Il prompt retroattivo appare al rientro se l'assegnazione è nel range di una campagna --- ## Comandi utili ```bash # Avviare i container docker compose up -d # Fermare i container docker compose down # Shell nel container app docker compose exec app bash # Eseguire migrazioni docker compose exec app php artisan migrate # Seed dati di sviluppo docker compose exec app php artisan db:seed # Compilare asset (dev con hot reload) docker compose exec app npm run dev # Compilare asset (produzione) docker compose exec app npm run build # Pulizia manuale audit log docker compose exec app php artisan audit:cleanup # Cache configurazione (produzione) docker compose exec app php artisan config:cache docker compose exec app php artisan route:cache docker compose exec app php artisan view:cache # Svuotare cache docker compose exec app php artisan optimize:clear ``` --- ## Produzione Per il deploy in produzione: 1. **Variabili d'ambiente**: - `APP_ENV=production` - `APP_DEBUG=false` - Password sicure per DB e Redis (non i default) - `APP_KEY` generata e conservata come secret 2. **HTTPS**: configurare un reverse proxy (Traefik, Nginx) con certificato SSL/TLS e HSTS 3. **Immagini Docker**: build senza volume codice montato, asset pre-compilati 4. **Backup**: backup cifrati del database con rotazione automatica 5. **Segreti**: gestire `APP_KEY`, password DB/Redis con Docker secrets o secret manager 6. **Performance**: - `php artisan config:cache && route:cache && view:cache` - OPcache abilitato (già configurato in `php.ini`) - Redis per cache, sessioni e code 7. **Monitoraggio**: configurare health checks e log aggregation --- ## Licenza Progetto privato — tutti i diritti riservati.