2026-10-13 00:25:34 -04:00
|
|
|
|
"""回款管理的请求/响应模型(需求 2.2.3)。
|
|
|
|
|
|
|
|
|
|
|
|
金额入参出参一律 str(服务层 Decimal,全程禁 float);字段契约**纯蛇形
|
|
|
|
|
|
直出**(2026-10-13 定稿,无驼峰 alias)。
|
|
|
|
|
|
|
|
|
|
|
|
payment_days 是派生值(发货日 → 回款日的天数,对照表 #1),不在写接口
|
|
|
|
|
|
入参内 —— 落库列只有 shipment_id 源数据,派生值实时计算,发货批次变更
|
|
|
|
|
|
后无需回写历史。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from datetime import date
|
|
|
|
|
|
|
|
|
|
|
|
from pydantic import BaseModel, ConfigDict, Field, field_validator
|
|
|
|
|
|
|
|
|
|
|
|
from app.core.response import PageQuery
|
|
|
|
|
|
|
|
|
|
|
|
# 金额校验是工资系统的红线口径(数字/非负/容量/两位小数拒绝),跨 schema
|
|
|
|
|
|
# 单点复用 T7 定稿工具,禁止各处复制导致口径漂移;AMOUNT_MAX 即
|
|
|
|
|
|
# DECIMAL(14,2) 的容量上限,与回款列容量同源
|
|
|
|
|
|
from app.schemas.business import AMOUNT_MAX, _check_amount
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ReceiptCreateIn(BaseModel):
|
|
|
|
|
|
"""新增回款:业务必选,发货批次可暂不指定(手动指定,对照表 #18)。
|
|
|
|
|
|
|
|
|
|
|
|
shipment_id 指向的发货单必须与本回款同属一个业务(服务层强校验,
|
|
|
|
|
|
数据完整性红线);shipment_id 可空 = 暂未指定,指定后回款天数方可派生。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
model_config = ConfigDict(str_strip_whitespace=True)
|
|
|
|
|
|
|
|
|
|
|
|
business_id: int = Field(ge=1, description="业务ID")
|
2026-10-14 06:46:43 -04:00
|
|
|
|
shipment_id: int | None = Field(default=None, ge=1, description="发货单ID,可空=暂未指定")
|
2026-10-13 00:25:34 -04:00
|
|
|
|
receipt_date: date = Field(description="回款到账日(M3 按此日匹配参数版本)")
|
|
|
|
|
|
amount: str = Field(description="回款金额(元),≥0,最多两位小数")
|
|
|
|
|
|
is_barter: int = Field(default=0, ge=0, le=1, description="以物抵顶标记:1是 0否")
|
|
|
|
|
|
remark: str | None = Field(default=None, max_length=255, description="备注")
|
|
|
|
|
|
|
|
|
|
|
|
@field_validator("amount")
|
|
|
|
|
|
@classmethod
|
|
|
|
|
|
def _check_amount_value(cls, value: str) -> str:
|
|
|
|
|
|
return _check_amount(value, "回款金额", AMOUNT_MAX) or value
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ReceiptUpdateIn(BaseModel):
|
|
|
|
|
|
"""编辑回款(全量替换语义)。
|
|
|
|
|
|
|
|
|
|
|
|
shipment_id 传 None = 清除指定(回到「暂未指定」);amount 是必填项,
|
|
|
|
|
|
全量替换下不存在「不传即不变」的歧义。已核算(settlement_status=1)
|
|
|
|
|
|
的回款在服务层禁改,schema 层不感知该状态。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
model_config = ConfigDict(str_strip_whitespace=True)
|
|
|
|
|
|
|
|
|
|
|
|
shipment_id: int | None = Field(
|
|
|
|
|
|
default=None, ge=1, description="发货单ID,可空=暂未指定(传空清除既有指定)"
|
|
|
|
|
|
)
|
|
|
|
|
|
receipt_date: date = Field(description="回款到账日")
|
|
|
|
|
|
amount: str = Field(description="回款金额(元),≥0,最多两位小数")
|
|
|
|
|
|
is_barter: int = Field(default=0, ge=0, le=1, description="以物抵顶标记:1是 0否")
|
|
|
|
|
|
remark: str | None = Field(default=None, max_length=255, description="备注")
|
|
|
|
|
|
|
|
|
|
|
|
@field_validator("amount")
|
|
|
|
|
|
@classmethod
|
|
|
|
|
|
def _check_amount_value(cls, value: str) -> str:
|
|
|
|
|
|
return _check_amount(value, "回款金额", AMOUNT_MAX) or value
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ReceiptOut(BaseModel):
|
|
|
|
|
|
"""回款响应(列表与写操作回包共用)。
|
|
|
|
|
|
|
|
|
|
|
|
business_no/shipment_no 为关联冗余展示;payment_days 为派生值:
|
|
|
|
|
|
未指定发货批次时为 None,指定后 = 发货日到回款日的天数(发货日首日
|
|
|
|
|
|
计第 1 天)。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
model_config = ConfigDict(from_attributes=True)
|
|
|
|
|
|
|
|
|
|
|
|
id: int
|
|
|
|
|
|
receipt_batch_no: str
|
|
|
|
|
|
business_id: int
|
|
|
|
|
|
business_no: str
|
|
|
|
|
|
shipment_id: int | None = None
|
|
|
|
|
|
shipment_no: str | None = None
|
|
|
|
|
|
receipt_date: date
|
|
|
|
|
|
amount: str
|
|
|
|
|
|
is_barter: int
|
|
|
|
|
|
settlement_status: int
|
|
|
|
|
|
payment_days: int | None = None
|
|
|
|
|
|
remark: str | None = None
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class ReceiptQuery(PageQuery):
|
|
|
|
|
|
"""回款列表查询条件(筛选参数纯蛇形直出,同 BusinessQuery 契约)。"""
|
|
|
|
|
|
|
|
|
|
|
|
business_id: int | None = Field(default=None, ge=1, description="业务筛选")
|
|
|
|
|
|
date_from: date | None = Field(default=None, description="回款到账日起(含)")
|
|
|
|
|
|
date_to: date | None = Field(default=None, description="回款到账日止(含)")
|
|
|
|
|
|
is_barter: int | None = Field(default=None, ge=0, le=1, description="以物抵顶筛选:1是 0否")
|
|
|
|
|
|
settlement_status: int | None = Field(
|
|
|
|
|
|
default=None, ge=0, le=1, description="核算状态筛选:0未核算 1已核算"
|
|
|
|
|
|
)
|