# documents

file_path: /var/www/html/dev/yii/_documentation/README.md
title: Documentazione applicazioni SOPHIA
scanned_at: 2026-04-16 13:43:13
content:
# Documentazione applicazioni SOPHIA

Questo repository contiene tutta la documentazione composta da file .MD delle applicazioni SOPHIA.

Si prevede di utilizzare un branch separato per ogni applicazione.

**N.B.**: scaricare queste documentazioni dentro una cartella `_documentation` all'interno della relativa applicazione e poi escludere via `.gitignore`.


file_path: /var/www/html/dev/yii/_documentation/sophia_customizations.md
title: Sophia customizations versioned
scanned_at: 2026-04-16 13:43:13
content:
# Sophia customizations versioned

## Ambito
Questo documento elenca solo le customizzazioni Sophia versionate presenti nel repository Yii.

Regole applicate:
- baseline: `327a486` (`yii_1.1.23`);
- inclusi solo commit presenti nella history Git;
- escluse eventuali modifiche locali non committate.

## Lettura della matrice
- `commit` = hash breve del commit che ha introdotto o modificato la customizzazione;
- `ticket` = riferimento ticket presente nel messaggio commit;
- `impatto` = effetto tecnico osservabile sul framework o sulla UI.

## Matrice commit

| file | commit | ticket | impatto |
|---|---|---|---|
| `framework/web/CPagination.php` | `af68372` | `#0001616` | Porta la paginazione di default sotto `CPagination.php` tramite costante di framework, spostando la configurazione fuori dal `config_frm`. |
| `framework/web/CPagination.php` | `506e38f` | `#0002230` | Rafforza la gestione della costante `DEFAULT_PAGINATION_ROWS`: controllo di esistenza e fallback esplicito con eccezione se manca la definizione. |
| `framework/web/widgets/captcha/CCaptchaAction.php` | `dc2542d` | `#0001661` | Ripristina la visualizzazione del captcha nel recupero password con `ob_clean()` prima degli header immagine. |
| `framework/zii/widgets/assets/gridview/jquery.yiigridview.js` | `d304668` | `#0001841` | Introduce la gestione dei form di filtri avanzati nella griglia. |
| `framework/zii/widgets/assets/gridview/jquery.yiigridview.js` | `31d825c` | `#0001841` | Raffina la prima implementazione dei filtri avanzati nella griglia. |
| `framework/zii/widgets/assets/gridview/jquery.yiigridview.js` | `31e0166` | `#0001841` | Piccolo fix sulla stessa area, in pratica un ritocco puntuale al supporto dei filtri avanzati. |
| `framework/zii/widgets/assets/gridview/jquery.yiigridview.js` | `4371cc6` | n/d | Adatta la griglia ai filtri inline quando sono presenti anche filtri di ricerca avanzata. |
| `framework/zii/widgets/assets/gridview/jquery.yiigridview.js` | `98b0aef` | n/d | Aggiunge supporto specifico ai filtri textarea nelle griglie. |
| `framework/zii/widgets/assets/gridview/jquery.yiigridview.js` | `4e9aafd` | `#0003338` | Corregge il comportamento dei form di ricerca avanzata nelle griglie admin. |
| `framework/web/helpers/CHtml.php` | `34184f4` | `#0003186` | Modifica `errorSummary()` per evitare occorrenze duplicate degli stessi messaggi di errore. |
| `framework/web/CHttpSession.php` | `6e8c646` | n/d | Aggiunge `Cache-Control: no cache` all'apertura sessione per rendere piu' affidabile il back del browser. |
| `framework/base/CErrorHandler.php` | `f005c12` | `#0004693` | In ambiente `YII_DEBUG` renderizza sempre il dettaglio dell'errore, evitando la sola `site/error`. |
| `framework/views/exception.php` | `b213644` | `#0005405` | Scrive i dettagli dell'eccezione su `Exceptions_logs.txt` prima del rendering della pagina. |
| `framework/zii/widgets/grid/CGridColumn.php` | `ac110b6` | `#0006725` `#0006747` | Introduce `footer2` e la seconda cella/footer row per le griglie. |
| `framework/zii/widgets/grid/CGridView.php` | `ac110b6` | `#0006725` `#0006747` | Aggiunge il rendering della seconda riga di footer e il relativo check `getHasFooter2()`. |

## Dettaglio per file

### `framework/web/CPagination.php`
Commit chiave:
- `af68372` per la migrazione della paginazione di default su costante;
- `506e38f` per il controllo robusto della costante.

Impatto:
- la pagina corrente, il limite e il numero di pagine non dipendono piu' solo dal config applicativo;
- se la costante manca, il framework fallisce in modo esplicito invece di degradare in modo silenzioso.

Nota operativa:
- e' una customizzazione di core framework, quindi i controller Musa che usano `CActiveDataProvider` o query paginated ereditano subito il comportamento.

### `framework/web/widgets/captcha/CCaptchaAction.php`
Commit chiave:
- `dc2542d` (`#0001661`).

Impatto:
- la risposta immagine viene ripulita prima degli header;
- si evita che output residuo rompa il captcha nelle pagine sensibili.

### `framework/zii/widgets/assets/gridview/jquery.yiigridview.js`
Commit chiave:
- `d304668`, `31d825c`, `31e0166`, `4371cc6`, `98b0aef`, `4e9aafd`.

Impatto:
- la griglia supporta filtri avanzati e filtri inline nello stesso ecosistema;
- textarea e campi complessi vengono trattati in modo specifico;
- Musa puo' usare il pattern `RenderSettings` senza perdere il comportamento AJAX della griglia.

Lettura tecnica:
- questo file e' il punto di raccordo tra view, filtri e comportamento client-side;
- le customizzazioni qui hanno effetto diretto su UX e su eventuali casi di filtro non sincronizzato.

### `framework/web/helpers/CHtml.php`
Commit chiave:
- `34184f4` (`#0003186`).

Impatto:
- `errorSummary()` non ripete lo stesso messaggio piu' volte;
- i form risultano piu' leggibili, soprattutto quando piu' regole generano lo stesso testo.

### `framework/web/CHttpSession.php`
Commit chiave:
- `6e8c646`.

Impatto:
- l'header `Cache-Control: no cache` supporta il back del browser con sessione attiva;
- riduce gli effetti di pagine stale o contenuto non aggiornato dopo redirect e login.

### `framework/base/CErrorHandler.php`
Commit chiave:
- `f005c12` (`#0004693`).

Impatto:
- in debug l'utente sviluppatore vede il dettaglio completo dell'errore;
- fuori debug resta il percorso standard di errore applicativo;
- la scelta viene fatta nel framework, non in singole action.

### `framework/views/exception.php`
Commit chiave:
- `b213644` (`#0005405`).

Impatto:
- ogni eccezione renderizzata passa anche da logging su file;
- utile per diagnosi post-mortem quando il rendering HTML non basta.

### `framework/zii/widgets/grid/CGridColumn.php` e `framework/zii/widgets/grid/CGridView.php`
Commit chiave:
- `ac110b6` (`#0006725`, `#0006747`).

Impatto:
- le griglie possono esporre un secondo footer (`footer2`);
- la view di grid deve verificare sia il footer standard sia il nuovo footer esteso;
- il comportamento e' pensato per casi di consuntivazione con riepiloghi multipli.

## Sintesi per area

### Griglie
Le customizzazioni piu' invasive sono sulla parte grid:
- `jquery.yiigridview.js` per i filtri avanzati;
- `CGridColumn.php` e `CGridView.php` per footer multipli.

Effetto sul progetto Musa:
- le griglie admin possono combinare filtri inline, ricerca avanzata e componenti custom come `TbSelect2` senza spezzare il rendering standard.

### Errori
La catena error handling e' stata rinforzata in tre punti:
- `CErrorHandler.php` decide cosa mostrare;
- `exception.php` scrive i dettagli su log;
- `CHtml.php` riduce il rumore dei messaggi duplicati.

### Paginazione e sessione
La paginazione usa una costante di framework e la sessione applica cache-control esplicito.

Effetto sul progetto Musa:
- comportamento uniforme tra moduli;
- minori differenze tra browser e ambienti;
- meno logica duplicata nel `config` applicativo.


file_path: /var/www/html/dev/yii/_documentation/structure_and_functions.md
title: Yii 1.1: struttura e funzioni chiave
scanned_at: 2026-04-16 13:43:13
content:
# Yii 1.1: struttura e funzioni chiave

## Scopo
Questo documento serve a due tipi di lettori:
- developer che devono capire dove intervenire senza perdere tempo nel framework;
- AI agent che devono orientarsi nel codice Musa e scegliere il punto di modifica corretto.

Il focus e' sui componenti Yii che Musa usa davvero: controller, helper HTML, sessioni, paginazione, grid, captcha ed error handling.

## Vista d'insieme
In Musa il flusso tipico e':
1. Il controller prepara modello, data provider e configurazione di rendering.
2. La view compone la pagina usando widget Yii e helper `CHtml`.
3. Le parti interattive della griglia vengono coordinate da JS (`jquery.yiigridview.js`) e da `CGridView`.
4. Gli errori vengono gestiti da `CErrorHandler` e dalla view `framework/views/exception.php`.

Pattern ricorrente in Musa:
- logica di presentazione spinta nel controller tramite `RenderSettings`;
- view relativamente sottile;
- HTML generato con helper Yii, non con stringhe sparse;
- grid guidate da `dataProvider`, `columns` e filtri AJAX.

## Struttura del framework rilevante

| Area | Ruolo pratico | Quando usarla |
|---|---|---|
| `framework/base` | Fondazioni del framework: componenti, eventi, error handler, classi base application | Quando serve intercettare errori o costruire componenti applicativi riusabili |
| `framework/web` | Strato web: request, response, controller, sessioni, paginazione, HTML helper, captcha | Quando il codice gira dentro una richiesta HTTP |
| `framework/zii/widgets/grid` | Widget per tabelle interattive e colonne configurabili | Quando una lista deve essere filtrabile, ordinabile o azionabile |
| `framework/views` | View di sistema, inclusa la pagina di eccezione | Quando si vuole cambiare il comportamento di fallback degli errori |

## Funzioni e responsabilita'

### `CPagination`
File: [`framework/web/CPagination.php`](/var/www/html/dev/yii/framework/web/CPagination.php)

Responsabilita':
- calcolare pagina corrente, offset e limit;
- costruire URL di paginazione;
- applicare `LIMIT` e `OFFSET` ai criteri SQL.

Funzioni chiave:
- `getPageSize()` e `setPageSize()` per dimensionare il numero di righe per pagina;
- `getPageCount()` per calcolare il totale delle pagine;
- `getCurrentPage()` e `setCurrentPage()` per leggere o forzare la pagina corrente;
- `createPageUrl()` per generare il link di pagina;
- `applyLimit()` per applicare il limite al `CDbCriteria`;
- `getOffset()` e `getLimit()` per integrazioni SQL.

Uso in Musa:
- la paginazione e' stata resa dipendente da una costante di configurazione del framework;
- il comportamento e' stato centralizzato nel core Yii per evitare logiche duplicate nei config applicativi.

### `CCaptchaAction`
File: [`framework/web/widgets/captcha/CCaptchaAction.php`](/var/www/html/dev/yii/framework/web/widgets/captcha/CCaptchaAction.php)

Responsabilita':
- generare l'immagine captcha;
- salvare il codice di verifica in sessione;
- validare l'input dell'utente.

Funzioni chiave:
- `run()` per servire l'immagine o il codice;
- `getVerifyCode()` per recuperare o rigenerare il valore;
- `validate()` per confrontare l'input con il codice atteso;
- `renderImageGD()` e `renderImageImagick()` per il rendering grafico.

Uso in Musa:
- tipicamente collegato a form di login, recupero password e flussi sensibili;
- la customizzazione Sophia corregge un caso in cui il captcha non veniva visualizzato correttamente.

### `CHtml`
File: [`framework/web/helpers/CHtml.php`](/var/www/html/dev/yii/framework/web/helpers/CHtml.php)

Responsabilita':
- generare markup HTML sicuro e coerente;
- costruire form controls legati ai model Yii;
- produrre markup per link, bottoni, label, error summary.

Funzioni chiave:
- `link()` per link HTML con supporto a `submit`;
- `submitButton()` per bottoni di submit;
- `activeLabel()` e `activeLabelEx()` per etichette collegate al model;
- `activeTextArea()` e `activeDropDownList()` per campi di form;
- `errorSummary()` per mostrare gli errori di validazione;
- `tag()` per generare tag generici.

Uso in Musa:
- il controller costruisce etichette, bottoni e widget direttamente tramite `CHtml`;
- `errorSummary()` e' usato nei form classici e nelle schermate di manutenzione;
- molte view mantengono il markup coerente con Bootstrap o con i widget booster.

### `CHttpSession`
File: [`framework/web/CHttpSession.php`](/var/www/html/dev/yii/framework/web/CHttpSession.php)

Responsabilita':
- aprire, chiudere e mantenere la sessione HTTP;
- esporre la sessione come oggetto accessibile via array;
- gestire cookie, timeout, ID e garbage collection.

Funzioni chiave:
- `open()` e `close()` per il ciclo di vita della sessione;
- `regenerateID()` per sicurezza e riallineamento della sessione;
- `getTimeout()`, `setTimeout()`, `getCookieParams()`, `setCookieParams()` per la configurazione;
- `ArrayAccess` (`offsetGet`, `offsetSet`, `offsetUnset`) per uso pratico come `Yii::app()->session[...]`.

Uso in Musa:
- e' il punto giusto quando un flusso dipende dalla persistenza lato browser;
- la customizzazione Sophia aggiunge header di cache-control per migliorare il back del browser.

### `CErrorHandler`
File: [`framework/base/CErrorHandler.php`](/var/www/html/dev/yii/framework/base/CErrorHandler.php)

Responsabilita':
- intercettare eccezioni e errori PHP;
- scegliere se renderizzare la pagina di errore standard o la view di dettaglio;
- costruire trace, source code snippet e header HTTP appropriati.

Funzioni chiave:
- `handle()` come entrypoint del gestore errori;
- `handleException()` e `handleError()` per i due rami principali;
- `renderException()` e `renderError()` per la fase di output;
- `getViewFile()` per risolvere il file di view corretto;
- `renderSourceCode()` per stampare il contesto della riga di errore.

Uso in Musa:
- utile per distinguere ambiente DEV e produzione;
- la customizzazione Sophia permette il dettaglio completo quando `YII_DEBUG` e' attivo.

### `framework/views/exception.php`
File: [`framework/views/exception.php`](/var/www/html/dev/yii/framework/views/exception.php)

Responsabilita':
- presentare all'utente la pagina di eccezione di default;
- stampare tipo errore, messaggio, file, riga e stack trace.

Uso in Musa:
- e' stato esteso per loggare i dettagli dell'eccezione su file;
- e' il punto di fallback visuale quando l'errore non viene gestito altrove.

### `CGridColumn`
File: [`framework/zii/widgets/grid/CGridColumn.php`](/var/www/html/dev/yii/framework/zii/widgets/grid/CGridColumn.php)

Responsabilita':
- rappresentare una colonna della griglia;
- renderizzare header, filter cell, data cell e footer;
- incapsulare le regole di output di una singola colonna.

Funzioni chiave:
- `renderHeaderCell()` e `renderHeaderCellContent()`;
- `renderFilterCell()` e `renderFilterCellContent()`;
- `renderDataCell()` e `renderDataCellContent()`;
- `renderFooterCell()` e `renderFooterCellContent()`;
- `getDataCellContent()` per il contenuto della cella dati.

Uso in Musa:
- le colonne vengono configurate dal controller via array e oggetti `RenderSettings`;
- il commit Sophia ha introdotto il concetto di `footer2` per supportare una seconda riga di footer.

### `CGridView`
File: [`framework/zii/widgets/grid/CGridView.php`](/var/www/html/dev/yii/framework/zii/widgets/grid/CGridView.php)

Responsabilita':
- orchestrare il rendering della tabella, dei filtri, dei footer e del client script;
- integrare `CGridColumn` e il `dataProvider`;
- gestire l'output della griglia interattiva.

Funzioni chiave:
- `init()` e `initColumns()` per preparare il widget;
- `registerClientScript()` per caricare il JS della griglia;
- `renderItems()` per il rendering completo;
- `renderTableHeader()`, `renderFilter()`, `renderTableBody()`, `renderTableFooter()`;
- `getHasFooter()` e, nella customizzazione Sophia, `getHasFooter2()`.

Uso in Musa:
- la griglia e' spesso sostituita o estesa con widget personalizzati come `widgets.FrmGridView`;
- il controller passa `dataProvider`, `columns`, `ajaxType`, `responsiveTable` e la logica di filtro.

## Pattern Musa da ricordare

### 1. RenderSettings come layer di presentazione
Musa usa oggetti `RenderSettings` nel controller per descrivere come deve essere resa ogni sezione della UI.

