# 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.