fix(m3): code-review P0 六项——算错钱与不可用
- 经理聚合分成放大 100 倍:参数按百分数存储(12.5=12.5%),parse_fraction 后调用方又 ×100、函数内部再 ÷100,净效应「绩效×12.5」;去掉调用方 ×100,rate_text 改用实际参数原文(原硬编码 12.5%+5% 参数调整后失真) - 审批联动只认终审:财务节点通过(1→2)不再提前 mark_locked/调整单生效, 否则领导驳回后 locked_at/locked_by 残留、两级审批形同虚设;驳回在任何 节点即时联动;mark_rejected 补清锁定字段 - 调整单新建不可用:ENABLE_CODE_BY_TYPE 未登记 type=3 → is_enabled 恒 400; 补登记 approval.adjustment.enabled。另修复叠加缺陷——开关关闭分支手工 ApprovalStep(order_id=调整单id),而该外键指向 approval_orders,必然 errno 1452;统一改走 submit_order(自动通过留痕由它负责) - 重算双重计提:业务级一次性计提的「进度登记」回款无生效台账行,重算会 凭空落新行;无旧行一律 400 - 前端重算传错 id:台账行主键当 receipt_id 传给重算接口,会作废无关回款 的台账;改传 row.receipt_id(聚合行防御) - quantize 显式 ROUND_HALF_UP:9 处金额 quantize 缺省银行家舍入, x.xx5 与四舍五入口径差 1 分(docstring 却声称 HALF_UP) 测试:显式控制审批开关(V8 起种子默认开启,用例不再依赖默认值); 新增回归 4 例(经理聚合比例/调整单即生效/进度登记重算 400/财务节点不提前 锁定),test_calc+test_settlements 22 passed Co-Authored-By: Claude Code <noreply@anthropic.com>
This commit is contained in:
1 parent
35fe37fb0c
commit
cb4f38dfd9
6 files changed
+274
-68
No files matched your search
@@ -15,7 +15,7 @@
|
||||
|
||||
import logging
|
||||
from dataclasses import dataclass
|
||||
from decimal import Decimal
|
||||
from decimal import ROUND_HALF_UP, Decimal
|
||||
from fractions import Fraction
|
||||
from typing import Any
|
||||
|
||||
@@ -118,11 +118,17 @@ def calc_receipt(
|
||||
if business.owner_personnel_id is None:
|
||||
raise BadRequestError("业务未指定负责营销人员,无法核算(先在业务归属中指定)")
|
||||
|
||||
# 重算:先作废旧版本行(is_active=0),折算体随后按当前参数重算
|
||||
# 重算:先作废旧版本行(is_active=0),折算体随后按当前参数重算。
|
||||
# 无生效行 = 该回款是「进度登记」(业务级一次性计提 #25 的第二笔及
|
||||
# 以后)——本无独立计提,继续重算会凭空落一行生效行,同业务出现
|
||||
# 两行生效行导致双重计提 → 一律 400
|
||||
if is_recalc:
|
||||
old = performance_ledger_repository.get_active_by_receipt(session, receipt_id)
|
||||
if old is not None:
|
||||
performance_ledger_repository.mark_inactive(session, old)
|
||||
if old is None:
|
||||
raise BadRequestError(
|
||||
"该回款为进度登记(业务已按一次性计提核算),无独立台账行可重算"
|
||||
)
|
||||
performance_ledger_repository.mark_inactive(session, old)
|
||||
|
||||
# 核算粒度 #25(一期口径,仅首算模式):业务级一次性计提——已有生效
|
||||
# 台账行时,本笔回款仅置已核算状态(支付进度),不重复计提
|
||||
@@ -195,8 +201,11 @@ def calc_receipt(
|
||||
"revenue": str(row_revenue),
|
||||
"profit": str(row_profit),
|
||||
# 行级折算同样固化为两位(to_decimal 对整数值无小数位,
|
||||
# 快照/台账口径需与列一致)
|
||||
"converted": str(row_converted.quantize(Decimal("0.01"))),
|
||||
# 快照/台账口径需与列一致;显式 HALF_UP——Python 默认
|
||||
# 银行家舍入会让 x.xx5 少 1 分)
|
||||
"converted": str(
|
||||
row_converted.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
|
||||
),
|
||||
}
|
||||
)
|
||||
|
||||
@@ -244,8 +253,14 @@ def calc_receipt(
|
||||
snapshot_json["strategy_note"] = _NOTE_MANAGER_PENDING
|
||||
|
||||
def q2(value: Decimal | None) -> Decimal | None:
|
||||
"""金额统一两位小数(HALF_UP):内存/DB/序列化三方一致。"""
|
||||
return value.quantize(Decimal("0.01")) if value is not None else None
|
||||
"""金额统一两位小数(HALF_UP):内存/DB/序列化三方一致。
|
||||
|
||||
显式传 rounding——quantize 缺省是上下文 ROUND_HALF_EVEN(银行家
|
||||
舍入),x.xx5 会舍成偶数值,与业务四舍五入口径差 1 分。
|
||||
"""
|
||||
if value is None:
|
||||
return None
|
||||
return value.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)
|
||||
|
||||
row = performance_ledger_repository.add(
|
||||
session,
|
||||
|
||||
Reference in new issue
Block a user