fix(bep-caliber): expense and profit sums use net (debit minus credit) under carry_forward=0
ci/woodpecker/push/main Pipeline failed

ASK-20261002-06 fix04u: admin(5602%) and depreciation(560213) take net amount in both the dashboard card helper and the BEP deriver; sales (5001) keeps credit_amount. Verbatim per proposal section 2. No DB writes, no kpi_values backfill.
This commit is contained in:
Hermes CI Fix
2026-10-02 11:22:38 +08:00
parent 6c1ea85d71
commit 6be903fbc9
3 changed files with 121 additions and 12 deletions
+14 -7
View File
@@ -9,8 +9,8 @@
口径(与财务Bot报告一致):
- 销售收入: voucher_details.subject_code='5001'(主营业务收入) 贷方合计,当年1月至目标月 YTD 月均
- 管理费: subject_code LIKE '5602%'(管理费用,含560213折旧) 借方合计,YTD 月均 → 账面口径
- 折旧: subject_code = '560213'(管理费用-折旧叶子) 借方合计,YTD 月均 → 现金口径剔除项(eq精确匹配,防5602130误含)
- 管理费: subject_code LIKE '5602%'(管理费用,含560213折旧) 借−贷净额合计(carry_forward=0),YTD 月均 → 账面口径
- 折旧: subject_code = '560213'(管理费用-折旧叶子) 借−贷净额合计(carry_forward=0),YTD 月均 → 现金口径剔除项(eq精确匹配,防5602130误含)
- 渠补率: 厂家政策定死 84.61% (571103渠补支出/5001销售, 1-7月累计凭证验证≈84.0%~84.6%)
- 边际贡献率 = 1 - 渠补率 = 15.39%
- 目标月: --period 显式指定;默认自动选最近「已结账」完整月(当月跳过)。
@@ -137,8 +137,15 @@ def _month_range(period: str):
def _sum_field(db, entity_id: int, period_from: str, period_to: str,
field: str, subject_filter=None) -> float:
"""聚合 voucher_details 金额(元)。subject_filter: ('eq', code) / ('like', prefix)"""
q = db.query(func.sum(getattr(VoucherDetail, field))).filter(
"""聚合 voucher_details 金额(元)。subject_filter: ('eq', code) / ('like', prefix)
field="net" = 借−贷 净额(口径4:费用/损益一律净额)。
⚠️ 净额只在 carry_forward==0 行域成立(含结转腿时损益类净额恒 0)
—— 见 /srv/hermes/wisdom/_decisions/cma-expense-profit-net-caliber-20261002.md。
"""
expr = (VoucherDetail.debit_amount - VoucherDetail.credit_amount
if field == "net" else getattr(VoucherDetail, field))
q = db.query(func.sum(expr)).filter(
VoucherDetail.entity_id == entity_id,
VoucherDetail.carry_forward == 0,
VoucherDetail.period >= period_from,
@@ -299,9 +306,9 @@ def run_derive(db, entity_id: int, period: str, rebate_rate_pct: float,
# 1. 取数(元 → 万元)
sales_sum_w = _sum_field(db, entity_id, period_from, period_to, "credit_amount", ("eq", SALES_CODE)) / 10000.0
admin_sum_w = _sum_field(db, entity_id, period_from, period_to, "debit_amount", ("like", ADMIN_PREFIX)) / 10000.0
rebate_sum_w = _sum_field(db, entity_id, period_from, period_to, "debit_amount", ("eq", REBATE_CODE)) / 10000.0
dep_sum_w = _sum_field(db, entity_id, period_from, period_to, "debit_amount", ("eq", DEP_SUBJECT)) / 10000.0
admin_sum_w = _sum_field(db, entity_id, period_from, period_to, "net", ("like", ADMIN_PREFIX)) / 10000.0
rebate_sum_w = _sum_field(db, entity_id, period_from, period_to, "net", ("eq", REBATE_CODE)) / 10000.0
dep_sum_w = _sum_field(db, entity_id, period_from, period_to, "net", ("eq", DEP_SUBJECT)) / 10000.0
sales_avg = sales_sum_w / months
admin_avg = admin_sum_w / months