def test_list_vehicles_filters_by_status(ops_client): response = ops_client.get("/api/v1/vehicles", params={"status": "maintenance"}) assert response.status_code == 200 vehicles = response.json() assert len(vehicles) > 0 assert all(v["operational_status"] == "maintenance" for v in vehicles) def test_attention_only_filters_flagged_vehicles(ops_client): response = ops_client.get("/api/v1/vehicles", params={"attention_only": True}) assert response.status_code == 200 vehicles = response.json() assert len(vehicles) > 0 assert all(v["attention"] for v in vehicles) assert all(v["attention_reason"] for v in vehicles) def test_vehicle_list_exposes_planning_and_service_context(ops_client): vehicles = ops_client.get("/api/v1/vehicles").json() assert vehicles assert all("service_remaining_km" in vehicle for vehicle in vehicles) assert all("next_booking_ref" in vehicle for vehicle in vehicles) location = vehicles[0]["location"] filtered = ops_client.get("/api/v1/vehicles", params={"location": location}).json() assert filtered assert all(vehicle["location"].casefold() == location.casefold() for vehicle in filtered) def test_vehicle_page_preserves_filters_and_limits_rendered_records(ops_client): response = ops_client.get( "/api/v1/vehicles", params={"status": "maintenance", "page": 1, "page_size": 25}, ) assert response.status_code == 200 body = response.json() assert len(body["items"]) <= 25 assert all(v["operational_status"] == "maintenance" for v in body["items"]) assert body["total"] >= len(body["items"]) def test_vehicle_detail_includes_related_records(ops_client): response = ops_client.get("/api/v1/vehicles/MO-016") assert response.status_code == 200 body = response.json() assert body["public_ref"] == "MO-016" assert len(body["quality_issues"]) >= 1 def test_employee_vehicle_detail_never_exposes_quality_evidence(employee_client): response = employee_client.get("/api/v1/vehicles/MO-016") assert response.status_code == 200 assert response.json()["quality_issues"] == [] def test_vehicle_detail_404_for_unknown_ref(ops_client): response = ops_client.get("/api/v1/vehicles/MO-999") assert response.status_code == 404 def test_manager_can_record_maintenance_and_release_vehicle(ops_client): vehicle = ops_client.get("/api/v1/vehicles", params={"status": "available"}).json()[0] response = ops_client.post( f"/api/v1/vehicles/{vehicle['public_ref']}/maintenance", json={ "occurred_at": "2051-01-15T09:00:00Z", "odometer_km": vehicle["odometer_km"] + 100, "category": "periodic_service", "summary": "Periodic service completed and safety checks passed.", "next_service_km": vehicle["odometer_km"] + 20100, "mark_maintenance": True, }, ) assert response.status_code == 201 detail = ops_client.get(f"/api/v1/vehicles/{vehicle['public_ref']}").json() assert detail["operational_status"] == "maintenance" assert any( item["public_ref"] == response.json()["public_ref"] for item in detail["maintenance"] ) released = ops_client.post( f"/api/v1/vehicles/{vehicle['public_ref']}/release", json={"reason": "Service completed and vehicle inspected"}, ) assert released.status_code == 200 assert released.json()["operational_status"] == "available" def test_low_maintenance_reading_keeps_canonical_and_opens_quality_issue(ops_client): existing_issues = ops_client.get( "/api/v1/data-quality/issues", params={"status": "open", "rule_type": "odometer_regression"}, ).json() unavailable_refs = {issue["entity_ref"] for issue in existing_issues} vehicles = ops_client.get("/api/v1/vehicles", params={"status": "available"}).json() vehicle = next( candidate for candidate in vehicles if candidate["odometer_km"] > 0 and candidate["public_ref"] not in unavailable_refs ) response = ops_client.post( f"/api/v1/vehicles/{vehicle['public_ref']}/maintenance", json={ "occurred_at": "2053-01-15T12:00:00Z", "odometer_km": vehicle["odometer_km"] - 1, "category": "inspection", "summary": "Imported workshop reading requires verification.", "mark_maintenance": True, }, ) assert response.status_code == 201 detail = ops_client.get(f"/api/v1/vehicles/{vehicle['public_ref']}").json() assert detail["odometer_km"] == vehicle["odometer_km"] issues = ops_client.get( "/api/v1/data-quality/issues", params={"status": "open", "rule_type": "odometer_regression"}, ).json() issue = next(item for item in issues if item["entity_ref"] == vehicle["public_ref"]) assert issue["evidence"]["source_type"] == "maintenance" assert issue["evidence"]["correctable_booking_refs"] == [] issue_detail = ops_client.get(f"/api/v1/data-quality/issues/{issue['public_ref']}").json() assert any( snapshot["entity_type"] == "maintenance" and snapshot["public_ref"] == response.json()["public_ref"] for snapshot in issue_detail["related_snapshots"] ) retained = ops_client.post( f"/api/v1/data-quality/issues/{issue['public_ref']}/resolve-odometer-regression", json={"decision": "retain_canonical"}, ) assert retained.status_code == 200 def test_employee_cannot_record_maintenance(employee_client): response = employee_client.post( "/api/v1/vehicles/MO-001/maintenance", json={ "occurred_at": "2051-01-15T09:00:00Z", "odometer_km": 100, "category": "repair", "summary": "Unauthorised attempt", }, ) assert response.status_code == 403