# FTWEB — note tecniche sull'API (WS APL v7.0, 17/09/2024)

Sintesi operativa del documento "FTWEB_WS_SpecificheTecnichediIntegrazione_v7.0.pdf" (5.796 pagine) e dei sette
Excel che vi sono incorporati (copiati in `docs/formatemp/allegati/`). Contiene solo ciò che serve a EasyForma:
autenticazione, formato delle risposte, modello dati di progetto/calendario/registro e gli endpoint utili.
Le sezioni su rendicontazione, preventivi, PFA, verifiche ex-ante e variazioni sono fuori perimetro.

## 1. Ambienti e autenticazione

| Ambiente   | Base URL                        |
| ---------- | ------------------------------- |
| Collaudo   | `http://ftweb-col.formatemp.it` |
| Produzione | `https://ftweb.formatemp.it`    |

Tutti i servizi stanno sotto `/services/rs/...` tranne quello di autenticazione.

Flusso di autenticazione (sessione HTTP, durata 45 minuti):

1. `GET /services/autenticationcsrftoken` con header `SM_USER`, `SM_PASSWORD`, `Content-Type: application/json`.
   Negli esempi più recenti compare anche `SM_SDOMAIN` (es. `.rete.forma`) con `SM_USER` nella forma `RETE\\nome.cognome`.
2. Il body della risposta è il token CSRF (stringa). Dall'header `Set-Cookie` si prende `JSESSIONID`.
3. Ogni chiamata successiva porta: `X-XSRF-TOKEN: <token>`, `Cookie: JSESSIONID=<id>`, `SM_USER`, `SM_PASSWORD`,
   `Content-Type: application/json`.

Le utenze sono per APL/ente: EasyForma deve operare con le credenziali del cliente (già cifrate su `companies`).

## 2. Formato delle risposte

Tutte le risposte hanno lo stesso involucro; il payload vero è in una chiave che dipende dal servizio
(`progetto`, `registro`, `fasce`, `anagrafiche`, `anagrafica`, `idAnagrafica`...).

```json
{
    "httpCode": 200,
    "returnCode": "OK",
    "returnObjects": null,
    "okMessages": ["Operazione avvenuta con successo."],
    "koMessages": [],
    "exceptionMessage": null,
    "operationTimeMs": 131,
    "registro": {}
}
```

Convenzioni: date come epoch in millisecondi (`"data": 1559606400000`), orari come `"HH:mm"` (a volte `"HH:mm:ss"`),
durate come `"HH:mm"`. Le tipologiche sono oggetti `{id, label, descrizione, rimosso}`; i luoghi sono annidati
(comune → provincia → regione → nazione) e vanno passati completi.

Identificativi con prefisso, tutti stringhe:

| Prefisso                     | Entità                                                         |
| ---------------------------- | -------------------------------------------------------------- |
| `AnaApl_`                    | anagrafica dell'APL/ente                                       |
| `ProBas_`, `ProQuaAff_`, ... | progetto (il prefisso dipende dalla tipologia)                 |
| `AnaDis_`                    | anagrafica discente (a livello di APL, riusabile tra progetti) |
| `ParPro_`                    | partecipante di un progetto                                    |
| `GioCal_`                    | giornata di calendario                                         |
| `FasOraGioCal_`              | fascia oraria di una giornata                                  |
| `RegPreFas_`                 | registro presenze di una fascia                                |
| `AssPreFasPar_`              | riga di presenza di un partecipante in una fascia              |
| `PerCoi_`                    | personale coinvolto nella fascia (docente/codocente)           |
| `AnaRefRilPre_`              | referente rilevazione presenze                                 |
| `AnaSedForApl_`              | sede di formazione                                             |

`path progetto` negli URL vale: `base`, `professionale`, `onthejob`, `quaprof`, `riqprof`, `quaprofaff`, `profti`.
`idTipoProgetto` è l'id numerico di `tipologiaFormativa` (es. 1 = BASE, 6 = QUALIFICAZIONE_PROFESSIONALE_AFFIANCAMENTO;
negli esempi dell'app presenze compare `"idTipologiaProgetto": "2"` per un progetto `PRO`).
Stati progetto visti: `IN_BOZZA`, `PRESENTATO_IN_VERIFICA`, `PRESENTATO`, `IN_RENDICONTAZIONE`, `RENDICONTATO`
(più `AVVIATO`/`CHIUSO` citati nel testo).

