# Guida all'applicazione ADO Update

## Panoramica

**ADO Update** è un'applicazione web sviluppata con il framework **CodeIgniter 4** (PHP) per la gestione delle adozioni a distanza della **Comunità Papa Giovanni XXIII**. Permette di tenere traccia dei bambini seguiti dai missionari, dei testi di aggiornamento associati e delle fotografie, con la possibilità di generare report PDF pronti per la stampa o la distribuzione ai donatori.

---

## Struttura del database

Il database si chiama **`adoupdate_afdev`** (MySQL, charset `utf8`). È composto da quattro tabelle applicative principali.

### Relazioni tra le tabelle

```
users (id) ──────────────────── childs (user_related)
                                      │
                           ┌──────────┴──────────┐
                           │                     │
               child_updates (child_id)   child_photos (child_id)
```

- Un **utente** può essere referente di molti bambini (`users` 1 → N `childs`).
- Un **bambino** può avere molti testi di aggiornamento (`childs` 1 → N `child_updates`), di cui uno solo attivo.
- Un **bambino** può avere molte foto (`childs` 1 → N `child_photos`), di cui una sola attiva.

---

### Tabella `users`

Gestita dal model `UsersModel`. La password non viene mai salvata in chiaro: il hook `beforeInsert`/`beforeUpdate` la converte in hash bcrypt nel campo `password_hash` e rimuove `password` prima della scrittura.

| Colonna | Tipo | Note |
|---|---|---|
| `id` | INT(5) UNSIGNED AUTO_INCREMENT | Chiave primaria |
| `is_admin` | TINYINT | `0` = normale, `1` = amministratore |
| `firstname` | VARCHAR(50) | Nome |
| `lastname` | VARCHAR(50) | Cognome |
| `phone` | VARCHAR(15) | Telefono |
| `email` | VARCHAR(100) UNIQUE | Email (usata per il login) |
| `password_hash` | VARCHAR(255) | Hash bcrypt della password |
| `role_id` | INT | Livello di accesso (vedi tabella ruoli) |
| `is_active` | TINYINT | `0` = disabilitato, `1` = abilitato |
| `activation_hash` | VARCHAR(64) UNIQUE | Hash HMAC-SHA256 per l'attivazione via email; `NULL` dopo l'attivazione |
| `created_at` | DATETIME | Gestito automaticamente da CI4 |
| `updated_at` | DATETIME | Gestito automaticamente da CI4 |

**Valori di `role_id` definiti nel form di gestione:**

| `role_id` | Etichetta nell'interfaccia |
|---|---|
| `2` | Utente (missionario base) |
| `4` | Editor |
| `6` | Stampa |
| `8` | Manager |
| `> 8` | Super-admin (assegnato manualmente via DB) |

> `is_admin` e `role_id` sono ortogonali: un utente con `is_admin = 1` accede alla gestione utenti indipendentemente dal `role_id`. I controlli di visibilità nel menu e nelle viste usano `role_id` tramite la sessione (`session()->user_role`).

---

### Tabella `childs`

Gestita dal model `ChildsModel` (PK non standard: `idchild`). Contiene l'anagrafica completa di ogni bambino e i flag di flusso lavoro.

| Colonna | Tipo | Note |
|---|---|---|
| `idchild` | INT UNSIGNED AUTO_INCREMENT | Chiave primaria |
| `project_code` | VARCHAR | Codice del progetto missionario (maiuscolo) |
| `child_code` | VARCHAR | Codice identificativo del bambino (maiuscolo); usato nel nome del PDF |
| `firstname` | VARCHAR | Nome (title-case) |
| `lastname` | VARCHAR | Cognome (title-case) |
| `gender` | TINYINT | `1` = Maschio, `2` = Femmina, `3` = Altro |
| `dob` | DATE | Data di nascita; `1970-01-01` = non nota |
| `is_dob_real` | TINYINT | `1` = data certa, `0` = approssimativa |
| `status` | TINYINT | Stato adozione (vedi tabella valori) |
| `city_village` | VARCHAR | Città o villaggio di origine |
| `country` | VARCHAR | Nazione di origine |
| `note` | TEXT | Note libere |
| `to_be_reviewed` | TINYINT | `0` = da revisionare / in lavorazione, `1` = revisionato / bloccato |
| `to_be_extracted` | TINYINT | `1` = da estrarre per elaborazione esterna |
| `to_be_asset` | TINYINT | `1` = da aggiornare nel sistema ASSET |
| `is_welcome` | TINYINT | `1` = usare la lettera di benvenuto nel report |
| `pdf_generated` | TINYINT | `1` = il PDF è già stato generato almeno una volta |
| `user_related` | INT | FK → `users.id`; il missionario referente del bambino |
| `codana` | VARCHAR | Codice anagrafica del donatore associato (visibile solo a `role_id > 8`) |
| `created_at` | DATETIME | Gestito automaticamente da CI4 |
| `updated_at` | DATETIME | Gestito automaticamente da CI4 |

**Valori di `status`:**

