450 lines
18 KiB
Markdown
450 lines
18 KiB
Markdown
# 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 <repository-url> 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.
|