## 3. Modello dati rilevante

```
progetto {codiceProgetto, tipologiaFormativa, dataInizio/FineProgetto, numeroAllieviProgetto,
  sezionePartecipanti.partecipanti[] → ParPro_ {partecipante: AnaDis_ {...anagrafica completa...}, tipoDestinatario, flagRitirato, ...}
  sezioneModuli.moduli*[] {modalitaErogazione {1 AULA | 2 FAD}, durataOre, oreTeoria, orePratica,
                           piattaformaFAD, utenzaPiattaformaFAD, passwordPiattaformaFAD,
                           oraInizioAccessoFAD, oraFineAccessoFAD, durataOreMinimaFAD, registroFAD, fasceOrarieGiornata[]}
  sezioneGiornate.giornateCalendario[] → GioCal_ {titolo, flagFAD, data, durataOre,
      registroGiornataCalendario {statoRegistro: REGISTRO_DA_INVIARE | REGISTRO_INVIATO, dataInvioRegistro, note},
      referentiRegistroGiornata[] (AnaRefRegGio_),
      fasceOrarie[] → FasOraGioCal_ {titolo, oraInizio, oraFine, flagCongiunto, sedeFormazione,
          durataPausaOre, oraInizioPausa, oraFinePausa, durataOreFascia,
          registroPresenze → RegPreFas_ {
              personaleCoinvolto[] → PerCoi_ {nome, cognome, tipoIncarico {1 DOCENTE | 2 CODOCENTE}, firma},
              presenze[] → AssPreFasPar_ {partecipante: ParPro_, orePresenza "HH:mm",
                  oraFirmaInizioLezione, oraFirmaFineLezione, oraFirmaInizioPausa, oraFirmaFinePausa,
                  firmaIngressoLezione, firmaUscitaLezione  (PNG base64 "data:image/png;base64,...")},
              flagRilevazioneApp, flagRegistroConsolidato, filePresenze}}}
}
```

Osservazioni:

- Il registro presenze è per fascia oraria, non per giornata: una lezione EasyForma corrisponde a una fascia.
- `flagFAD` è previsto sulla giornata, `modalitaErogazione = FAD` sul modulo; in tutti gli esempi del documento
  sono `false`/`AULA` e `registroFAD` è sempre `null`. La struttura del registro FAD non è documentata: si assume
  che per la FAD sincrona valga lo stesso registro per fascia (da confermare con Forma.Temp, vedi domande aperte).
- Le piattaforme FAD sono un'anagrafica dell'APL (servizio 2.33) con documenti allegati (relazione tecnica, domanda
  di accesso firmata digitalmente) e `ambitiDocenza`: l'iscrizione della piattaforma è un passaggio amministrativo,
  non solo tecnico.

## 4. Endpoint utili a EasyForma

### 4.1 Rilevazione presenze (servizi dell'app mobile, cap. 6) — il percorso più corto

Sono i servizi che usa il "referente rilevazione presenze" della giornata. Lavorano per `idFascia` +
`codiceProgetto` + `idTipoProgetto`, senza dover gestire l'oggetto progetto.

