fix(workbench): remove synthetic check projections

This commit is contained in:
2026-09-24 12:01:01 +08:00
parent 1a6ff64bbe
commit e374b5b3cb
25 changed files with 953 additions and 935 deletions
+9 -11
View File
@@ -10,7 +10,7 @@ from app.domain.schemas.shared import NonEmptyStr, PositiveInt, StrictModel
from app.domain.schemas.operational_data import TaskDataSnapshot
from app.domain.schemas.workbench_runtime import (
WorkbenchDateTime,
WorkbenchRuntimeWorkOrderSubtask,
WorkOrderActivity,
)
@@ -290,19 +290,17 @@ class ExternalWorkOrderSnapshot(StrictModel):
work_order_type: Literal["general", "water_quality_complaint", "burst_report"] = "general"
location: NonEmptyStr | None = None
scenario_code: NonEmptyStr | None = None
subtasks: Annotated[
list[WorkbenchRuntimeWorkOrderSubtask], Field(min_length=1, max_length=50)
] | None = None
feedback_requirements: list[NonEmptyStr] = Field(default_factory=list)
activity: list[WorkOrderActivity] = Field(default_factory=list)
origin: Literal["synthetic"]
updated_at: WorkbenchDateTime
@model_validator(mode="after")
def unique_subtasks(self):
if self.subtasks is not None and len(
{item.id for item in self.subtasks}
) != len(self.subtasks):
raise ValueError("work order subtask ids must be unique")
return self
@model_validator(mode="before")
@classmethod
def accept_legacy_snapshot(cls, value):
if isinstance(value, dict):
return {key: item for key, item in value.items() if key != "subtasks"}
return value
class OperationalTaskRun(StrictModel):
+26 -43
View File
@@ -2,7 +2,7 @@
from typing import Annotated, Literal
from pydantic import AwareDatetime, BeforeValidator, JsonValue, model_validator
from pydantic import AwareDatetime, BeforeValidator, Field, JsonValue, model_validator
from app.domain.schemas.shared import (
NonEmptyStr,
@@ -129,42 +129,13 @@ class WorkbenchAnalysisHistoryPage(StrictModel):
next_offset: NonNegativeInt | None
class WorkbenchRuntimeWorkOrderStage(StrictModel):
id: NonEmptyStr
class WorkOrderActivity(StrictModel):
sequence: PositiveInt
occurred_at: WorkbenchDateTime
actor: NonEmptyStr
kind: Literal["created", "updated", "feedback"]
title: NonEmptyStr
status: Literal["done", "current", "pending", "blocked", "skipped"]
owner: NonEmptyStr
time_label: NonEmptyStr
description: NonEmptyStr
class WorkbenchRuntimeWorkOrderSubtask(StrictModel):
id: NonEmptyStr
title: NonEmptyStr
summary: NonEmptyStr
status: Literal["pending", "running", "blocked", "completed", "cancelled"]
scheduled_at: WorkbenchDateTime
location: NonEmptyStr
assignee: NonEmptyStr
duration_minutes: PositiveInt
reply_window_minutes: PositiveInt
stages: list[WorkbenchRuntimeWorkOrderStage]
reply_requirements: list[NonEmptyStr]
@model_validator(mode="after")
def validate_stages(self):
if not self.stages:
raise ValueError("subtask stages must not be empty")
if [stage.sequence for stage in self.stages] != list(
range(1, len(self.stages) + 1)
):
raise ValueError("subtask stages must use contiguous sequence numbers")
if len({stage.id for stage in self.stages}) != len(self.stages):
raise ValueError("subtask stage ids must be unique")
if sum(stage.status == "current" for stage in self.stages) > 1:
raise ValueError("subtask stages may contain at most one current stage")
return self
detail: NonEmptyStr
class WorkbenchRuntimeWorkOrder(StrictModel):
@@ -181,16 +152,28 @@ class WorkbenchRuntimeWorkOrder(StrictModel):
duration_minutes: PositiveInt
source: NonEmptyStr
dispatcher: NonEmptyStr
location: NonEmptyStr | None = None
assignee: NonEmptyStr | None = None
priority: Literal["normal", "urgent"]
subtasks: list[WorkbenchRuntimeWorkOrderSubtask]
feedback_requirements: list[NonEmptyStr] = Field(default_factory=list)
activity: list[WorkOrderActivity] = Field(default_factory=list)
@model_validator(mode="after")
def validate_subtasks(self):
if not self.subtasks:
raise ValueError("work order subtasks must not be empty")
if len({subtask.id for subtask in self.subtasks}) != len(self.subtasks):
raise ValueError("work order subtask ids must be unique")
return self
@model_validator(mode="before")
@classmethod
def accept_legacy_document(cls, value):
if not isinstance(value, dict) or "subtasks" not in value:
return value
document = {key: item for key, item in value.items() if key != "subtasks"}
subtasks = value.get("subtasks") or []
first = subtasks[0] if subtasks else {}
document.setdefault("location", first.get("location"))
document.setdefault("assignee", first.get("assignee"))
document.setdefault("feedback_requirements", list(dict.fromkeys(
requirement for subtask in subtasks
for requirement in subtask.get("reply_requirements", [])
)))
document.setdefault("activity", [])
return document
class WorkbenchRuntimeSnapshot(StrictModel):