打通 T+ 快照、业务、发货、回款和核算准备链路,保留来源差异并提供待补状态。 新增业务自动接入任务、跨平台读取服务托管、权限复核、来源关联和前端核对页面。 补充迁移、隔离集成测试、浏览器模拟验收及角色授权边界修复。
68 lines
2.0 KiB
Python
68 lines
2.0 KiB
Python
"""正式工资核算的最小输入契约;金额使用字符串,资料版本显式校验。"""
|
|
|
|
from typing import Literal
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
|
|
from app.core.month import validate_month
|
|
from app.schemas.tplus_workbench import HandoverFact, _decimal
|
|
|
|
|
|
class PayrollMonthIn(BaseModel):
|
|
month: str
|
|
reason: str | None = Field(default=None, min_length=1, max_length=255)
|
|
|
|
@field_validator("month")
|
|
@classmethod
|
|
def check_month(cls, value):
|
|
return validate_month(value)
|
|
|
|
|
|
class ShipmentOwnershipIn(BaseModel):
|
|
model_config = ConfigDict(extra="forbid")
|
|
shipment_item_id: int = Field(ge=1)
|
|
personnel_id: int = Field(ge=1)
|
|
manager_id: int | None = Field(default=None, ge=1)
|
|
unit_cost: str
|
|
freight_amount: str | None = None
|
|
|
|
@field_validator("freight_amount")
|
|
@classmethod
|
|
def check_freight(cls, value):
|
|
if value is not None:
|
|
_decimal(value, 2)
|
|
return value
|
|
|
|
@field_validator("unit_cost")
|
|
@classmethod
|
|
def check_cost(cls, value):
|
|
_decimal(value, 4)
|
|
return value
|
|
|
|
|
|
class PayrollSetupIn(PayrollMonthIn):
|
|
model_config = ConfigDict(extra="forbid")
|
|
expected_version: int = Field(default=0, ge=0)
|
|
evidence: str = Field(min_length=1, max_length=500)
|
|
opening_balance: str
|
|
history_confirmed: Literal[True]
|
|
guidance_finalized: Literal[True]
|
|
shipment_ownerships: list[ShipmentOwnershipIn] = Field(min_length=1, max_length=10000)
|
|
handovers: list[HandoverFact] = Field(default_factory=list, max_length=1000)
|
|
|
|
@field_validator("opening_balance")
|
|
@classmethod
|
|
def check_opening(cls, value):
|
|
_decimal(value, 2)
|
|
return value
|
|
|
|
|
|
class AllocationAdjustmentIn(BaseModel):
|
|
"""分配差额仅允许归生成当月;关联已结算原台账留痕。"""
|
|
|
|
ledger_id: int = Field(ge=1)
|
|
personnel_id: int = Field(ge=1)
|
|
direction: Literal[1, 2]
|
|
amount: str = Field(pattern=r"^\d{1,12}(\.\d{1,2})?$")
|
|
reason: str = Field(min_length=1, max_length=255)
|