fix(kpi): BEP保本KPI阈值按>=85口径修正 + 新增现金口径派生KPI(剔除折旧560213) + bep-card现金读派生单一事实源 (fin-fix-bep-threshold-20260908)
This commit is contained in:
@@ -1,13 +1,16 @@
|
||||
"""保本点(盈亏平衡)派生KPI执行器 — 管理会计OS (cma-bep-kpi 2026-09-08)
|
||||
|
||||
按财务Bot权威口径(陕西酣客_保本点分析_2026年1-7月.md)自动计算并落库三个派生KPI:
|
||||
F_BEP_REVENUE 保本销售额(万元) = 月均管理费 ÷ 边际贡献率
|
||||
F_BEP_COVER 保本覆盖率(%) = 月均销售 ÷ 保本销售额 × 100 (正向: >=100绿 >=85黄 <85红)
|
||||
F_BEP_GAP 保本缺口(%) = (保本销售额-月均销售) ÷ 保本销售额 × 100 (反向: <=0绿 <=15黄 >15红)
|
||||
按财务Bot权威口径(陕西酣客_保本点分析_2026年1-7月.md)自动计算并落库五个派生KPI:
|
||||
F_BEP_REVENUE 保本销售额(万元) = 月均管理费 ÷ 边际贡献率 (账面口径,含折旧)
|
||||
F_BEP_COVER 保本覆盖率(%) = 月均销售 ÷ 保本销售额 × 100 (正向: >=100绿 >=85黄 <85红)
|
||||
F_BEP_GAP 保本缺口(%) = (保本销售额-月均销售) ÷ 保本销售额 × 100 (反向: <=0绿 <=15黄 >15红)
|
||||
F_BEP_REVENUE_CASH 现金保本销售额(万元) = (月均管理费-月均折旧) ÷ 边际贡献率 (现金口径,剔除折旧560213,中性无阈值)
|
||||
F_BEP_COVER_CASH 现金保本覆盖率(%) = 月均销售 ÷ 现金保本销售额 × 100 (正向: >=100绿 >=85黄 <85红)
|
||||
|
||||
口径(与财务Bot报告一致):
|
||||
- 销售收入: voucher_details.subject_code='5001'(主营业务收入) 贷方合计,当年1月至目标月 YTD 月均
|
||||
- 管理费: subject_code LIKE '5602%'(管理费用,含560213折旧) 借方合计,YTD 月均 → 账面口径
|
||||
- 折旧: subject_code = '560213'(管理费用-折旧叶子) 借方合计,YTD 月均 → 现金口径剔除项(eq精确匹配,防5602130误含)
|
||||
- 渠补率: 厂家政策定死 84.61% (571103渠补支出/5001销售, 1-7月累计凭证验证≈84.0%~84.6%)
|
||||
- 边际贡献率 = 1 - 渠补率 = 15.39%
|
||||
- 目标月: --period 显式指定;默认自动选最近完整月(当月跳过;最近月销售额<近6月均30%视为未结账回退)
|
||||
@@ -45,10 +48,16 @@ TARGET_KPIS = [
|
||||
("F_BEP_REVENUE", "保本销售额"),
|
||||
("F_BEP_COVER", "保本覆盖率"),
|
||||
("F_BEP_GAP", "保本缺口"),
|
||||
("F_BEP_REVENUE_CASH", "现金口径保本销售额"),
|
||||
("F_BEP_COVER_CASH", "现金口径保本覆盖率"),
|
||||
]
|
||||
|
||||
# 现金口径 KPI 编码(计算路径独立于账面,remark 文案用现金口径)
|
||||
CASH_CODES = {"F_BEP_REVENUE_CASH", "F_BEP_COVER_CASH"}
|
||||
|
||||
SALES_CODE = "5001" # 主营业务收入
|
||||
ADMIN_PREFIX = "5602" # 管理费用(含折旧叶子560213)
|
||||
DEP_SUBJECT = "560213" # 管理费用-折旧(现金口径剔除项,eq 精确匹配防 5602130 误含)
|
||||
REBATE_CODE = "571103" # 渠补/捐赠支出(校验用,不直接进公式)
|
||||
|
||||
|
||||
@@ -160,7 +169,7 @@ def _eval_static_threshold(value: float, kpi) -> tuple:
|
||||
|
||||
def run_derive(db, entity_id: int, period: str, rebate_rate_pct: float,
|
||||
write_kpi: bool = True) -> dict:
|
||||
"""计算并落库三个派生KPI。返回结果摘要。"""
|
||||
"""计算并落库五个派生KPI(账面3条+现金2条)。返回结果摘要。"""
|
||||
kpis = {k.kpi_code: k for k in db.query(KPIDefinition).filter(
|
||||
KPIDefinition.entity_id == entity_id,
|
||||
KPIDefinition.kpi_code.in_([c for c, _ in TARGET_KPIS]),
|
||||
@@ -179,9 +188,12 @@ def run_derive(db, entity_id: int, period: str, rebate_rate_pct: float,
|
||||
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
|
||||
|
||||
sales_avg = sales_sum_w / months
|
||||
admin_avg = admin_sum_w / months
|
||||
dep_avg = dep_sum_w / months
|
||||
cash_admin_avg = admin_avg - dep_avg # 现金口径固定成本(剔除折旧纸面费用)
|
||||
|
||||
# 2. 渠补率:厂家政策值优先,日志附凭证累计校验
|
||||
calc_rebate = (rebate_sum_w / sales_sum_w * 100.0) if sales_sum_w > 0 else 0.0
|
||||
@@ -189,15 +201,19 @@ def run_derive(db, entity_id: int, period: str, rebate_rate_pct: float,
|
||||
rebate_rate_pct = POLICY_REBATE_RATE_PCT
|
||||
cm_pct = 100.0 - rebate_rate_pct # 边际贡献率(%)
|
||||
|
||||
# 3. 派生计算(万元 / %)
|
||||
# 3. 派生计算(万元 / %)——账面3条路径不变;现金口径在账面基础上剔除折旧
|
||||
bep = admin_avg / (cm_pct / 100.0) if cm_pct > 0 else 0.0
|
||||
cover = (sales_avg / bep * 100.0) if bep > 0 else 0.0
|
||||
gap = ((bep - sales_avg) / bep * 100.0) if bep > 0 else 0.0
|
||||
cash_bep = cash_admin_avg / (cm_pct / 100.0) if cm_pct > 0 else 0.0
|
||||
cash_cover = (sales_avg / cash_bep * 100.0) if cash_bep > 0 else 0.0
|
||||
|
||||
values = {
|
||||
"F_BEP_REVENUE": round(bep, 1),
|
||||
"F_BEP_COVER": round(cover, 1),
|
||||
"F_BEP_GAP": round(gap, 1),
|
||||
"F_BEP_REVENUE_CASH": round(cash_bep, 1),
|
||||
"F_BEP_COVER_CASH": round(cash_cover, 1),
|
||||
}
|
||||
|
||||
# 4. upsert kpi_values (source_type='derived',幂等)
|
||||
@@ -206,6 +222,11 @@ def run_derive(db, entity_id: int, period: str, rebate_rate_pct: float,
|
||||
value_rows = {}
|
||||
for code, _ in TARGET_KPIS:
|
||||
kpi = kpis[code]
|
||||
if code in CASH_CODES:
|
||||
remark = (f"现金口径: 管理费月均{admin_avg:.2f}万-折旧月均{dep_avg:.2f}万"
|
||||
f"=固定现金{cash_admin_avg:.2f}万 ÷ 边际贡献率{cm_pct:.2f}% → 保本{cash_bep:.2f}万")
|
||||
else:
|
||||
remark = f"保本派生器: 销售月均{sales_avg:.1f}万/管理费月均{admin_avg:.1f}万/渠补率{rebate_rate_pct:.2f}%"
|
||||
existing = db.query(KPIValue).filter(
|
||||
KPIValue.kpi_id == kpi.id,
|
||||
KPIValue.period == period,
|
||||
@@ -216,7 +237,7 @@ def run_derive(db, entity_id: int, period: str, rebate_rate_pct: float,
|
||||
if existing:
|
||||
existing.actual_value = values[code]
|
||||
existing.source_batch = batch
|
||||
existing.remark = f"保本派生器: 销售月均{sales_avg:.1f}万/管理费月均{admin_avg:.1f}万/渠补率{rebate_rate_pct:.2f}%"
|
||||
existing.remark = remark
|
||||
existing.data_status = "pending"
|
||||
else:
|
||||
existing = KPIValue(
|
||||
@@ -227,7 +248,7 @@ def run_derive(db, entity_id: int, period: str, rebate_rate_pct: float,
|
||||
source_type="derived",
|
||||
source_batch=batch,
|
||||
data_status="pending",
|
||||
remark=f"保本派生器: 销售月均{sales_avg:.1f}万/管理费月均{admin_avg:.1f}万/渠补率{rebate_rate_pct:.2f}%",
|
||||
remark=remark,
|
||||
)
|
||||
db.add(existing)
|
||||
db.flush()
|
||||
@@ -281,6 +302,9 @@ def run_derive(db, entity_id: int, period: str, rebate_rate_pct: float,
|
||||
"sales_avg": round(sales_avg, 2),
|
||||
"admin_sum_w": round(admin_sum_w, 2),
|
||||
"admin_avg": round(admin_avg, 2),
|
||||
"dep_sum_w": round(dep_sum_w, 2),
|
||||
"dep_avg": round(dep_avg, 2),
|
||||
"cash_admin_avg": round(cash_admin_avg, 2),
|
||||
"rebate_sum_w": round(rebate_sum_w, 2),
|
||||
"rebate_policy_pct": rebate_rate_pct,
|
||||
"rebate_calc_pct": round(calc_rebate, 2),
|
||||
@@ -308,11 +332,15 @@ def main():
|
||||
f"(YTD {r['months']}个月) mode={'dry-run' if args.dry_run else 'write'}")
|
||||
print(f" 销售收入累计 {r['sales_sum_w']:.2f}万 月均 {r['sales_avg']:.2f}万")
|
||||
print(f" 管理费累计 {r['admin_sum_w']:.2f}万 月均 {r['admin_avg']:.2f}万 (含折旧,账面口径)")
|
||||
print(f" 折旧累计 {r['dep_sum_w']:.2f}万 月均 {r['dep_avg']:.2f}万 (560213) | "
|
||||
f"现金固定成本月均 {r['cash_admin_avg']:.2f}万 (管理费-折旧)")
|
||||
print(f" 渠补支出累计 {r['rebate_sum_w']:.2f}万 | 渠补率: 政策{r['rebate_policy_pct']:.2f}% "
|
||||
f"(凭证累计校验 {r['rebate_calc_pct']:.2f}%) | 边际贡献率 {r['cm_pct']:.2f}%")
|
||||
print(f" F_BEP_REVENUE 保本销售额 = {r['values']['F_BEP_REVENUE']} 万元")
|
||||
print(f" F_BEP_COVER 保本覆盖率 = {r['values']['F_BEP_COVER']} %")
|
||||
print(f" F_BEP_GAP 保本缺口 = {r['values']['F_BEP_GAP']} %")
|
||||
print(f" F_BEP_REVENUE_CASH 现金保本销售额 = {r['values']['F_BEP_REVENUE_CASH']} 万元")
|
||||
print(f" F_BEP_COVER_CASH 现金保本覆盖率 = {r['values']['F_BEP_COVER_CASH']} %")
|
||||
print(f" 落库: {r['written']}")
|
||||
finally:
|
||||
db.close()
|
||||
|
||||
Reference in New Issue
Block a user