Esempio reale:
- [`MusaCorsiIscrizioniController.php`](/var/www/html/dev/musa_app/protected/controllers/MusaCorsiIscrizioniController.php#L119)
- [`MusaCorsiFormazioniDettController.php`](/var/www/html/dev/musa_app/protected/controllers/MusaCorsiFormazioniDettController.php#L238)

Effetto pratico:
- la stessa action puo' esporre rendering diverso per griglia, filtri, form e bottoni;
- il controller conserva la logica di mapping, la view resta piu' semplice.

### 2. Grid view guidata dal controller
In [`musaCorsiSessioni/admin.php`](/var/www/html/dev/musa_app/protected/views/musaCorsiSessioni/admin.php#L30) la view:
- disegna i pulsanti gia' preparati dal controller;
- abilita o disabilita i filtri inline in base a `RenderSettings`;
- passa `dataProvider`, `columns` e opzioni al widget della griglia.

### 3. CHtml per markup coerente
Le view e i controller Musa usano `CHtml` per:
- bottoni di submit e link di ritorno;
- label active legate ai model;
- `errorSummary()` per i form;
- tag generici per intestazioni e wrapper.

### 4. Estensioni widget
Musa usa anche widget o helper custom quando il comportamento Yii standard non basta, per esempio:
- `widgets.FrmGridView`;
- `booster.widgets.TbSelect2`;
- `booster.widgets.TbButtonColumn`.

## Come lavorare su questi file
- Se il problema e' di impaginazione o limiti pagina, parti da `CPagination`.
- Se riguarda input captcha o recupero password, parti da `CCaptchaAction`.
- Se vuoi cambiare HTML di form o link, parti da `CHtml`.
- Se il problema e' di sessione o browser back, parti da `CHttpSession`.
- Se vuoi cambiare la gestione errori, guarda prima `CErrorHandler` e poi `framework/views/exception.php`.
- Se il problema riguarda una tabella, la catena da seguire e' `CGridView` -> `CGridColumn` -> `jquery.yiigridview.js`.


file_path: /var/www/html/dev/sophia_framework2/_documentation/architecture_layers_frm_app_cli.md
title: Architecture Layers FRM APP CLI
scanned_at: 2026-04-16 13:45:11
content:
# Architecture Layers FRM APP CLI

## Significato Dei Layer
In questo progetto i layer non indicano solo "cartelle diverse": indicano livelli di override e responsabilita.

Attenzione: qui `cli` non significa console command di Yii. Nel codice corrente `cli` e il layer client-specific, cioe la variante di progetto che puo sovrascrivere il comportamento FRM/APP.

## FRM
Il layer FRM e la base condivisa del framework.

Esempi di path:

- `protected/controllers/frm`
- `protected/models/frm`
- `protected/views`
- `protected/extensions`

Qui stanno:

- modelli base e anagrafiche comuni;
- controller base;
- helper condivisi;
- rendering e widget standard;
- costanti runtime condivise.

## APP
Il layer APP contiene la specializzazione applicativa.

Esempi reali:

- `protected/controllers/app/AbilitazioniAppController.php`
- `protected/controllers/app/SiteAppController.php`
- `protected/controllers/app/AppAnaCommesseController.php`
- `protected/models/app/AppAnaUtentiStg.php`
- `protected/models/app/AppAnaCommesse.php`

Qui trovi:

- logica di business aggiuntiva;
- override di FRM;
- schedulazioni o procedura specifiche;
- adattamenti al dominio Musa.

## CLI / Client
Il layer client-specific e configurato in:

- `protected/config/config_client.php`

Le mappe reali mostrano che i controller `Frm...` vengono redirectati verso implementazioni client:

- `FrmAnaCommesse` -> `application.controllers.cli.CliAnaCommesseController`
- `FrmAnaDipartimenti` -> `application.controllers.cli.CliAnaDipartimentiController`
- `FrmAnaUtentiStg` -> `application.controllers.cli.CliAnaUtentiStgController`
- `FrmAnaCdc` -> `application.controllers.cli.CliAnaCdcController`
- `FrmAnaSocietaUtente` -> `application.controllers.cli.CliAnaSocietaUtenteController`

I file fisici sono in:

- `protected/controllers/cli`
- `protected/models/cli` come import di `application.models.cli.*`

## Relazione Tra I Layer
La gerarchia reale e visibile anche nelle abilitazioni:

- `AbilitazioniCliController` estende `AbilitazioniAppController`
- `AbilitazioniAppController` estende `AbilitazioniFrmController`

Questo pattern significa:

1. prima si prova il comportamento client;
2. poi il comportamento applicativo;
3. infine il comportamento framework.

## Caricamento E Import
La configurazione base (`protected/config/config_frm.php`) importa:

- `application.models.*`
- `application.models.frm.*`
- `application.components.*`
- `application.components.frm.*`
- `application.modules.cruge.components.*`

La configurazione cliente (`protected/config/config_client.php`) aggiunge:

- `application.models.cli.*`
- controllerMap client-specific.

## Implicazioni Per Lo Sviluppo

- se la logica e condivisa, va in FRM;
- se e specifica del dominio applicativo, va in APP;
- se cambia per cliente o per variante di installazione, va in CLI/client;
- non duplicare la stessa regola in piu layer senza una motivazione esplicita;
- quando un override diventa stabile e comune, valuta il suo spostamento verso FRM.

## Esempi Pratici

- `protected/controllers/app/AbilitazioniAppController.php` decide i menu e i pulsanti;
- `protected/controllers/cli/AbilitazioniCliController.php` delega all APP quando non ha override;
- `protected/models/app/AppAnaUtentiStg.php` specializza il flusso staging utente;
- `protected/controllers/app/SiteAppController.php` contiene procedure schedulate e import/export.

## File Di Riferimento

- `protected/config/config_frm.php`
- `protected/config/config_client.php`
- `protected/controllers/frm/AbilitazioniFrmController.php`
- `protected/controllers/app/AbilitazioniAppController.php`
- `protected/controllers/cli/AbilitazioniCliController.php`
- `protected/controllers/app/SiteAppController.php`
- `protected/models/app/AppAnaUtentiStg.php`
- `protected/models/app/AppAnaCommesse.php`


file_path: /var/www/html/dev/sophia_framework2/_documentation/configuration_and_environments.md
title: Configuration And Environments
scanned_at: 2026-04-16 13:45:11
content:
# Configuration And Environments

## Struttura A Tre Livelli
La configurazione e divisa in tre blocchi principali:

- `protected/config/main.php`
- `protected/config/config_frm.php`
- `protected/config/config_app.php`
- `protected/config/config_client.php`

Il bootstrap finale costruisce `$configurazione` includendo questi file in sequenza.

## main.php
`protected/config/main.php` definisce i default generali del runtime:

- `DEBUG`
- `DEBUGTool`
- `SessionExpiredFromHourNomessage`
- `DEFAULT_PAGINATION_ROWS`
- `NUM_DECIMALS`
- `NUM_DECIMALSEPARATOR`
- `NUM_THOUSANDSEPARATOR`
- `NUM_CURRENCYSIGN`

Poi include:

- `config_frm.php`
- `config_app.php`
- `config_client.php`

## config_frm.php
`protected/config/config_frm.php` contiene la base framework:

- `sourceLanguage = 'xx'`
- `language = 'it'`
- preload di `log`, `booster`, `kint`
- import di model e componenti comuni
- modulo `gii`
- modulo `cruge`
- componenti `user`, `authManager`, `urlManager`, `db`, `file`

Punti importanti:

- login path: `cruge/ui/login`
- Gii usa `generatorPaths` verso `application.gii`
- CRUGE usa `tableprefix = 'frm_cruge_'`

## config_app.php
`protected/config/config_app.php` contiene i parametri applicativi, per esempio:

- `DEFAULT_PAGINATION_ROWS`
- `NUM_DECIMALS`
- `NUM_CURRENCYSIGN`
- eventuali costanti o parametri di business

E anche il routing post-login e altri parametri specifici dell applicazione.

## config_client.php
`protected/config/config_client.php` contiene gli override cliente.

I punti reali sono:

- import di `application.models.cli.*`
- controllerMap di `FrmAnaCommesse`, `FrmAnaDipartimenti`, `FrmAnaUtentiStg`, `FrmAnaCdc`, `FrmAnaSocietaUtente`

Qui il layer client puo cambiare la semantica delle pagine senza toccare la base FRM.

## Environment Files
Le differenze per ambiente stanno in:

- `protected/config/environment/dev.php`
- `protected/config/environment/demo.php`
- `protected/config/environment/test.php`
- `protected/config/environment/preprod.php`
- `protected/config/environment/prod.php`

Ogni file seleziona:

- il DB corretto;
- il file mailer corretto;
- eventuali differenze di Gii o debug.

## Database Per Ambiente
Le connessioni DB attuali sono:

- dev: `musa_app_dev`
- demo: `musa_demo`
- test: `musa_test`
- preprod: `musa_preprod`
- prod: `musa_country`

## Regole Operative

- non hardcodare valori ambientali nel codice business;
- se serve un cambio di DB o mailer, modificalo nel file environment corretto;
- se una feature va resa disponibile solo in dev, usa l environment e non un if sparso;
- se modifichi Gii, verifica sia `config_frm.php` sia `environment/dev.php`;
- non confondere parametri globali con parametri cliente.

## File Di Riferimento

- `protected/config/main.php`
- `protected/config/config_frm.php`
- `protected/config/config_app.php`
- `protected/config/config_client.php`
- `protected/config/environment/dev.php`
- `protected/config/environment/demo.php`
- `protected/config/environment/test.php`
- `protected/config/environment/preprod.php`
- `protected/config/environment/prod.php`
- `protected/config/db/dbconnect.dev.php`
- `protected/config/db/dbconnect.demo.php`
- `protected/config/db/dbconnect.test.php`
- `protected/config/db/dbconnect.preprod.php`
- `protected/config/db/dbconnect.prod.php`


file_path: /var/www/html/dev/sophia_framework2/_documentation/costants_management.md
title: Costants Management
scanned_at: 2026-04-16 13:45:11
content:
# Costants Management

## Scopo
Questa documentazione descrive come il framework SOPHIA gestisce le costanti a runtime e quale impatto ha la loro modifica sul codice applicativo.

Le costanti non sono solo "valori condivisi": in questo progetto sono parte della governance applicativa. Una variazione nel DB puo cambiare menu, label, stati, ruoli, tipi documento e logiche di business senza toccare il codice PHP.

## Fonti Dati
Le sorgenti ufficiali delle costanti sono due tabelle:

- `frm_sys_costanti`
- `frm_sys_costanti_applicazione`

I model corrispondenti sono:

- `protected/models/FrmSysCostanti.php`
- `protected/models/FrmSysCostantiApplicazione.php`

Entrambi espongono la stessa struttura logica:

- `nome`
- `value`
- `label`
- `descrizione`
- `gestioneadmin`

## Generazione Runtime
Il caricamento runtime avviene in `protected/extensions/costanti.php`.

Il flusso attuale e:

1. legge `frm_sys_costanti` e `frm_sys_costanti_applicazione` con una `UNION`;
2. per ogni record definisce `define($nome, $value)`;
3. definisce anche la versione label come `define($nome . '_label', $label)`;
4. crea costanti derivate per alcuni domini applicativi, per esempio:
   - `FRM_IDSOCIETA`
   - `FRM_IDSTABILIMENTO`
   - `TIPO_COMM_*`
   - `LIV_COMM_*`
   - `TIPO_ARTICOLO_*`
   - `STATO_ARTICOLO_*`
   - `RUOLO_*`
   - `COD_TIPO_DOC_*`
   - `COD_STAT_DOC_*`

Il file e richiamato in almeno questi punti reali:

- `protected/controllers/MusaFormazioniDettController.php`
- `protected/controllers/MusaFormazioniRichiesteController.php`
- `protected/views/frmGestioneCostanti/admin.php`

## Regole Di Governance
Usare le costanti significa accettare queste regole:

- la definizione e runtime, quindi il valore del DB diventa parte del bootstrap logico dell'app;
- una modifica al DB puo avere effetto su piu controller e viste nello stesso ciclo di richiesta;
- il nome costante deve essere stabile e cercabile nel codice;
- la label generata con `_label` va considerata API pubblica, non dettaglio estetico.

### Scelta della tabella
Indicazione pratica:

- usa `frm_sys_costanti` per costanti framework/shared;
- usa `frm_sys_costanti_applicazione` per costanti specifiche di app o cliente.

### Versione framework
Nel file e presente anche la costante `VERSION` e la logica di allineamento con `FRM_VERSION`.

Nota operativa importante: il codice prepara la query di aggiornamento/inserimento della versione, ma chi legge questo file deve verificare con attenzione il percorso reale di esecuzione prima di considerare la sincronizzazione automatica come garantita.

## Impatto
La modifica di una costante puo influire su:

- routing e feature flag;
- stati documento e workflow;
- menu visibili;
- permessi di griglia e pulsanti;
- traduzioni di label derivate dalle costanti;
- query SQL che usano costanti come `FRM_IDSOCIETA` e `FRM_IDSTABILIMENTO`.

Questo significa che una variazione apparentemente innocua puo rompere:

- join che assumono valori fissi;
- condizioni `if` su ruoli o stati;
- selettori di combo;
- controlli di visibilita lato view.

## Costanti E UI Admin
La gestione manuale delle costanti passa dalla vista:

- `protected/views/frmGestioneCostanti/admin.php`

Questa vista usa:

- `GetAbilitazioni(get_class($model), 'grid_view_buttons')`
- `widgets.FrmGridView`
- `booster.widgets.TbEditableColumn`

Quindi il valore `value` viene modificato inline, con controllo autorizzativo centralizzato.

## Checklist Per Nuove Costanti
Prima di aggiungere o rinominare una costante:

- verifica se il dato deve stare in `frm_sys_costanti` o in `frm_sys_costanti_applicazione`;
- cerca l uso attuale nel repo;
- controlla eventuali `define()` gia presenti;
- verifica se esiste una label associata e se la UI la consuma;
- verifica l impatto su permessi, menu, workflow e report;
- evita nomi ambigui o troppo generici.

## File Di Riferimento

- `protected/extensions/costanti.php`
- `protected/models/FrmSysCostanti.php`
- `protected/models/FrmSysCostantiApplicazione.php`
- `protected/views/frmGestioneCostanti/admin.php`
- `protected/controllers/frm/SiteController.php`
- `protected/controllers/MusaFormazioniDettController.php`
- `protected/controllers/MusaFormazioniRichiesteController.php`


file_path: /var/www/html/dev/sophia_framework2/_documentation/cruge_rbac_authentication.md
title: Cruge RBAC Authentication
scanned_at: 2026-04-16 13:45:11
content:
# Cruge RBAC Authentication

## Ruolo Di CRUGE Nel Progetto
CRUGE e il sottosistema di autenticazione e autorizzazione del framework.

In SOPHIA non e usato come semplice login page: CRUGE governa:

- autenticazione utente;
- stato account;
- RBAC;
- sessione;
- redirect post-login;
- protezione delle aree amministrative.

## Configurazione Base
I parametri principali sono in `protected/config/config_frm.php`.

Punti chiave:

- `cruge.superuserName = 'admin'`
- `cruge.tableprefix = 'frm_cruge_'`
- `availableAuthMethods = array('default')`
- `availableAuthModes = array('username','email')`
- `rbacSetupEnabled = true`
- `allowUserAlways = false`
- `useEncryptedPassword = true`
- `hash = 'md5'`
- `afterLoginUrl = array('/site/index')`
- `afterSessionExpiredUrl = array('/site/login_scaduto')`

Il componente utente e:

- `application.modules.cruge.components.CrugeWebUser`

Il manager di autorizzazione e:

- `application.modules.cruge.components.CrugeAuthManager`

La login URL di default e:

- `cruge/ui/login`

## Tabelle CRUGE
Le tabelle CRUGE hanno prefisso `frm_cruge_`.

Il model reale piu importante e:

- `protected/models/FrmCrugeUser.php`

Questo model punta alla tabella:

- `frm_cruge_user`

e mostra campi tipici di autenticazione:

- `username`
- `email`
- `password`
- `authkey`
- `state`
- `totalsessioncounter`
- `currentsessioncounter`

## Ruoli E Permessi
Le regole di business di SOPHIA non si fermano al RBAC standard: il progetto usa anche ruoli applicativi e helper custom.

I pezzi da conoscere sono:

- `hasAnyRole(...)` in `protected/extensions/global.php`
- `DescrizioneRuolo(...)` e helper collegati alla tabella `frm_sys_ruoli_applicazione`
- `GetAbilitazioni(...)` per menu e feature

Questo significa che:

- CRUGE gestisce l accesso;
- il progetto aggiunge un livello di policy applicativa sopra i ruoli base.

## Sessioni
Nel commento di `config_frm.php` e ricordato anche il riferimento alla tabella:

- `frm_cruge_system`

con il campo:

- `sessionmaxdurationmins`

Questa e una governance importante per i timeout e non va trattata come dettaglio marginale.

## Integrazione Con Menu E UI
CRUGE interagisce con i menu e con le griglie tramite:

- `Yii::app()->user->isSuperAdmin`
- `hasAnyRole(...)`
- `GetAbilitazioni(...)`

Quindi l autenticazione non vive isolata: influenza visibilita, menu e azioni disponibili.

## Regole Di Governance

- non usare query ad hoc per sostituire CRUGE;
- non duplicare la logica di login in controller sparsi;
- i nuovi ruoli applicativi devono avere una chiara corrispondenza con `frm_sys_ruoli_applicazione`;
- le feature amministrative vanno protette sia dal ruolo sia, se necessario, dal superadmin;
- il prefisso `frm_cruge_` e parte della convenzione e va mantenuto.

## File Di Riferimento

- `protected/config/config_frm.php`
- `protected/models/FrmCrugeUser.php`
- `protected/extensions/global.php`
- `protected/modules/cruge/components`
- `protected/modules/cruge/views/ui`


file_path: /var/www/html/dev/sophia_framework2/_documentation/db_structure.md
title: DB Structure
scanned_at: 2026-04-16 13:45:11
content:
# DB Structure

## Convenzione Generale
Nel codice SOPHIA le tabelle seguono due prefissi principali:

- `frm_` per il framework condiviso
- `musa_` per la parte applicativa / di dominio Musa

Il prefisso e parte della semantica del progetto: indica ownership, riuso e livello di stabilita della tabella.

## Convenzioni Di Naming

### `frm_`
Le tabelle `frm_` rappresentano dati condivisi, anagrafiche, lookup, costanti, sicurezza e strutture base del framework.

Esempi reali:

- `frm_ana_societa`
- `frm_ana_attributi`
- `frm_ana_cdc_dipartimenti`
- `frm_sys_costanti`
- `frm_sys_costanti_applicazione`
- `frm_cruge_user`

### `musa_`
Le tabelle `musa_` rappresentano il dominio applicativo Musa e le sue relazioni specifiche.

Esempi reali:

- `musa_task_dipartimenti`
- `musa_task_dipartimenti_progetti`
- `musa_formazioni_richieste`
- `musa_sys_qualifiche_copernico`

## Campi Standard
La maggior parte delle tabelle operative segue lo stesso zoccolo standard:

- `idsocieta`
- `idstabilimento`
- `stamp_insert`
- `stamp_update`
- `stamp_insert_user`
- `stamp_update_user`

Questi campi sono visibili in piu model del repo, per esempio:

- `protected/models/FrmAnaAttributi.php`
- `protected/models/FrmAnaCdcDipartimenti.php`
- `protected/models/MusaTaskDipartimenti.php`
- `protected/models/app/AppAnaUtentiStg.php`

### Significato operativo

- `idsocieta` e `idstabilimento` delimitano il tenant e il perimetro fisico/organizzativo;
- `stamp_insert` e `stamp_update` memorizzano la traccia temporale;
- `stamp_insert_user` e `stamp_update_user` collegano il record all utente CRUGE che ha fatto la modifica.

## Evidenza Corrente Nel Codice
La convenzione e confermata da piu model reali:

- `protected/models/FrmAnaAttributi.php`
- `protected/models/FrmAnaSocieta.php`
- `protected/models/FrmAnaCdcDipartimenti.php`
- `protected/models/MusaTaskDipartimenti.php`
- `protected/models/app/AppAnaUtentiStg.php`

In questi file trovi:

- `tableName()` con il nome reale della tabella;
- relazioni verso `FrmAnaSocieta`, `FrmAnaStabilimento` e `FrmCrugeUser`;
- `search()` con filtri su `idsocieta`, `idstabilimento` e campi audit.

## Eccezioni Importanti

### Sys
Le tabelle `frm_sys_*` sono spesso tabelle di configurazione o lookup e possono avere una struttura piu compatta.

Esempio:

- `frm_sys_costanti`
- `frm_sys_costanti_applicazione`

Qui i campi prevalenti sono:

- `nome`
- `value`
- `label`
- `descrizione`
- `gestioneadmin`

### Cruge
Le tabelle di autenticazione usano il prefisso:

- `frm_cruge_`

Esempio:

- `frm_cruge_user`

Il model `protected/models/FrmCrugeUser.php` mostra chiaramente una struttura diversa dal classico schema tenant/audit.

### Staging
Le tabelle di staging import/export sono eccezioni funzionali.

Esempio:

- `frm_ana_utenti_stg`

Il model `protected/models/app/AppAnaUtentiStg.php` espone campi di importazione come:

- `idfile`
- `codice`
- `statoelaborazione`
- `dataoracaricamento`
- `dataoraelaborazione`
- `errori`

Questa struttura e orientata al caricamento, non al classico CRUD anagrafico.

## Evidenza Database Attuale
La configurazione DB nel repo mostra piu ambienti:

- `protected/config/db/dbconnect.dev.php` -> `musa_app_dev`
- `protected/config/db/dbconnect.demo.php` -> `musa_demo`
- `protected/config/db/dbconnect.test.php` -> `musa_test`
- `protected/config/db/dbconnect.preprod.php` -> `musa_preprod`
- `protected/config/db/dbconnect.prod.php` -> `musa_country`

Questa e la prova pratica che la struttura va pensata per ambienti multipli e non per un solo database statico.

## Regole Da Seguire Quando Si Aggiunge Una Tabella

- scegli il prefisso corretto;
- aggiungi i campi tenant e audit salvo eccezione esplicita;
- crea la relazione verso `FrmAnaSocieta`, `FrmAnaStabilimento` e `FrmCrugeUser` quando ha senso;
- allinea le label tramite `tr()` o `Yii::t()`;
- usa `frmCActiveRecord` quando il modello deve seguire il comportamento del framework;
- documenta in modo esplicito se la tabella e sys, cruge o staging.

## File Di Riferimento

- `protected/models/FrmAnaAttributi.php`
- `protected/models/FrmAnaSocieta.php`
- `protected/models/FrmAnaCdcDipartimenti.php`
- `protected/models/MusaTaskDipartimenti.php`
- `protected/models/FrmCrugeUser.php`
- `protected/models/app/AppAnaUtentiStg.php`
- `protected/models/FrmSysCostanti.php`
- `protected/models/FrmSysCostantiApplicazione.php`
- `protected/config/db/dbconnect.dev.php`
- `protected/config/db/dbconnect.demo.php`
- `protected/config/db/dbconnect.test.php`
- `protected/config/db/dbconnect.preprod.php`
- `protected/config/db/dbconnect.prod.php`


file_path: /var/www/html/dev/sophia_framework2/_documentation/export_management.md
title: Gestione export
scanned_at: 2026-04-16 13:45:11
content:
# Gestione export

Questo documento spiega il flusso export del Musa app basato su `toExcel()`, `EExcelBehavior` ed `EExcelView`.

## Panoramica

L'export standard segue un contratto semplice:

- il controller prepara il data provider;
- costruisce una lista di colonne esportabili;
- invoca `toExcel()` sul controller;
- `EExcelBehavior` istanzia `EExcelView`;
- il file viene streammato al browser o salvato su disco.

## Behavior base

Il `Controller` base espone:

```php
public function behaviors() {
    return array(
        'eexcelview' => array(
            'class' => 'ext.eexcelview.EExcelBehavior',
        ),
    );
}
```

Questo rende disponibile `toExcel()` in tutti i controller che ereditano dal base controller.

## Flusso tipico di un export

Nei controller del Musa app il pattern e` questo:

```php
public function actionExport()
{
    set_time_limit(3600);
    ini_set('memory_limit', '512M');

    $model = new $this->className('search');
    $model->unsetAttributes();
    $model->initDefaultFilters();
    $model = $this->usefiltersession($model);

    $columns = array(
        array('name' => 'codcorso', 'header' => $model->getAttributeLabel('codcorso'), 'type' => 'raw'),
        array('name' => 'descrizione', 'header' => $model->getAttributeLabel('descrizione'), 'type' => 'raw'),
    );

    $title = date('YmdHis').$model->getAttributeLabel('suffissoexport');
    $dataProvider = $model->search();
    $dataProvider->setPagination(false);

    $this->toExcel($dataProvider, $columns, $title, array(), 'Excel5');
}
```

## `EExcelBehavior::toExcel()`

La firma reale e`:

```php
toExcel($model = null, $columns = array(), $title = null, $documentDetails = array(), $exportType = 'Excel2007', $exit = true)
```

### Input supportati

- `null`
- stringa con nome modello
- array di record
- `CDataProvider` o sottoclasse

### Comportamento

- Se `model` e` `null`, usa il controller corrente come nome del modello.
- Se e` una stringa, crea un `CActiveDataProvider`.
- Se e` un array, prova a costruire un `CActiveDataProvider` dal primo elemento.
- Se e` un `CDataProvider`, lo usa direttamente.
- Normalizza le colonne e merge-a eventuali metadati addizionali.
- Invoca `EExcelView`.
- Se `exit=true`, chiude la request con `Yii::app()->end()`.

## `EExcelView`

`EExcelView` e` una `CGridView` specializzata per l'export.

### Opzioni principali

- `exportType`
- `title`
- `filename`
- `stream`
- `autoWidth`
- `disablePaging`
- `intestazione`

### Formati supportati

- `Excel5`
- `Excel2007`
- `PDF`
- `HTML`
- `CSV`

### Caratteristiche reali

- Alla `init()` crea l'oggetto `PHPExcel`.
- Imposta le proprieta` del documento.
- `renderHeader()` scrive intestazione e header colonne.
- Se `intestazione` e` valorizzata, la mette in prima riga e fonde le celle.
- `renderBody()` disabilita la paginazione se `disablePaging=true`.
- `renderRow()` gestisce valori espliciti da `value`, nomi campo semplici, path relazionali separati da `.`, formattazione date e scrittura di stringhe come testo esplicito.
- `renderFooter()` scrive eventuali footer colonna.
- `run()` auto-regola le colonne e streamma il file al browser.

## Convenzioni di export nel Musa app

Le colonne da esportare sono costruite manualmente nel controller e non copiano la griglia 1:1.

### Best practice osservate

- Esportare solo i campi realmente utili all'utente.
- Usare header leggibili con `getAttributeLabel()`.
- Usare campi calcolati o relazionali gia` pronti per l'export.
- Disattivare la paginazione del data provider prima della chiamata a `toExcel()`.
- Dare al file un nome deterministico, spesso con timestamp.

### Esempi reali

- `MusaCorsiController::actionExport()`
- `MusaCorsiSessioniController::actionExport()`
- `MusaCorsiIscrizioniController::actionExport()`

Tutti seguono lo stesso schema: model in scenario `search`, filtri applicati, colonne costruite a mano, `setPagination(false)` e `toExcel(...)`.

## Cautela operativa

- Per dataset grandi, il consumo di memoria cresce rapidamente: il codice storico usa `512M` e `3600s` come margini.
- L'export non dovrebbe portare con se` colonne d'azione come bottoni o link UI.
- Se vuoi esportare il risultato di una ricerca gia` aperta, devi riapplicare gli stessi filtri nel controller oppure usare `usefiltersession()`.
- Se l'export deve essere richiamato da uno script o da un processo automatico, imposta `exit=false` solo se sai cosa succede dopo `toExcel()`.

## Quando usare `intestazione`

- Se vuoi un titolo unificato sopra gli header delle colonne.
- Se il file deve essere presentato come report formale.
- Se ti serve una riga introduttiva comune per tutte le colonne.

## Regole pratiche

- Usa `Excel5` se devi restare allineato ai controller storici del Musa app.
- Mantieni la lista colonne separata da quella della griglia, anche se i campi sono gli stessi.
- Preferisci valori gia` formattati dal model quando il formato finale e` importante.
- Se esporti date, controlla sempre la formattazione effettiva del valore.


file_path: /var/www/html/dev/sophia_framework2/_documentation/forms_fields_management.md
title: Gestione campi e form
scanned_at: 2026-04-16 13:45:11
content:
# Gestione campi e form

Questo documento raccoglie le convenzioni reali per disegnare campi, form e pulsanti nel Musa app usando `RenderSettings`, `drawInitFields()` e `drawInitButtons()`.

## Contratto base

Il framework non disegna i campi direttamente nel controller. La logica corretta e` questa:

- in `initfields()` si valorizza `RenderSettings`;
- in `getrenderform()` / `getrenderfilters()` / `getrenderadmin()` si decide l'ordine;
- nelle viste si richiama `drawInitFields()` o `drawInitButtons()`.

Ogni campo in `RenderSettings` puo` avere:

- `visible`
- `renderadmin`
- `renderfilter`
- `renderform`
- `renderadminbtn`
- `renderformbtn`

## Struttura tipica di un campo

Nei controller il pattern piu` comune e` questo:

```php
$model->RenderSettings->codcorso->renderform = array(
    'label' => CHtml::activeLabel($model, 'codcorso', array('class' => 'col-md-1 control-label')),
    'html' => CHtml::activeTextField($model, 'codcorso', array('maxlength' => 50, 'class' => 'form-control')),
    'col_width' => 2,
);
```

Questo schema viene usato sia per i campi di ricerca sia per i campi di edit.

## Convenzioni di rendering

- `renderfilter` va usato per i campi della form di ricerca.
- `renderform` va usato per create e update.
- `renderadmin` va usato per le colonne griglia.
- `renderformbtn` e `renderadminbtn` gestiscono la toolbar.

### `label`

- Di solito e` costruita con `CHtml::activeLabel()` o `CHtml::activeLabelEx()`.
- La classe Bootstrap tipica e` `col-md-1 control-label`.

### `html`

- Deve contenere l'HTML del widget o del campo.
- I widget piu` usati sono `booster.widgets.TbSelect2`, `booster.widgets.TbDatePicker`, `CHtml::activeTextField`, `CHtml::activeTextArea` e `CHtml::activeHiddenField`.

### `col_width`

- Pu`o essere un intero, per esempio `6`.
- Pu`o essere un array, per esempio `array('md' => 6, 'sm' => 12)`.
- Il metodo `drawInitFields()` usa questi valori per costruire le classi Bootstrap.

## Esempi reali

### Select2

Nel controller `MusaCorsiSessioniController` il filtro del corso usa `TbSelect2` come dropdown:

```php
'html' => $this->widget('booster.widgets.TbSelect2', array(
    'asDropDownList' => true,
    'name' => get_class($model).'[idcorso]',
    'value' => $model->idcorso,
    'data' => $comboCorsi,
    'options' => array('placeholder' => tr('-'), 'allowClear' => true),
    'htmlOptions' => array('style' => 'width:100%;'),
), true),
```

### DatePicker

Per i filtri data il pattern e` lo stesso, con opzioni localizzate:

```php
'html' => $this->widget('booster.widgets.TbDatePicker', array(
    'name' => get_class($model).'[data_sessione_da]',
    'value' => $model->data_sessione_da,
    'options' => array(
        'language' => 'it',
        'format' => 'yyyy-mm-dd',
        'autoclose' => true,
        'todayHighlight' => true,
        'clearBtn' => true,
    ),
    'htmlOptions' => array('class' => 'form-control'),
), true),
```

### Help block

Alcuni controller aggiungono un messaggio di supporto sotto il campo con `appendHelpBlock()`:

```php
private function appendHelpBlock($html, $helpText)
{
    return $html.CHtml::tag('small', array('class' => 'help-block'), $helpText);
}
```

Il pattern e` utile quando un campo ha una regola di compilazione non ovvia, per esempio una scelta tra fornitore descrittivo e fornitore da anagrafica.

### Campo raw in griglia

Nel render admin si usa spesso:

```php
'type' => 'raw',
'value' => '$data->fornitoreDesc',
```

oppure una callback:

```php
'value' => function($data) {
    return $data->societautente->nome;
},
```

## `drawInitFields()`

Questo helper gestisce il layout dei campi.

### Comportamento

- Apre una `row`.
- Stampa ogni campo in un contenitore `col-md-*`.
- Se `visible` e` vuoto, applica la classe `hidden`.
- Se `new_row=true`, forza la chiusura e riapertura della riga.
- Se la somma delle colonne supera 12, rompe automaticamente la riga.

### Modalita` vertical e horizontal

- In verticale la label va sopra il campo.
- In orizzontale la label viene disegnata separatamente dal controllo.

### Regola pratica

- Se il markup passato in `html` contiene gia` `class="form-group"`, il helper evita di duplicare il wrapper.

## Pulsanti

### `drawInitButtons()`

- Stampa i pulsanti della form.
- E utile per `btn_save` e `btn_goback`.

### `drawInitAdminButtons()`

- Divide i pulsanti in sinistra e destra.
- I pulsanti con `position = sx` vengono disegnati a sinistra.
- Gli altri finiscono a destra.

### Esempio reale

Nel controller `MusaCorsiController` il bottone export e` configurato cosi`:

```php
$model->RenderSettings->btn_export->renderadminbtn = array(
    'html' => CHtml::link(
        '<i class="fa fa-file-excel-o"></i> '.tr('Export Excel'),
        '#',
        array(
            'class' => 'btn btn-success',
            'data-id-grid' => 'musa-corsi-grid',
            'data-id-search-form' => 'MusaCorsiFormSearch',
            'data-url-export' => Yii::app()->controller->createUrl('export'),
            'data-url-admin' => Yii::app()->controller->createUrl('admin'),
            'onclick' => 'exportexcel($(this)); return false;',
        )
    ),
);
```

## Ordine dei campi

Le funzioni `getrenderfilters()`, `getrenderadminbtns()`, `getrenderadmin()`, `getrenderform()` e `getrenderformbtn()` servono a fissare l'ordine di visualizzazione.

- Se il metodo restituisce un array vuoto, il framework usa tutti i campi presenti in `RenderSettings`.
- Se restituisce un elenco, vengono presi solo quei campi e nell'ordine dichiarato.

## Form di ricerca

Le viste di ricerca tipiche seguono questo schema:

- form `TbActiveForm`
- `drawInitFields($filters)`
- pulsante `Applica Filtri`
- messaggio `filter_message.php`

Il messaggio di aiuto avvisa che la ricerca supporta operatori come `<`, `<=`, `>`, `>=`, `<>` e `=` all'inizio del valore.

## Consigli pratici

- Non costruire i campi direttamente nelle view se esiste gia` una convenzione in `initfields()`.
- Mantieni coerenti label, widget e dimensioni colonne.
- Usa `visible=false` per nascondere un campo senza perdere il dato nel model.
- Per i campi date o select complessi, preferisci `TbDatePicker` e `TbSelect2` al markup HTML puro.
- Se un campo serve solo alla logica e non all'UI, usa `CHtml::activeHiddenField()`.


file_path: /var/www/html/dev/sophia_framework2/_documentation/gii_and_code_generation.md
title: Gii And Code Generation
scanned_at: 2026-04-16 13:45:11
content:
# Gii And Code Generation

## Scopo
Gii e il punto di partenza per generare CRUD, model e controller base, ma in questo progetto la generazione non finisce con il template standard di Yii.

Il repo usa template personalizzati e regole di post-processing per allineare il codice generato al framework SOPHIA.

## Abilitazione
La configurazione Gii e presente in:

- `protected/config/config_frm.php`
- `protected/config/environment/dev.php`

I dettagli osservabili sono:

- class: `system.gii.GiiModule`
- password: `aihpos`
- in FRM gli IP consentiti sono `127.0.0.1` e `::1`
- in dev gli IP sono aperti con `'*'`
- `generatorPaths` punta a `application.gii`

## Template Custom
I template custom reali sono in:

- `protected/gii/model/templates/sophia/model.php`
- `protected/gii/crud/templates/bootstrap/controller.php`
- `protected/gii/crud/templates/bootstrap/admin.php`
- `protected/gii/crud/templates/bootstrap/create.php`
- `protected/gii/crud/templates/bootstrap/update.php`
- `protected/gii/crud/templates/bootstrap/view.php`
- `protected/gii/crud/templates/bootstrap/_form.php`
- `protected/gii/crud/templates/bootstrap/_search.php`

Questi template non sono ornamentali: incorporano le convenzioni del progetto, per esempio:

- `tr()`
- `GetAbilitazioni()`
- `TbButtonColumn`
- `FrmGridView`
- stile bootstrap custom

## Relazione Con Le Traduzioni
Il file di estrazione traduzioni:

- `protected/messages/config_translation.php`

esclude `/gii`.

Questo e corretto per governance: i template del generatore possono contenere codice boilerplate o testo tecnico che non dovrebbe inquinare il catalogo traduzioni business.

## Regola Pratica
Quando si genera nuovo codice:

1. usare il generator path custom;
2. verificare che il CRUD prodotto rispetti i nomi dei layer FRM / APP / CLI;
3. inserire i controlli permessi nelle view e nel controller di abilitazione;
4. sostituire le label hardcoded con `tr()` o `Yii::t()`;
5. verificare i campi standard tenant/audit;
6. controllare che la griglia usi il pattern `grid_view_buttons`.

## Esempio Di Output Atteso
Un CRUD utile nel progetto non e quello stock di Yii, ma quello che:

- usa i widget Bootstrap del progetto;
- supporta inline edit o button columns dove serve;
- si integra con CRUGE e con i ruoli applicativi;
- legge costanti da DB quando necessario;
- rispetta i namespace e i controllerMap dei layer.

## Dove Vedere La Personalizzazione
Un esempio concreto di output gia allineato al progetto e:

- `protected/views/frmGestioneCostanti/admin.php`

qui trovi:

- `widgets.FrmGridView`
- `booster.widgets.TbEditableColumn`
- `GetAbilitazioni(...)`

Questo e il comportamento che i generatori custom devono saper produrre o facilitare.

## File Di Riferimento

- `protected/config/config_frm.php`
- `protected/config/environment/dev.php`
- `protected/gii/model/templates/sophia/model.php`
- `protected/gii/crud/templates/bootstrap/controller.php`
- `protected/gii/crud/templates/bootstrap/admin.php`
- `protected/gii/crud/templates/bootstrap/_form.php`
- `protected/messages/config_translation.php`
- `protected/views/frmGestioneCostanti/admin.php`


file_path: /var/www/html/dev/sophia_framework2/_documentation/grids_management.md
title: Gestione griglie
scanned_at: 2026-04-16 13:45:11
content:
# Gestione griglie

Questo documento descrive il comportamento reale delle griglie nel Musa app, con particolare attenzione a `FrmGridView`, ai filtri avanzati, ai bottoni di toolbar e alla paginazione.

## Widget principale

Il widget standard del progetto e` `widgets.FrmGridView`.

### Caratteristiche

- Estende `TbExtendedGridView`.
- Forza `ajaxType = 'POST'`.
- Rende la tabella dentro un contenitore scrollabile `containerTable`.
- Applica una classe di default alla tabella.
- Imposta un `afterAjaxUpdate` che riattacca gli editable, aggiorna le dimensioni griglia, fissa l'header della tabella e reinizializza popover, tooltip, datepicker e select2.

### Riga con PK

- Se il model ha una primary key disponibile, la riga riceve un id del tipo `data-pk-<valore>`.
- Questo e` utile per gli aggiornamenti JS post-Ajax.

## Flusso tipico di una pagina admin

Le viste amministrative seguono quasi sempre questo schema:

- titolo pagina
- form di ricerca nascosta
- toolbar bottoni
- griglia `FrmGridView`

Esempio reale:

```php
<div class="search-form" style="display:none">
    <?php $this->renderPartial('/'.$this->rootviews.'/_search', array(
        'model' => $model,
        'filters' => $filters,
    )); ?>
</div>

<?php $this->drawInitAdminButtons($buttons); ?>

<?php $this->widget('widgets.FrmGridView', array(
    'id' => 'musa-corsi-grid',
    'dataProvider' => $dataProvider,
    'ajaxType' => 'POST',
    'responsiveTable' => true,
    'htmlOptions' => array('class' => 'boosterTable'),
    'columns' => $columns,
)); ?>
```

## Filtri avanzati

Il pattern piu` usato nel repo e` il filtro avanzato con form nascosta.

### Comportamento

- Il bottone `Visualizza Filtri` mostra o nasconde la sezione `search-form`.
- Il bottone `Applica Filtri` serializza il form e aggiorna la griglia via Ajax.
- In alcune pagine lo stesso comportamento e` gestito con script JS dedicato.

### Esempio su `site/scripts.php`

- il form filtri e` in `_searchScripts.php`
- la griglia riceve `CArrayDataProvider`
- il submit del form chiama `yiiGridView('update', { data: $(this).serialize() })`

### Nota operativa

- Nel codice corrente le viste principali usano il form di ricerca nascosto piu` che il filtro nativo in riga.
- Il flag `inline_filters` compare in alcune viste come selettore di comportamento della schermata; nelle pagine verificate non ho trovato un uso uniforme del `filter` nativo del widget.

## Filtri inline

Quando serve editing inline o visualizzazione inline, il progetto usa spesso `TbEditableColumn`.

### Pattern

- colonna con `class => 'booster.widgets.TbEditableColumn'`
- `editable['url']` puntato a `UpdateInline`
- `editable['mode'] = 'inline'`
- `editable['type']` spesso `select2` o `text`
- `success` chiama una funzione JS per riallineare la UI

Esempio reale:

```php
'class' => 'booster.widgets.TbEditableColumn',
'editable' => array(
    'url' => Yii::app()->controller->createUrl('UpdateInline'),
    'mode' => 'inline',
    'type' => 'select2',
    'success' => 'js: function(data){ fwhelper.completeAjaxAction(data,"FrmAnaSocietaUtenteCardsFormSearch"); }',
    'source' => array(1 => tr('Si'), 0 => tr('No')),
),
```

### Cosa ricordare

- L'editing inline è una funzione diversa dal filtro inline.
- Se usi `TbEditableColumn`, devi predisporre un'azione `UpdateInline` nel controller.

## Colonne e bottoni

### Colonne

Le colonne vengono costruite nei controller con `getrenderadmin()` e poi passate alla griglia.

Pattern ricorrenti:

- colonna con `name`
- colonna con `header`
- colonna `raw`
- colonna con `value` espressione o callback
- colonna `grid_view_buttons`

### Bottoni

- I bottoni di toolbar non vanno mescolati alle colonne.
- Le azioni per riga vanno nella `TbButtonColumn`.
- `grid_view_buttons` e` una colonna speciale usata in vari controller per i pulsanti contestuali.

### Esempio di bottone per riga

Nel view `site/scripts.php` la griglia mostra un bottone `Esegui` con `TbButtonColumn` e URL costruita dinamicamente.

## Paginazione

La paginazione e` controllata quasi sempre dal model tramite `nRighe`.

### Flusso

- `RenderSettings` espone `nRighe` come filtro.
- `actionAdmin()` fa `setPagination(array("pageSize" => $model->nRighe))`.
- La toolbar consente di cambiare il numero di righe con il select2 `Visualizza:`.

### Impatto

- La scelta di `nRighe` va rispettata anche nei controller export quando si vuole mantenere il filtro, ma in export la paginazione viene in genere disattivata.

## `TbGroupGridView`

Il progetto include anche `TbGroupGridView` per le griglie raggruppate.

### Comportamento

- E` una estensione di `TbGridView`.
- Permette di definire `mergeColumns` e `extraRowColumns`.
- Se si usano colonne di gruppo, disabilita i filtri sulle colonne coinvolte.
- Registra il supporto Ajax e la ricostruzione della griglia.

### Quando usarla

- Quando vuoi raggruppare righe per attributo.
- Quando ti serve una riga extra di gruppo o una fusione di celle.

## Regole pratiche

- Usa `FrmGridView` come default.
- Usa `TbEditableColumn` solo se l'azione inline e` davvero necessaria.
- Non dimenticare `ajaxType => 'POST'` quando i filtri sono numerosi.
- Se una griglia ha molti contenuti o toolbar complessa, mantieni `responsiveTable => true`.
- Se non servono filtri di riga, imposta `filter => false` o evita di passarli.


file_path: /var/www/html/dev/sophia_framework2/_documentation/menu_and_permissions_management.md
title: Menu And Permissions Management
scanned_at: 2026-04-16 13:45:11
content:
# Menu And Permissions Management

## Idea Centrale
Nel framework SOPHIA menu e permessi non sono gestiti in modo sparso nelle view: la logica centrale vive in controller dedicati e viene consumata dalle viste tramite helper comuni.

Il flusso standard e:

1. la view chiede una abilitazione;
2. l helper centralizzato la valuta;
3. il controller di abilitazioni decide quali action, menu o pulsanti griglia sono visibili;
4. la view renderizza solo cio che e abilitato.

## Catena Dei Controller
La catena reale e questa:

- `protected/controllers/frm/AbilitazioniFrmController.php`
- `protected/controllers/app/AbilitazioniAppController.php`
- `protected/controllers/cli/AbilitazioniCliController.php`

`AbilitazioniCliController` estende `AbilitazioniAppController`, che a sua volta estende `AbilitazioniFrmController`.

Questo significa che:

- FRM definisce la base comune;
- APP aggiunge le regole applicative;
- CLI/client puo sovrascrivere o specializzare il comportamento.

## Helper Di Accesso
L accesso standard passa da:

- `protected/extensions/global.php`

La funzione `GetAbilitazioni($controller, $action)` importa il controller CLI e richiama:

- `AbilitazioniCliController::getAbilitazioneRuolo($controller, $action)`

Questa scelta e importante: la view non parla direttamente con la logica di business, ma passa da un punto unico di decisione.

## Menu Based On Role
Il metodo `getAbilitazioneRuolo()` tratta esplicitamente il controller `menu`.

Nel file FRM trovi, per esempio:

- `anagrafiche`
- `anagrafiche_users`
- `anagrafiche_utenti`
- `articoli`
- `admin`
- `help`
- `login`

Nel file APP trovi una lista diversa, piu ampia e centrata sulle aree operative:

- `management`
- `management_censimento`
- `management_valutazione_skill`
- `management_multiskills`
- `qualifications`
- `qualifications_ansf`
- `qualifications_ehs`
- `qualifications_controlli_nd`
- `qualifications_self_inspection`

## Regole Di Abilitazione
La valutazione usa soprattutto questi elementi:

- `hasAnyRole(...)`
- `Yii::app()->user->isSuperAdmin`
- costanti `RUOLO_*`
- costanti di feature flag tipo `ABIL_MENU_ADMIN_COSTANTI`

L uso dei ruoli e centrale. Non si tratta di un semplice booleano, ma di una combinazione di:

- ruolo utente;
- superadmin;
- feature flag da configurazione o DB;
- contesto controller/action.

## Grid Buttons
Un secondo uso importante del sistema di abilitazioni riguarda i pulsanti delle griglie.

Pattern reale:

```php
$abilitazione_grid_view_buttons = GetAbilitazioni(get_class($model), 'grid_view_buttons');
if ($abilitazione_grid_view_buttons['abilitazione']) {
  $grid_view_buttons = $abilitazione_grid_view_buttons['grid_view_buttons'];
}
```

Esempi reali:

- `protected/views/frmAnaDipartimenti/admin.php`
- `protected/views/frmAnaDipartimenti/adminEPUmgr.php`
- `protected/views/frmGestioneCostanti/admin.php`
- `protected/views/musaSkill/admin.php`
- `protected/views/ggsSchedeAllegati/admin.php`

## Cosa Restituisce Il Controller
`getAbilitazioneRuolo()` restituisce in genere:

- `abilitazione`
- `messaggio`
- `grid_view_buttons`

La view usa questi valori per costruire il template della `TbButtonColumn` o per bloccare del tutto la funzionalita.

## Governance Pratica

- aggiungi o modifica i permessi nel controller di abilitazione, non nella view;
- se introduci una nuova action di menu, devi gestirla nel case `menu`;
- se introduci un nuovo pulsante griglia, devi gestire `grid_view_buttons`;
- se il permesso dipende dal ruolo, usa `hasAnyRole()` e non un controllo sparso;
- se la feature deve essere visibile solo al superadmin, esplicitalo nel controller.

## Ruoli E Menu
I ruoli applicativi sono governati da costanti come `RUOLO_AMMINISTRATORE_SISTEMA` e da dati presenti nel dominio ruoli.

Questo si riflette in:

- menu di alto livello;
- feature amministrative;
- azioni speciali sulle griglie;
- pulsanti custom come `attiva`, `abbinaCdc`, `elimina`, `richiediFormazione`.

## File Di Riferimento

- `protected/extensions/global.php`
- `protected/controllers/frm/AbilitazioniFrmController.php`
- `protected/controllers/app/AbilitazioniAppController.php`
- `protected/controllers/cli/AbilitazioniCliController.php`
- `protected/views/frmAnaDipartimenti/admin.php`
- `protected/views/frmAnaDipartimenti/adminEPUmgr.php`
- `protected/views/frmGestioneCostanti/admin.php`
- `protected/views/musaSkill/admin.php`


file_path: /var/www/html/dev/sophia_framework2/_documentation/scripts_management.md
title: Gestione script DB
scanned_at: 2026-04-16 13:45:11
content:
# Gestione script DB

Questo documento descrive il lifecycle reale degli script di aggiornamento database nel Musa app, con attenzione ai file di registry, al menu di esecuzione, ai modelli di tracking e ai rischi operativi.

## Panoramica

Gli script sono gestiti come una catena di elementi separati:

- registri file-backed con la definizione della query SQL;
- vista di consultazione ed esecuzione da browser;
- tabelle di tracking per memorizzare esito e note;
- costanti di stato usate nel rendering e nel logging.

La logica e` centralizzata in `protected/controllers/frm/SiteController.php`.

## File di registry

Nel repository sono presenti i registry seguenti:

- `protected/data/scripts_aggiornamento_framework.php`
- `protected/data/scripts_aggiornamento_application.php`

Il modello `_scripts_aggiornamento_client` esiste ed e` supportato dal controller, ma in questa tree non compare il file dati `application.data.scripts_aggiornamento_client.php`. Se il modo `Cli` viene usato in ambiente, quel file va verificato nel filesystem del deployment.

### Struttura dei registry

Ogni voce dell'array contiene questi campi:

- `applicazione`
- `data`
- `TICKET`
- `descrizione`
- `sql`

Esempio reale:

```php
'20151209_AM_1' => array(
    'applicazione' => $application,
    'data' => '09/12/2015',
    'TICKET' => '0000681',
    'descrizione' => 'campo codicecommessa a varchar(20)',
    'sql' => 'ALTER TABLE frm_ana_commesse MODIFY codicecommessa VARCHAR(20);',
)
```

### Regola editoriale

- Il file `scripts_aggiornamento_framework.php` riporta in testa l'avviso di essere mantenuto sul framework e poi copiato nell'applicazione.
- Le entry devono essere aggiunte come record indipendenti e ordinati nel tempo.

## Modelli `_scripts_aggiornamento_*`

I tre modelli sono basati su `ArrayModel`:

- `_scripts_aggiornamento_framework`
- `_scripts_aggiornamento_application`
- `_scripts_aggiornamento_client`

### Comportamento dell'ArrayModel

- I dati vengono letti dal file PHP indicato da `fileName()`.
- `getData()` usa `require()` e cache interna.
- `setData()` riscrive il file su disco.
- `findAll()` e `findById()` lavorano sulla struttura in memoria.
- `save()` persiste il contenuto nel file, non nel database.
- La `search()` presente nei tre modelli e` legacy e non e` il percorso usato dal controller `ScriptsDB`, che legge i dati con `findAll()`.

Nel caso degli script, il controller non usa il percorso di salvataggio dell'`ArrayModel` per modificare il registry dalla UI; usa invece il file come sorgente di lettura per la griglia.

### Campi esposti dai modelli

- `id`
- `applicazione`
- `data`
- `TICKET`
- `descrizione`
- `sql`

### Note di presentazione

- `getIconaStatoEsecuzione()` legge lo stato dalla tabella `frm_sys_scriptsdb_*` corrispondente.
- `getNoteEsecuzione()` legge le note dalla stessa tabella.
- `getStatoTitle()` e `getStatoImage()` traducono il valore di esito in label e icona.

## Tracking DB

Il tracking e` affidato alle tabelle:

- `frm_sys_scriptsdb_frm`
- `frm_sys_scriptsdb_app`
- `frm_sys_scriptsdb_cli`

Tutte e tre hanno la stessa struttura logica:

- `idscript` come chiave primaria
- `esito`
- `note`
- `stamp_insert_user`
- `stamp_update_user`
- `stamp_insert`
- `stamp_update`

Le tre AR che le rappresentano sono:

- `FrmSysScriptsdbFrm`
- `FrmSysScriptsdbApp`
- `FrmSysScriptsdbCli`

Questi model estendono `frmCActiveRecord`, quindi aggiornano in automatico i timestamp e gli user stamp.

## Stati ed esiti

Le costanti usate nel codice sono:

- `ESITO_SCRIPT_NO`
- `ESITO_SCRIPT_OK`
- `ESITO_SCRIPT_KO`
- `ESITO_SCRIPT_NF`

Nel setup storico le costanti vengono create in `frm_sys_costanti` con valore numerico e label leggibile:

- `0` -> `Non Eseguito`
- `1` -> `OK`
- `2` -> `KO`
- `3` -> `Not Found`

Le icone visuali usate dai modelli sono:

- `vDefault.png` per `NO`
- `vApproved.png` per `OK`
- `vRejected.png` per `KO` e `NF`

## UI di consultazione

La vista `protected/views/site/scripts.php` mostra:

- selezione del modo `Frm`, `App` o `Cli`
- ricerca avanzata tramite form nascosto
- bottone `Visualizza Filtri`
- bottone `Reset Filtri`
- selettore del numero di righe
- bottone `Esegui massivamente`
- colonna azione con `Esegui` per il singolo script

La tabella e` costruita con `widgets.FrmGridView` e una `CArrayDataProvider`.

## `actionScriptsDB($modo)`

Questa action costruisce la griglia iniziale.

### Flusso

- Legge `modo` dalla request o dal parametro di metodo.
- Seleziona il modello corretto: `Frm` -> `_scripts_aggiornamento_framework`, `App` -> `_scripts_aggiornamento_application`, `Cli` -> `_scripts_aggiornamento_client`.
- Legge i filtri dal form specifico del modello.
- Mappa i campi di ricerca consentiti in una query array: `Descrizione %`, `Query %`, `TICKET %` e `id %`.
- Applica `nRighe` se presente.
- Costruisce il `CArrayDataProvider` e la `CSort`.

### Ordinamento

L'ordinamento espone:

- `id`
- `Date`
- `TICKET`
- `Applicazione`
- `IconaStatoEsecuzione`
- `Descrizione`
- `Query`

## `actionexecuteScriptDB()`

E` l'esecuzione singola dello script.

### Flusso

- Legge `idscript`, `modo` e `page` dalla request.
- Recupera il record del registry corrispondente.
- Esegue la query con `Yii::app()->db->createCommand($query)->execute()`.
- Imposta l'esito: `ESITO_SCRIPT_OK` se la query è andata a buon fine, `ESITO_SCRIPT_KO` se l'esecuzione genera eccezione, `ESITO_SCRIPT_NF` se lo script non viene trovato.
- Salva o aggiorna il record in `FrmSysScriptsdbFrm`, `FrmSysScriptsdbApp` o `FrmSysScriptsdbCli`.
- Ritorna alla griglia `ScriptsDB` mantenendo il modo e la pagina.

### Cautela operativa

- L'esecuzione non e` transazionale a livello applicativo: il comando SQL gira direttamente sul DB.
- Il salvataggio del tracking avviene dopo l'esecuzione, quindi query e tracking possono divergere se la write del model fallisce.

## `actionexecuteScriptDBMassively()`

E` l'esecuzione massiva di tutti gli script del registry.

### Flusso

- Legge `modo`.
- Carica tutti gli script del file registry con `findAll()`.
- Per ogni script controlla se esiste gia` una riga nella tabella tracking con `findByPk($script->id)`.
- Se esiste una riga, lo script viene saltato.
- Se non esiste, la query viene eseguita e il tracking viene creato.

### Implicazione importante

- Il massivo non ricalcola gli script gia` presenti in tracking, indipendentemente dall'esito.
- Non e` un rerun “forzato”: e` un esecutore di soli script non ancora tracciati.

### Cautela tecnica

- La variabile `$note` non viene azzerata a ogni iterazione del loop; in caso di errore seguito da successo, il testo dell'errore precedente puo` rimanere in memoria se non viene sovrascritto.
- In caso di `ESITO_SCRIPT_KO`, il codice interrompe il flusso con output di debug (`dd($note)`), quindi la procedura non e` pensata per esecuzioni automatiche silenziose.

## `actionInstallUpdateScript()`

Questa action e` uno script di bootstrap storico esposto via browser.

### Cosa fa

- Crea `frm_sys_scriptsdb_app`.
- Crea `frm_sys_scriptsdb_frm`.
- Inserisce le costanti `ESITO_SCRIPT_NO`, `ESITO_SCRIPT_OK`, `ESITO_SCRIPT_KO`, `ESITO_SCRIPT_NF` in `frm_sys_costanti`.

### Cautela operativa

- La procedura non provisiona la tabella `frm_sys_scriptsdb_cli`.
- E` una utility amministrativa da usare solo in ambiente controllato, non una action da esporre all'utente finale.

## Best practice

- Tenere separati i livelli `Frm`, `App`, `Cli`.
- Verificare sempre l'effetto collaterale delle query prima del deploy.
- Evitare il massivo su database di produzione senza copia di verifica.
- Aggiornare il file registry prima di eseguire gli script e non il contrario.
- Preferire il singolo script quando serve tracciabilita` puntuale del ticket o un rollback manuale.


file_path: /var/www/html/dev/sophia_framework2/_documentation/sophia_framework.md
title: SOPHIA Framework 2 - Developer Agent Guide
scanned_at: 2026-04-16 13:45:11
content:
# SOPHIA Framework 2 - Developer Agent Guide

Questo documento descrive l'architettura e le convenzioni del framework SOPHIA 2 (basato su Yii 1.1) per facilitare l'orientamento e lo sviluppo da parte di agenti software.

## 1. Architettura Core (MVC & Hierarchy)

Il framework utilizza un pattern di ereditarietà e override a tre livelli:

- **FRM (Framework):** Contiene la logica di base, le anagrafiche comuni e le tabelle di sistema.
  - *Controller:* `protected/controllers/frm/` (es. `FrmAnaArticoliController`)
  - *Model:* `protected/models/frm/` (es. `FrmAnaArticoli`)
- **APP (Application):** Contiene la logica specifica del business/progetto. Le classi APP solitamente estendono quelle FRM.
  - *Controller:* `protected/controllers/app/` (es. `AppAnaArticoliController extends FrmAnaArticoliController`)
  - *Model:* `protected/models/app/` (es. `AppAnaArticoli extends FrmAnaArticoli`)
- **CLI (Command Line):** Task batch e processi in background.
  - *Controller:* `protected/controllers/cli/`
  - *Model:* `protected/models/cli/`

### Sistema di Override (ControllerMap)
L'applicazione decide quale controller caricare tramite la `controllerMap` definita nelle configurazioni.
- `protected/config/config_frm.php` definisce i mapping di default (livello FRM).
- `protected/config/config_app.php` sovrascrive questi mapping puntando ai controller APP.
*Esempio:* Quando l'URL richiede `FrmAnaArticoli`, il framework istanzia `AppAnaArticoliController` se mappato in `config_app.php`.

## 2. Configurazioni

La configurazione è modulare e caricata gerarchicamente in `protected/config/main.php`:

1. **Environment:** Caricato da `protected/config/environment/{AMBIENTE}.php` (definito in `environment.php` in root).
2. **Framework:** `protected/config/config_frm.php` (Parametri base, import, moduli come Cruge, controllerMap base).
3. **Application:** `protected/config/config_app.php` (Override di APP su FRM).
4. **Client:** `protected/config/config_client.php` (Personalizzazioni specifiche per il cliente finale).
5. **Database/Mailer:** Caricati dai path `protected/config/db/` e `protected/config/mailer/`.

## 3. Convenzioni dei Modelli e Controller

### Models
- Tutti i modelli DB estendono `frmCActiveRecord`.
- I modelli APP estendono i rispettivi modelli FRM per aggiungere attributi o logica specifica.
- Funzione `tr()`: Usata per la traduzione (wrapper di `Yii::t()`).

### Controllers & Rendering (RenderSettings)
Il framework utilizza un sistema dinamico per definire la UI nel controller tramite l'oggetto `RenderSettings`.
- **`initfields($model, $rendertype)`**: Metodo nel controller che definisce visibilità, label, larghezza colonne e widget per ogni campo in base al contesto (`renderfilter`, `renderadmin`, `renderform`).
- **`rootviews`**: Proprietà del controller che determina la cartella delle viste da utilizzare (es. `frmAnaArticoli`).

## 4. Front-end e Asset

- **JavaScript:**
  - `js/frm*.js`: Script base del framework.
  - `js/app*.js`: Script specifici per l'applicazione (possono essere placeholder vuoti se non necessari).
  - `js/framework.js`: Core utility JS.
  - `js/custom.js`: Personalizzazioni JS globali.
- **CSS:** `css/global.css` è il file principale caricato dal controller base.

## 5. CLI e Scheduler

- **Yii Console:** Gestibile tramite `protected/yiic`.
- **Sophia Scheduler:** Situato in `/sophiascheduler/`, è un sistema di cron-job PHP personalizzato che si integra con il DB dell'applicazione.

## 6. Sicurezza e Accessi
- Il modulo **Cruge** gestisce RBAC (Role-Based Access Control) e autenticazione.
- Prefisso tabelle Cruge: `frm_cruge_`.
- Funzione helper `hasrole($role)` in `global.php` per verifiche rapide.

## 7. Funzioni Globali
- `protected/global.php`: Contiene centinaia di helper function (date formatting, log, export, utility DB).
- `protected/global_app.php`: Helper specifici per l'applicazione.


file_path: /var/www/html/dev/sophia_framework2/_documentation/structure_and_functions.md
title: Struttura e funzioni del Sophia Framework
scanned_at: 2026-04-16 13:45:11
content:
# Struttura e funzioni del Sophia Framework

Questo documento descrive la struttura reale del Musa app basata sui pattern FRM / APP / CLI presenti nel codice, con focus su controller, rendering dinamico dei campi e comportamento della base dati dei modelli.

## Obiettivo

- Dare una mappa rapida del framework a chi deve estendere il codice.
- Spiegare il contratto tra controller, modelli e viste.
- Evidenziare i punti di estensione realmente usati nel repo.

## Livelli FRM / APP / CLI

- `FRM` è il livello framework condiviso.
- `APP` sovrascrive o estende i controller FRM con logica applicativa.
- `CLI` sovrascrive o estende gli stessi controller per esecuzioni batch o client-side non interattive.

Nel repo il layering e realizzato con `controllerMap`:

- `protected/config/config_frm.php` mappa le route base verso i controller FRM, ad esempio `site` -> `application.controllers.frm.SiteController`.
- `protected/config/config_app.php` rimappa gli stessi identificativi verso i controller applicativi, ad esempio `FrmAnaCommesse` -> `application.controllers.app.AppAnaCommesseController` e `siteApp` -> `application.controllers.app.SiteAppController`.
- `protected/config/config_client.php` rimappa verso i controller CLI, ad esempio `FrmAnaCommesse` -> `application.controllers.cli.CliAnaCommesseController`.

Questa scelta consente di mantenere la stessa route logica ma cambiare l'implementazione per ambiente o canale di esecuzione.

## Controller Map

- Il nome della route resta spesso quello FRM, mentre l'implementazione cambia tramite `controllerMap`.
- `SiteController` è il punto comune per login, error handling, import, export, gestione script e utility trasversali.
- `SiteAppController` eredita da `SiteController` e ospita le action specifiche dell'applicazione.
- I controller `Cli*` ereditano dai corrispondenti controller `App*`, quindi la CLI riusa la logica applicativa e ne modifica solo i punti necessari.

## Base Controller

Il file centrale e `protected/components/Controller.php`.

### `init()`

- Carica costanti e CSS globali.
- Registra `global.css` e `xupload_buttons.css`.
- Imposta la lingua tramite `ELangPick::setLanguage()`.
- Inizializza `rootviews` quando `className` e valorizzato, costruendo il path delle viste convenzionali.

### `behaviors()`

- Aggancia `ext.eexcelview.EExcelBehavior`.
- Questo rende disponibile `toExcel()` su tutti i controller che estendono la base.

### `initfields($model, $rendertype)`

- Prepara i campi standard del modello per i diversi tipi di render.
- Se `renderfilter` e attivo, inizializza il filtro `nRighe` come hidden field.
- Se `renderadminbtn` e attivo, crea i pulsanti standard della griglia: `Visualizza Filtri`, `Reset Filtri` e il selettore `Visualizza:` per il numero di righe.

Il selettore `nRighe` aggiorna il campo hidden e rilancia l'azione di filtro.

### `getrendersettings($rendersettings, $render, $Fields = array())`

- Trasforma `RenderSettings` nel set ordinato di campi da visualizzare.
- Filtra per tipo di render: `renderadmin`, `renderadminbtn`, `renderfilter`, `renderform`, `renderformbtn`.
- Gestisce l'ordinamento tramite `order` o `htmlOptions['order']`.
- Gestisce la visibilità: per i campi form/filter, `visible=false` porta a un contenitore nascosto; per i pulsanti, `visible=false` produce un wrapper con classe `btn-hidden`.
- Se viene passato `$Fields`, restituisce solo quei campi nell'ordine richiesto.

### `drawInitFields($fields, $captureOutput = false, $autoSetColSm = false, $formType = TbActiveForm::TYPE_VERTICAL)`

- Disegna i campi in righe Bootstrap.
- Accetta `col_width` come intero oppure come array `['md' => x, 'sm' => y]`.
- Se `autoSetColSm` e attivo, calcola automaticamente le classi `col-sm-*`.
- Se la somma delle colonne supera 12 o se il campo ha `new_row=true`, chiude la riga e ne apre una nuova.
- Supporta `TbActiveForm::TYPE_VERTICAL` con label sopra il campo e `TbActiveForm::TYPE_HORIZONTAL` con label affiancata.
- Se `captureOutput=true`, restituisce l'HTML invece di stamparlo direttamente.

### `drawInitButtons($buttons, $drawRow = true)`

- Disegna i pulsanti del form.
- Se il valore `html` e` un `TbButtonGroup`, richiama `run()`.
- Altrimenti stampa direttamente l'HTML.

### `drawInitAdminButtons($buttons)`

- Divide i pulsanti in due blocchi: a sinistra quando `position = sx`, a destra per tutti gli altri.
- E utile per toolbar amministrative con pulsanti di ricerca, reset, export e azioni massicce.

### `usefiltersession($model, $controllerid = null, $actionid = null)`

- Salva i filtri corrente in sessione per supportare il ritorno da pagine di dettaglio.
- Se la request contiene `isgoback`, ripristina i filtri salvati.
- La chiave di sessione e` per controller e action, quindi il filtro resta isolato per schermata.

### Flusso CRUD standard

- `actionAdmin()` crea il modello in scenario `search`, inizializza i filtri di default, applica la sessione filtro, invoca `initfields()`, costruisce filtri/pulsanti/colonne con `getrendersettings()`, imposta la paginazione con `nRighe` e renderizza la vista `admin`.
- `actionCreate()` e `actionUpdate()` inizializzano i campi form, gestiscono validazione Ajax, salvano il modello e poi reindirizzano oppure restano sulla form con flash message.

## `frmCActiveRecord`

Il base model e` `protected/models/frmCActiveRecord.php`.

### `RenderSettings`

- Ogni istanza inizializza `RenderSettings` in `init()`.
- Per ogni colonna del modello crea un oggetto con `visible`, `renderadmin`, `renderfilter` e `renderform`.
- Questo è il punto di estensione per tutte le viste dinamiche.

### `nRighe`

- E` il parametro usato per la dimensione pagina delle griglie.
- Viene valorizzato nei filtri e letto nei controller admin.

### Timestamp e utenti

- `beforeSave()` aggiorna sempre `stamp_update_user` e `stamp_update`.
- Se il record è nuovo, valorizza anche `stamp_insert_user` e `stamp_insert`.

### Supporto al ciclo di vita

- `OldAttributes` conserva lo stato precedente al salvataggio.
- `initDefaultFields()` e `initDefaultFilters()` sono hook vuoti da specializzare.
- `logicalDelete()` sposta l'oggetto agendo su `idsocieta`.
- `Archivia()` e `annullaArchivia()` implementano la logica di archiviazione con offset numerici.
- `deleterelateddata()` e` un hook generico per cancellazioni collegate.

## Regole pratiche

- Se un controller usa `initfields()`, deve anche dichiarare gli array ordinati `getrenderfilters()`, `getrenderadminbtns()`, `getrenderadmin()`, `getrenderform()` e `getrenderformbtn()`.
- I campi custom vanno sempre agganciati a `RenderSettings`, non disegnati “a mano” nelle viste, salvo casi eccezionali.
- I pulsanti e i campi renderizzati dinamicamente devono restare coerenti con il tipo di render richiesto.
- Quando si aggiunge una nuova schermata, conviene partire da `actionAdmin()`, `actionCreate()` e `actionUpdate()` gia presenti nella base controller.


file_path: /var/www/html/dev/sophia_framework2/_documentation/translation_management.md
title: Translation Management
scanned_at: 2026-04-16 13:45:11
content:
# Translation Management

## Regola Base
Nel framework SOPHIA le traduzioni business passano attraverso Yii, non attraverso un sistema custom separato.

I due punti di accesso da usare sono:

- `tr('testo')`
- `Yii::t('categoria', 'testo')`

Il wrapper `tr()` e definito in `protected/extensions/global.php` e delega a:

```php
return Yii::t('Global', $text);
```

## Cataloghi Di Traduzione
I cataloghi principali sono file PHP sotto:

- `protected/messages/it/`
- `protected/messages/en/`

Esempi reali presenti nel repo:

- `protected/messages/it/Global.php`
- `protected/messages/it/menu.php`
- `protected/messages/it/login.php`
- `protected/messages/en/Global.php`
- `protected/messages/en/menu.php`
- `protected/messages/en/login.php`
- `protected/messages/en/app_admin.php`

Questi file sono generati da Yii e possono poi essere rifiniti a mano.

## Configurazione Di Estrazione
Il file di configurazione dell estrazione e:

- `protected/messages/config_translation.php`

I punti chiave osservabili sono:

- `sourcePath` punta a `protected`
- `messagePath` punta a `protected/messages`
- le lingue dichiarate sono `it` e `en`
- `fileTypes` include `php`
- `overwrite` e attivo
- sono esclusi `messages`, `vendors`, `web/js` e `gii`

L esclusione di `/gii` e importante: i template custom del generatore non devono diventare rumore nel catalogo traduzioni.

## Generazione
La generazione standard avviene con il comando Yii:

- `yiic message`

In pratica:

1. Yii scansiona il codice PHP;
2. estrae le stringhe marcate con `tr()` o `Yii::t()`;
3. aggiorna i cataloghi sotto `protected/messages/*`;
4. i traduttori completano i valori mancanti.

## Regole Di Governance

- per stringhe UI business usa `tr()` o `Yii::t()`;
- preferisci una category coerente con il dominio se il testo non e globale;
- non introdurre un sistema JSON custom per le traduzioni business;
- non usare file front-end separati come fonte primaria per la localizzazione applicativa;
- mantieni le traduzioni in PHP, cosi restano compatibili con il flusso Yii e con l extraction.

Nel repository non si vede un catalogo JSON dedicato alle traduzioni business: i file JSON presenti sono di dipendenze o metadata, non il meccanismo applicativo di i18n.

## Uso Pratico Nel Codice
Esempi reali:

- `protected/models/FrmAnaSocieta.php` usa `Yii::t('FrmAnaSocieta', ...)`
- `protected/models/FrmAnaAttributi.php` usa `tr(...)`
- `protected/views/frmGestioneCostanti/admin.php` usa `tr(...)`
- `protected/views/frmAnaDipartimenti/admin.php` usa `tr(...)`

La scelta pratica e semplice:

- `tr()` per label e messaggi globali o di uso comune;
- `Yii::t()` quando serve dichiarare esplicitamente la category.

## Errori Da Evitare

- hardcodare testo visibile nell HTML;
- creare traduzioni solo lato JS senza passare dal catalogo PHP;
- aggiungere file traduzione fuori da `protected/messages`;
- dimenticare di eseguire `yiic message` dopo aver aggiunto nuove stringhe;
- usare category incoerenti tra vista, model e controller.

## File Di Riferimento

- `protected/extensions/global.php`
- `protected/messages/config_translation.php`
- `protected/messages/it/Global.php`
- `protected/messages/en/Global.php`
- `protected/models/FrmAnaSocieta.php`
- `protected/models/FrmAnaAttributi.php`
- `protected/views/frmGestioneCostanti/admin.php`


file_path: /var/www/html/dev/sophia_framework2/_documentation/widgets_and_ui_components.md
title: Widgets And UI Components
scanned_at: 2026-04-16 13:45:11
content:
# Widgets And UI Components

## Stack UI Principale
Il frontend del framework usa in modo esteso `yiibooster` e widget custom che seguono lo stesso stile.

La configurazione gia pre-carica `booster` in `protected/config/config_frm.php`, quindi le view possono usarlo come base standard.

## Form
I form piu comuni usano:

- `booster.widgets.TbActiveForm`
- `booster.widgets.TbDatePicker`
- `booster.widgets.TbDateTimePicker`
- `booster.widgets.TbDateRangePicker`
- `booster.widgets.TbTimePicker`
- `booster.widgets.TbSelect2`
- `booster.widgets.TbCKEditor`
- `booster.widgets.TbRedactorJs`

Esempi reali:

- `protected/views/frmAnaUbicazioni/_form.php`
- `protected/views/frmAnaSocietaUtente/_form.php`
- `protected/views/musaCambiomansione/_form.php`
- `protected/views/musaFormazioniRichieste/_form.php`
- `protected/views/musaCorsiSessioni/_form.php`

## Griglie
Le griglie usano frequentemente:

- `booster.widgets.TbExtendedGridView`
- `booster.widgets.TbButtonColumn`
- `booster.widgets.TbRelationalColumn`
- `booster.widgets.TbEditableColumn`
- `widgets.FrmGridView`

Esempi reali:

- `protected/views/frmAnaUbicazioni/admin.php`
- `protected/views/frmAnaCdc/admin.php`
- `protected/views/musaFormazioniRichieste/admin.php`
- `protected/views/frmGestioneCostanti/admin.php`

### Punti Da Ricordare

- `TbButtonColumn` e quasi sempre controllata da `GetAbilitazioni(...)`;
- `TbEditableColumn` e usata per edit inline, per esempio sulle costanti;
- `TbExtendedGridView` e la base per griglie responsive e complete;
- `FrmGridView` e un wrapper custom del progetto.

## Pulsanti E Modalita Di Interazione
I pulsanti custom sono costruiti spesso dentro le colonne azione.

Pattern tipici:

- `update`
- `delete`
- `attiva`
- `abbinaCdc`
- `richiediFormazione`
- `spostadip`
- `assegnadip`

Questi nomi non sono estetici: devono essere coerenti con i case gestiti dal controller di abilitazione.

## Modal, Alert E Widget A Supporto
Il progetto usa anche:

- `booster.widgets.TbAlert`
- `booster.widgets.TbModalManager`
- `booster.widgets.TbDetailView`
- `booster.widgets.TbButtonGroup`
- `booster.widgets.TbButtonGroupColumn`

Esempi:

- `protected/views/frmAnaSocietaUtente/_response.php`
- `protected/views/frmAnaUbicazioni/view.php`
- `protected/views/ggsAnaMusaPersonale/admin.php`

## Chart E Componenti Speciali
La libreria include anche widget piu specialistici:

- `booster.widgets.TbHighCharts`
- `booster.widgets.TbModalManager`
- `booster.widgets.input.*`

Le risorse del plugin Booster mostrano che Select2, DatePicker e altri input sono parte del pacchetto standard del progetto.

## FullCalendar E UI Avanzata
`protected/views/musaCorsiSessioni/calendar.php` mostra un altro pattern importante:

- caricamento di `fullcalendar`
- uso di `TbSelect2` dentro una modal
- inizializzazione JS custom per i select nel modal

Questo e un buon esempio di integrazione tra asset esterni e widget Booster.

## Regole Di Governance

- preferisci i widget gia adottati dal progetto;
- se aggiungi un nuovo widget, verifica che sia compatibile con il bootstrap e con il resto del layout;
- mantieni il contratto `gridButtons` sulle griglie che dipendono dai permessi;
- usa `tr()` o `Yii::t()` per i testi visibili nei widget;
- non mescolare markup custom e widget standard senza una ragione forte.

## File Di Riferimento

- `protected/config/config_frm.php`
- `protected/views/frmAnaUbicazioni/admin.php`
- `protected/views/frmAnaUbicazioni/_form.php`
- `protected/views/frmAnaUbicazioni/view.php`
- `protected/views/frmAnaCdc/admin.php`
- `protected/views/frmGestioneCostanti/admin.php`
- `protected/views/musaFormazioniRichieste/admin.php`
- `protected/views/musaCorsiSessioni/calendar.php`
- `protected/extensions/yiibooster/widgets/TbSelect2.php`
- `protected/extensions/yiibooster/widgets/input/TbInputHorizontal.php`


file_path: /var/www/html/dev/musa_app/_documentation/context.md
title: Contesto documentazione app
scanned_at: 2026-04-16 13:47:57
content:
# Contesto documentazione app

Questa cartella raccoglie note operative per le principali funzioni applicative di `musa_app`.
Lo scopo e rendere rapidi gli interventi di manutenzione, il passaggio di consegne e la consultazione da parte di agenti AI.

## Struttura logica

- `functions/management_*`: area censimento, valutazioni skill e analisi gap.
- `functions/qualifications_*`: area qualifiche e flussi speciali EHS, ANSF, processi speciali, controlli ND e self inspection.
- `functions/corsi.md`: dominio nuovo `musa_corsi_*` per anagrafica, sessioni, iscrizioni e abbinamenti con le qualifiche.
- `functions/documents_docpers.md`: documenti e allegati legati alla persona e alle qualifiche.
- `functions/advanced_*`: lettura avanzata di storico, commesse, progetti e archivi.
- `functions/database_*`: riferimenti alle anagrafiche operative e alle tabelle usate come master data.
- `functions/ehs_*`: rischio, valutazioni EHS e collegamento con le scadenze di qualifica.
- `functions/admin_operazioni_tecniche.md`: import, export, webservice, batch e attivita tecniche.
- `functions/ggs_integrazioni.md`: integrazione con i flussi GGS / iForm / schede / piani azione.

## Riferimenti ricorrenti

- Corsi: `MusaCorsiController`, `MusaCorsiSessioniController`, `MusaCorsiIscrizioniController`, `MusaCorsiFormazioniDettController`.
- Qualifiche: `MusaFormazioniRichiesteController`, `MusaFormazioniDettController`, `MusaFormazioniInattesaController`.
- Skill: `MusaValutazioniSkillController`, `MusaGapAnalisysController`, `MusaSkillArchiveController`.
- EHS / rischi: `MusaRiskController`, `MusaRiskAllegatiController`, `app/SiteAppController`.
- Integrazioni: `frm/FrmApiIFormController`, `frm/SiteController`, `app/SiteAppController`.

## Ticket spostato

- `tickets/ticket_10768_analisi_tecnica_corsi.md`


file_path: /var/www/html/dev/musa_app/_documentation/functions/admin_operazioni_tecniche.md
title: Admin Operazioni Tecniche
scanned_at: 2026-04-16 13:47:57
content:
# Admin Operazioni Tecniche

## 1. Descrizione funzionale

Area di servizio per operazioni tecniche: import, export, webservice, staging, log e batch applicativi.
E il livello da usare per capire dove passa il dato prima che arrivi alle funzioni di business.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/frm/SiteController.php`: `actioncallwebservice()`, import utenti, gestione staging e mapping import.
- `protected/controllers/app/SiteAppController.php`: export, import, schedulazioni, consolidamento record pendenti.
- `protected/controllers/frm/FrmApiIFormController.php`: ingest dei record iForm verso `GgsSchede` e `GgsPianoazioni`.
- `protected/controllers/MusaRiskController.php` e `protected/controllers/MusaFormazioniRichiesteController.php` per upload allegati e conferme di caricamento.

## 3. Sezione DB (tabelle/campi principali)

- `frm_sys_remotelinks`: configurazione dei webservice remoti.
- `frm_ana_utenti_stg`: staging utenti per import.
- `ggs_iform_pages_records`: record grezzi importati da iForm.
- `ggs_schede`, `ggs_pianoazioni`: destinazioni applicative dei dati elaborati.
- `musa_formazioni_allegati`, `musa_risk_allegati`: allegati gestiti da upload tecnico.


file_path: /var/www/html/dev/musa_app/_documentation/functions/advanced_archivio_musa.md
title: Advanced Archivio Musa
scanned_at: 2026-04-16 13:47:57
content:
# Advanced Archivio Musa

## 1. Descrizione funzionale

Archivio trasversale dei principali oggetti MUSA, utile per leggere pratiche, allegati, code e snapshot derivati.
Non e un singolo CRUD ma una vista di consolidamento fra piu sotto-domini applicativi.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaFormazioniInattesaController.php`: vista coda / archivio delle richieste in attesa.
- `protected/controllers/MusaFormazioniRichiesteController.php`: allegati, export, stati e record di pratica.
- `protected/controllers/MusaSkillArchiveController.php`: storico skill come archivio storico MUSA.
- `protected/controllers/app/SiteAppController.php`: importazioni e consolidamenti di record pendenti.

## 3. Sezione DB (tabelle/campi principali)

- `musa_formazioni_inattesa`: vista derivata per le richieste in attesa.
- `musa_formazioni_richieste`: pratica centrale del dominio formazione / qualifica.
- `musa_formazioni_allegati`: allegati della pratica.
- `musa_skill_archive`, `musa_skill_archive_attr`: storico skill.
- `musa_formazioni_richieste_sp_verifiche_export`: export storico delle verifiche speciali.


file_path: /var/www/html/dev/musa_app/_documentation/functions/advanced_archivio_skill.md
title: Advanced Archivio Skill
scanned_at: 2026-04-16 13:47:57
content:
# Advanced Archivio Skill

## 1. Descrizione funzionale

Archivio storico delle skill con lettura per persona, task e livello.
La funzione e pensata per recuperare l'evoluzione di una competenza senza interferire con lo stato corrente della skill.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaSkillArchiveController.php`: gestione archivio, export e griglia.
- `protected/models/MusaSkillArchive.php`: record storico della skill.
- `protected/models/MusaSkillArchiveAttr.php`: attributi storici collegati al record archivio.
- `protected/views/musaSkillArchive/admin.php` e `_search.php`.

## 3. Sezione DB (tabelle/campi principali)

- `musa_skill_archive`: `idskillarchive`, `idskill`, `idanautente`, `idtask`, `level`, `idmanager`, `active`, `evaluationdate`.
- `musa_skill_archive_attr`: `iddipartimentoarea`, `idcommessa`, `iddipartimentomansione`, `iddipartimentoesito`.
- `musa_skill`: stato corrente per confronto.
- `musa_task`, `frm_ana_dipartimenti`, `frm_ana_commesse`: contesto del record storico.


file_path: /var/www/html/dev/musa_app/_documentation/functions/advanced_commesse.md
title: Advanced Commesse
scanned_at: 2026-04-16 13:47:57
content:
# Advanced Commesse

## 1. Descrizione funzionale

Approfondimento sul dominio commesse con focus sui legami operativi verso task, workstation, dipartimenti e abbinamenti utente.
La lettura serve quando la commessa non e solo anagrafica ma parte di una catena di abilitazioni o di valutazione skill.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/frm/FrmAnaCommesseController.php`: CRUD e mantenimento della master commessa.
- `protected/controllers/MusaTaskDipartimentiController.php` e `protected/models/MusaTaskDipartimentiProgetti.php`: abbinamenti task / dipartimento / progetto.
- `protected/controllers/FrmAnaArticoliController.php`: uso delle commesse come perimetro di applicabilita.
- `protected/models/MusaValutazioniSkill.php`: filtri basati sui progetti.

## 3. Sezione DB (tabelle/campi principali)

- `frm_ana_commesse`: `idcommessa`, `codicecommessa`, `desccommessa`, `datainizio`, `datafine`, `idtipocommessa`, `idlivello`, `idparent`, `idroot`.
- `frm_ana_commesse_utente`: legame commessa/utente con ruolo.
- `frm_ana_commesse_dipartimenti`: legame commessa/dipartimento.
- `musa_task_dipartimenti_progetti`: ponte operativa tra task e commessa.
- `musa_task_dipartimenti`: regole di bisogno e abilitazione per dipartimento.


file_path: /var/www/html/dev/musa_app/_documentation/functions/advanced_progetti.md
title: Advanced Progetti
scanned_at: 2026-04-16 13:47:57
content:
# Advanced Progetti

## 1. Descrizione funzionale

Vista avanzata dei progetti intesi come contenitore operativo, soprattutto quando devono dialogare con task, valutazioni skill e workcenter.
E il livello di lettura piu vicino alla logica di assegnazione e all'uso trasversale delle commesse nel resto dell'app.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/frm/FrmAnaCommesseController.php` e `protected/models/frm/FrmAnaCommesse.php` per la base progetto.
- `protected/controllers/MusaValutazioniSkillController.php` e `protected/models/MusaValutazioniSkill.php` per i filtri su progetto.
- `protected/controllers/MusaRiskController.php` per la lettura dei progetti in valutazione rischi.
- `protected/models/GgsAnaMusaCommesse.php` per il raccordo con il dominio GGS.

## 3. Sezione DB (tabelle/campi principali)

- `frm_ana_commesse`: anagrafica progetto con date, codice e gerarchia.
- `frm_ana_commesse_dipartimenti`: progetto collegato a dipartimenti/workstation.
- `ggs_ana_musa_commesse`: mapping esterno dei progetti GGS.
- `musa_task_dipartimenti_progetti`: relazione operativa tra task e progetto.
- `musa_valutazioni_skill`: filtro progetto su censimento e skill.


file_path: /var/www/html/dev/musa_app/_documentation/functions/advanced_storico.md
title: Advanced Storico
scanned_at: 2026-04-16 13:47:57
content:
# Advanced Storico

## 1. Descrizione funzionale

Lettura storica dei record operativi, utile per audit, ricostruzione eventi e confronto fra stato corrente e stato precedente.
La vista privilegia la traccia degli snapshot rispetto alla modifica live.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaSkillArchiveController.php`: archivio storico delle skill.
- `protected/models/MusaSkillArchive.php` e `MusaSkillArchiveAttr.php`: storico e attributi associati.
- `protected/controllers/MusaFormazioniRichiesteController.php`: gestione storica delle pratiche qualifica e allegati.
- `protected/controllers/MusaRiskController.php` e `protected/controllers/app/SiteAppController.php`: eventi storici su rischi, allegati e import.

## 3. Sezione DB (tabelle/campi principali)

- `musa_skill_archive`: `idskillarchive`, `idskill`, `idanautente`, `idtask`, `level`, `idmanager`, `evaluationdate`.
- `musa_skill_archive_attr`: `iddipartimentoarea`, `idcommessa`, `iddipartimentomansione`, `iddipartimentoesito`, `idsupmanager`.
- `musa_formazioni_richieste`: scadenze e stati storici delle qualifiche.
- `musa_formazioni_allegati`: storico allegati collegati alla pratica.


file_path: /var/www/html/dev/musa_app/_documentation/functions/corsi.md
title: Corsi
scanned_at: 2026-04-16 13:47:57
content:
# Corsi

## 1. Descrizione funzionale

Gestione dei corsi come entita autonoma: anagrafica, abbinamento alle qualifiche, sessioni calendario, iscrizioni dei dipendenti e cambio stato rapido.
La struttura nasce per non riusare `commesse` o `dipartimenti` come master dei corsi.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaCorsiController.php`: `actionUpdate()`, `actionDuplica()`, `actionExport()`.
- `protected/controllers/MusaCorsiSessioniController.php`: `actionCalendar()`, `actionCalendarFeed()`, `actionDettaglioSessione()`, `actionQuickChangeStato()`, `actionBulkIscriviDipendenti()`, `actionExport()`.
- `protected/controllers/MusaCorsiIscrizioniController.php`: `actionBulkAggiornaStato()`, `actionExport()`.
- `protected/controllers/MusaCorsiFormazioniDettController.php`: `actionCaricaComboFormazioniDettByCorso()`, `actionSalvaAbbinamentiCorso()`.
- `protected/models/MusaCorsi.php`, `MusaCorsiSessioni.php`, `MusaCorsiIscrizioni.php`, `MusaCorsiFormazioniDett.php`.
- `protected/views/musaCorsi/*` e `protected/views/musaCorsiSessioni/calendar.php`.

## 3. Sezione DB (tabelle/campi principali)

- `musa_corsi`: `idcorso`, `idsocieta`, `idstabilimento`, `idformazione`, `codcorso`, `descrizione`, `fornitore_descrizione`, `idsocietautente_fornitore`, `data_inizio`, `data_termine_iscrizioni`, `durata_testo`, `note`, `enabled`, `visible`.
- `musa_corsi_formazioni_dett`: ponte tra corso e `musa_formazioni_dett` con `idcorso`, `idformazionedett`.
- `musa_corsi_sessioni`: `idcorsosessione`, `idcorso`, `data_sessione`, `ora_inizio`, `ora_fine`, `note`.
- `musa_corsi_iscrizioni`: `idcorsoiscrizione`, `idcorsosessione`, `idanautente`, `idstatoiscrizione`, `idformazionerichiesta_target`, `note`.
- `musa_corsi_sys_stati_iscrizione`: stati `PREVISTO`, `ISCRITTO`, `CONFERMATO`.


file_path: /var/www/html/dev/musa_app/_documentation/functions/database_anagrafiche_operativa.md
title: Database Anagrafiche Operativa
scanned_at: 2026-04-16 13:47:57
content:
# Database Anagrafiche Operativa

## 1. Descrizione funzionale

Riferimento rapido alle anagrafiche operative usate dall'app: persone, societa, stabilimenti, commesse, dipartimenti, task e stabilimenti logici.
Serve come mappa base per capire dove leggere un dato master prima di entrare nelle funzioni verticali.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/frm/FrmAnaSocietaUtenteController.php` e `protected/models/app/GgsIformPages.php` per societa e anagrafiche collegate.
- `protected/controllers/frm/FrmAnaCommesseController.php` e `protected/models/frm/FrmAnaCommesse.php` per le commesse operative.
- `protected/controllers/frm/FrmAnaDipartimentiController.php` e `protected/models/frm/FrmAnaDipartimenti.php` per dipartimenti e workstation.
- `protected/controllers/GgsAnaMusaPersonaleController.php` e `protected/models/GgsAnaMusaPersonale.php` per il personale GGS.
- `protected/controllers/MusaTaskController.php` e `protected/models/MusaTask.php` per i task.

## 3. Sezione DB (tabelle/campi principali)

- `frm_ana_utenti`: persona applicativa con `idanautente`, `nome`, `cognome`, `codice`.
- `frm_ana_societa_utente`: societa / fornitore / plant con `idsocietautente`, `nome`, `idtiposocieta`.
- `frm_ana_stabilimento`: stabilimento e contesto societario.
- `frm_ana_commesse`: `codicecommessa`, `desccommessa`, `datainizio`, `datafine`.
- `frm_ana_dipartimenti`: `codicedipartimento`, `descrdipartimento`, `idtipodipartimento`, `idparent`, `idroot`.
- `musa_task`: `codtask`, `desctask`, `iddipartimento_workshop`, `iddipartimento_mansione`.
- `ggs_ana_musa_personale`, `ggs_ana_musa_commesse`: anagrafiche esterne e mapping verso il mondo GGS.


file_path: /var/www/html/dev/musa_app/_documentation/functions/documents_docpers.md
title: Documents DocPers
scanned_at: 2026-04-16 13:47:57
content:
# Documents DocPers

## 1. Descrizione funzionale

Gestione dei documenti personali e degli allegati legati alle qualifiche.
Serve per archiviare file, documenti di supporto e allegati operativi associati alla persona o alla pratica formativa.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaFormazioniDettController.php`: `actionCreatePersonalDocs()`, `actionAdminPersonalDocs()`.
- `protected/controllers/MusaFormazioniRichiesteController.php`: `actionCreateDocPers()`, `actionUpdateDocPers()`, `actionAdminDocPers()`, `actionUploadAllegati()`.
- `protected/views/musaFormazioniRichieste/_formallegati.php` e `_form_qualifica.php` per la parte allegati.
- `protected/models/MusaFormazioniDett.php`: export label `_Export_Documenti_Personale`.

## 3. Sezione DB (tabelle/campi principali)

- `musa_formazioni_allegati`: `idformazionerichallegato`, `idformazionerichiesta`, `idfile`, `descrizione`, `stamp_*`.
- `frm_files_upload`: repository del file fisico caricato.
- `musa_formazioni_richieste`: pratica di riferimento con `idanautente`, `idformazionedett`, `dataend`, `idstatoformazione`.
- `musa_formazioni_dett`: qualifica o documento di origine.
- `musa_formazioni_visite`: utile quando il documento personale e collegato a visite o idoneita.


file_path: /var/www/html/dev/musa_app/_documentation/functions/ehs_rischi_e_valutazioni.md
title: EHS Rischi e Valutazioni
scanned_at: 2026-04-16 13:47:57
content:
# EHS Rischi e Valutazioni

## 1. Descrizione funzionale

Gestione della valutazione rischi, dei relativi allegati e delle azioni correttive.
Il ramo EHS dialoga anche con le qualifiche scadute, i reminder e le matrici di valutazione workstation / mansione.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaRiskController.php`: `actionValutazioneRischi()`, `actionadminValutazioneRischi()`, `actionDoValutazione()`, `actionExportValutazioneRischi()`, `actionEreditaValutazione()`.
- `protected/models/MusaRisk.php`, `MusaRiskAllegati.php`, `MusaRiskTipo.php` per dominio rischio.
- `protected/controllers/app/SiteAppController.php`: routine EHS per scadenze e export delle qualifiche.
- `protected/views/musaRisk/valutazioneRischi.php` e `_formvalutazioneRischi.php`.

## 3. Sezione DB (tabelle/campi principali)

- `musa_risk`: anagrafica rischio, livello e contesto operativo.
- `musa_risk_allegati`: allegati del rischio.
- `musa_risk_tipo`: catalogo tipi rischio.
- `ggs_schede`: schede EHS / osservazioni con `idscheda`, `idprogetto`, `idworkstation`, `idstato`.
- `ggs_pianoazioni`: azioni correttive con `idscheda`, `idcondizione`, `idpriorita`, `idresponsabile`, `dataprevistachiusura`, `idstato`.
- `musa_formazioni_richieste`, `musa_alert_ehs`: scadenze EHS collegate alle qualifiche.


file_path: /var/www/html/dev/musa_app/_documentation/functions/ggs_integrazioni.md
title: GGS Integrazioni
scanned_at: 2026-04-16 13:47:57
content:
# GGS Integrazioni

## 1. Descrizione funzionale

Integrazione tra iForm / GGS e il dominio applicativo MUSA.
Copre la lettura delle schede, il trasferimento dei record, la generazione delle azioni e il collegamento con personale e progetti.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/frm/FrmApiIFormController.php`: estrazione e trasformazione dei record `TO_BE` verso `GgsSchede` e `GgsPianoazioni`.
- `protected/controllers/frm/SiteController.php`: chiamate webservice e supporto ai flussi remoti.
- `protected/controllers/app/SiteAppController.php`: import dei record pendenti e consolidamento finale.
- `protected/models/app/GgsIformPages.php`, `GgsIformPagesRecords.php`, `GgsIformPagesRecordsAsic.php`, `GgsIformPagesRecordsAins.php`, `GgsIformPagesRecordsCins.php`.
- `protected/models/GgsSchede.php`, `GgsPianoazioni.php`, `GgsAnaMusaPersonale.php`, `GgsAnaMusaCommesse.php`.

## 3. Sezione DB (tabelle/campi principali)

- `ggs_iform_pages`: anagrafica delle pagine e dei profili iForm con `idiformpages`, `iddipartimento`, `id_societautente`, `name`, `label`, `attivo`.
- `ggs_iform_pages_records`: record base con `idiformpagerecord`, `idiformpages`, `created_date`, `modified_date`, `user_iform`, `mail___user`, `data___ora`, `json`, `codicestatoelab`.
- `ggs_iform_pages_records_asic`, `ggs_iform_pages_records_ains`, `ggs_iform_pages_records_cins`: record specializzati per atti sicuri, atti insicuri e condizioni insicure.
- `ggs_iform_options`, `ggs_iform_optionList`: cataloghi e liste di opzioni dei form.
- `ggs_schede`: schede finali con `idscheda`, `idprogetto`, `idworkstation`, `idstato`, `idtiposegnalazione`.
- `ggs_pianoazioni`: piano azioni con `idpianoazione`, `idscheda`, `idpriorita`, `idresponsabile`, `dataprevistachiusura`, `idstato`.


file_path: /var/www/html/dev/musa_app/_documentation/functions/management_censimento.md
title: Management Censimento
scanned_at: 2026-04-16 13:47:57
content:
# Management Censimento

## 1. Descrizione funzionale

Censimento competenze e copertura operativa delle persone su task, mansioni, commesse e workstation.
La funzione serve a capire chi e abilitato, su quale attivita, con quale manager e con quale livello di copertura del fabbisogno.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaValutazioniSkillController.php`: `actionAdmin()`, `actionSchedavalutazione()`, `actionMultiskills()`, `actionsearchUtentibyJob()`, `actionsearchMansioniByProgetto()`, `actiongetNextCombo()`.
- `protected/models/MusaValutazioniSkill.php`: filtri su utente, manager, area, commessa, mansione, task, livello e flag `filled_search`.
- `protected/views/musaValutazioniSkill/admin.php`, `multiskills.php`, `schedavalutazione.php`, `_searchMultiskills.php`.
- `protected/models/MusaTask.php`, `protected/models/MusaTaskDipartimenti.php`, `protected/models/MusaTaskDipartimentiProgetti.php` per il legame task/mansione/progetto.

## 3. Sezione DB (tabelle/campi principali)

- `musa_valutazioni_skill`: `idanautente`, `idmanager`, `idsupmanager`, `idarea`, `idcommessa`, `idmansione`, `idtask`, `idvalutazione`, `level`, `evaluationdate`, `attivo`, `attivocensimento`, `statusid`.
- `musa_skill`: stato skill corrente per `idanautente`, `idtask`, `level`, `idmanager`, `evaluationdate`, `active`.
- `musa_task`: `codtask`, `desctask`, `iddipartimento_workshop`, `iddipartimento_mansione`, `enabled`.
- `musa_task_dipartimenti`: legame tra task e dipartimenti/workstation con `idtask`, `iddipartimento`, `idtipodipartimento`, `need`, `active`.
- `musa_task_dipartimenti_progetti`: ponte tra task_dipartimenti e `frm_ana_commesse`.
- `frm_ana_commesse`, `frm_ana_dipartimenti`, `frm_ana_utenti`: anagrafiche di supporto per progetto, mansione e persona.


file_path: /var/www/html/dev/musa_app/_documentation/functions/management_gap_analysis.md
title: Management Gap Analysis
scanned_at: 2026-04-16 13:47:57
content:
# Management Gap Analysis

## 1. Descrizione funzionale

Analisi del gap tra competenze richieste e competenze effettive.
La vista confronta task, livelli e risorse disponibili per evidenziare carenze, coperture e zone di rischio.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaGapAnalisysController.php`: `actionAdmin()`, `actionExport()`.
- `protected/models/MusaGapAnalisys.php`: ricerca per persona, manager, task, esito e formazione/gap.
- `protected/views/musaGapAnalisys/admin.php` e `_search.php`.
- `protected/models/MusaValutazioniSkill.php` e `protected/models/MusaTaskDipartimenti.php` per il calcolo del fabbisogno.

## 3. Sezione DB (tabelle/campi principali)

- `musa_gap_analisys`: `idanautente`, `idmanager`, `idsupmanager`, `idtask`, `esitoid`, `idformazione`, `idformazionedett`.
- `musa_skill`: copertura attuale della skill.
- `musa_task`, `musa_task_dipartimenti`, `musa_task_dipartimenti_progetti`: fabbisogno e contesto operativo.
- `musa_formazioni_richieste`, `musa_formazioni_dett`: riferimento qualifica / formazione associata al gap.


file_path: /var/www/html/dev/musa_app/_documentation/functions/management_multiskills.md
title: Management Multiskills
scanned_at: 2026-04-16 13:47:57
content:
# Management Multiskills

## 1. Descrizione funzionale

Vista multi-competenza per confrontare piu skill, mansioni e coperture in una sola schermata.
E usata per analisi comparative, selezione rapida e controllo del perimetro operativo su piu task.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaValutazioniSkillController.php`: `actionMultiskills()`, `actionsearchMansioniByProgetto()`, `actionsearchUtentibyJob()`, `actiongetNextCombo()`.
- `protected/views/musaValutazioniSkill/multiskills.php` e `_searchMultiskills.php`.
- `protected/models/MusaValutazioniSkill.php`: filtri `workshop_search`, `epu_search`, `shownames_search`, `filled_search`, `checkconoscenze`.
- `protected/models/MusaTaskDipartimenti.php` e `protected/models/MusaTaskDipartimentiProgetti.php` per la matrice task-progetto.

## 3. Sezione DB (tabelle/campi principali)

- `musa_valutazioni_skill`: `idanautente`, `idtask`, `level`, `idcommessa`, `idmansione`, `idarea`.
- `musa_skill`: skill corrente per persona e task.
- `musa_task_dipartimenti`: `idtask`, `iddipartimento`, `need`, `active`.
- `musa_task_dipartimenti_progetti`: `idtaskdipartimento`, `idcommessa`.
- `frm_ana_commesse`, `frm_ana_dipartimenti`, `frm_ana_utenti`: filtri e anagrafiche di supporto.


file_path: /var/www/html/dev/musa_app/_documentation/functions/management_ultima_valutazione.md
title: Management Ultima Valutazione
scanned_at: 2026-04-16 13:47:57
content:
# Management Ultima Valutazione

## 1. Descrizione funzionale

Storico dell'ultima valutazione skill per persona, task e contesto operativo.
La funzione serve per risalire all'ultimo livello assegnato e al suo perimetro storico senza leggere tutte le transazioni correnti.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaSkillArchiveController.php`: `actionAdmin()`, `actionExport()`, CRUD base dell'archivio.
- `protected/models/MusaSkillArchive.php`: archivio delle valutazioni skill.
- `protected/models/MusaSkillArchiveAttr.php`: attributi storici collegati all'archivio.
- `protected/views/musaSkillArchive/admin.php` e `_search.php`.

## 3. Sezione DB (tabelle/campi principali)

- `musa_skill_archive`: `idskillarchive`, `idskill`, `idanautente`, `idtask`, `level`, `idmanager`, `active`, `evaluationdate`.
- `musa_skill_archive_attr`: `idskillarchive`, `iddipartimentoarea`, `idcommessa`, `iddipartimentomansione`, `iddipartimentoesito`, `idsupmanager`.
- `musa_skill`: stato corrente, utile per confronto con lo storico.
- `musa_task`, `frm_ana_dipartimenti`, `frm_ana_commesse`: contesto organizzativo e di progetto.


file_path: /var/www/html/dev/musa_app/_documentation/functions/management_valutazione_skill.md
title: Management Valutazione Skill
scanned_at: 2026-04-16 13:47:57
content:
# Management Valutazione Skill

## 1. Descrizione funzionale

Gestione della valutazione puntuale della skill della persona su un task, con salvataggio del livello assegnato e della data di valutazione.
La funzione copre la scheda di valutazione, la modifica del livello e l'export operativo.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaValutazioniSkillController.php`: `actionSchedavalutazione()`, `actionAdmin()`, `actionExport()`, `actionsaverichiesta()`.
- `protected/models/MusaValutazioniSkill.php`: validazioni, search, label di export `ultima_valutazione_skill`, gestione della data valutazione.
- `protected/views/musaValutazioniSkill/schedavalutazione.php` e `admin.php` per scheda e griglia.
- `protected/controllers/MusaSkillController.php` e `protected/views/musaSkill/*` per il CRUD della skill corrente.

## 3. Sezione DB (tabelle/campi principali)

- `musa_valutazioni_skill`: `idvalutazione`, `idanautente`, `idtask`, `level`, `evaluationdate`, `idmanager`, `idsupmanager`, `idcommessa`.
- `musa_skill`: anagrafica skill corrente con `idtask`, `idanautente`, `level`, `evaluationdate`, `active`.
- `musa_task`: `idtask`, `codtask`, `desctask`, `iddipartimento_mansione`.
- `frm_ana_utenti`, `frm_ana_commesse`, `frm_ana_dipartimenti`: riferimenti per persona, progetto e mansione.


file_path: /var/www/html/dev/musa_app/_documentation/functions/qualifications_ansf.md
title: Qualifications ANSF
scanned_at: 2026-04-16 13:47:57
content:
# Qualifications ANSF

## 1. Descrizione funzionale

Gestione delle qualifiche ANSF con scadenze, alert e stato della richiesta per la persona.
Copre creazione, aggiornamento, consultazione e alimentazione delle code di scadenza dedicate.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaFormazioniRichiesteController.php`: `actionCreateAnsf()`, `actionUpdateAnsf()`, `actionAdminAnsf()`.
- `protected/models/MusaFormazioniRichieste.php`: ramo specifico ANSF con `alert_search`, stato qualifica e export.
- `protected/models/MusaAlertAnsf.php`: alert e scadenza ANSF.
- `protected/controllers/app/SiteAppController.php`: logiche di aggiornamento / mail per scadenze ANSF.

## 3. Sezione DB (tabelle/campi principali)

- `musa_formazioni_richieste`: `idformazionerichiesta`, `idanautente`, `idformazione`, `idformazionedett`, `idtipoformazione`, `idstatoformazione`, `datastart`, `dataend`, `codqualifica`.
- `musa_alert_ansf`: `idformazionerichiesta`, `duedate`, `alertid`, `alert`.
- `musa_formazioni`, `musa_formazioni_dett`: master formazione e dettaglio qualifica.
- `musa_formazioni_allegati`: allegati della richiesta / abilitazione.


file_path: /var/www/html/dev/musa_app/_documentation/functions/qualifications_controlli_nd.md
title: Qualifications Controlli ND
scanned_at: 2026-04-16 13:47:57
content:
# Qualifications Controlli ND

## 1. Descrizione funzionale

Gestione delle qualifiche e degli alert legati ai Controlli ND.
Il flusso copre la richiesta, il cambio stato, la gestione delle scadenze e l'estrazione operativa per i promemoria.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaFormazioniRichiesteController.php`: `actioncreateControlliND()`, `actionUpdateControlliND()`, `actionAdminControlliND()`.
- `protected/models/MusaAlertControllind.php` per le scadenze ND.
- `protected/controllers/app/SiteAppController.php`: routine di reminder e export per i Controlli ND.
- `protected/views/musaFormazioniRichieste/admin.php` e `_searchsp.php` per i filtri operativi.

## 3. Sezione DB (tabelle/campi principali)

- `musa_formazioni_richieste`: `idformazionerichiesta`, `idanautente`, `idformazionedett`, `datastart`, `dataend`, `idstatoformazione`.
- `musa_alert_controllind`: `idformazionerichiesta`, `duedate`, `alertid`, `alert`.
- `musa_formazioni_allegati`: allegati della pratica.
- `musa_formazioni`, `musa_formazioni_dett`: master e dettaglio della qualifica.


file_path: /var/www/html/dev/musa_app/_documentation/functions/qualifications_ehs.md
title: Qualifications EHS
scanned_at: 2026-04-16 13:47:57
content:
# Qualifications EHS

## 1. Descrizione funzionale

Gestione delle qualifiche EHS, incluse scadenze sanitarie, controlli e notifiche di rinnovo.
E il ramo piu legato alle visite e alle regole di alert automatico sui rinnovi.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaFormazioniRichiesteController.php`: `actionCreateEhs()`, `actionUpdateEhs()`, `actionAdminEhs()`.
- `protected/controllers/MusaFormazioniDettController.php`: `actionCreateEhs()`, `actionAdminEhs()` per il master delle qualifiche EHS.
- `protected/models/MusaAlertEhs.php` e `protected/models/MusaFormazioniRichieste.php` per la logica scadenze.
- `protected/controllers/app/SiteAppController.php`: mail programmate e export per scadenze EHS.

## 3. Sezione DB (tabelle/campi principali)

- `musa_formazioni_richieste`: `idformazionerichiesta`, `idanautente`, `idformazionedett`, `datastart`, `dataend`, `idstatoformazione`.
- `musa_alert_ehs`: `idformazionerichiesta`, `duedate`, `alertid`, `alert`.
- `musa_formazioni_visite`: collegamento tra qualifica EHS e tipologia visita.
- `musa_formazioni_visite_eta`: soglie di eta per le visite.
- `musa_formazioni_allegati`: documenti allegati alla qualifica o alla visita.


file_path: /var/www/html/dev/musa_app/_documentation/functions/qualifications_in_attesa.md
title: Qualifications In Attesa
scanned_at: 2026-04-16 13:47:57
content:
# Qualifications In Attesa

## 1. Descrizione funzionale

Coda delle richieste di formazione ancora da lavorare o da chiudere.
La vista e utile per intercettare le pratiche sospese prima che diventino scadenze o alert.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaFormazioniInattesaController.php`: `actionAdmin()`, `actionExport()`, `actionDelete()`.
- `protected/models/MusaFormazioniInattesa.php`: view di appoggio per richieste e alert.
- `protected/views/musaFormazioniInattesa/admin.php` e `_search.php`.
- `protected/controllers/MusaFormazioniRichiesteController.php` e `MusaFormazioniDettController.php` per l'origine delle richieste.

## 3. Sezione DB (tabelle/campi principali)

- `musa_formazioni_inattesa`: view derivata, non tabella transazionale.
- `musa_formazioni_richieste`: richiesta origine con `idformazionerichiesta`, `idanautente`, `idformazionedett`, `datarichiesta`, `idstatoformazione`.
- `musa_formazioni_allegati`: allegati della pratica.
- `musa_alert_*`: alert specializzati che alimentano la coda.


file_path: /var/www/html/dev/musa_app/_documentation/functions/qualifications_processi_speciali.md
title: Qualifications Processi Speciali
scanned_at: 2026-04-16 13:47:57
content:
# Qualifications Processi Speciali

## 1. Descrizione funzionale

Gestione delle qualifiche per processi speciali, con scadenze, allegati, filtri e controlli di aggiornamento.
E un flusso dedicato per abilitazioni tecniche che richiedono verifiche periodiche.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaFormazioniRichiesteController.php`: `actionCreateProcessiSpeciali()`, `actionUpdateProcessiSpeciali()`, `actionAdminProcessiSpeciali()`.
- `protected/controllers/MusaFormazioniDettController.php`: `actionCreateSpecialProcess()`, `actionAdminSpecialProcess()`.
- `protected/models/MusaAlertSp.php` per l'alert di scadenza.
- `protected/controllers/app/SiteAppController.php`: schedulazioni e export collegati alle qualifiche speciali.

## 3. Sezione DB (tabelle/campi principali)

- `musa_formazioni_richieste`: `idformazionerichiesta`, `idanautente`, `idformazionedett`, `datastart`, `dataend`, `idstatoformazione`.
- `musa_alert_sp`: `idformazionerichiesta`, `duedate`, `alertid`, `alert`.
- `musa_formazioni_dett`: definizione della qualifica e delle regole di validazione.
- `musa_formazioni_allegati`: allegati e documenti di supporto.


file_path: /var/www/html/dev/musa_app/_documentation/functions/qualifications_self_inspection.md
title: Qualifications Self Inspection
scanned_at: 2026-04-16 13:47:57
content:
# Qualifications Self Inspection

## 1. Descrizione funzionale

Gestione delle qualifiche Self Inspection con regole dedicate, allegati e scadenze.
Questo ramo e separato dagli altri processi perche segue logiche di formazione e rinnovo specifiche.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaFormazioniRichiesteController.php`: `actionCreateSelfInspection()`, `actionUpdateSelfInspection()`, `actionAdminSelfInspection()`.
- `protected/controllers/MusaFormazioniDettController.php`: `actionCreateSelfInspection()`, `actionAdminSelfInspection()`.
- `protected/models/MusaFormazioniDettSelf.php`: associazione tra qualifica self inspection, workstation e task.
- `protected/models/MusaAlertSi.php` per gli alert di scadenza.

## 3. Sezione DB (tabelle/campi principali)

- `musa_formazioni_dett_self`: `idformazionedett`, `idformazionedettself`, `iddipartimento_workstation`, `idtask`.
- `musa_formazioni_richieste`: `idformazionerichiesta`, `idanautente`, `idformazionedett`, `dataend`, `idstatoformazione`.
- `musa_alert_si`: `idformazionerichiesta`, `duedate`, `alertid`, `alert`.
- `musa_formazioni_allegati`: documenti di supporto alla qualifica.


file_path: /var/www/html/dev/musa_app/_documentation/functions/qualifications_tutte.md
title: Qualifications Tutte
scanned_at: 2026-04-16 13:47:57
content:
# Qualifications Tutte

## 1. Descrizione funzionale

Vista completa del registro qualifiche e richieste formazione.
Raccoglie il flusso generale, i filtri per stato, gli allegati, gli export e i casi speciali ANSF, EHS, processi speciali, controlli ND e self inspection.

## 2. Sezione tecnica (riferimenti codice)

- `protected/controllers/MusaFormazioniRichiesteController.php`: `actionAdmin()`, `actionExport()`, `actionUploadAllegati()`, `actionConfermaCaricamento()`, `actionAdminAllegati()`.
- `protected/views/musaFormazioniRichieste/admin.php`, `_form_qualifica.php`, `_formallegati.php`, `_searchsp.php`.
- `protected/models/MusaFormazioniRichieste.php`: filtri per alert, stato, formazione, qualifica, dipendente e allegati.
- `protected/controllers/MusaFormazioniDettController.php` per il master delle qualifiche e dei form speciali.

## 3. Sezione DB (tabelle/campi principali)

- `musa_formazioni_richieste`: anagrafica della qualifica sulla persona con `idanautente`, `idformazione`, `idformazionedett`, `datastart`, `dataend`, `idstatoformazione`.
- `musa_formazioni_richieste_stati`: storico stati della richiesta, usato per il dominio qualifica.
- `musa_formazioni`, `musa_formazioni_dett`: master e dettaglio delle qualifiche.
- `musa_formazioni_allegati`: allegati e documentazione della richiesta.
- `musa_sys_stati_formazione`, `musa_sys_stati_qualifica`: stati operativi e stati di qualifica.


file_path: /var/www/html/dev/musa_app/_documentation/linee_guida_funzionali_rilevate.md
title: Linee guida funzionali rilevate
scanned_at: 2026-04-16 13:47:57
content:
# Linee guida funzionali rilevate

## Scopo

Questa nota sintetizza i flussi utente e operativi osservati nel modulo corsi del repo `musa_app`.
L'obiettivo e aiutare il passaggio di consegne con una vista pratica: cosa fa l'utente, da quale schermata parte e quali regole incontra.

## Perimetro osservato

- formazione
- qualifiche
- corsi
- sessioni
- iscrizioni
- stati iscrizione

## 1. Formazione e qualifiche

### Formazione

- il corso appartiene a una sola formazione master (`musa_corsi.idformazione`);
- la formazione e il filtro principale per proporre le qualifiche collegabili;
- la descrizione della formazione compare in griglie, export e dettagli operativi.

### Qualifiche

- le qualifiche selezionabili per il corso sono prese da `musa_formazioni_dett`;
- la selezione e limitata alle qualifiche della stessa formazione del corso;
- la lista delle qualifiche collegate e visibile nella sezione abbinamenti della `update` del corso;
- la gestione non richiede l'inserimento manuale di ID: l'utente lavora su combo e multiselezione.

## 2. Corsi

### Anagrafica corso

- l'utente gestisce descrizione, codice, formazione, fornitore, date, durata, note e flag attivo/visibile;
- la data termine iscrizioni deve essere coerente con la data inizio corso;
- il fornitore puo essere compilato come testo libero oppure da anagrafica;
- almeno uno dei due campi fornitore deve essere valorizzato.

### Duplicazione

- dalla griglia corsi e disponibile la duplicazione;
- la copia non trascina i campi che richiedono completamento manuale;
- il flusso finale lascia all'operatore il completamento di codice e date.

### Consultazione

- la griglia admin mostra descrizioni leggibili e non solo ID tecnici;
- l'export Excel segue i filtri impostati nella griglia;
- il dettaglio corso riporta le qualifiche collegate.

## 3. Abbinamenti corso-qualifiche

### Accesso funzionale

- gli abbinamenti non sono esposti come menu indipendente nella UI generale;
- l'operativita passa dalla modifica del corso;
- la sezione abbinamenti vive sotto il form del corso come blocco dedicato.

### Flusso utente

1. l'utente apre il corso in modifica;
2. vede le qualifiche gia collegate;
3. seleziona le qualifiche da mantenere;
4. salva;
5. il sistema sostituisce integralmente il set precedente.

### Regole

- sono accettate solo qualifiche appartenenti alla stessa formazione;
- il salvataggio e di tipo sync esatto, non merge incrementale;
- la sezione funziona come riepilogo e come mantenimento selezione.

## 4. Sessioni

### Griglia sessioni

- la griglia mostra corso, formazione, fornitore, data sessione, ora inizio, ora fine ed attivo;
- i filtri osservati sono periodo, fornitore, corso e scadenza iscrizioni;
- il flusso e pensato per la consultazione operativa rapida prima del calendario.

### Calendario

- il calendario e una vista dedicata delle sessioni;
- l'utente puo filtrare per corso, fornitore e scadenza iscrizioni;
- la vista supporta mese e settimana;
- il click sull'evento apre il dettaglio sessione in modal.

### Dettaglio sessione

- nel modal l'utente vede gli iscritti alla sessione;
- per ogni iscritto puo cambiare stato con le transizioni ammesse;
- se non ci sono iscritti, il modal mostra un messaggio esplicito;
- il modal contiene anche il flusso di inserimento massivo dipendenti.

### Inserimento massivo

- l'operatore seleziona uno o piu dipendenti;
- sceglie lo stato iniziale dell'iscrizione;
- conferma l'inserimento;
- il sistema riporta esiti `ok`, `skip` e `ko`.

## 5. Iscrizioni

### Consultazione

- la griglia iscrizioni e il punto di lavoro principale per dipendente, stato, sessione, corso e scadenze;
- sono presenti filtri per dipendente, stato, sessione, corso, fornitore, scadenza iscrizioni, fascia scadenza qualifica e intervallo date;
- il dato di scadenza qualifica viene derivato dalla qualifica target collegata.

### Creazione e modifica

- l'iscrizione richiede sessione, dipendente e stato;
- in creazione lo stato di default parte da `PREVISTO`;
- la scelta della sessione e limitata a quelle operative;
- la form e guidata con combo e help testuali.

### Cambio stato massivo

- l'utente seleziona piu iscrizioni dalla griglia;
- sceglie uno stato target comune;
- l'azione aggiorna le righe una ad una con report finale;
- vengono mostrati gli esiti di successo, skip ed errore.

### Cambio stato singolo

- dal dettaglio sessione l'utente puo aggiornare ogni iscrizione con le sole transizioni consentite;
- il sistema rifiuta transizioni non ammesse dalla matrice di business;
- il badge colore dello stato e allineato allo stato sys.

## 6. Stati iscrizione

### Stati osservati

- `PREVISTO`
- `ISCRITTO`
- `CONFERMATO`
- `COMPLETATO`
- `ANNULLATO`
- `ASSENTE`

### Uso operativo

- `PREVISTO` e lo stato iniziale piu naturale per nuove iscrizioni;
- `ISCRITTO` e `CONFERMATO` rappresentano il ciclo operativo progressivo;
- `COMPLETATO`, `ANNULLATO` e `ASSENTE` chiudono il percorso con semantica finale;
- il colore del calendario e i badge in modal sono guidati dagli stati sys.

## 7. Flusso consigliato di lavoro

1. creare o aggiornare il corso;
2. agganciare le qualifiche compatibili;
3. aprire o generare le sessioni;
4. iscrivere i dipendenti;
5. aggiornare gli stati dal calendario o dalla griglia iscrizioni;
6. esportare quando serve il riepilogo operativo.

## 8. Nota di handover

Il modulo osservato e gia pensato come flusso a catena:

- corso come anagrafica;
- abbinamenti come relazione di dominio;
- sessione come occorrenza operativa;
- iscrizione come stato dipendente-per-sessione;
- sys stati come motore della lettura e delle transizioni.

Questa separazione aiuta a evitare sovrapposizioni tra planning, partecipazione e qualifica.


file_path: /var/www/html/dev/musa_app/_documentation/linee_guida_tecniche_rilevate.md
title: Linee guida tecniche rilevate
scanned_at: 2026-04-16 13:47:57
content:
# Linee guida tecniche rilevate

## Scopo

Questa nota raccoglie i pattern implementativi riusati nel modulo corsi del repo `musa_app`.
L'idea e documentare la forma del codice, cosi il passaggio di consegne e rapido quando si devono estendere le stesse logiche su altre entita.

## 1. ACL e sicurezza

- i controller principali del modulo usano `accessControl` e bloccano gli utenti non autorizzati;
- l'accesso e limitato al ruolo `amministratore_sistema` tramite `GetUtentiRuoliApplicazione(...)`;
- le azioni critiche sono protette con `postOnly`;
- le azioni a impatto operativo, come bulk e cambio stato, non sono lasciate a GET.

### Pattern osservato

- `MusaCorsiController`
- `MusaCorsiSessioniController`
- `MusaCorsiIscrizioniController`
- `MusaCorsiFormazioniDettController`

## 2. Render settings e griglie

### Struttura usata

- i controller definiscono i campi in `initfields($model, $rendertype)`;
- i campi vengono poi estratti con `getrendersettings(...)`;
- le viste restano sottili e si limitano a disegnare titolo, filtri, bottoni e griglia;
- la stessa struttura viene usata per admin, form, filtri e bottoni.

### Widget ricorrenti

- `booster.widgets.TbSelect2`
- `booster.widgets.TbDatePicker`
- `booster.widgets.TbActiveForm`
- `booster.widgets.TbButtonColumn`
- `widgets.FrmGridView`

### Convenzioni di UI

- `grid_view_buttons` per update/delete;
- `btn_create`, `btn_export`, `btn_goback` e bottoni speciali come `btn_calendar` o `btn_bulk_aggiorna_stato`;
- `appendHelpBlock(...)` per i suggerimenti field-level;
- classi CSS dedicate come `musa-corsi-ui.css` e `musa-corsi-form-shell`.

## 3. Date e formattazione

### Getter formattati

Il modulo usa getter dedicati al posto di formattazioni inline ripetute:

- `getDataInizioFormatted`
- `getDataTermineIscrizioniFormatted`
- `getdata_sessioneformatted`
- `getOraInizioFormatted`
- `getOraFineFormatted`
- `getFornitoreDisplay`
- `getEnabledDesc`
- `getVisibleDesc`
- `getSessioneDesc`
- `getCorsoDesc`

### Regola pratica

- i campi data vengono salvati in formato DB e mostrati in formato utente;
- la conversione avviene in model, non sparsa nella view;
- le stringhe di export riusano gli stessi getter delle griglie.

## 4. Export Excel

### Pattern comune

- azione `actionExport`;
- costruzione di un array `columns`;
- `setPagination(false)` sul data provider;
- `toExcel(..., "Excel5")`;
- titolo file con timestamp e suffisso preso dall'attribute label.

### Cosa cambia tra i moduli

- nel corso l'export include codice, descrizione, formazione, fornitore, date e flag;
- nelle sessioni esporta anche date/ore;
- nelle iscrizioni esporta dipendente, stato, sessione, corso e campi di scadenza.

## 5. Bulk JSON e flussi asincroni

### Pattern usato

- gli endpoint AJAX rispondono con JSON esplicito tramite `CJSON::encode`;
- gli errori vengono riportati con messaggi testuali e, quando serve, dettagli per riga;
- i flussi bulk non manipolano la pagina con logica nascosta: il client costruisce il form POST e invia la richiesta.

### Esempi concreti

- `actionCalendarFeed` genera il feed eventi;
- `actionQuickChangeStato` aggiorna una singola iscrizione;
- `actionBulkIscriviDipendenti` inserisce piu dipendenti su una sessione;
- `actionBulkAggiornaStato` cambia lo stato di piu iscrizioni;
- `actionSalvaAbbinamentiCorso` salva il set finale degli abbinamenti;
- `jsonResponse(...)` standardizza success, message e payload.

## 6. Convenzioni controller/model/view

### Controller

- `public $className` identifica il model principale;
- `init()` imposta il CSS del modulo e `rootviews`;
- `performAjaxValidation(...)` segue la convenzione Yii;
- `getrenderfilters`, `getrenderadminbtns`, `getrenderadmin`, `getrenderform`, `getrenderformbtn` ordinano la UI.

### Model

- `tableName()`, `rules()`, `relations()`, `attributeLabels()`;
- `initDefaultFields()` per i default di creazione;
- `initDefaultFilters()` per i default di ricerca;
- `search()`, `initcriteriaforsearch()`, `initsortforsearch()`;
- `getcombodata()` e `searchRawData()` come helper riusabile per le combo.

### View

- `admin.php` si occupa solo di renderizzare griglia e bottoni;
- `_form.php` disegna il form tramite `drawInitFields()` e `drawInitButtons()`;
- `update.php` puo aggiungere sezioni speciali di dominio, come gli abbinamenti;
- il dettaglio operativo complesso viene spostato in partial dedicati, come il modal sessione.

## 7. Pattern di business validati nel modello

### Corsi

- almeno uno tra fornitore testuale e fornitore da anagrafica deve essere presente;
- la data termine iscrizioni non puo essere successiva alla data inizio corso;
- la duplicazione resetta i campi che devono essere rivalorizzati.

### Sessioni

- `ora_fine` deve essere maggiore di `ora_inizio`;
- la sessione non deve collidere con un'altra sullo stesso corso, data e ora inizio;
- la form usa datepicker e input time nativi.

### Iscrizioni

- una coppia `sessione + dipendente` non puo essere duplicata;
- la sessione deve essere operativa;
- il corso deve essere attivo e visibile;
- le iscrizioni non possono nascere dopo la scadenza;
- le transizioni di stato sono governate da una matrice centralizzata.

### Abbinamenti

- corso e qualifica devono appartenere alla stessa formazione;
- la coppia `idcorso + idformazionedett` deve rimanere unica;
- il salvataggio massivo tratta il set selezionato come verita finale.

## 8. Pattern di integrazione dati

- le combo corsi, sessioni, stati e utenti sono costruite lato model, non inline nella view;
- i filtri dipendono spesso da relazioni `with(...)` e `together = true`;
- il calendario usa feed JSON da controller, mentre il modal usa partial server-side;
- il colore della UI deriva dalla tabella sys e non da costanti hardcoded.

## 9. Cose da riusare quando si estende il modulo

1. tenere il controller sottile e portare la logica nel model quando e un vincolo di dominio;
2. usare render settings per evitare duplicazione tra admin, form e filtri;
3. mantenere separati export, feed JSON e view HTML;
4. definire una tabella sys quando stati, colori e transizioni diventano un vero dominio;
5. preferire helper getter per descrizioni e formattazioni condivise.


file_path: /var/www/html/dev/musa_app/_documentation/tickets/ticket_10768_analisi_tecnica_corsi.md
title: Ticket 10768 - Analisi tecnica gestione Corsi
scanned_at: 2026-04-16 13:47:57
content:
# Ticket 10768 - Analisi tecnica gestione Corsi

## Metadati

- Ticket: `10768`
- Titolo ticket: `**CORSI** - Analisi iniziale`
- Data analisi: `2026-04-03`
- Data chiusura: `2026-04-10`
- Ambiente osservato: repository `musa_app` e database `dev` configurato dal progetto
- Focus richiesto: scelta delle tabelle piu adatte per la nuova entita `corsi`, incluse eventuali tabelle `sys`

## Obiettivo

Analizzare il ticket `10768` con focus specifico sulla modellazione dati della nuova entita `corsi`, verificando se sia conveniente riusare tabelle esistenti come:

- `frm_ana_dipartimenti`
- `frm_ana_commesse`
- tabelle collegate (`frm_ana_dipartimenti_utente`, `frm_ana_commesse_utente`, `frm_ana_commesse_dipartimenti`, ecc.)

oppure se sia preferibile introdurre nuove tabelle dedicate nel dominio `musa_*`.

## Fonti analizzate

### Ticket e documentazione

- Ticket Mantis `10768`
- `_documentation/docs/MUSA/gestione_qualifiche.md`
- `_documentation/docs/MUSA/gestione_collegamenti_commesse_dipartimenti_task.md`
- `_documentation/docs/help/Management.md`

### Codice applicativo

- `protected/models/MusaFormazioniRichieste.php`
- `protected/models/MusaFormazioniRichiesteStati.php`
- `protected/models/MusaFormazioniInattesa.php`
- `protected/controllers/app/SiteAppController.php`
- `protected/views/musaFormazioniDett/admin.php`

### Database

Sono state verificate in particolare le seguenti tabelle/view:

- `musa_formazioni`
- `musa_formazioni_dett`
- `musa_formazioni_richieste`
- `musa_formazioni_richieste_stati`
- `musa_formazioni_inattesa`
- `musa_sys_stati_formazione`
- `musa_sys_stati_qualifica`
- `frm_ana_dipartimenti`
- `frm_ana_dipartimenti_utente`
- `frm_sys_tipi_dipartimenti`
- `frm_ana_commesse`
- `frm_ana_commesse_utente`
- `frm_ana_commesse_dipartimenti`
- `frm_sys_tipo_commesse`
- `frm_ana_societa_utente`
- `sys_tipo_societa`

## Sintesi decisionale

### Raccomandazione

La nuova entita `corsi` non dovrebbe essere modellata riusando `frm_ana_dipartimenti` o `frm_ana_commesse`.

La soluzione piu coerente e manutenibile e:

1. riusare `musa_formazioni` e `musa_formazioni_dett` solo come dominio di riferimento per qualifiche/formazioni collegabili al corso;
2. introdurre nuove tabelle dedicate nel dominio `musa_*` per persistere corsi, sessioni e iscrizioni;
3. introdurre una tabella `sys` dedicata per lo stato dell'iscrizione al corso.

### Assetto adottato come base

- `musa_corsi`
- `musa_corsi_formazioni_dett`
- `musa_corsi_sessioni`
- `musa_corsi_iscrizioni`
- `musa_corsi_sys_stati_iscrizione`

## Stato avanzamento

Alla data di aggiornamento di questo documento risultano gia smarcati i seguenti punti:

- analisi tecnica iniziale prodotta in questo documento;
- scelta architetturale confermata su tabelle dedicate `musa_corsi...`, senza riuso di `dipartimenti` o `commesse` come master;
- script applicativi gia inseriti per la creazione delle tabelle `musa_corsi`, `musa_corsi_formazioni_dett`, `musa_corsi_sessioni`, `musa_corsi_iscrizioni` e `musa_corsi_sys_stati_iscrizione`;
- modelli applicativi base gia creati per le nuove entita `musa_corsi...`;
- controller base gia creati per la gestione CRUD delle nuove entita applicative `musa_corsi...`;
- viste base gia create per la gestione CRUD delle nuove entita applicative `musa_corsi...`.

L'analisi che segue resta valida come motivazione tecnica delle scelte effettuate, ma va letta come dossier di stato avanzamento e non piu come sola proposta teorica.

### Perche non riusare dipartimenti/commesse

- `dipartimenti` modella tassonomie e strutture organizzative, non eventi pianificati con partecipanti e stati operativi;
- `commesse` modella progetti, non erogazioni formative;
- entrambe richiederebbero comunque tabelle aggiuntive per qualifiche collegate, dipendenti iscritti e stato iscrizione;
- il riuso introdurrebbe ambiguita semantica e coupling con logiche esistenti non legate alla formazione.

## Requisiti osservati dal ticket

Dal ticket `10768` risultano questi requisiti funzionali.

### Anagrafica corso

- descrizione
- fornitore
- data inizio
- data termine iscrizioni
- durata
- riferimento a `N` qualifiche/formazioni della stessa formazione
- duplicazione corso

### Calendario corsi

- vista settimana/mese
- filtri per periodo, scadenza iscrizione, corso, fornitore, dipendente
- inserimento di uno o piu dipendenti su un corso/data
- raggruppamento dipendenti per scadenza qualifica
- stato da `sys` con valori iniziali:
  - `PREVISTO`
  - `ISCRITTO`
  - `CONFERMATO`
- colore della visualizzazione guidato dallo stato
- cambio stato rapido da calendario

### Implementazioni secondarie

- export Excel
- email schedulata di promemoria
- riepilogo corsi nel dettaglio qualifica/persona

## Evidenze osservate

### Dominio qualifiche/formazioni

- `musa_formazioni` contiene il master delle famiglie di formazione.
- `musa_formazioni_dett` contiene il dettaglio delle qualifiche/corsi associati alla famiglia.
- Nel codice applicativo `musa_formazioni_dett` viene gia chiamata in piu punti "corso".
- In `protected/views/musaFormazioniDett/admin.php` il campo `idtipologiaformazione` viene mostrato come:
  - `Corso di Formazione`
  - `Corso di Aggiornamento`
- In `protected/controllers/app/SiteAppController.php` esistono commenti e logiche che parlano di:
  - `corsi base`
  - `corso di aggiornamento`

### Implicazione

Nel dominio MUSA attuale la parola `corso` e gia usata come sinonimo di dettaglio formazione/qualifica (`musa_formazioni_dett`), non come sessione pianificata con partecipanti.

Questo e un punto importante: la nuova entita del ticket non coincide con `musa_formazioni_dett`, ma la usa come riferimento.

### Stato attuale delle qualifiche persona

- `musa_formazioni_richieste` contiene `6703` record.
- Tutti i record osservati hanno `idtipoformazione = 2` (`Qualifica`).
- Distribuzione `idstatoformazione` osservata:
  - `NULL`: `6674`
  - `1`: `29`
- `musa_formazioni_richieste` contiene molti campi specifici di qualifica:
  - `datastart`
  - `dataend`
  - `idistruttore`
  - `codqualifica`
  - `idcodiceabilitazione`
  - `idcodicelivello`
  - campi commissione/verifica
  - campi tecnici di qualifica

### Implicazione

`musa_formazioni_richieste` rappresenta l'istanza di qualifica/formazione sulla persona, non una iscrizione pianificata a un corso futuro.

Creare qui dentro la pianificazione corsi significherebbe mescolare:

- dato di planning
- dato di partecipazione
- dato di consuntivazione qualifica

in uno stesso contenitore gia fortemente specializzato.

### Storico stati qualifica

- `musa_formazioni_richieste_stati` ha `0` record nel database osservato.
- Il model `MusaFormazioniRichiesteStati` non gestisce stati di iscrizione al corso, ma stati di qualifica:
  - `Formazione`
  - `Tirocinio`
  - `Abilitato`
  - `Sospeso`
  - `Cancellato`
- `musa_sys_stati_qualifica` contiene solo questi stati.

### Implicazione

Questo pattern non e coerente con i nuovi stati richiesti dal ticket:

- `PREVISTO`
- `ISCRITTO`
- `CONFERMATO`

che sono stati di partecipazione/iscrizione, non stati di qualifica.

### Stati formazione

- `musa_sys_stati_formazione` contiene:
  - `Aperta`
  - `Chiusa`
  - `Regolare`
  - `In Scadenza`
  - `Scaduta`
  - `Aggiornata`
  - `Disabilitata`
- Nel database osservato questi stati sono poco usati su `musa_formazioni_richieste`.

### Implicazione

`musa_sys_stati_formazione` descrive lo stato della qualifica/formazione sulla persona, non lo stato dell'iscrizione a un corso.

Non e consigliabile riusare questa tabella per il calendario corsi.

### Coda "In attesa"

- `musa_formazioni_inattesa` e una `VIEW`, non una tabella transazionale.
- La documentazione utente (`_documentation/docs/help/Management.md`) la descrive come pagina che mostra le richieste di formazione.

### Implicazione

Non e una candidata adatta per salvare:

- corsi
- date di calendario
- iscrizioni
- stato di iscrizione

Puo al massimo restare una vista derivata o futura fonte di filtro, ma non la struttura principale.

### Dipartimenti

- `frm_ana_dipartimenti` ha schema tipico da anagrafica gerarchica:
  - `iddipartimento`
  - `codicedipartimento`
  - `descrdipartimento`
  - `idtipodipartimento`
  - `idparent`
  - `idroot`
  - `active`
- `frm_ana_dipartimenti_utente` lega utenti a dipartimenti con:
  - `idanautente`
  - `iddipartimento`
  - `idtipodipartimento`
  - `active`
  - `stamp_dipartimento_start`
- Nel database osservato `frm_ana_dipartimenti` contiene `352` righe, concentrate sui tipi:
  - `Area`
  - `Mansione`
- `frm_sys_tipi_dipartimenti` contiene tipi semantici come:
  - `Area`
  - `Team`
  - `Workshop`
  - `EPU`
  - `Workstation`
  - `Mansione`
  - `Contesto_Operativo`
  - `Codice_Abilitazione`
  - `Esito_Verifica`

### Implicazione

Il pattern `dipartimenti` e adatto a:

- tassonomie
- strutture organizzative
- classificazioni riusabili
- collegamenti statici utente-struttura

ma non e adatto, da solo, a modellare:

- calendario
- data corso
- termine iscrizioni
- stato di iscrizione per persona
- multi-qualifica sul corso

### Commesse

- `frm_ana_commesse` ha schema da anagrafica progetto:
  - `idcommessa`
  - `idlivello`
  - `idtipocommessa`
  - `idparent`
  - `datainizio`
  - `datafine`
  - `desccommessa`
- `frm_ana_commesse_dipartimenti` collega commesse e dipartimenti.
- `frm_ana_commesse_utente` collega commesse e utenti con un campo `ruolo`.
- Nel database osservato:
  - `frm_ana_commesse`: `0` righe
  - `frm_ana_commesse_dipartimenti`: `0` righe
  - `frm_ana_commesse_utente`: `0` righe
- La documentazione esistente descrive `commesse` come progetti/MUSA wizard, EPU, workstation, task.

### Implicazione

Il pattern `commesse` resta semanticamente orientato a progetto/produzione.

Ha in comune con il ticket solo alcuni campi generici (`descrizione`, `date`), ma non copre bene:

- relazione con qualifiche della stessa formazione
- stato di iscrizione per persona
- calendario per persona
- logica di scadenza qualifica

### Anagrafica fornitori

- `frm_ana_societa_utente` esiste ed e una anagrafica trasversale di aziende/societa.
- `sys_tipo_societa` contiene tipi come:
  - `FORNITORE`
  - `CLIENTE`
  - `PLANT`
  - altri
- Nel tenant osservato `frm_ana_societa_utente` contiene `89` righe, di cui `87` di tipo `PLANT`.

### Implicazione

Per il campo `fornitore`:

- in fase 1 conviene non bloccare il progetto su una anagrafica dedicata;
- in fase 2 si puo valutare il riuso di `frm_ana_societa_utente`, ma oggi i dati osservati non mostrano ancora una anagrafica fornitori "corsi" pronta all'uso.

## Matrice di valutazione delle tabelle candidate

| Candidato | Vantaggi | Criticita | Esito |
| --- | --- | --- | --- |
| `frm_ana_dipartimenti` | gia presente, gerarchica, con tabella `sys` tipi | semantica organizzativa, nessuna gestione naturale di iscrizione/stato/calendario, richiederebbe molte estensioni | non consigliata come tabella master corsi |
| `frm_ana_commesse` | gia presente, ha descrizione e date, link a utenti/dipartimenti | semantica progetto, nessun legame naturale a qualifiche, nessuno stato iscrizione, zero dati osservati nel DB dev | non consigliata come tabella master corsi |
| `musa_formazioni_richieste` | gia nel dominio formazione/persona | rappresenta la qualifica sulla persona, non il planning del corso; campi troppo specifici; stati attuali non coerenti | non consigliata come contenitore dei corsi |
| `musa_formazioni_inattesa` | gia usata per richieste di formazione | e una `VIEW`, non una base transazionale | da non usare per persistenza |
| `musa_formazioni_dett` | e il riferimento giusto per le qualifiche collegabili al corso | non rappresenta un evento pianificato ma il dettaglio della qualifica/formazione | da riusare solo come riferimento |
| `frm_ana_societa_utente` | possibile anagrafica fornitori futura | nel tenant osservato non ci sono ancora dati coerenti per fornitori corsi | opzionale, per fase 2 |

## Inferenza principale

La nuova entita `corsi` e un oggetto di business nuovo e trasversale, con queste caratteristiche:

- ha una propria anagrafica;
- si collega a piu `musa_formazioni_dett`;
- viene pianificata a calendario;
- ha partecipanti;
- ha stati di iscrizione propri;
- puo in futuro produrre o aggiornare record in `musa_formazioni_richieste`, ma non coincide con essi.

Per questo la soluzione piu pulita, e gia adottata come base tecnica, e introdurre nuove tabelle dedicate con radice `musa_corsi_*`.

## Modello dati adottato come base

### Struttura di riferimento

### 1. `musa_corsi`

Tabella master del corso/anagrafica.

Campi consigliati:

- `idcorso` PK
- `idsocieta`
- `idstabilimento`
- `codcorso` opzionale
- `descrizione`
- `idformazione`
- `fornitore_descrizione`
- `idsocietautente_fornitore` nullable
- `data_inizio`
- `data_termine_iscrizioni`
- `durata_testo`
- `note`
- `enabled` / `visible`
- campi `stamp_*`

### Motivazione

- il ticket richiede un'anagrafica autonoma;
- il corso e riferito a una sola famiglia `musa_formazioni`, ma puo collegare piu record di `musa_formazioni_dett`;
- consente duplicazione semplice del master.

### 2. `musa_corsi_formazioni_dett`

Bridge molti-a-molti tra corso e qualifiche/dettagli formazione.

Campi consigliati:

- `idcorsoformazionedett` PK
- `idcorso`
- `idformazionedett`
- campi `stamp_*`

Vincoli consigliati:

- unique su (`idcorso`, `idformazionedett`)
- validazione applicativa: tutti gli `idformazionedett` associati devono avere lo stesso `idformazione` del master corso

### Motivazione

Il ticket richiede esplicitamente il collegamento a `N` qualifiche/formazioni della stessa formazione.

La tabella migliore da riusare come riferimento e `musa_formazioni_dett`.

### 3. `musa_corsi_sessioni`

Tabella delle occorrenze a calendario del corso.

Campi consigliati:

- `idcorsosessione` PK
- `idcorso`
- `data_sessione`
- `ora_inizio` nullable
- `ora_fine` nullable
- `note`
- campi `stamp_*`

### Motivazione

Questa tabella e consigliata perche il ticket contiene due segnali distinti:

- nell'anagrafica del corso e presente `data inizio`;
- nel popup del calendario e presente di nuovo il campo `Data`.

Questo lascia aperta la possibilita che uno stesso corso possa essere pianificato su piu date/sessioni.

Con una tabella `sessioni` si evita di forzare tutto su un solo record master.

### 4. `musa_corsi_iscrizioni`

Tabella che lega dipendente, sessione e stato di iscrizione.

Campi consigliati:

- `idcorsoiscrizione` PK
- `idcorsosessione`
- `idanautente`
- `idstatoiscrizione`
- `idformazionerichiesta_target` nullable
- `note`
- campi `stamp_*`

Vincoli consigliati:

- unique su (`idcorsosessione`, `idanautente`)
- indici su:
  - `idanautente`
  - `idstatoiscrizione`
  - `idcorsosessione`

### Motivazione

Gli stati richiesti dal ticket sono chiaramente stati della partecipazione del dipendente al corso, non stati del corso master.

L'eventuale collegamento a `musa_formazioni_richieste` deve restare opzionale e differito, da valorizzare solo quando la partecipazione produce davvero una qualifica o un aggiornamento.

### 5. `musa_corsi_sys_stati_iscrizione`

Tabella `sys` dedicata agli stati della iscrizione.

Campi consigliati:

- `idstatoiscrizione` PK
- `codice`
- `descrizione`
- `label`
- `htmlColor`
- `ordinamento`
- `default_flag`

Seed iniziale consigliato:

- `PREVISTO`
- `ISCRITTO`
- `CONFERMATO`

Nella struttura base gia predisposta e stato scelto di estendere da subito il seed anche con:

- `ANNULLATO`
- `ASSENTE`
- `COMPLETATO`

### Motivazione

Non conviene riusare:

- `musa_sys_stati_formazione`
- `musa_sys_stati_qualifica`

perche descrivono semantiche diverse.

La nuova tabella `sys` deve governare:

- colore in calendario
- combo di selezione
- cambio rapido stato
- possibili estensioni future (`ANNULLATO`, `ASSENTE`, `COMPLETATO`)

## Variante minima

Se in una fase successiva viene chiarito che:

- un corso coincide sempre con una sola data;
- il campo `Data` nel popup e solo la data gia presente sul master;

allora si potra valutare una semplificazione del modello rimuovendo `musa_corsi_sessioni` e portando la data direttamente su `musa_corsi` oppure su `musa_corsi_iscrizioni`.

Ad oggi, con il testo del ticket disponibile e con la struttura base gia creata, la variante con `sessioni` resta la scelta di riferimento.

## Cosa riusare davvero dall'esistente

### Da riusare

- `musa_formazioni` come famiglia di formazione del corso
- `musa_formazioni_dett` come elenco qualifiche collegabili al corso
- `frm_ana_utenti` come anagrafica dipendenti
- opzionalmente `frm_ana_societa_utente` come futura anagrafica fornitore

### Da non riusare come tabella principale corsi

- `frm_ana_dipartimenti`
- `frm_ana_dipartimenti_utente`
- `frm_ana_commesse`
- `frm_ana_commesse_utente`
- `frm_ana_commesse_dipartimenti`
- `musa_formazioni_richieste`
- `musa_formazioni_inattesa`

## Gestione del fornitore

### Raccomandazione pratica

### Fase 1

Gestire il fornitore nel master corso con:

- `fornitore_descrizione` obbligatorio o facoltativo secondo UI
- `idsocietautente_fornitore` nullable

### Fase 2

Valutare una combo basata su `frm_ana_societa_utente`, introducendo se necessario:

- un filtro per tipo societa dedicato
- oppure un nuovo valore in `sys_tipo_societa` del tipo `FORNITORE_CORSI`

### Motivo

Il ticket stesso indica che la gestione strutturata del fornitore puo essere una miglioria successiva.

Questa scelta evita di bloccare il progetto su una anagrafica che, nel tenant osservato, oggi non appare ancora pronta per questo scopo.

## Impatto sui flussi esistenti

### Flussi che non vanno alterati

- `musa_formazioni_richieste` deve continuare a rappresentare la qualifica/formazione sulla persona
- `musa_formazioni_inattesa` puo restare una vista o un filtro operativo
- `musa_sys_stati_formazione` e `musa_sys_stati_qualifica` non devono essere reinterpretate

## Collegamento futuro tra corsi e qualifiche

Il collegamento tra partecipazione al corso e creazione/aggiornamento della qualifica va tenuto esplicito ma opzionale:

- iscrizione al corso != qualifica conseguita
- conferma presenza/esito corso puo generare o aggiornare una `musa_formazioni_richieste`
- il legame puo essere salvato su `musa_corsi_iscrizioni.idformazionerichiesta_target`

## Punti aperti

### Punto aperto 1 - cardinalita corso/data

Il ticket non chiarisce in modo definitivo se:

- un corso ha sempre una sola data;
- oppure un corso puo avere piu sessioni a calendario.

### Raccomandazione

Procedere con `musa_corsi_sessioni` salvo esplicita conferma contraria.

### Punto aperto 2 - stati post-corso

Il ticket cita solo:

- `PREVISTO`
- `ISCRITTO`
- `CONFERMATO`

Non e chiaro se in seguito servano anche stati come:

- `ANNULLATO`
- `ASSENTE`
- `COMPLETATO`

### Stato attuale / raccomandazione

La tabella `musa_corsi_sys_stati_iscrizione` e gia stata predisposta con seed esteso, mantenendo i tre stati richiesti dal ticket come nucleo iniziale e aggiungendo stati utili per le fasi successive.

### Punto aperto 3 - momento di creazione della qualifica

Non e definito se la qualifica su `musa_formazioni_richieste` debba essere:

- creata al momento della iscrizione;
- creata alla conferma;
- creata solo dopo esito positivo del corso.

### Raccomandazione

Non creare automaticamente la qualifica in fase di semplice iscrizione.

## Rischi se si sceglie il riuso improprio

### Se si usa `frm_ana_dipartimenti`

- si mescolano strutture organizzative ed eventi formativi;
- si rischia di impattare filtri, combo e join esistenti;
- servirebbero comunque tabelle aggiuntive per iscrizioni e qualifiche.

### Se si usa `frm_ana_commesse`

- si mescolano progetti e formazione;
- si introduce semantica errata per gli utenti applicativi;
- si dovrebbero aggiungere comunque relazioni extra per qualifiche e stati iscrizione.

### Se si usa `musa_formazioni_richieste`

- si anticipa troppo presto la creazione della qualifica;
- si sporca il registro qualifiche con dati solo pianificati;
- si complica la gestione di scadenze, alert, allegati e storico.

## Conclusione

La scelta tecnica corretta e stata quella di creare una nuova area dati dedicata ai corsi nel dominio `musa_corsi_*`, mantenendo separati:

- il planning corsi;
- le iscrizioni e gli stati di partecipazione;
- il dominio qualifiche esistente su `musa_formazioni` e `musa_formazioni_richieste`.

### Decisione confermata

- non usare `dipartimenti` come master corsi
- non usare `commesse` come master corsi
- non usare `musa_formazioni_richieste` come calendario/iscrizione
- usare `musa_formazioni` e `musa_formazioni_dett` solo come riferimento alle qualifiche
- introdurre e mantenere come base:
  - `musa_corsi`
  - `musa_corsi_formazioni_dett`
  - `musa_corsi_sessioni`
  - `musa_corsi_iscrizioni`
  - `musa_corsi_sys_stati_iscrizione`

Questa soluzione, gia tradotta in schema DB e base CRUD applicativa, e quella con il miglior equilibrio tra:

- coerenza semantica
- riuso dell'esistente dove sensato
- isolamento della nuova funzionalita
- possibilita di estensione futura

## Stato finale implementato

Alla chiusura dello stop attuale, nel repo risultano effettivamente implementati questi blocchi:

### Anagrafica corsi

- modello `MusaCorsi` con validazioni dedicate su fornitore e range date;
- griglia admin con colonne descrittive, filtri e azioni standard;
- form guidato con `Select2`, datepicker e help testuali;
- export Excel dell'anagrafica con filtri attivi;
- duplicazione corso con copia controllata dei campi e reset dei campi da completare manualmente.

### Abbinamenti corso-qualifiche

- sezione dedicata integrata nella `update` del corso;
- selezione multipla delle qualifiche ammesse;
- filtro server-side sulle sole qualifiche della stessa formazione del corso;
- salvataggio in modalita sync: quello che viene inviato diventa lo stato finale degli abbinamenti;
- validazione antiduplo e controllo di coerenza formazione lato model;
- mantenimento della logica fuori dal menu principale, senza una voce separata esposta all'utente finale.

### Sessioni

- modello `MusaCorsiSessioni` con controlli su orario e collisioni;
- griglia admin con filtri su corso, fornitore, periodo, scadenza iscrizioni ed attivo/non attivo;
- vista calendario con FullCalendar, filtri dinamici e dettaglio sessione in modal;
- feed JSON eventi con colore derivato dallo stato delle iscrizioni;
- cambio stato rapido su iscrizione;
- inserimento massivo di dipendenti su sessione;
- export Excel delle sessioni.

### Iscrizioni

- modello `MusaCorsiIscrizioni` con default stato e controlli di unicita;
- griglia admin con filtro per dipendente, stato, sessione, corso, fornitore, scadenza e fascia qualifica;
- cambio stato massivo su selezione multipla;
- export Excel delle iscrizioni;
- collegamento opzionale a `musa_formazioni_richieste` per la qualifica target, senza generazione automatica alla sola iscrizione;
- gestione dei messaggi di errore business per sessioni non operative, corsi disattivi o scadenze non valide.

### Stati

- tabella sys dedicata `musa_corsi_sys_stati_iscrizione`;
- stati effettivamente previsti dal codice: `PREVISTO`, `ISCRITTO`, `CONFERMATO`, `COMPLETATO`, `ANNULLATO`, `ASSENTE`;
- matrice transizioni centralizzata nel model iscrizioni;
- colore evento e badge stato guidati dalla configurazione sys.

## Decisioni finali

- decoupling 1:1 corso-qualifica: il corso resta master autonomo e non viene fuso con la qualifica; la relazione con le qualifiche e gestita in sezione dedicata e con vincolo di stessa formazione;
- menu abbinamenti nascosto lato UI: non esiste una voce di menu dedicata esposta nella navigazione generale; l'operativita sugli abbinamenti passa dalla `update` del corso;
- roadmap successiva fuori scope: eventuali evoluzioni ulteriori, integrazioni o raffinamenti non ancora implementati non fanno parte di questo documento di chiusura.

## Nota di chiusura

Questo documento fotografa lo stato reale del codice al momento dello stop attuale. Le sezioni di analisi iniziale restano valide come motivazione architetturale, ma le attivita ancora non presenti nel repo non devono essere lette come lavoro gia completato.


