"""服务项目 Schema""" from typing import Optional, List from datetime import datetime from pydantic import BaseModel, Field class ProjectBase(BaseModel): """项目基础字段""" project_code: str = Field(..., min_length=1, max_length=50, description="项目编码") project_name: str = Field(..., min_length=1, max_length=100, description="项目名称") category_id: Optional[int] = Field(None, description="项目分类ID") description: Optional[str] = Field(None, description="项目描述") duration_minutes: int = Field(0, ge=0, description="操作时长(分钟)") is_active: bool = Field(True, description="是否启用") class ProjectCreate(ProjectBase): """创建项目请求""" pass class ProjectUpdate(BaseModel): """更新项目请求""" project_code: Optional[str] = Field(None, min_length=1, max_length=50, description="项目编码") project_name: Optional[str] = Field(None, min_length=1, max_length=100, description="项目名称") category_id: Optional[int] = Field(None, description="项目分类ID") description: Optional[str] = Field(None, description="项目描述") duration_minutes: Optional[int] = Field(None, ge=0, description="操作时长(分钟)") is_active: Optional[bool] = Field(None, description="是否启用") class CostSummaryBrief(BaseModel): """成本汇总简要信息""" total_cost: float = Field(..., description="总成本(最低成本线)") material_cost: float = Field(..., description="耗材成本") equipment_cost: float = Field(..., description="设备折旧成本") labor_cost: float = Field(..., description="人工成本") fixed_cost_allocation: float = Field(..., description="固定成本分摊") class Config: from_attributes = True class ProjectResponse(ProjectBase): """项目响应""" id: int category_name: Optional[str] = Field(None, description="分类名称") cost_summary: Optional[CostSummaryBrief] = Field(None, description="成本汇总") created_at: datetime updated_at: datetime class Config: from_attributes = True class ProjectListResponse(ProjectBase): """项目列表响应""" id: int category_name: Optional[str] = Field(None, description="分类名称") cost_summary: Optional[CostSummaryBrief] = Field(None, description="成本汇总") created_at: datetime updated_at: datetime class Config: from_attributes = True class ProjectQuery(BaseModel): """项目查询参数""" page: int = Field(1, ge=1, description="页码") page_size: int = Field(20, ge=1, le=100, description="每页数量") category_id: Optional[int] = Field(None, description="分类筛选") keyword: Optional[str] = Field(None, description="关键词搜索") is_active: Optional[bool] = Field(None, description="是否启用") sort_by: str = Field("created_at", description="排序字段") sort_order: str = Field("desc", description="排序方向")