From 85a00dea1b5e14634864f725ef639713231a8363 Mon Sep 17 00:00:00 2001 From: AdrianoDev Date: Mon, 4 May 2026 10:42:16 +0200 Subject: [PATCH] fix(api): allow MeasurementTec to list measurements for task_complete MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GET /api/measurements required Metrologist, but the operator workflow calls it from task_complete.html to render the post-recipe riepilogo — silently empty for every non-Metrologist user. Open to any authenticated user; payload carries no PII beyond numeric values + recipe ref. Regression test added. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/backend/api/routers/measurements.py | 11 ++++++-- src/backend/tests/test_measurements.py | 37 +++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/src/backend/api/routers/measurements.py b/src/backend/api/routers/measurements.py index d23c393..a3057e9 100644 --- a/src/backend/api/routers/measurements.py +++ b/src/backend/api/routers/measurements.py @@ -97,10 +97,17 @@ async def get_measurements( pass_fail: str | None = Query(None, pattern="^(pass|warning|fail)$"), page: int = Query(1, ge=1), per_page: int = Query(50, ge=1, le=500), - user: User = Depends(require_metrologist), + user: User = Depends(get_current_user), db: AsyncSession = Depends(get_db), ): - """Query measurements with filters and pagination.""" + """Query measurements with filters and pagination. + + Available to any authenticated user. The MeasurementTec workflow needs + this endpoint to render `task_complete.html` after running through a + recipe; the Metrologist dashboard uses the same endpoint with broader + filters. Measurements carry no PII beyond numeric values + a recipe + reference, so role-gating beyond authentication isn't justified. + """ # Build filter conditions filters = [] if recipe_id is not None: diff --git a/src/backend/tests/test_measurements.py b/src/backend/tests/test_measurements.py index a5b6d4e..fbdce25 100644 --- a/src/backend/tests/test_measurements.py +++ b/src/backend/tests/test_measurements.py @@ -211,6 +211,43 @@ class TestListMeasurements: assert "total" in data assert data["total"] >= 3 + async def test_measurement_tec_can_list_measurements( + self, + client: AsyncClient, + measurement_tec_user: User, + db_session: AsyncSession, + ): + """Regression: MeasurementTec must be able to list measurements. + + The Flask client renders task_complete.html by calling GET + /api/measurements?version_id=X right after the operator finishes a + recipe. The endpoint used to require Metrologist, which silently + produced an empty riepilogo for every operator without that role. + """ + recipe = await create_test_recipe(db_session, measurement_tec_user.id) + subtask_id, version_id = await _get_subtask_and_version( + client, measurement_tec_user, recipe.id + ) + + for val in [9.8, 10.0, 10.2]: + await client.post( + "/api/measurements/", + headers=auth_headers(measurement_tec_user), + json={ + "subtask_id": subtask_id, + "version_id": version_id, + "value": val, + }, + ) + + resp = await client.get( + f"/api/measurements/?version_id={version_id}", + headers=auth_headers(measurement_tec_user), + ) + assert resp.status_code == 200, resp.text + data = resp.json() + assert data["total"] >= 3 + async def test_measurement_by_recipe_filter( self, client: AsyncClient,