"""月度结算的请求/响应模型(M3 ④)。""" import re from datetime import datetime from decimal import Decimal from pydantic import BaseModel, ConfigDict, Field, field_validator from app.core.response import PageQuery _MONTH_RE = re.compile(r"^\d{4}-\d{2}$") def _check_month(value: str) -> str: """月份格式 YYYY-MM(settlement_month 全表唯一的维度)。""" if not _MONTH_RE.match(value): raise ValueError("月份格式须为 YYYY-MM") return value class SettlementGenerateIn(BaseModel): """月结生成入参。""" month: str = Field(description="结算月份 YYYY-MM") @field_validator("month") @classmethod def _v_month(cls, value: str) -> str: return _check_month(value) class SettlementQuery(PageQuery): """月结列表查询。""" status: int | None = Field(default=None, ge=1, le=4, description="状态筛选") class SettlementItemOut(BaseModel): """月结明细行。""" model_config = ConfigDict(from_attributes=True) id: int personnel_id: int personnel_name: str role_code: str calc_type: int performance_sum: Decimal payable_sum: Decimal basic_amount: Decimal | None = None salary_mode: str | None = None net_amount: Decimal | None = None is_probation: int probation_note: str | None = None class SettlementOut(BaseModel): """月结头表响应。""" model_config = ConfigDict(from_attributes=True) id: int settlement_month: str status: int total_performance: Decimal | None = None total_payable: Decimal | None = None person_count: int approval_order_no: str | None = None submitter_name: str locked_at: datetime | datetime | None = None locked_by: str | None = None create_time: datetime class SettlementDetailOut(SettlementOut): """月结详情:附明细。""" items: list[SettlementItemOut] = Field(default_factory=list) class AdjustmentCreateIn(BaseModel): """调整单创建入参(金额恒正,方向表达补发/扣减)。""" model_config = ConfigDict(str_strip_whitespace=True) settlement_month: str = Field(description="调整月份 YYYY-MM") personnel_id: int = Field(ge=1, description="调整人员ID") direction: int = Field(ge=1, le=2, description="1补发 2扣减") amount: str = Field(description="金额(元,两位小数)") reason: str = Field(min_length=1, max_length=255, description="扣补说明")