From e7889f80a33150e2150fba145f03cf2d93629c2b Mon Sep 17 00:00:00 2001 From: Adriano Dal Pastro Date: Tue, 28 Jul 2026 15:55:59 +0000 Subject: [PATCH] docs: aggiungi il documento delle modifiche del 28/07/2026 Elenco dei 15 punti concordati con Trafilo, con lo stato verificato sul codice al commit 2a56632, l'architettura d'installazione decisa il 28/07 e le nove domande la cui risposta dipende dal cliente. E' il riferimento del lavoro su V3.0.0. Co-Authored-By: Claude Opus 5 (1M context) --- TieMeasureFlow_modifiche_2026-07-28.md | 614 +++++++++++++++++++++++++ 1 file changed, 614 insertions(+) create mode 100644 TieMeasureFlow_modifiche_2026-07-28.md diff --git a/TieMeasureFlow_modifiche_2026-07-28.md b/TieMeasureFlow_modifiche_2026-07-28.md new file mode 100644 index 0000000..878a0a6 --- /dev/null +++ b/TieMeasureFlow_modifiche_2026-07-28.md @@ -0,0 +1,614 @@ +# TieMeasureFlow — modifiche da apportare + +**Data:** 28 luglio 2026 (agg. serale: architettura d'installazione, punti 7-8 precisati, punti 14-15 nuovi, timer bidirezionale nel punto 3) +**Riferimento codice:** branch `V2.0.0`, commit `2a56632` +**Destinatari:** Parte 1 leggibile da cliente e rivenditore · Parte 2 per chi mette mano al codice + +--- + +## Come leggere questo documento + +La **Parte 1** dice *cosa deve fare* il sistema e *perché*: si può mandare a Ricerca e +Misure e a Tràfilo. La **Parte 2** dice *dove si interviene*, con file e criteri di +completamento. La **Parte 3** elenca le domande la cui risposta non dipende da noi. + +Ogni punto porta lo **stato verificato sul codice**, non riferito: `già fatto`, +`parziale`, `da fare`. Serve a evitare l'equivoco emerso in questi giorni — diverse +funzioni risultano "già implementate" perché **l'interfaccia c'è**, ma dietro non +succede nulla. + +**Fonti:** specifica *Schema sviluppo SW TieFlow rev. 04-2026*; *MODIFICHE TIEMEASURE +v260519*; call del 28/07/2026; rettifica di Marco Menoncin del 28/07; lettura diretta +del codice. + +--- + +## Il punto che regge tutti gli altri + +**Lo stato della produzione oggi vive dentro una pagina del browser.** + +Il timer, il conteggio dei cicli, il flag "produzione avviata" e le misure in corso +sono variabili del componente Alpine di `task_execute.html`. La navigazione fra un +task e l'altro è un **ricaricamento completo di pagina** (`window.location.href`). + +Conseguenza diretta: **cambiando task si perde tutto.** Il timer smette di esistere, +il conteggio dei cicli riparte, "produzione avviata" si dimentica. + +Questo spiega, senza bisogno di altre ipotesi: + +- perché il loop di misura non regge quando la ricetta ha altri task dopo la misura; +- perché con più task di misura non si sa a quale tornare allo scadere del timer; +- perché *fermo linea* e *fine produzione* non hanno nulla da fermare o da chiudere; +- perché non esiste storico di cosa è successo durante una produzione. + +**Va risolto per primo**: i punti 2, 3, 6 e 8 dipendono da questa scelta, e affrontarli +prima significa rifarli dopo. + +--- + +## Architettura d'installazione (decisa il 28/07) + +Chiude la domanda D-3 lato Tielogic. L'installazione a Tràfilo è così composta: + +``` +SERVER (uno, del cliente) STAZIONE (una per PC, installata in locale) +┌─────────────────────────┐ ┌──────────────────────────────────────┐ +│ MySQL │◄──API──│ App di stazione: │ +│ Backend dati (API) │ │ · interfaccia operatore (frontend) │ +│ File dei disegni │ │ · agente hardware: calibro USB, │ +│ Migrazioni dello schema │ │ driver camera, colonnina/cicalino │ +│ Adattatore GAIA │ │ · elaborazione visione (futura: │ +└─────────────────────────┘ │ XF compare, pattern matching) │ + └──────────────────────────────────────┘ +``` + +- **Sul server vive tutto ciò che è stato**: il database, i file dei disegni, le + migrazioni dello schema e l'unico punto di contatto col gestionale GAIA. + Aggiornare la logica dati = un deploy, in un posto solo. +- **Sulla stazione vive tutto ciò che tocca l'hardware**: calibro, telecamera, + segnalazione luminosa/acustica, e in prospettiva l'elaborazione visione — che + così non carica il server (rilevante per il dimensionamento, D-4). + L'app di stazione è **senza stato**: non tocca il database direttamente, parla + col backend dati via API e gli manda risultati e immagini. +- **L'identità della stazione è data dall'installazione** (configurata sul PC), + non più dal container sul server: il vincolo "una stazione = un container" + decade. +- La **licenza per postazione** ha l'aggancio naturale nell'app di stazione + installata. + +**Correzione a quanto detto in call:** i disegni **non stanno nel database** — +stanno su filesystem (`uploads/`), serviti dal backend. Con questa architettura +restano sul server, in un posto solo: nessuna cartella da sincronizzare fra i PC. + +Conseguenza per lo sviluppo: lo stato della produzione (punto 1) va nel database +**per obbligo architetturale**, non per scelta — con 20 app di stazione non esiste +altro posto dove possa vivere. + +--- + +# Parte 1 — Cosa deve fare il sistema + +## Quadro: cosa già funziona + +Da mettere a verbale, perché in parte era dato per mancante: + +| Funzione | Stato | +|---|---| +| Stazioni e assegnazione ricette alle stazioni | ✅ presente | +| Ruolo **capoturno** con autorizzazione a login | ✅ presente | +| Timer d'intervallo misura con **conto alla rovescia a video** e cicalino | ✅ presente | +| Logout automatico per inattività, configurabile | ✅ presente | +| Tolleranze con soglie di attenzione (UTL/UWL/LWL/LTL) ed esito per quota | ✅ presente | +| Versionamento delle ricette con storico delle modifiche | ✅ presente | +| Registrazione del **tempo di inserimento** di ogni misura | ✅ presente (28/07) | +| Pulsanti *Fermo linea*, *Fine produzione*, *Avvio produzione* | ⚠️ solo interfaccia | + +L'ultima riga è la più importante: i tre pulsanti esistono, chiedono correttamente +l'autorizzazione del capoturno, **e poi non fanno nulla**. + +--- + +## 1. Memoria della produzione in corso `da fare` · prerequisito + +**Oggi:** lo stato di una produzione esiste solo finché l'operatore resta sulla stessa +schermata. + +**Deve:** la produzione diventa un'entità con una vita propria — si apre quando parte, +registra ciò che accade (avvio, cicli di misura, fermo linea, ripresa, chiusura) e si +chiude quando il capoturno la chiude. Se l'operatore cambia task, esce e rientra, o il +tablet si riavvia, la produzione è ancora lì con il suo timer. + +**Perché conta:** senza questo, *fermo linea* e *fine produzione* non possono +funzionare, il loop di misura non è realizzabile e non esiste il dato storico su cui +poggiano sia la statistica sia l'integrazione col gestionale. + +--- + +## 2. Tipo di task esplicito `da fare` + +**Oggi:** il sistema distingue un task di misura da un task documentale **deducendolo**: +se ha delle quote è una misura, altrimenti è una nota. Non esiste un tipo dichiarato. + +**Deve:** ogni task nasce con un tipo scelto da chi crea la ricetta — **nota**, +**misura**, **disegno** — predisposto per i tipi futuri (confronto profilo/DXF, misura +con camera). + +**Perché conta:** è la richiesta n. 1 di Menoncin, ed è ciò a cui si agganciano timer e +loop. Con la deduzione attuale un task di misura a cui non sono ancora state inserite le +quote viene trattato come una nota: il sistema si comporta in modo diverso a seconda di +quanto è completa la ricetta. + +--- + +## 3. Loop di misura e ripetizione `parziale` + +**Oggi:** allo scadere del timer suona il cicalino e il ciclo si riazzera — ma solo se +l'operatore è rimasto su quella schermata. + +**Deve:** +- l'operatore esegue i task in sequenza fino al primo task di misura; +- da lì **resta in loop sulla misura** finché la produzione non viene chiusa; +- il conto alla rovescia di **quanto manca alla prossima misura** è sempre visibile; +- **arrivato a zero, il contatore riparte nell'altro senso**: mostra da quanto tempo + si è **oltre** l'intervallo di misura, in evidenza — così il ritardo si vede, non + si deduce (richiesta dell'operatore, 28/07); +- allo scadere del timer la misura **si ripropone** ovunque si trovi l'operatore; +- se la ricetta ha **più task di misura**, il timer riparte alla fine dell'**ultimo**; +- dev'essere possibile **girare il pezzo e rimisurare** senza chiudere il ciclo. + +**Perché conta:** è la seconda richiesta di Menoncin e il comportamento descritto al +punto 4.10 della specifica del 19/05. La logica c'è già in gran parte: manca che +sopravviva al cambio di schermata (punto 1). + +--- + +## 4. Limite di tentativi prima del capoturno `da fare` + +**Oggi:** l'operatore può ripetere la misura quante volte vuole. + +**Deve:** dopo un numero di tentativi definito nella ricetta, per proseguire serve +l'autorizzazione del capoturno. + +**Perché conta:** è nella specifica ed è la contromisura al caso in cui si ripete finché +non "viene bene". Il meccanismo di autorizzazione esiste già: manca il contatore e la +soglia. + +--- + +## 5. Avanzamento solo se in tolleranza `da verificare` + +**Deve:** si passa alla quota successiva in autonomia **solo se la quota è in +tolleranza**; per confermare una quota fuori tolleranza serve il capoturno. + +**Nota:** il gate del capoturno per il fuori tolleranza è implementato. Va verificato +sul campo che **blocchi davvero l'avanzamento** e non sia solo una richiesta di conferma. +Se blocca, il punto si chiude senza sviluppo. + +--- + +## 6. Fermo linea e Fine produzione: dare effetto `parziale` + +**Oggi:** entrambi chiedono l'autorizzazione del capoturno, poi non succede niente. + +**Deve:** +- **Fermo linea** — sospende il timer e la produzione; il capoturno può riattivarla; +- **Fine produzione** — chiude la produzione, ferma il timer definitivamente e **invia + i dati di misura dell'intera produzione** al file di statistica. + +**Perché conta:** il comportamento verso il gestionale è ancora da definire (Parte 3), +ma **tutto ciò che sta prima del gestionale si può e si deve fare adesso**: sospendere, +riprendere, chiudere, registrare. Consegnare i pulsanti funzionanti senza il gestionale +è possibile; il contrario no. + +--- + +## 7. Gestione delle stazioni `parziale` + +**Deve:** +- la lista stazioni mostra, oltre a codice e postazione, **le ricette collegate**; +- esiste un **reset della stazione**, con un pulsante **per riga** nella lista: + la stazione torna senza ricette associate e si riassegna (precisazione + dell'operatore, 28/07); +- la **stazione corrente si può cambiare al volo**, per poter provare più stazioni da un + solo computer senza riconfigurare l'installazione. + +**Perché conta:** è la terza richiesta di Menoncin. Il cambio al volo non è un vezzo da +sviluppatori: senza, la sessione di collaudo con Menoncin richiede tanti PC quante sono +le stazioni da provare. + +--- + +## 8. Tracciabilità obbligatoria `parziale` + +**Oggi:** numero di lotto e numero seriale sono facoltativi e si inseriscono nella lista +task, cioè dopo aver iniziato. + +**Deve:** l'obbligatorietà di lotto e seriale si **decide alla creazione della +ricetta** (obbligatori sì/no); l'operatore li inserisce **alla selezione della +ricetta**, e finché mancano il pulsante *Avvia* **non si attiva** (precisazione +dell'operatore, 28/07). + +**Perché conta:** una misura senza lotto non è tracciabile a posteriori, e la +tracciabilità è metà del valore del sistema in un audit. + +--- + +## 9. Blocco dell'inserimento manuale `da fare` + +**Oggi:** il sistema registra **come** è stata inserita una misura (calibro o tastiera), +ma accetta sempre entrambi. + +**Deve:** un'impostazione della ricetta consente o vieta l'inserimento manuale, **con +divieto come impostazione predefinita**: si misura col calibro. + +**Perché conta:** è il punto sollevato in call — senza questo vincolo un valore in +tolleranza si può digitare. Il dato su *come* è stata inserita c'è già: manca la regola +che lo impedisce. + +--- + +## 10. Interfaccia operatore: sequenza e conferme `da fare` + +Richieste del 19/05, tutte di interfaccia: + +- un pulsante che **avvia i task in sequenza**, senza sceglierli a uno a uno; +- la lista completa dei task retrocessa a **secondo livello**, per tornare a vedere i + task precedenti; +- «inizia misure» rinominato **«visualizza singolo TASK»**; +- dentro il task, «Riepilogo» sostituito da **«Completato»** per passare al successivo; +- un task lasciato a metà **resta incompiuto** e si vede; +- «fine ciclo misura» **cliccabile solo quando tutte le quote hanno un valore**. + +--- + +## 11. Formattazione delle descrizioni `da fare` + +**Deve:** le descrizioni dei task accettano andate a capo e grassetto. + +**Perché conta:** chi crea le ricette fa **copia e incolla dal PDF della scheda +tecnica**; oggi il testo arriva appiattito e va risistemato a mano ogni volta. + +--- + +## 12. Funzionamento senza internet `da fare` · bloccante per l'installazione + +**Oggi:** l'applicazione **non funziona senza collegamento a internet**. Cinque librerie +vengono scaricate al volo da servizi esterni ogni volta che si apre una pagina. + +**In una rete di produzione isolata — la norma in fabbrica — il risultato è una pagina +bianca.** Non un degrado: l'interfaccia non parte proprio, e senza le altre non si vedono +i disegni tecnici né i grafici statistici. + +**Deve:** tutte le librerie sono incluse nell'installazione e l'applicazione funziona a +rete staccata. + +**Perché conta ora:** l'installazione a Tràfilo è on-premise e prevista per settembre. +È poco lavoro, ma va fatto **prima**, non in fabbrica il giorno dell'installazione. + +**Beneficio collaterale non ovvio:** oggi una delle librerie è agganciata a una versione +"qualunque della serie 3" — cioè **l'applicazione cambia da sola** quando gli autori +pubblicano un aggiornamento, senza che nessuno l'abbia validata. Per un sistema che +produce evidenze per audit ISO 9001 / IATF 16949 questo è di per sé un problema. +Includendo le librerie le versioni si congelano: da difetto diventa argomento di vendita. + +--- + +## 13. Generazione dei task dalla scheda tecnica con l'AI `fuori offerta` + +**Richiesta:** leggere il PDF della scheda tecnica e **creare un task per blocco**, +invece del copia-incolla manuale. + +**Storia:** posta il **19/05/2026** nel documento delle modifiche, rimasta senza +risposta; **rilanciata da Tràfilo il 28/07** come elaborazione massiva iniziale delle +schede, «senza installare agenti nel sistema». + +**Stato:** non è in nessuna offerta. Prima di quotare servono tre informazioni: quante +sono le schede, se il formato è standard, e se l'elaborazione è una-tantum in fase di +avviamento o una funzione permanente del prodotto. Sono domande da fare, non da +supporre — vedi Parte 3. + +--- + +## 14. Stabilità del layout `da fare` · da circoscrivere + +**Oggi:** le dimensioni delle viste **cambiano a seconda del menu**: passando da una +schermata all'altra la finestra non mantiene proporzioni stabili. + +**Deve:** il layout resta stabile nel passaggio fra le viste. + +**Nota:** segnalazione dell'operatore del 28/07, non ancora circoscritta sul codice — +prima di intervenire va riprodotta e va stilato l'elenco delle viste interessate. + +--- + +## 15. Statistica: si registra sempre, si consulta a parte `già fatto` · da confermare sul campo + +**Richiesta (28/07):** a fine misura l'operatore **non va portato nella pagina della +statistica**. I dati **entrano comunque in statistica**: cambia solo chi la consulta — +serve l'**utente con il ruolo adeguato**, che apre la pagina dedicata. + +**Verificato sul codice:** è già così. Tutte le pagine di statistica richiedono il +ruolo **Metrologo** (`role_required("Metrologist")` su ogni route), e a fine ciclo +l'operatore viene portato al **riepilogo**, non alla statistica. + +**Resta da fare:** niente sviluppo; il requisito entra come **criterio di collaudo** +(l'operatore non deve poter raggiungere la statistica da nessun percorso) e va tenuto +fermo quando il punto 10 ridisegna la navigazione a fine task. + +--- + +# Parte 2 — Dove si interviene + +Riferimenti al branch `V2.0.0`, commit `2a56632`. + +## Ordine consigliato + +``` +12 (offline) ──────────────► indipendente, si può fare subito + bloccante per l'installazione + + 1 (stato produzione) ──┬───► 3 (loop misura) + ├───► 6 (fermo linea / fine produzione) + └───► 4 (limite tentativi) + + 2 (tipo task) ─────────────► 3, 10 + + 7 (stazioni) · 8 (tracciabilità) · 9 (inserimento manuale) · 11 (formattazione) + indipendenti fra loro + + 5 (avanzamento in tolleranza) ──► prima verificare, forse è già a posto + +14 (layout) ────────────────► prima riprodurre e circoscrivere le viste + +15 (statistica riservata) ──► già a posto: solo criterio di collaudo, + da non rompere lavorando sul punto 10 +``` + +La separazione **backend dati sul server / app di stazione in locale** (vedi +*Architettura d'installazione*) non è un punto di questa lista: è il contesto in +cui i punti 1, 3, 6 e 7 vanno progettati. In pratica: API senza stato, stato solo +nel database, niente dipendenze dal container per l'identità della stazione. + +## 1 · Stato della produzione lato server + +**Problema tecnico:** `task_execute.html` tiene in variabili Alpine +(`timerActive`, `timerRemaining`, `_timerInterval`, `cycleCount`, `cycleConfirmed`, +`productionStarted`, `measurements`) uno stato che deve sopravvivere alla pagina. +`goToNextTask()` fa `window.location.href` → il componente viene distrutto. +Lato server la sessione conserva soltanto `lot_number` e `serial_number`. + +**Intervento:** +- nuove tabelle `production_runs` e `production_events` (avvio, ciclo completato, fermo + linea, ripresa, chiusura), con `station_id`, `recipe_version_id`, `operator_id`, + `supervisor_id` dove serve, timestamp; +- endpoint REST per aprire, interrogare e aggiornare la produzione corrente della + stazione; +- il frontend legge lo stato all'apertura di ogni pagina invece di tenerlo in memoria; + il conto alla rovescia si **ricalcola dall'orario di scadenza** salvato lato server, + non da un contatore locale; +- gli endpoint vanno progettati **senza stato in memoria di processo**: con l'app di + stazione installata su ogni PC (vedi *Architettura d'installazione*) il database è + l'unico posto condiviso. + +**File:** `src/backend/models/orm/` (nuovo modulo), `src/backend/migrations/versions/` +(migrazione 005), `src/backend/api/routers/`, `src/frontend/flask_app/blueprints/measure.py`, +`src/frontend/flask_app/templates/measure/task_execute.html`. + +**Fatto quando:** avviata una produzione, si naviga fra i task, si esce e si rientra, e +il timer prosegue coerente; il riavvio del browser non azzera nulla. + +--- + +## 2 · Tipo di task + +**Problema tecnico:** `RecipeTask` non ha campo tipo; il frontend decide con +`subtasks.length > 0` (`task_execute.html`, `task_list.html`). + +**Intervento:** campo `type` su `recipe_tasks` con valori `note | measure | drawing` +(predisposto per `xf_compare`, `camera_measure`), migrazione con valorizzazione dei dati +esistenti secondo la regola attuale, selezione del tipo nell'editor ricetta, +sostituzione dei controlli su `subtasks.length` con il tipo. + +**File:** `src/backend/models/orm/task.py`, nuova migrazione, +`src/backend/models/api/`, `src/frontend/flask_app/templates/maker/task_editor.html`, +`templates/measure/task_execute.html`, `templates/measure/task_list.html`. + +**Fatto quando:** una ricetta con un task di misura ancora privo di quote si comporta da +task di misura. + +--- + +## 3 · Loop di misura + +**Base già presente:** `confirmCycle()`, `startMeasurementTimer()`, `onTimerExpired()`, +`timerDisplay`, `playBuzzer()` in `task_execute.html` (righe ~955-1050). La logica è +corretta; il problema è la persistenza (punto 1) e il fatto che allo scadere non si può +riportare l'operatore sul task giusto. + +**Intervento:** spostare la scadenza sul server; alla scadenza, **redirezione al task di +misura** della produzione corrente; con più task di misura far ripartire il timer al +completamento dell'**ultimo**; aggiungere «rimisura» che riapre il ciclo senza chiuderlo. + +**Timer bidirezionale:** oggi il contatore **solo decrementa e si ferma a zero** +(`timerRemaining--`, poi `onTimerExpired()`); `timerDisplay` formatta minuti:secondi +dal residuo. Va esteso: sotto zero il valore continua **in negativo** e la +visualizzazione passa a "oltre da m:s", con stile in evidenza. Calcolando dal +timestamp di scadenza lato server (come sopra), il ritardo è coerente su qualunque +schermata e sopravvive al ricaricamento. + +**Fatto quando:** con una ricetta a due task di misura e task documentali in coda, allo +scadere del timer l'operatore viene riportato alla misura da qualunque schermata. + +--- + +## 4 · Limite di tentativi + +**Problema tecnico:** nessun `max_retries` nel codice. + +**Intervento:** campo sulla ricetta (accanto a `measurement_interval_minutes`, che segue +lo stesso schema), contatore per quota nella produzione corrente, superata la soglia +riuso del modale capoturno esistente con motivo `max_retries`. + +**File:** `src/backend/models/orm/recipe.py`, migrazione, +`templates/maker/recipe_editor.html` (accanto al timer), `task_execute.html`. + +--- + +## 5 · Avanzamento in tolleranza — prima verificare + +Il modale capoturno gestisce già `out_of_tolerance` (`task_execute.html`, +`openSupervisorModal`, `validateSupervisor`, endpoint +`measure.validate_supervisor`). **Prima di sviluppare, provare**: se il rifiuto blocca +l'avanzamento, il punto è chiuso. Se è solo una conferma, va reso vincolante. + +--- + +## 6 · Fermo linea e Fine produzione + +**Problema tecnico:** in `task_execute.html` i due pulsanti aprono il modale e poi +ricadono su un commento: `fermo_linea and fine_produzione are handled by GAIA +integration (future)`. `startProduction()` è un `TODO` con la chiamata commentata. + +**Intervento (senza gestionale):** scrivere gli eventi su `production_events`, +sospendere e riprendere il timer, chiudere la produzione, ed **emettere il file di +statistica** con tutte le misure della produzione. L'invio al gestionale resta un +adattatore separato da riempire quando il protocollo sarà definito (Parte 3): va +previsto il punto d'innesto, non l'implementazione. + +**Fatto quando:** *fermo linea* congela il timer e solo il capoturno lo riattiva; *fine +produzione* chiude e produce il file. + +--- + +## 7 · Stazioni + +**Base presente:** `Station` e `StationRecipeAssignment` (`models/orm/station.py`, +migrazione 002). + +**Intervento:** ricette collegate nella lista stazioni; pulsante di reset **per riga** +che rimuove le assegnazioni; selezione della stazione corrente da parametro URL con +ricaduta sulla variabile d'ambiente, per il collaudo da una sola macchina. + +**Nota (28/07, chiude il dubbio che era in D-3):** in produzione l'identità della +stazione è data dall'**installazione locale** dell'app di stazione, non dal container. +Il cambio al volo via URL resta come strumento di **collaudo**. + +--- + +## 8 · Tracciabilità + +**Base presente:** `lot_number` e `serial_number` su `Measurement`, salvataggio in +sessione (`measure.save_traceability`), inserimento in `task_list.html`. + +**Intervento:** flag sulla ricetta (`richiede lotto`, `richiede seriale`); spostare +l'inserimento sull'avvio produzione; *Avvia* disabilitato finché mancano. + +--- + +## 9 · Inserimento manuale + +**Base presente:** `Measurement.input_method` (`manual | usb_caliper`), valorizzato dal +frontend. + +**Intervento:** flag sulla ricetta `consente inserimento manuale`, **predefinito falso**; +validazione **lato server** — un flag solo nel frontend non protegge da nulla; tastierino +nascosto quando vietato. + +--- + +## 10 · Interfaccia operatore + +Interventi su `templates/measure/task_list.html` e `task_execute.html`: pulsante di +avvio in sequenza, retrocessione della lista a secondo livello, rinomina dei due +pulsanti, stato «incompiuto» sui task abbandonati, «fine ciclo misura» abilitato solo a +quote complete. + +--- + +## 11 · Formattazione descrizioni + +`RecipeTask.description` è già `Text`. Serve un editor minimale (grassetto e a capo) e +la resa corrispondente in esecuzione, con **sanificazione dell'HTML** in ingresso. + +**File:** `templates/maker/task_editor.html`, `templates/measure/task_execute.html`. + +--- + +## 12 · Funzionamento senza internet + +**Verificato sul codice.** Cinque librerie esterne in sei template: + +| Libreria | Dove | Senza rete si perde | +|---|---|---| +| Alpine.js `3.x.x` | `base.html` | **tutta l'interfaccia** | +| Plotly `2.32.0` | `statistics/dashboard.html` | carte di controllo e istogrammi | +| PDF.js `3.11.174` | `task_execute`, `recipe_preview`, `task_drawing`, `task_editor` | visualizzazione dei disegni | +| Fabric.js `5.3.1` | `maker/task_drawing.html` | editor delle annotazioni | +| Google Fonts | `base.html` | estetica e attese al caricamento | + +**Intervento:** scaricare le librerie in `src/frontend/flask_app/static/vendor/` (la +cartella **esiste già ed è vuota**), ripuntare i tag, chiudere la policy di sicurezza in +`security_headers.py` da elenco-di-CDN a solo-origine-locale. + +⚠️ **Trappola da non mancare:** PDF.js ha una **seconda** referenza al CDN, +`pdfjsLib.GlobalWorkerOptions.workerSrc`, presente in **quattro file**. Ripuntando solo +lo script principale la libreria si carica in locale **e il worker continua a cercare +internet**: sembra funzionare finché non si apre un disegno. + +**Fatto quando:** con la rete staccata si percorre login → scelta ricetta → esecuzione +task → annotazione disegno → statistiche → report, senza errori in console. + +--- + +# Parte 3 — Decisioni che non dipendono da noi + +Da chiudere **prima** che i punti collegati entrino in sviluppo. Vanno girate a Tràfilo +tramite Menoncin. + +| # | Domanda | Blocca | Chi risponde | +|---|---|---|---| +| **D-1** | **Protocollo del gestionale GAIA**: come si scambiano i dati — servizi web, database condiviso, file? | avvio produzione, fermo linea, fine produzione verso il gestionale; lettura dei codici articolo per stazione | IT Tràfilo + fornitore GAIA | +| **D-2** | **Rete e credenziali** per raggiungere GAIA dal server dove sarà installato | come sopra | IT Tràfilo | +| ~~**D-3**~~ | ~~Una applicazione per stazione o una sola per tutte?~~ **Decisa il 28/07** lato Tielogic: backend dati sul server, app di stazione installata su ogni PC — vedi *Architettura d'installazione*. Resta la validazione con l'IT di Tràfilo (macchina e rete) | — | chiusa (noi); validazione in D-4 | +| **D-4** | **Server**: quale macchina, quanto spazio disco. Sul server stanno database **e file dei disegni** (`uploads/`); l'elaborazione visione **non** è sul server (sta sull'app di stazione), quindi pesa lo spazio disco, non la potenza di calcolo | installazione | IT Tràfilo | +| **D-5** | **Cicalino**: basta il suono del browser o serve una segnalazione luminosa? La specifica chiede luce **e** suono accesi per tutta la misura, visibili da lontano. Con l'architettura del 28/07 l'app di stazione **può pilotare una colonnina**: la domanda diventa *quale hardware* | punto 3 | Tràfilo | +| **D-6** | **Autorizzazione capoturno**: username e password come oggi, o PIN rapido / badge? Venti volte al giorno la password è un attrito | punti 4, 5, 6 | Tràfilo | +| **D-7** | **Numero di tentativi** consentiti prima del capoturno: quanti, e uguali per tutte le ricette? | punto 4 | Tràfilo | +| **D-8** | **Schede tecniche**: quante sono, il formato è standard, e serve una conversione una-tantum o una funzione permanente? | punto 13 e la sua quotazione | Tràfilo | +| **D-9** | Modificare i parametri di una ricetta (timer, tentativi) **crea una nuova versione** o no? Sono parametri di esercizio, non di prodotto | punti 4, 3 | noi, con conferma cliente | + +**Nota su D-1 e D-2:** finché non hanno risposta, del gestionale si può solo predisporre +il punto d'innesto. Tutto il resto del punto 6 — sospendere, riprendere, chiudere, +registrare, produrre il file — **si fa comunque e va fatto adesso**. + +--- + +## Appendice — Come è stato verificato + +Ogni «già fatto» e ogni «da fare» viene dalla lettura del codice al commit `2a56632`, +non dai documenti. In particolare: + +- il **tipo di task** è dedotto da `subtasks.length > 0` in `task_execute.html:117` e + `task_list.html:169`; +- il **ruolo capoturno** esiste come `Supervisor` + (`api/middleware/api_key.py:71`, `blueprints/measure.py:350`); +- **fermo linea / fine produzione / avvio produzione** hanno interfaccia e gate ma + nessun effetto (`task_execute.html:1017-1021`, `1118`); +- il **timer** è un `setInterval` locale alla pagina (`task_execute.html:968-995`) e la + navigazione fra task è un ricaricamento (`task_execute.html:1054`); +- **`max_retries`** e **`production_events`** non compaiono in nessun file; +- le **cinque librerie da CDN** sono ai riferimenti citati al punto 12, e + `static/vendor/` contiene solo `.gitkeep`; +- i **disegni stanno su filesystem**, non nel database: cartella `uploads/` servita + dal backend (`api/routers/files.py:201`, `FileResponse`) — verifica del 28/07 sera, + corregge quanto detto in call; +- la **statistica è già riservata**: ogni route di `blueprints/statistics.py` porta + `@role_required("Metrologist")`; a fine ciclo il frontend va al riepilogo + (`task_execute.html:1126`), non alla statistica; +- il **timer si ferma a zero**: decremento in `task_execute.html:974-975` con uscita + su `onTimerExpired()` — il conteggio del ritardo (punto 3) oggi non esiste; +- lo stack attuale è a 4 container (`docker-compose.yml`): MySQL 8, backend FastAPI, + frontend Flask, nginx — base della sezione *Architettura d'installazione*. + +Il punto 14 (layout) è l'unico **non verificato sul codice**: è una segnalazione +dell'operatore del 28/07, da riprodurre.