| Valore | Significato | Lista di appartenenza |
|---|---|---|
| `1` | Libero (adottabile) | Elenco generale + Adottabili |
| `2` | Adottato | Elenco generale + Adottati |
| `3` | Non adottabile | Non adottabili (se `to_be_reviewed = 0`) / N.A. Chiusi (se `to_be_reviewed = 1`) |
| `4` | Adozione revocata | Elenco generale + Adozioni revocate |

**Comportamento automatico dei flag alla generazione del PDF:**

Quando viene generato il PDF, il controller `PrintPdf` aggiorna il record impostando:

```
pdf_generated    = 1
to_be_reviewed   = 1   ← blocca la modifica di testo e foto
to_be_extracted  = 0
to_be_asset      = 0
is_welcome       = 0
```

---

### Tabella `child_updates`

Gestita dal model `UpdatesModel` (PK: `idupdate`). Contiene i testi di aggiornamento associati a ciascun bambino.

| Colonna | Tipo | Note |
|---|---|---|
| `idupdate` | INT UNSIGNED AUTO_INCREMENT | Chiave primaria |
| `child_id` | INT | FK → `childs.idchild` |
| `message` | TEXT | Testo HTML (max ~2500 caratteri); supporta `<p>` e `<br>` per il PDF |
| `active` | TINYINT | `1` = testo predefinito usato nel PDF, `0` = archiviato |
| `created_at` | DATETIME | Gestito automaticamente da CI4 |
| `updated_at` | DATETIME | Gestito automaticamente da CI4 |

> **Invariante gestita dall'applicazione:** esiste al più un record con `active = 1` per ogni `child_id`. Quando si inserisce o si modifica un testo marcandolo come attivo, l'applicazione esegue `UPDATE child_updates SET active=0 WHERE child_id=?` prima dell'inserimento/aggiornamento.

---

### Tabella `child_photos`

Gestita dal model `PhotosModel` (PK: `idphoto`). Archivia i riferimenti alle immagini caricate sul server.

| Colonna | Tipo | Note |
|---|---|---|
| `idphoto` | INT UNSIGNED AUTO_INCREMENT | Chiave primaria |
| `child_id` | INT | FK → `childs.idchild` |
| `path` | VARCHAR | Percorso relativo dentro `writable/uploads/`; struttura `A{child_id}/{filename}` |
| `active` | TINYINT | `1` = foto predefinita usata nel PDF, `0` = archiviata |
| `created_at` | DATETIME | Gestito automaticamente da CI4 |
| `updated_at` | DATETIME | Gestito automaticamente da CI4 |

> **Invariante gestita dall'applicazione:** esiste al più un record con `active = 1` per ogni `child_id`, con la stessa logica di `child_updates`. L'eliminazione di una foto rimuove sia il record DB sia il file fisico (`unlink`).

---

### Archiviazione file sul server

```
writable/
└── uploads/
    └── A{idchild}/          ← una cartella per bambino
        ├── img_abc123.jpg
        └── img_xyz456.png

public/
└── REPORTS/
    └── {child_code}_{lastname}_{firstname}.pdf
```

---

## Ruoli utente

L'applicazione usa due meccanismi distinti per il controllo degli accessi:

- **`is_admin`** (flag booleano): abilita la sezione di gestione utenti (`/Users`). Verificato dal filtro `AdminFilter`.
- **`role_id`** (intero): controlla la visibilità di sezioni, campi e liste. Salvato in sessione come `user_role` al momento del login. Verificato inline nelle view e nei controller.

| `role_id` | Etichetta | Cosa può fare in più rispetto al livello inferiore |
|---|---|---|
| `2` | Utente | Vede il menu bambini; accede solo ai bambini assegnati a sé (`user_related = id`) |
| `4` | Editor | Vede `project_code`, `child_code`; può gestire flag (`to_be_reviewed`, ecc.); può assegnare il bambino a un missionario diverso da sé |
| `6` | Stampa | Stesso perimetro dell'Editor per i controlli `role_id > 2` |
| `8` | Manager | Vede anche la lista "Bambini N.A. Chiusi" (`role_id > 7`) |
| `> 8` | Super-admin | Vede i report generati; vede e modifica il campo `codana` |
| `is_admin` | Amministratore | Accede a `/Users` (CRUD completo degli utenti) |

---

## Funzionalità disponibili

### 1. Accesso e registrazione

- **Login** (`/login`): accesso con email e password; l'account deve avere `is_active = 1`.
- **Registrazione** (`/signup`): un nuovo utente può registrarsi autonomamente. Viene generato un token casuale (16 byte hex), il cui hash HMAC-SHA256 è salvato in `activation_hash`; la email di attivazione contiene il token in chiaro. Al click del link, il token viene ri-hashato e confrontato con il DB per attivare l'account (`is_active = 1`, `activation_hash = NULL`).
- **Recupero password** (`/password_recovery`): pagina di richiesta recupero (form presente, logica di invio non ancora implementata).
- **Logout** (`/logout`): distrugge la sessione PHP.

