Files
govoplan-tasks/src/govoplan_tasks/backend/schemas.py
T

119 lines
3.7 KiB
Python

from __future__ import annotations
from datetime import datetime
from typing import Any, Literal
from pydantic import BaseModel, Field, model_validator
class WorkAssignmentPayload(BaseModel):
kind: Literal[
"account",
"group",
"role",
"function",
"function_assignment",
"anyone",
]
id: str = Field(min_length=1, max_length=255)
label: str | None = Field(default=None, max_length=500)
class WorkSourcePayload(BaseModel):
module_id: str = Field(min_length=1, max_length=100)
resource_type: str = Field(min_length=1, max_length=100)
resource_id: str = Field(min_length=1, max_length=255)
revision: str | None = Field(default=None, max_length=255)
url: str | None = Field(default=None, max_length=1500)
label: str | None = Field(default=None, max_length=500)
class WorkItemResponse(BaseModel):
id: str
provider_id: str
owner_module: str
tenant_id: str
title: str
status: str
priority: str
summary: str | None = None
required_action: str | None = None
action_url: str | None = None
due_at: datetime | None = None
deferred_until: datetime | None = None
assignments: list[WorkAssignmentPayload] = Field(default_factory=list)
sources: list[WorkSourcePayload] = Field(default_factory=list)
provenance: dict[str, Any] = Field(default_factory=dict)
metadata: dict[str, Any] = Field(default_factory=dict)
revision: str
etag: str | None = None
created_at: datetime | None = None
updated_at: datetime | None = None
class WorkProviderDiagnostic(BaseModel):
provider_id: str
owner_module: str
code: str
message: str
class WorkItemListResponse(BaseModel):
items: list[WorkItemResponse]
total: int
truncated: bool = False
diagnostics: list[WorkProviderDiagnostic] = Field(default_factory=list)
class WorkSummaryResponse(BaseModel):
total: int
open: int
in_progress: int
deferred: int
blocked: int
overdue: int
urgent: int
truncated: bool = False
diagnostics: list[WorkProviderDiagnostic] = Field(default_factory=list)
class TaskCreatePayload(BaseModel):
title: str = Field(min_length=1, max_length=500)
summary: str | None = Field(default=None, max_length=4000)
priority: Literal["low", "normal", "high", "urgent"] = "normal"
due_at: datetime | None = None
required_action: str | None = Field(default=None, max_length=500)
action_url: str | None = Field(default=None, max_length=1500)
assignments: list[WorkAssignmentPayload] = Field(min_length=1, max_length=100)
sources: list[WorkSourcePayload] = Field(default_factory=list, max_length=100)
provenance: dict[str, Any] = Field(default_factory=dict)
metadata: dict[str, Any] = Field(default_factory=dict)
idempotency_key: str = Field(min_length=1, max_length=255)
class TaskActionPayload(BaseModel):
action: Literal["start", "complete", "defer", "reopen", "cancel"]
expected_revision: int = Field(ge=1)
deferred_until: datetime | None = None
comment: str | None = Field(default=None, max_length=4000)
@model_validator(mode="after")
def validate_action(self) -> "TaskActionPayload":
if self.action == "defer" and self.deferred_until is None:
raise ValueError("Deferring a task requires a date and time.")
if self.action != "defer" and self.deferred_until is not None:
raise ValueError("Only a defer action accepts deferred_until.")
return self
__all__ = [
"TaskActionPayload",
"TaskCreatePayload",
"WorkAssignmentPayload",
"WorkItemListResponse",
"WorkItemResponse",
"WorkProviderDiagnostic",
"WorkSourcePayload",
"WorkSummaryResponse",
]