feat(settlement): 月度结算快照生成与审批锁定,调整单(补发/扣减)与审批联动

- settlement_service:generate(确认回款口径 #8 策略点=有效台账行按回款日
  归月、经理聚合 #12 暂口径基数不含经理个人户、月结 uk 一行一月、草稿/
  驳回可重生成、已审定/待审 400)→ submit(审批开关分流,关=自动通过即
  锁定、开=待财务复核)→ approval_service.act 扩 order_type=2/3 钩子
  (通过=mark_locked/调整单生效;驳回=回草稿/作废,延迟导入防循环)
- 锁定拦截:回款新增写路径校验回款月已审定 400(比需求「提示」取硬,
  一期安全侧;M2 已核算禁改防线先于其生效)
- 调整单:新建(TZ 单号,开关分流自动通过留痕/走审批)+ 列表
- schemas settlement:金额 Decimal 声明(str 声明遇 Decimal 入参拒绝)
- 测试 6 例:生成回填/无记录 400/已审定重生成 400/关自动锁定/锁定后回款
  禁改/开两节点流转至锁定(finance→leader)

Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
liuwenxinandClaude Code committed 2026-10-17 00:33:31 +08:00
1 parent 22a2872100
commit e7e47d88bc
8 files changed
+1177

No files matched your search

+26
View File
@@ -240,6 +240,32 @@ def act(
business_repository.delete_allocations(session, order.ref_id)
# 审批结果联动(服务层回调,不 commit):月结 通过=锁定/驳回=回草稿;
# 调整单 通过=生效/驳回=作废。函数内延迟导入防循环依赖。
if order.order_type == 2 or order.order_type == 3:
from app.models import AdjustmentOrder
from app.models.settlement import (
ADJUSTMENT_STATUS_EFFECTIVE,
)
from app.models.settlement import (
ADJUSTMENT_STATUS_REJECTED as ADJ_REJECTED,
)
from app.services import settlement_service
if order.order_type == 2:
from app.models.settlement import MonthlySettlement
target = session.get(MonthlySettlement, order.ref_id)
if target is not None:
if rejected:
settlement_service.mark_rejected(session, target, operator=operator)
else:
settlement_service.mark_locked(session, target, operator=operator)
else:
adj = session.get(AdjustmentOrder, order.ref_id)
if adj is not None:
adj.status = ADJ_REJECTED if rejected else ADJUSTMENT_STATUS_EFFECTIVE
# 出参(含 steps)在 **commit 之前** 固化:audit 禁止 commit 后再碰
# ORM/查询——commit 后的任何 SELECT 失败都会让「已通过的审批」被记
# 成失败审计,与库中事实相反(全 services 层唯一例外不许再犯)