---

### 2. Gestione profilo personale

Ogni utente loggato può:

- **Visualizzare il proprio profilo** (`/profilemanager/{id}`)
- **Modificare i propri dati** (`/editprofile/{id}`): nome, cognome, telefono, email, password (il campo password viene ignorato se lasciato vuoto)

---

### 3. Gestione bambini

#### Liste disponibili nel menu

| Voce di menu | Filtro applicato | Visibilità |
|---|---|---|
| Elenco Bambini | Tutti (o solo propri se `role_id ≤ 2`) | `role_id > 1` |
| Bambini adottabili | `status = 1` | `role_id > 1` |
| Bambini non adottabili | `status = 3` AND `to_be_reviewed = 0` | `role_id > 1` |
| Bambini N.A. Chiusi | `status = 3` AND `to_be_reviewed = 1` | `role_id > 7` |
| Bambini adottati | `status = 2` | `role_id > 1` |
| Adozioni revocate | `status = 4` | `role_id > 1` |
| Report generati | `pdf_generated = 1` | `role_id > 8` |

#### Operazioni sui bambini

- **Aggiungere** (`/Childs/add`): i campi `project_code` e `child_code` sono visibili solo se `role_id > 2`; il campo `user_related` è fisso sull'utente corrente se `role_id < 4`.
- **Visualizzare il dettaglio** (`/Childs/view/{id}`): scheda anagrafica, testo attivo, storico testi, foto attiva, archivio foto.
- **Modificare** (`/Childs/edit/{id}`)
- **Eliminare** (`/Childs/delete/{id}`)
- **Generare il PDF** (`/Childs/generatepdf/{id}`)

---

### 4. Aggiornamenti (testi del report)

- **Aggiungere** (`/Updates/addbychild/{child_id}`): l'editor usa **Summernote** (rich-text HTML). Limite di 2500 caratteri.
- **Modificare** (`/Updates/edit/{id}`)
- **Eliminare** (`/Updates/delete/{id}`)

> Testo e pulsanti di modifica/eliminazione sono nascosti nell'interfaccia quando `to_be_reviewed = 1` e `role_id ≤ 2`.

---

### 5. Gestione foto

- **Caricare** (`/Photos/addbychild/{child_id}`): JPG o PNG, max 2,5 MB. File salvato in `writable/uploads/A{child_id}/`.
- **Impostare come predefinita** (`/Photos/setAsDefault/{id}`)
- **Eliminare** (`/Photos/delete/{id}`): elimina record DB e file fisico.
- **Eliminare tutte le foto di un bambino** (`/Childs/deleteimages/{id}`): solo `role_id > 2`; cancella i record DB ma **non** i file fisici (attenzione: potenziale accumulo di file orfani).
- **Strumento di ritaglio** (`/Cropper`): apre un tool per ridimensionare le immagini prima del caricamento.

---

### 6. Gestione utenti (solo Amministratori)

Accessibile da `/Users`, protetto dal filtro `AdminFilter` (`is_admin = 1`).

- **Elenco** (`/Users`): tutti gli utenti registrati.
- **Aggiungere** (`/Users/add`): tutti i campi inclusi ruolo e flag `is_admin`/`is_active`.
- **Visualizzare** (`/Users/view/{id}`)
- **Modificare** (`/Users/edit/{id}`): la password non viene modificata se i campi sono lasciati vuoti. Un amministratore non può togliersi il flag `is_admin` da solo (il checkbox è disabilitato sulla propria scheda).
- **Eliminare** (`/Users/delete/{id}`)

---

### 7. Generazione PDF

Usa la libreria **TCPDF**. Il layout è fisso (A4 verticale, margini 15mm):

| Elemento | Posizione nel PDF |
|---|---|
| Logo APG23 | In alto a sinistra (64mm larghezza) |
| "Cartiglio" (cornice dati) | Centro-destra (100–181mm) |
| Foto del bambino | In alto a sinistra sotto il logo (45mm, `active = 1`) |
| Nome e cognome | Dentro il cartiglio |
| Città/villaggio e nazione | Dentro il cartiglio |
| Codice bambino | Dentro il cartiglio |
| Testo di aggiornamento | Sotto il cartiglio (da `y = 120`) |
| Footer grafico | In fondo alla pagina (`y = 270`) |

Il file viene salvato come:
```
public/REPORTS/{child_code}_{lastname}_{firstname}.pdf
```

---

## Stack tecnologico

| Componente | Tecnologia |
|---|---|
| Backend | PHP 8.x + CodeIgniter 4 |
| Database | MySQL — database `adoupdate_afdev` su `localhost` |
| Generazione PDF | TCPDF |
| Editor rich-text | Summernote |
| Frontend | AdminLTE 3 (Bootstrap 4 + Font Awesome) |
| Email | SMTP Gmail (TLS porta 587) |
| Lingua interfaccia | Italiano (`app.defaultLocale = 'it'`) |
| Timezone | Europe/Rome |