| #   | Metodo | Endpoint                                                                                        | Note                                                                                                                                                                                                                   |
| --- | ------ | ----------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 6.1 | GET    | `/services/rs/fasce`                                                                            | fasce assegnate all'utente: `{fasce:[{idFascia, codiceProgetto, idTipologiaProgetto, nomeProgetto, dataFascia "YYYY-MM-DD", orarioInizio, orarioFine, sedeSvolgimento, statoFascia, idReferenteRilevazionePresenze}]}` |
| 6.2 | PUT    | `/services/rs/visitare/aggiornastato/fascia/{idFascia}/{codiceProgetto}/{idTipoProgetto}`       | attiva/disattiva la fascia (body N/A)                                                                                                                                                                                  |
| 6.3 | GET    | `/services/rs/visitare/registropresenze/{idFascia}/{codiceProgetto}/{idTipoProgetto}`           | `{registro: RegPreFas_ {...}}` con l'elenco `presenze[]` già popolato con tutti i partecipanti del progetto                                                                                                            |
| 6.4 | POST   | `/services/rs/visitare/registropresenze/{idRegistro}/personalecoinvolto`                        | body `{personaleCoinvolto: {nome, cognome, tipoIncarico, firma}}`                                                                                                                                                      |
| 6.5 | PUT    | `/services/rs/visitare/registropresenze/{idRegistro}/partecipante/firma`                        | body `{assPresenzeFasciaPartecipanti: AssPreFasPar_ {...partecipante..., orePresenza, oraFirmaInizioLezione, oraFirmaFineLezione, firmaIngressoLezione, firmaUscitaLezione}}` (una chiamata per partecipante)          |
| 6.6 | PUT    | `/services/rs/visitare/consolida/registropresenze/{idFascia}/{codiceProgetto}/{idTipoProgetto}` | consolida la fascia; irreversibile                                                                                                                                                                                     |

### 4.2 Servizi progetto (cap. 3)

| #         | Metodo          | Endpoint                                                                               | Note                                                                                                                                                                                                    |
| --------- | --------------- | -------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 3.9       | GET             | `/services/rs/gestione/progetto/{path}/id/{idProgetto}`                                | intero oggetto progetto (partecipanti, moduli, giornate)                                                                                                                                                |
| 3.35      | POST            | `/services/rs/gestione/progetto/{path}/sezione/partecipante/{idProgetto}`              | body `{partecipanteProgetto: {partecipante: AnaDis_ {...}, tipoDestinatario, ...}}`                                                                                                                     |
| 3.38      | POST            | `/services/rs/gestione/progetto/{path}/sezione/giornata/{idProgetto}`                  | crea giornata; body come 3.39 senza id                                                                                                                                                                  |
| 3.39      | PUT             | `/services/rs/gestione/progetto/{path}/sezione/giornata/{idProgetto}`                  | `{giornataCalendario: {id, data, flagFAD, durataOre, fasceOrarie:[{oraInizio, oraFine, sedeFormazione, ...}]}}`                                                                                         |
| 3.40      | DELETE          | `/services/rs/gestione/progetto/{path}/sezione/giornata/prg/{idProgetto}`              |                                                                                                                                                                                                         |
| 3.41      | GET             | `/services/rs/gestione/registropresenze/{idFascia}/{codiceProgetto}/{idTipoProgetto}`  | stesso `registro` del 6.3 (lato ApL)                                                                                                                                                                    |
| 3.42      | PUT             | `/services/rs/gestione/progetto/{path}/invia/registropresenze/{idProgetto}/{idFascia}` | consolida/invia il registro della fascia (lato ApL). Nel PDF il body d'esempio è un'anagrafica: refuso, verificare in collaudo                                                                          |
| 3.43–3.45 | POST/PUT/DELETE | `/services/rs/anag/apl/refrilevazionepresenze/gestione[/{id}]`                         | referente rilevazione presenze: `{anagrafica: {nome, cognome, codFiscale, email, sesso, dataNascita, luogo di nascita..., cellulare}}` → risposta con `idAnagrafica`, `username`, `passwordProvvisoria` |

### 4.3 Anagrafiche (cap. 2)

