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:
1 parent
2e0c64849b
commit
4c32a556de
28 files changed
+1458
-76
No files matched your search
@@ -229,6 +229,19 @@ class TestSubmitAndLock:
|
||||
assert out["approval_order_no"] and out["approval_order_no"].startswith("AP")
|
||||
assert out["locked_at"] is not None
|
||||
|
||||
# 自动通过路径同样固化送审快照(月结头 + 按人明细)
|
||||
order = client.get(
|
||||
"/api/v1/system/approvals",
|
||||
params={"keyword": out["approval_order_no"], "pageSize": 1},
|
||||
headers=admin["headers"],
|
||||
).json()["data"]["list"][0]
|
||||
detail = client.get(
|
||||
f"/api/v1/system/approvals/{order['id']}", headers=admin["headers"]
|
||||
).json()["data"]
|
||||
assert detail["content_source"] == "snapshot"
|
||||
assert detail["snapshot"]["data"]["settlement_month"] == "2026-10"
|
||||
assert detail["snapshot"]["data"]["items"], "月结快照须含按人明细"
|
||||
|
||||
def test_锁定后回款禁改(self, client: TestClient, admin: dict) -> None:
|
||||
from sqlalchemy import select
|
||||
|
||||
@@ -603,6 +616,21 @@ class TestAdjustment:
|
||||
out = resp.json()["data"]
|
||||
assert out["status"] == 2 # 已生效
|
||||
|
||||
# 调整单送审快照:复核者能看到金额/方向/说明,而非只有调整单号
|
||||
order = client.get(
|
||||
"/api/v1/system/approvals",
|
||||
params={"keyword": out["order_no"], "pageSize": 1},
|
||||
headers=admin["headers"],
|
||||
).json()["data"]["list"][0]
|
||||
assert order["order_type"] == 3
|
||||
detail = client.get(
|
||||
f"/api/v1/system/approvals/{order['id']}", headers=admin["headers"]
|
||||
).json()["data"]
|
||||
assert detail["content_source"] == "snapshot"
|
||||
assert detail["snapshot"]["data"]["amount"] == "500.00"
|
||||
assert detail["snapshot"]["data"]["direction"] == 1
|
||||
assert detail["snapshot"]["data"]["reason"] == "补发差额"
|
||||
|
||||
def test_金额恒正校验(self, client: TestClient, admin: dict) -> None:
|
||||
"""守金额无校验缺陷:负数会反转补发/扣减语义,非数值直落库 500。"""
|
||||
_set_switch(client, admin["headers"], "approval.adjustment.enabled", "0")
|
||||
|
||||
Reference in new issue
Block a user