fix(measure): riepilogo fine task filtrato per lotto/seriale/operatore, pagina oltre 500 (#30)

task_complete(): GET /api/measurements ora porta lot_number/serial_number
(sessione) + measured_by (utente corrente), invece del solo version_id -
una seconda produzione sulla stessa versione non pesca più le misure di
altre stazioni/giorni. Risposte oltre 500 misure vengono cicliche per
pagina invece di troncate al primo per_page=500.
production_run_id sarebbe il filtro più preciso ma GET /api/measurements
non lo accetta (lotto A3) e task_execute.html non lo passa in query
(lotto B1): MANCA, annotato nel codice.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-21 22:49:59 +02:00
parent e20299548f
commit 1bb00b14f2
2 changed files with 115 additions and 20 deletions
+44 -20
View File
@@ -354,6 +354,8 @@ def task_complete(recipe_id: int):
"""Task completion summary with all measurements."""
# Retrieve version_id from query params
version_id = request.args.get("version_id")
lot_number = session.get("lot_number", "")
serial_number = session.get("serial_number", "")
# Load recipe for context
recipe_resp = api_client.get(f"/api/recipes/{recipe_id}")
@@ -382,30 +384,52 @@ def task_complete(recipe_id: int):
# Load measurements if version_id provided
measurements = []
if version_id:
meas_resp = api_client.get(
"/api/measurements",
params={"version_id": version_id, "per_page": 500},
)
if not (isinstance(meas_resp, dict) and meas_resp.get("error")):
raw = (
# Scoped to this measurement session, not the whole version (#30): a
# second production run on the same recipe version used to pull in
# every other station's/day's readings too. GET /api/measurements has
# no production_run_id filter yet (that's lotto A3), so lot/serial +
# the current operator is the closest available identity - MANCA:
# once the backend accepts production_run_id, prefer it when the
# active run is known (see _current_run_id()).
params = {"version_id": version_id, "per_page": 500}
if lot_number:
params["lot_number"] = lot_number
if serial_number:
params["serial_number"] = serial_number
user_id = session.get("user_id")
if user_id:
params["measured_by"] = user_id
raw = []
page = 1
while True:
meas_resp = api_client.get(
"/api/measurements", params={**params, "page": page},
)
if isinstance(meas_resp, dict) and meas_resp.get("error"):
break
page_items = (
meas_resp if isinstance(meas_resp, list)
else meas_resp.get("items", [])
)
# Enrich each measurement with nested subtask data
for m in raw:
st = subtask_map.get(m.get("subtask_id"), {})
m["subtask"] = st
m["task_info"] = subtask_task_map.get(m.get("subtask_id"), {})
# Compute deviation if not present
if m.get("deviation") is None and st.get("nominal") is not None:
try:
m["deviation"] = m["value"] - st["nominal"]
except (TypeError, KeyError):
m["deviation"] = 0.0
measurements = raw
raw.extend(page_items)
total_pages = meas_resp.get("pages", 1) if isinstance(meas_resp, dict) else 1
if page >= total_pages or not page_items:
break
page += 1
lot_number = session.get("lot_number", "")
serial_number = session.get("serial_number", "")
# Enrich each measurement with nested subtask data
for m in raw:
st = subtask_map.get(m.get("subtask_id"), {})
m["subtask"] = st
m["task_info"] = subtask_task_map.get(m.get("subtask_id"), {})
# Compute deviation if not present
if m.get("deviation") is None and st.get("nominal") is not None:
try:
m["deviation"] = m["value"] - st["nominal"]
except (TypeError, KeyError):
m["deviation"] = 0.0
measurements = raw
return render_template(
"measure/task_complete.html",