Nuovo tipo di task: controllo OK/NOK con note #54

Closed
opened 2026-10-07 09:54:55 +00:00 by Adriano · 4 comments
Owner

RICHIESTA: task per controlli visivi/funzionali/estetici; l'operatore fa il controllo, preme «completato» ed eventualmente scrive note.
DA DECIDERE con Menoncin: esito OK e NOK distinti (registrati nella sessione) o solo «completato»? Il titolo del docx dice OK/NOK.
FONTE: UPDATE TIEMEASUREFLOW_180926.docx (Tràfilo via Menoncin, test del 18/09/2026), daitarn:D:\Sorgenti\Clienti\Ricerca_e_Misura\0_REM-Tielogic_SHARED\1_TRAFILO\0_Specifiche\ (16 screenshot nel docx). Raccolta: TieMeasureFlow#44.

RICHIESTA: task per controlli visivi/funzionali/estetici; l'operatore fa il controllo, preme «completato» ed eventualmente scrive note. DA DECIDERE con Menoncin: esito OK e NOK distinti (registrati nella sessione) o solo «completato»? Il titolo del docx dice OK/NOK. FONTE: UPDATE TIEMEASUREFLOW_180926.docx (Tràfilo via Menoncin, test del 18/09/2026), daitarn:D:\Sorgenti\Clienti\Ricerca_e_Misura\0_REM-Tielogic_SHARED\1_TRAFILO\0_Specifiche\ (16 screenshot nel docx). Raccolta: TieMeasureFlow#44.
Adriano added the sviluppo label 2026-10-07 09:54:55 +00:00
Author
Owner

