fix(api): allow MeasurementTec to list measurements for task_complete
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) <noreply@anthropic.com>
This commit is contained in:
@@ -97,10 +97,17 @@ async def get_measurements(
|
|||||||
pass_fail: str | None = Query(None, pattern="^(pass|warning|fail)$"),
|
pass_fail: str | None = Query(None, pattern="^(pass|warning|fail)$"),
|
||||||
page: int = Query(1, ge=1),
|
page: int = Query(1, ge=1),
|
||||||
per_page: int = Query(50, ge=1, le=500),
|
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),
|
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
|
# Build filter conditions
|
||||||
filters = []
|
filters = []
|
||||||
if recipe_id is not None:
|
if recipe_id is not None:
|
||||||
|
|||||||
@@ -211,6 +211,43 @@ class TestListMeasurements:
|
|||||||
assert "total" in data
|
assert "total" in data
|
||||||
assert data["total"] >= 3
|
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(
|
async def test_measurement_by_recipe_filter(
|
||||||
self,
|
self,
|
||||||
client: AsyncClient,
|
client: AsyncClient,
|
||||||
|
|||||||
Reference in New Issue
Block a user