2026-10-12 23:22:34 -04:00
|
|
|
|
"""回款模型:回款记录与批次追溯。
|
|
|
|
|
|
|
|
|
|
|
|
- shipment_id 为**手动指定**的发货批次(对照表 #18):可空=暂未指定;
|
|
|
|
|
|
必须与 business_id 同属一个业务(服务层强校验,无数据库级约束可表达
|
|
|
|
|
|
跨表同属关系);指定后回款天数方可由 formula.payment_days 派生
|
|
|
|
|
|
- settlement_status 是 **M3 核算防重锚点**(需规 2.3.3「每笔回款仅核算一次,
|
|
|
|
|
|
台账记录核销状态」):预置于本表避免 M3 反向迁移改 M2 表;M3 台账建立后
|
|
|
|
|
|
由核算服务写入,M2 仅维护 0(未核算)
|
|
|
|
|
|
- receipt_date 是 M3 参数版本匹配日(对照表 #11:按回款到账日取时点参数)
|
|
|
|
|
|
- 一期禁负数金额(≥0):红字/退款冲销需求出现时先补设计再放开
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
2026-11-05 05:47:13 -05:00
|
|
|
|
from datetime import date, datetime
|
2026-10-12 23:22:34 -04:00
|
|
|
|
from decimal import Decimal
|
|
|
|
|
|
|
2026-11-05 05:47:13 -05:00
|
|
|
|
from sqlalchemy import Date, DateTime, ForeignKey, Index, Numeric, String
|
2026-10-12 23:22:34 -04:00
|
|
|
|
from sqlalchemy.orm import Mapped, mapped_column
|
|
|
|
|
|
|
|
|
|
|
|
from app.models.base import (
|
|
|
|
|
|
BIGINT_UNSIGNED,
|
|
|
|
|
|
TINYINT_TYPE,
|
|
|
|
|
|
Base,
|
|
|
|
|
|
TimestampMixin,
|
|
|
|
|
|
TPlusSyncMixin,
|
|
|
|
|
|
mysql_table_args,
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
# 绩效核算状态(receipts.settlement_status)
|
|
|
|
|
|
SETTLEMENT_PENDING = 0
|
|
|
|
|
|
SETTLEMENT_DONE = 1
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
class Receipt(Base, TimestampMixin, TPlusSyncMixin):
|
|
|
|
|
|
"""回款表(需求 2.2.3):按业务登记到账款项,批次号系统内唯一。"""
|
|
|
|
|
|
|
|
|
|
|
|
__tablename__ = "receipts"
|
|
|
|
|
|
__table_args__ = mysql_table_args(
|
|
|
|
|
|
"回款表(手动指定发货批次;已核算回款禁改禁删)",
|
|
|
|
|
|
Index("idx_receipts_business_id", "business_id"),
|
|
|
|
|
|
Index("idx_receipts_receipt_date", "receipt_date"),
|
|
|
|
|
|
Index("idx_receipts_settlement_status", "settlement_status"),
|
|
|
|
|
|
Index("idx_receipts_shipment_id", "shipment_id"),
|
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
|
|
id: Mapped[int] = mapped_column(
|
|
|
|
|
|
BIGINT_UNSIGNED, primary_key=True, autoincrement=True, comment="主键ID"
|
|
|
|
|
|
)
|
|
|
|
|
|
receipt_batch_no: Mapped[str] = mapped_column(
|
|
|
|
|
|
String(32),
|
|
|
|
|
|
nullable=False,
|
|
|
|
|
|
unique=True,
|
|
|
|
|
|
comment="回款批次号,自动生成 HK{YYYYMMDD}-{4位当日序号}(系统内唯一;T+ 同步回款以 source_no 幂等)",
|
|
|
|
|
|
)
|
|
|
|
|
|
business_id: Mapped[int] = mapped_column(
|
|
|
|
|
|
BIGINT_UNSIGNED,
|
|
|
|
|
|
ForeignKey("businesses.id", ondelete="RESTRICT"),
|
|
|
|
|
|
nullable=False,
|
|
|
|
|
|
comment="业务ID(businesses.id)",
|
|
|
|
|
|
)
|
|
|
|
|
|
shipment_id: Mapped[int | None] = mapped_column(
|
|
|
|
|
|
BIGINT_UNSIGNED,
|
|
|
|
|
|
ForeignKey("shipments.id", ondelete="RESTRICT"),
|
|
|
|
|
|
comment="发货单ID(shipments.id;手动指定的回款对应批次,须与本行业务一致;NULL=暂未指定)",
|
|
|
|
|
|
)
|
|
|
|
|
|
receipt_date: Mapped[date] = mapped_column(
|
|
|
|
|
|
Date, nullable=False, comment="回款到账日(M3 按此日匹配参数版本,对照表 #11)"
|
|
|
|
|
|
)
|
|
|
|
|
|
amount: Mapped[Decimal] = mapped_column(
|
|
|
|
|
|
Numeric(14, 2), nullable=False, comment="回款金额(≥0;一期禁负数/红字)"
|
|
|
|
|
|
)
|
|
|
|
|
|
is_barter: Mapped[int] = mapped_column(
|
|
|
|
|
|
TINYINT_TYPE,
|
|
|
|
|
|
nullable=False,
|
|
|
|
|
|
server_default="0",
|
|
|
|
|
|
comment="以物抵顶标记:1是 0否(M3 核算按应发绩效×barter.discount 折算,M2 仅标记)",
|
|
|
|
|
|
)
|
|
|
|
|
|
settlement_status: Mapped[int] = mapped_column(
|
|
|
|
|
|
TINYINT_TYPE,
|
|
|
|
|
|
nullable=False,
|
|
|
|
|
|
server_default="0",
|
|
|
|
|
|
comment="绩效核算状态:0未核算 1已核算(M3 核算防重锚点;已核算回款禁改禁删)",
|
|
|
|
|
|
)
|
2026-11-05 05:47:13 -05:00
|
|
|
|
confirmation_status: Mapped[int] = mapped_column(
|
|
|
|
|
|
TINYINT_TYPE, nullable=False, server_default="0", comment="人工确认状态:0待确认 1已确认,独立于凭证及核算状态"
|
|
|
|
|
|
)
|
|
|
|
|
|
confirmed_by: Mapped[str | None] = mapped_column(String(64), comment="人工确认人账号快照")
|
|
|
|
|
|
confirmed_at: Mapped[datetime | None] = mapped_column(DateTime, comment="人工确认时间")
|
|
|
|
|
|
confirmed_revision: Mapped[str | None] = mapped_column(String(64), comment="人工确认时回款关键内容指纹")
|
2026-10-12 23:22:34 -04:00
|
|
|
|
remark: Mapped[str | None] = mapped_column(String(255), comment="备注")
|