Files
smart-project-pricing/后端服务/app/schemas/project_cost.py
2026-01-31 21:33:06 +08:00

196 lines
5.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""项目成本相关 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