"""值班排班 Pydantic schemas""" from __future__ import annotations from datetime import date from typing import List, Literal, Optional from pydantic import BaseModel, Field, field_validator LinkStatus = Literal["open", "closed"] SourceType = Literal["assign", "grab"] class DutyAssignmentIn(BaseModel): source: SourceType = "assign" userId: Optional[str] = None personName: str = "" class DutySlotSaveIn(BaseModel): shiftType: str = Field(min_length=1, max_length=32) capacity: int = Field(ge=1, le=99) workPlans: List[str] = [] remark: Optional[str] = Field(default=None, max_length=500) startTime: Optional[str] = Field(default=None, description="HH:mm") endTime: Optional[str] = Field(default=None, description="HH:mm") crossDay: bool = False assignments: List[DutyAssignmentIn] = [] @field_validator("workPlans", mode="before") @classmethod def _split_work_plans(cls, v): if v is None: return [] if isinstance(v, str): return [p.strip() for p in v.replace(",", ",").split(",") if p.strip()] return v class DutyDaySaveBody(BaseModel): dutyDate: date slots: List[DutySlotSaveIn] linkStatus: Optional[LinkStatus] = None class DutyLinkBody(BaseModel): linkStatus: LinkStatus class DutyGrabBody(BaseModel): shiftType: str = Field(min_length=1, max_length=32) userId: str = Field(min_length=1, max_length=64) class DutyDictEnsureBody(BaseModel): dictType: Literal["duty_shift_type", "duty_work_plan", "duty_time_range"] label: str = Field(min_length=1, max_length=100) preferredValue: Optional[str] = Field(default=None, max_length=64)