fix(workbench): remove synthetic check projections
This commit is contained in:
@@ -5,7 +5,12 @@ import httpx
|
||||
import pytest
|
||||
|
||||
from scripts.run_operational_worker import CredentialProvider, WorkerSettings
|
||||
from scripts.sync_peripheral_work_orders import sync_once, work_order_snapshot
|
||||
from scripts.sync_peripheral_work_orders import (
|
||||
should_project_work_order,
|
||||
sync_once,
|
||||
work_order_snapshot,
|
||||
)
|
||||
from samples.peripheral.seed_identity import SEED_ACTOR_ID
|
||||
from app.domain.schemas.operational_task import ExternalFeedbackCommand
|
||||
|
||||
|
||||
@@ -14,6 +19,29 @@ def anyio_backend():
|
||||
return "asyncio"
|
||||
|
||||
|
||||
def test_unlinked_synthetic_checks_are_not_operational_tasks():
|
||||
order_id = str(uuid4())
|
||||
order = {
|
||||
"work_order_id": order_id,
|
||||
"origin": "synthetic",
|
||||
"created_by": str(SEED_ACTOR_ID),
|
||||
"title": "合成压力偏差复核",
|
||||
"work_order_type": "general",
|
||||
}
|
||||
|
||||
assert not should_project_work_order(order, set())
|
||||
assert should_project_work_order(order, {order_id})
|
||||
assert should_project_work_order(
|
||||
{**order, "work_order_type": "water_quality_complaint"}, set()
|
||||
)
|
||||
assert should_project_work_order(
|
||||
{**order, "title": "现场采样:二次供水出水及末端用户水样"}, set()
|
||||
) is False
|
||||
assert should_project_work_order(
|
||||
{**order, "created_by": str(uuid4()), "title": "合成管材接驳预约"}, set()
|
||||
)
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_sync_creates_one_task_and_only_applies_new_external_revisions():
|
||||
project_id, order_id, task_id = map(str, (uuid4(), uuid4(), uuid4()))
|
||||
@@ -55,12 +83,52 @@ async def test_sync_creates_one_task_and_only_applies_new_external_revisions():
|
||||
assert snapshot["assignee"] == "测试班组"
|
||||
assert snapshot["location"] == "测试位置"
|
||||
assert snapshot["scheduled_at"] == "2026-09-24T08:00:00Z"
|
||||
assert snapshot["subtasks"] is None
|
||||
assert snapshot["feedback_requirements"] == []
|
||||
assert snapshot["activity"] == []
|
||||
# Exercise the real API schema, including the prefixed external identity.
|
||||
accepted = ExternalFeedbackCommand.model_validate(writes[-1][1])
|
||||
assert str(accepted.work_order_snapshot.work_order_id) == order_id
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_sync_skips_unlinked_synthetic_check_before_writing():
|
||||
project_id, order_id = str(uuid4()), str(uuid4())
|
||||
order = {
|
||||
"project_id": project_id,
|
||||
"work_order_id": order_id,
|
||||
"origin": "synthetic",
|
||||
"created_by": str(SEED_ACTOR_ID),
|
||||
"revision": 1,
|
||||
"title": "合成通信核查",
|
||||
"summary": "仅用于外围样板联调",
|
||||
"priority": "normal",
|
||||
"status": "open",
|
||||
"created_at": "2026-09-23T08:00:00Z",
|
||||
"updated_at": "2026-09-23T08:00:00Z",
|
||||
"scheduled_at": None,
|
||||
"work_order_type": "general",
|
||||
}
|
||||
|
||||
def handler(request):
|
||||
assert request.method == "GET"
|
||||
if request.url.host == "sample.test":
|
||||
return httpx.Response(200, json={"items": [order], "next_cursor": None})
|
||||
return httpx.Response(200, json={"items": [], "next_offset": None})
|
||||
|
||||
settings = WorkerSettings(
|
||||
"http://server.test", "http://agent.test", project_id, bearer="TEST_ONLY"
|
||||
)
|
||||
async with httpx.AsyncClient(transport=httpx.MockTransport(handler)) as client:
|
||||
synchronized = await sync_once(
|
||||
client,
|
||||
settings,
|
||||
"http://sample.test",
|
||||
CredentialProvider(settings),
|
||||
)
|
||||
|
||||
assert synchronized == 0
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
async def test_sample_sync_rejects_cross_project_data_before_writing():
|
||||
def handler(request):
|
||||
@@ -74,17 +142,29 @@ async def test_sample_sync_rejects_cross_project_data_before_writing():
|
||||
|
||||
|
||||
@pytest.mark.anyio
|
||||
@pytest.mark.parametrize("investigation_status", ["waiting_human", "queued"])
|
||||
async def test_created_work_order_receipt_routes_feedback_back_to_investigation(investigation_status):
|
||||
@pytest.mark.parametrize(
|
||||
("investigation_status", "expected_feedback_count", "routes_to_investigation"),
|
||||
[
|
||||
("waiting_human", 2, True),
|
||||
("queued", 2, True),
|
||||
("completed", 1, False),
|
||||
],
|
||||
)
|
||||
async def test_created_work_order_receipt_preserves_projection_and_routes_active_feedback(
|
||||
investigation_status,
|
||||
expected_feedback_count,
|
||||
routes_to_investigation,
|
||||
):
|
||||
project_id, order_id, investigation_id, projection_id = map(str, (uuid4(), uuid4(), uuid4(), uuid4()))
|
||||
received = []
|
||||
def handler(request):
|
||||
if request.url.host == "sample.test":
|
||||
return httpx.Response(200, json={"items": [{
|
||||
"project_id": project_id, "work_order_id": order_id, "origin": "synthetic",
|
||||
"created_by": str(uuid4()),
|
||||
"revision": 2, "summary": "采样已完成", "status": "completed", "updated_at": "2026-09-23T09:00:00Z",
|
||||
"title": "合成采样工单", "priority": "normal",
|
||||
"work_order_type": "water_quality_complaint", "created_at": "2026-09-23T08:00:00Z",
|
||||
"work_order_type": "general", "created_at": "2026-09-23T08:00:00Z",
|
||||
"scheduled_at": None,
|
||||
}], "next_cursor": None})
|
||||
if request.method == "POST":
|
||||
@@ -106,8 +186,10 @@ async def test_created_work_order_receipt_routes_feedback_back_to_investigation(
|
||||
], "next_offset": None})
|
||||
settings = WorkerSettings("http://server.test", "http://agent.test", project_id, bearer="TEST_ONLY")
|
||||
async with httpx.AsyncClient(transport=httpx.MockTransport(handler)) as client:
|
||||
assert await sync_once(client, settings, "http://sample.test", CredentialProvider(settings)) == 2
|
||||
assert any(investigation_id in path for path in received)
|
||||
assert await sync_once(
|
||||
client, settings, "http://sample.test", CredentialProvider(settings)
|
||||
) == expected_feedback_count
|
||||
assert any(investigation_id in path for path in received) is routes_to_investigation
|
||||
assert any(projection_id in path for path in received)
|
||||
|
||||
|
||||
@@ -142,11 +224,20 @@ async def test_external_events_start_investigations_without_browser(event_kind):
|
||||
assert investigation["trigger"]["occurred_at"] == "2026-09-23T07:30:00Z"
|
||||
|
||||
|
||||
def test_snapshot_preserves_nested_process_without_inventing_completed_stages():
|
||||
def test_snapshot_preserves_recorded_activity_without_legacy_subtasks():
|
||||
order = {
|
||||
"work_order_id": str(uuid4()), "revision": 4, "title": "合成预约", "summary": "仅测试过程同步",
|
||||
"status": "in_progress", "priority": "normal", "origin": "synthetic",
|
||||
"updated_at": "2026-09-23T09:00:00Z", "work_order_type": "general",
|
||||
"feedback_requirements": ["回填现场检查结果"],
|
||||
"activity": [{
|
||||
"sequence": 1,
|
||||
"occurred_at": "2026-09-23T08:00:00Z",
|
||||
"actor": "测试调度",
|
||||
"kind": "created",
|
||||
"title": "工单创建",
|
||||
"detail": "已创建现场检查工单。",
|
||||
}],
|
||||
"subtasks": [{
|
||||
"id": "visit", "title": "现场检查", "summary": "合成测试,未现场执行",
|
||||
"status": "pending", "scheduled_at": "2026-09-24T08:00:00Z",
|
||||
@@ -157,6 +248,6 @@ def test_snapshot_preserves_nested_process_without_inventing_completed_stages():
|
||||
}],
|
||||
}
|
||||
snapshot = work_order_snapshot(order)
|
||||
assert snapshot["subtasks"] == order["subtasks"]
|
||||
assert snapshot["subtasks"][0]["stages"][0]["status"] == "pending"
|
||||
assert work_order_snapshot({key: value for key, value in order.items() if key != "subtasks"})["subtasks"] is None
|
||||
assert snapshot["feedback_requirements"] == ["回填现场检查结果"]
|
||||
assert snapshot["activity"] == order["activity"]
|
||||
assert "subtasks" not in snapshot
|
||||
|
||||
Reference in New Issue
Block a user