feat(approval): 审批单内容快照与二次分配方案版本化

补齐 code-review 遗留 2 项:审批单此前只固化 ref_id/refer_no 指针,复核者看到
的是业务当前内容;二次分配方案在编辑替换与驳回清空时一律物理删除,方案事实
无处回溯。

- 审批单加 version_no 与 snapshot_json(信封 schema_version/order_type/
  captured_at/data);二次分配、月结、调整单三类提交均固化送审内容,开关关闭
  的自动通过路径同样写快照;详情按 snapshot/live/missing 三态回显,历史单
  只读回退当前内容并显式告警,不回填历史快照
- 二次分配方案行改 append-only 版本化(version_no/is_active,唯一键扩为
  business+version+personnel):编辑替换与驳回清空只置历史,核算与详情默认
  只取生效行,业务详情新增 allocation_history
- 送审内容未变不重提、方案未变不新增版本:判据统一为送审内容,两个
  version_no 语义解耦(方案版本=内容第几版,审批单版本=第几次送审)
- 审批单列表、工作台待办、审批超时预警三处 defer 快照列,避免整列拉取
- 月结提交取行加 for_update,防并发提交算出重复的审批单版本号
- 修复审批类型筛选上界 le=2(调整单无法筛选)、快照金额把空值写成 0.00
- V11 迁移三件套同步(Alembic / db/migration / init-dev.sql)

测试:单元 +16(方案内容比较 10、审批入参 6)、集成 +12;全量 891 passed。

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
liuwenxinandClaude Code committed 2026-10-20 18:30:51 +08:00
1 parent 2e0c64849b
commit 4c32a556de
28 files changed
+1458 -76

No files matched your search

+5 -1
View File
@@ -248,7 +248,7 @@ def submit(
),
meta=meta,
):
settlement = settlement_repository.get_by_id(session, settlement_id)
settlement = settlement_repository.get_by_id(session, settlement_id, for_update=True)
if settlement is None:
raise NotFoundError("月结不存在")
if settlement.status not in (SETTLEMENT_STATUS_DRAFT, SETTLEMENT_STATUS_REJECTED):
@@ -260,6 +260,9 @@ def submit(
ref_id=settlement.id,
refer_no=f"JS{settlement.settlement_month.replace('-', '')}",
submitter=operator,
# 月结明细在生成时已固化;提交时快照让复核者看到的是送审版本,
# 而不是审批期间若发生重生成后的内容
snapshot=approval_service.settlement_content(session, settlement.id),
)
settlement.approval_order_no = order.order_no
if order.status == SETTLEMENT_STATUS_APPROVED:
@@ -573,6 +576,7 @@ def _wire_adjustment_approval(session: Session, order, operator: User) -> None:
ref_id=order.id,
refer_no=order.order_no,
submitter=operator,
snapshot=approval_service.adjustment_content(session, order.id),
)
order.status = (
ADJUSTMENT_STATUS_EFFECTIVE