ESITO: analisi
DECISIONE Adriano 07/10: due esiti, OK e NOK, più note; un NOK chiede la nota. L'esito entra nella sessione e nella statistica.
STATO: measurements non va bene (subtask_id e value NOT NULL, pass_fail solo pass/warning/fail, sporcherebbe le SPC: BE/models/orm/measurement.py:18,29); production_events ha run_id NOT NULL e nessun esito (BE/models/orm/production.py:124-154).
FILE: tipo check in TASK_TYPES (BE/models/orm/task.py:18, enum allargato come in migrations/versions/011_vision_graph.py:31) · nuova tabella task_results (task_id, version_id, production_run_id nullable, user_id, outcome ok|nok|done, note, payload JSON, attachments JSON, created_at), condivisa con #55 · router BE nuovo + proxy FE/blueprints/measure.py · editor (task_editor.html :276/:542) · esecuzione (task_execute.html :1773, footer :700-712).
MIGRAZIONE: sì (018, con #53). PIANO: ondata 2.
VERIFICATO su V3.0.0 a829bf3 (mappa del 07/10). Percorsi da src/; BE=backend/, FE=frontend/flask_app/.

ESITO: analisi DECISIONE Adriano 07/10: due esiti, OK e NOK, più note; un NOK chiede la nota. L'esito entra nella sessione e nella statistica. STATO: measurements non va bene (subtask_id e value NOT NULL, pass_fail solo pass/warning/fail, sporcherebbe le SPC: BE/models/orm/measurement.py:18,29); production_events ha run_id NOT NULL e nessun esito (BE/models/orm/production.py:124-154). FILE: tipo `check` in TASK_TYPES (BE/models/orm/task.py:18, enum allargato come in migrations/versions/011_vision_graph.py:31) · nuova tabella `task_results` (task_id, version_id, production_run_id nullable, user_id, outcome ok|nok|done, note, payload JSON, attachments JSON, created_at), condivisa con #55 · router BE nuovo + proxy FE/blueprints/measure.py · editor (task_editor.html :276/:542) · esecuzione (task_execute.html :1773, footer :700-712). MIGRAZIONE: sì (018, con #53). PIANO: ondata 2. VERIFICATO su V3.0.0 a829bf3 (mappa del 07/10). Percorsi da src/; BE=backend/, FE=frontend/flask_app/.
Author
Owner

ESITO: analisi (ondata 2, contratto fra backend e frontend; vale anche per #53 #55 e la modale capoturno di #59)
RAMO base: lavoro/daitarn-trafilo (= #46 + ondata 1).

CONTRATTO ONDATA 2 (#53 #54 #55, e PIN del capoturno #59). Lo scrive l'unità P5 nel backend; le unità frontend lavorano contro questo testo, mockando api_client.

Migrazione 018_task_loop_results, down_revision = '017_user_pin':

  • recipe_tasks: in_loop Boolean not null default false (l'upgrade mette true dove task_type è in MEASURING_TASK_TYPES); at_close Boolean not null default false; fields JSON nullable.
  • enum task_type allargato con check (come migrations/versions/011_vision_graph.py:31; downgrade lo toglie solo se nessun task lo usa, altrimenti fallisce con messaggio).
  • tabella task_results: id, task_id FK recipe_tasks, version_id FK, production_run_id FK nullable, user_id FK, outcome Enum('ok','nok','done'), note Text nullable, values JSON nullable, attachments JSON nullable, created_at.

Modelli task (src/backend/models/api/task.py create/update/response): in_loop: bool (alla creazione, se assente = task_type in MEASURING_TASK_TYPES o == 'check'), at_close: bool (default false; ammesso true solo per task_type 'note', altrimenti 422), fields (solo per 'note', altrimenti 422): lista di max 20 {"key": slug [a-z0-9_]{1,40} unico, "label": str 1-100, "type": "text"|"number", "default": str|null, "attachment": bool}. Il copy-on-write della versione copia i tre campi.

Tipo check («Controllo OK/NOK»): task senza quote; l'esecuzione registra un esito.

POST /api/task-results (require_measurement_tec), JSON {"task_id", "production_run_id": int|null, "outcome", "note": str|null, "values": {key: str}|null, "attachments": [{"key": str|null, "path": str, "name": str}]|null} → 201 con il record (id, campi, user_id, created_at).

  • task 'check': outcome 'ok' o 'nok'; 'nok' con note vuota → 422 «Per un NOK serve la nota».
  • task 'note': outcome 'done'; chiavi di values solo fra le fields.key del task (422 altrimenti); valore di un campo 'number' convertibile a numero (422).
  • altri tipi → 422. path degli allegati = percorso restituito da /api/files/upload (relativo, niente ..).
  • production_run_id, se dato, deve essere un run aperto della stessa versione (422).
    GET /api/task-results?production_run_id=&task_id= (require_measurement_tec): elenco, più recente prima.

Ciclo di misura: production_service.measurement_task_ids restituisce i task con in_loop = true della versione (stesso nome, stesso campo measurement_task_ids nella risposta del run), in ordine. Il resto di MEASURING_TASK_TYPES resta com'è. La risposta del run (_as_response in src/backend/api/routers/production.py) aggiunge close_task_ids: id dei task at_close = true della versione, in ordine.

Fine produzione (frontend): se close_task_ids non è vuoto, prima della modale del capoturno si compilano quei task (campi + allegati) e si registrano con POST task-results (outcome 'done', production_run_id del run); poi la modale e la chiusura come oggi.

PIN del capoturno (frontend, backend già fatto in #59): la modale del capoturno ha due modi, «PIN» (default: scelta del nome da GET /api/auth/pin-users + tastierino 4 cifre) e «Password» (come oggi). In modo PIN i proxy di measure.py che inoltrano le azioni del capoturno mandano supervisor_user_id + supervisor_pin invece di username/password. 401 «PIN errato», 423 con il detail.

ESITO: analisi (ondata 2, contratto fra backend e frontend; vale anche per #53 #55 e la modale capoturno di #59) RAMO base: lavoro/daitarn-trafilo (= #46 + ondata 1). CONTRATTO ONDATA 2 (#53 #54 #55, e PIN del capoturno #59). Lo scrive l'unità P5 nel backend; le unità frontend lavorano contro questo testo, mockando `api_client`. Migrazione `018_task_loop_results`, `down_revision = '017_user_pin'`: - recipe_tasks: `in_loop` Boolean not null default false (l'upgrade mette true dove task_type è in MEASURING_TASK_TYPES); `at_close` Boolean not null default false; `fields` JSON nullable. - enum task_type allargato con `check` (come migrations/versions/011_vision_graph.py:31; downgrade lo toglie solo se nessun task lo usa, altrimenti fallisce con messaggio). - tabella `task_results`: id, task_id FK recipe_tasks, version_id FK, production_run_id FK nullable, user_id FK, outcome Enum('ok','nok','done'), note Text nullable, `values` JSON nullable, attachments JSON nullable, created_at. Modelli task (src/backend/models/api/task.py create/update/response): `in_loop: bool` (alla creazione, se assente = task_type in MEASURING_TASK_TYPES o == 'check'), `at_close: bool` (default false; ammesso true solo per task_type 'note', altrimenti 422), `fields` (solo per 'note', altrimenti 422): lista di max 20 `{"key": slug [a-z0-9_]{1,40} unico, "label": str 1-100, "type": "text"|"number", "default": str|null, "attachment": bool}`. Il copy-on-write della versione copia i tre campi. Tipo `check` («Controllo OK/NOK»): task senza quote; l'esecuzione registra un esito. `POST /api/task-results` (require_measurement_tec), JSON `{"task_id", "production_run_id": int|null, "outcome", "note": str|null, "values": {key: str}|null, "attachments": [{"key": str|null, "path": str, "name": str}]|null}` → 201 con il record (`id`, campi, `user_id`, `created_at`). - task 'check': outcome 'ok' o 'nok'; 'nok' con note vuota → 422 «Per un NOK serve la nota». - task 'note': outcome 'done'; chiavi di `values` solo fra le `fields.key` del task (422 altrimenti); valore di un campo 'number' convertibile a numero (422). - altri tipi → 422. `path` degli allegati = percorso restituito da `/api/files/upload` (relativo, niente `..`). - production_run_id, se dato, deve essere un run aperto della stessa versione (422). `GET /api/task-results?production_run_id=&task_id=` (require_measurement_tec): elenco, più recente prima. Ciclo di misura: `production_service.measurement_task_ids` restituisce i task con `in_loop = true` della versione (stesso nome, stesso campo `measurement_task_ids` nella risposta del run), in ordine. Il resto di MEASURING_TASK_TYPES resta com'è. La risposta del run (`_as_response` in src/backend/api/routers/production.py) aggiunge `close_task_ids`: id dei task `at_close = true` della versione, in ordine. Fine produzione (frontend): se `close_task_ids` non è vuoto, prima della modale del capoturno si compilano quei task (campi + allegati) e si registrano con POST task-results (`outcome 'done'`, `production_run_id` del run); poi la modale e la chiusura come oggi. PIN del capoturno (frontend, backend già fatto in #59): la modale del capoturno ha due modi, «PIN» (default: scelta del nome da `GET /api/auth/pin-users` + tastierino 4 cifre) e «Password» (come oggi). In modo PIN i proxy di measure.py che inoltrano le azioni del capoturno mandano `supervisor_user_id` + `supervisor_pin` invece di username/password. 401 «PIN errato», 423 con il `detail`.
Adriano added the assegnata:daitarn label 2026-10-07 10:33:38 +00:00
Author
Owner

🔵 daitarn — preso in carico 2026-10-07T10:33:34Z
ramo: lavoro/daitarn · capacità: build-windows, gpu

🔵 daitarn — **preso in carico** 2026-10-07T10:33:34Z ramo: `lavoro/daitarn` · capacità: build-windows, gpu
Author
Owner

Soluzione

ESITO: fatto
COSA: decisione Adriano 07/10: tipo check «Controllo OK/NOK» con esiti OK e NOK più note; un NOK chiede la nota; esito registrato in task_results con la sessione.
FILE: src/backend/models/orm/task.py — check in TASK_TYPES
FILE: src/backend/models/orm/task_result.py, models/api/task_result.py, api/routers/task_results.py — tabella task_results, POST e GET /api/task-results (NOK senza nota → 422)
FILE: src/frontend/flask_app/templates/maker/task_editor.html — tipo nell'editor
FILE: src/frontend/flask_app/static/js/task-results.js, templates/measure/task_execute.html, blueprints/measure.py — pulsanti OK/NOK, nota, proxy
MIGRAZIONE: 018_task_loop_results
COMMIT: df1727b f541f4a c6d4260 21f8bae
PROVA: suite goldrake su b7cb061 → 835 passed 2 skipped (pytest 3.11 backend+frontend), 29 passed (pytest 3.13 vision), docker build vision ok; test src/backend/tests/test_task_results.py, src/frontend/flask_app/tests/test_measure_task_results.py, tests/js/test_task_results.js
DIFFERENZE DALL'ANALISI: l'esito sta nella sessione (task_results.production_run_id) ma non ancora nella vista statistica per sessione: resta in gitea:Adriano/TieMeasureFlow#58.
In V3.0.0 da b7cb061 (ramo lavoro/daitarn-trafilo unito in fast-forward da a829bf3).

**Soluzione** ESITO: fatto COSA: decisione Adriano 07/10: tipo check «Controllo OK/NOK» con esiti OK e NOK più note; un NOK chiede la nota; esito registrato in task_results con la sessione. FILE: src/backend/models/orm/task.py — check in TASK_TYPES FILE: src/backend/models/orm/task_result.py, models/api/task_result.py, api/routers/task_results.py — tabella task_results, POST e GET /api/task-results (NOK senza nota → 422) FILE: src/frontend/flask_app/templates/maker/task_editor.html — tipo nell'editor FILE: src/frontend/flask_app/static/js/task-results.js, templates/measure/task_execute.html, blueprints/measure.py — pulsanti OK/NOK, nota, proxy MIGRAZIONE: 018_task_loop_results COMMIT: df1727b f541f4a c6d4260 21f8bae PROVA: suite goldrake su b7cb061 → 835 passed 2 skipped (pytest 3.11 backend+frontend), 29 passed (pytest 3.13 vision), docker build vision ok; test src/backend/tests/test_task_results.py, src/frontend/flask_app/tests/test_measure_task_results.py, tests/js/test_task_results.js DIFFERENZE DALL'ANALISI: l'esito sta nella sessione (task_results.production_run_id) ma non ancora nella vista statistica per sessione: resta in gitea:Adriano/TieMeasureFlow#58. In V3.0.0 da b7cb061 (ramo lavoro/daitarn-trafilo unito in fast-forward da a829bf3).
Adriano removed the assegnata:daitarn label 2026-10-07 12:37:15 +00:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: Adriano/TieMeasureFlow#54