"""项目成本相关 Schema""" from typing import Optional, List from datetime import datetime from enum import Enum from pydantic import BaseModel, Field class CostItemType(str, Enum): """成本明细类型枚举""" MATERIAL = "material" # 耗材 EQUIPMENT = "equipment" # 设备 class AllocationMethod(str, Enum): """固定成本分摊方式枚举""" COUNT = "count" # 按项目数量平均分摊 REVENUE = "revenue" # 按项目营收占比分摊 DURATION = "duration" # 按项目时长占比分摊 # ============ 项目成本明细(耗材/设备)Schema ============ class CostItemBase(BaseModel): """成本明细基础字段""" item_type: CostItemType = Field(..., description="类型:material/equipment") item_id: int = Field(..., description="耗材/设备ID") quantity: float = Field(..., gt=0, description="用量") remark: Optional[str] = Field(None, max_length=200, description="备注") class CostItemCreate(CostItemBase): """创建成本明细请求""" pass class CostItemUpdate(BaseModel): """更新成本明细请求""" quantity: Optional[float] = Field(None, gt=0, description="用量") remark: Optional[str] = Field(None, max_length=200, description="备注") class CostItemResponse(BaseModel): """成本明细响应""" id: int item_type: CostItemType item_id: int item_name: Optional[str] = Field(None, description="耗材/设备名称") quantity: float unit: Optional[str] = Field(None, description="单位") unit_cost: float total_cost: float remark: Optional[str] = None created_at: datetime updated_at: datetime class Config: from_attributes = True # ============ 项目人工成本 Schema ============ class LaborCostBase(BaseModel): """人工成本基础字段""" staff_level_id: int = Field(..., description="人员级别ID") duration_minutes: int = Field(..., gt=0, description="操作时长(分钟)") remark: Optional[str] = Field(None, max_length=200, description="备注") class LaborCostCreate(LaborCostBase): """创建人工成本请求""" pass class LaborCostUpdate(BaseModel): """更新人工成本请求""" staff_level_id: Optional[int] = Field(None, description="人员级别ID") duration_minutes: Optional[int] = Field(None, gt=0, description="操作时长(分钟)") remark: Optional[str] = Field(None, max_length=200, description="备注") class LaborCostResponse(BaseModel): """人工成本响应""" id: int staff_level_id: int level_name: Optional[str] = Field(None, description="级别名称") duration_minutes: int hourly_rate: float labor_cost: float remark: Optional[str] = None created_at: datetime updated_at: datetime class Config: from_attributes = True # ============ 成本计算相关 Schema ============ class CalculateCostRequest(BaseModel): """计算成本请求""" fixed_cost_allocation_method: AllocationMethod = Field( AllocationMethod.COUNT, description="固定成本分摊方式" ) class CostBreakdownItem(BaseModel): """成本明细项""" name: str quantity: Optional[float] = None unit: Optional[str] = None unit_cost: Optional[float] = None depreciation_per_use: Optional[float] = None duration_minutes: Optional[int] = None hourly_rate: Optional[float] = None total: float class CostBreakdown(BaseModel): """成本分项""" items: List[CostBreakdownItem] subtotal: float class FixedCostAllocationDetail(BaseModel): """固定成本分摊详情""" method: str total_fixed_cost: float project_count: Optional[int] = None total_revenue: Optional[float] = None total_duration: Optional[int] = None allocation: float class CostCalculationResult(BaseModel): """成本计算结果""" project_id: int project_name: str cost_breakdown: dict = Field(..., description="成本分项明细") total_cost: float = Field(..., description="总成本") min_price_suggestion: float = Field(..., description="建议最低售价(等于总成本)") calculated_at: datetime class CostSummaryResponse(BaseModel): """成本汇总响应""" project_id: int material_cost: float equipment_cost: float labor_cost: float fixed_cost_allocation: float total_cost: float calculated_at: datetime class Config: from_attributes = True # ============ 项目详情(含成本)Schema ============ class ProjectDetailResponse(BaseModel): """项目详情响应(含成本明细)""" id: int project_code: str project_name: str category_id: Optional[int] category_name: Optional[str] description: Optional[str] duration_minutes: int is_active: bool cost_items: List[CostItemResponse] = [] labor_costs: List[LaborCostResponse] = [] cost_summary: Optional[CostSummaryResponse] = None created_at: datetime updated_at: datetime class Config: from_attributes = True