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) <noreply@anthropic.com>
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user