| #         | Metodo          | Endpoint                                                                                                                                                         | Note                                                                                                                                                                                                                                                                      |
| --------- | --------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 2.1–2.4   | GET             | `/services/rs/ang/nazione`, `/ang/filter/regione/{idNazione}/nazione`, `/ang/filter/provincia/{idRegione}/regione`, `/ang/filter/comune/{idProvincia}/provincia` | tipologiche geografiche, `{anagrafiche:[{id,label,...}]}`                                                                                                                                                                                                                 |
| 2.29      | POST            | `/services/rs/anag/apl/discenti/gestione/`                                                                                                                       | `{anagrafica: {nome, cognome, dataNascita, codFiscale, sesso, cellulare, email, nazione/regione/provincia/comune di nascita e domicilio, indirizzoDom, capDom, titoloStudio, creditoSicurezzaGenerale, creditoDirittiDoveri, dataConseguimentoCreditoSicurezzaGenerale}}` |
| 2.30      | POST            | `/services/rs/anag/apl/discenti/gestione/search/attivi`                                                                                                          | ricerca (stesso body, campi parziali)                                                                                                                                                                                                                                     |
| 2.31      | PUT             | `/services/rs/anag/apl/discenti/gestione/`                                                                                                                       | modifica                                                                                                                                                                                                                                                                  |
| 2.32      | DELETE          | `/services/rs/anag/apl/discenti/gestione/{idDiscente}`                                                                                                           |                                                                                                                                                                                                                                                                           |
| 2.33–2.35 | POST            | `/services/rs/anag/fad/gestione/`, `.../stato/anagrafica/cambiastato/{id}`                                                                                       | piattaforme FAD dell'APL (con documenti)                                                                                                                                                                                                                                  |
| 2.36–2.38 | POST/PUT/DELETE | `/services/rs/anag/apl/docenti/gestione`                                                                                                                         | docenti: `{anagrafica: {nome, cognome, dataNascita, codFiscale, nazioneNascita, sesso, cellulare, email}}`                                                                                                                                                                |
| 2.19      | POST            | `/services/rs/ops/file`                                                                                                                                          | upload file (multipart), restituisce `refDocumentale`                                                                                                                                                                                                                     |

## 5. Mappatura EasyForma → FTWEB

| EasyForma                          | FTWEB                                                                                    |
| ---------------------------------- | ---------------------------------------------------------------------------------------- |
| Company (credenziali Forma.Temp)   | utenza APL (`SM_USER`/`SM_PASSWORD`, eventuale `SM_SDOMAIN`)                             |
| Classroom                          | progetto (`codiceProgetto`, `idProgetto`, `path`, `idTipoProgetto`)                      |
| Meeting (lezione)                  | fascia oraria `FasOraGioCal_` di una giornata `GioCal_` con `flagFAD = true`             |
| Participant learner                | `AnaDis_` (anagrafica) + `ParPro_` (partecipante progetto)                               |
| Participant trainer                | `personaleCoinvolto` con `tipoIncarico` DOCENTE (e anagrafica docente 2.36 se richiesta) |
| Attendance (intervalli join/leave) | `AssPreFasPar_` con `orePresenza`, `oraFirmaInizioLezione`, `oraFirmaFineLezione`        |
| Fine lezione + verifica            | consolidamento fascia (6.6 o 3.42)                                                       |

Regole di calcolo proposte (da confermare con il Vademecum FAD): `orePresenza` = somma degli intervalli di
presenza nella fascia, unendo le disconnessioni ≤ 15 minuti; `oraFirmaInizioLezione` = primo ingresso;
`oraFirmaFineLezione` = ultima uscita (o fine fascia se ancora connesso); ore espresse in `HH:mm` arrotondate al minuto.

## 6. Lacune del documento

- Nessuno schema di errore oltre `koMessages`; nessun codice di errore tipizzato.
- Non è documentata la scadenza del token oltre i 45 minuti di sessione né il comportamento su sessione scaduta
  (si assume 401/403 o `returnCode: KO`): il client deve ri-autenticarsi e ripetere una volta.
- La request 3.38 (crea giornata) e 3.42 (consolida) nel PDF sono refusi (copiano una risposta o un'anagrafica).
- Nessun esempio con `flagFAD = true` o `registroFAD` valorizzato.
- Limiti di rate, dimensioni e concorrenza non indicati.
- Le firme (`firmaIngressoLezione`, `firmaUscitaLezione`) sono PNG base64 pensate per la firma su tablet:
  non è chiarito se siano obbligatorie per consolidare e cosa inviare in FAD sincrona.
