fix(cvp): BEP ⑤ 口径统一落地(变动成本率=完整口径)
ci/woodpecker/push/main Pipeline failed

- 派生器/口径:F_BEP_VC_RATE 新增;卡面/公式行文案改「月固定成本 ÷ 边际贡献率」
- 保本额 = 月固定成本 ÷ (1 − 变动成本率);实测渠补率(F_BEP_REBATE)降为 e1 专用 chip
- 报告卡口径说明文字同步(固定成本=固定费用合计)

任务: finance-20261003-cvp-fix-and-bohai-coverage-fullstack ⑤
This commit is contained in:
wecom-fullstack
2026-10-04 19:53:12 +08:00
committed by Hermes CI Fix
parent 4fe956fcf9
commit 587d5b3983
5 changed files with 240 additions and 77 deletions
+133 -44
View File
@@ -6,11 +6,14 @@
F_BEP_GAP 保本缺口(%) = (保本销售额-月均销售) ÷ 保本销售额 × 100 (反向: <=0绿 <=15黄 >15红)
F_BEP_REVENUE_CASH 现金保本销售额(万元) = (月均固定成本-月均折旧) ÷ 边际贡献率 (现金口径,中性无阈值)
F_BEP_COVER_CASH 现金保本覆盖率(%) = 月均销售 ÷ 现金保本销售额 × 100 (正向: >=100绿 >=85黄 <85红)
F_BEP_REBATE 变动/渠补率(%) = 见下方「实体口径注册表」 (YTD累计; 卡面单一事实源,无阈值)
F_BEP_VC_RATE 变动成本率(%) = 见下方「实体口径注册表」 (YTD累计; 保本公式分母,无阈值)
F_BEP_REBATE 实测渠补率(%) = e1 专用展示 chip(Σ571103÷Σ5001,YTD; e2 无渠补科目 ⇒ NULL)
实体口径注册表(2026-10-03 新增,任务 finance-20261003-cvp-fix-and-bohai-coverage-fullstack):
· entity 1 陕西酣客:变动成本率 = Σ571103借方 ÷ Σ5001贷方(实测渠补率);固定成本 = 5602% 净额;
折旧剔除 = 560213(管理费用-折旧叶子)。
· entity 1 陕西酣客:变动成本率 = Σ(5401销货成本 + 5403税金及附加 + 571103渠补 − 530103厂补) ÷ Σ5001贷方
〔⑤口径统一 2026-10-03,任总 18:00「统一」;勾稽:808.80 − 672.65 − 224.16 = −88.01 ≈ −88.00 营业利润〕;
固定成本 = 5601% + 5602% + 5603% 净额;折旧剔除 = 560213(管理费用-折旧叶子)。
实测渠补率 F_BEP_REBATE 保留(仍是渠补单一事实源),但**不再充当变动成本率**。
· entity 2 博海:**无渠补科目(571103)**,变动成本 = Σ6401借(主营业务成本),
变动成本率 = Σ6401借 ÷ Σ6001贷;固定成本 = (6601 销售费用 + 6602 管理费用 + 6603 财务费用) 净额;
折旧剔除 = 1602 累计折旧「当期贷方发生额」(博海科目表只到 4 位一级,无费用类折旧叶子;
@@ -21,11 +24,11 @@
口径(与财务Bot报告一致):
- 销售收入: entity1 = subject_code='5001'(主营业务收入) 贷方合计;entity2 = '6001' 贷方合计。当年1月至目标月 YTD 月均
- 固定成本: entity1 = subject_code LIKE '5602%'(管理费用,含560213折旧) 借−贷净额合计(carry_forward=0),YTD 月均
- 固定成本: entity1 = subject_code LIKE '5601%'/'5602%'/'5603%'(销售/管理/财务费用,含560213折旧) 借−贷净额合计(carry_forward=0),YTD 月均〔⑤扩容〕
entity2 = 6601/6602/6603 借−贷净额合计(同上,但另需剔除结转腿)
- 折旧: entity1 = '560213' 借−贷净额;entity2 = '1602' 贷方发生额(现金口径剔除项)
- 变动成本率: **实测累计口径**(2026-10-02 财务裁定,任总 11:43 CST 放行「改,这样数据更加真实」)
酣客 渠补率(实测) = Σ(571103 借方) ÷ Σ(5001 贷方) × 100,期间 = 年初至当期(YTD),保留 2 位小数。
- 变动成本率: **完整实测口径**(⑤口径统一 2026-10-03,任总 18:00「统一」;勾稽件 _reports/陕西酣客_边际贡献式损益表_20261003.md)
酣客 = Σ(5401销货成本 + 5403税金及附加 + 571103渠补 − 530103厂补) ÷ Σ(5001 贷方) × 100,YTD,保留 2 位小数。
`POLICY_REBATE_RATE_PCT = 84.61` 政策常量**仅作对照展示**(写进返回值 rebate_policy_pct / remark),
**不参与任何计算**;`--rebate-rate` 显式传值时视为人工诊断覆盖(正常调用不再使用)。
- 边际贡献率 = 100 − 变动成本率
@@ -85,13 +88,17 @@ TARGET_KPIS = [
("F_BEP_GAP", "保本缺口"),
("F_BEP_REVENUE_CASH", "现金口径保本销售额"),
("F_BEP_COVER_CASH", "现金口径保本覆盖率"),
("F_BEP_VC_RATE", "变动成本率"),
("F_BEP_REBATE", "实测渠补率"),
]
# 实测渠补率 KPI 编码(卡面单一事实源;无阈值,不参与预警级别判定)
# 变动成本率 KPI(⑤ 口径统一 2026-10-03:保本公式分子口径 = 销货成本+税金及附加+渠补−厂补)
VC_RATE_KPI = "F_BEP_VC_RATE"
# 实测渠补率 KPI 编码(卡面单一事实源;无阈值,不参与预警级别判定;⑤ 后**不再充当变动成本率**)
REBATE_KPI = "F_BEP_REBATE"
# 保本口径 KPI(缺 F_BEP_REBATE 定义时不阻断派生主流程,仅跳过渠补率落库并告警)
# 保本口径 KPI(缺 F_BEP_REBATE 定义时不阻断派生主流程,见 run_derive 告警分支)
CORE_KPI_CODES = [c for c, _ in TARGET_KPIS if c != REBATE_KPI]
# 现金口径 KPI 编码(计算路径独立于账面,remark 文案用现金口径)
@@ -222,6 +229,42 @@ def _subject_clause(kind: str, code: str):
raise ValueError(f"未知科目过滤类型: {kind}")
# 带号科目项的字段映射(terms 记法见 bep_caliber.ENTITY_CALIBERS)
_TERM_FIELD = {
"debit": lambda: VoucherDetail.debit_amount,
"credit": lambda: VoucherDetail.credit_amount,
"net": lambda: VoucherDetail.debit_amount - VoucherDetail.credit_amount,
}
def _sum_terms(db, entity_id: int, period_from: str, period_to: str,
terms, *, exclude_closing: bool = False) -> float:
"""按「带号科目项」聚合金额(元)。terms = [(sign, code, field), ...]
· sign='+' ⇒ 加该科目 field 发生额;sign='-' ⇒ 减之
· field ∈ {debit, credit, net}
· code 以 '%' 结尾时按前缀(like)匹配,否则精确匹配
⑤ 口径统一(2026-10-03):酣客变动成本 = (Σ5401借 + Σ5403借 + Σ571103借 − Σ530103贷)。
"""
total = 0.0
for sign, code, field in terms:
expr = _TERM_FIELD[field]()
q = db.query(func.sum(expr)).filter(
VoucherDetail.entity_id == entity_id,
VoucherDetail.carry_forward == 0,
VoucherDetail.period >= period_from,
VoucherDetail.period <= period_to,
)
q = (q.filter(VoucherDetail.subject_code.like(code)) if code.endswith("%")
else q.filter(VoucherDetail.subject_code == code))
if exclude_closing:
q = q.filter(or_(VoucherDetail.summary.is_(None),
~VoucherDetail.summary.like(CLOSING_SUMMARY_LIKE)))
v = float(q.scalar() or 0.0)
total += v if sign == "+" else -v
return total
def compute_margin_rate(db, entity_id: int, period_from: str, period_to: str,
caliber: dict = None) -> dict:
"""变动成本率(YTD 累计,2 位小数)—— 按实体口径现算。
@@ -236,9 +279,8 @@ def compute_margin_rate(db, entity_id: int, period_from: str, period_to: str,
(调用方不得回落政策常量,须按「不可得」处理)。
"""
cal = caliber or ENTITY_CALIBERS[entity_id]
num_raw = _sum_field(db, entity_id, period_from, period_to,
cal["varcost_field"], cal["varcost_filter"],
exclude_closing=cal["exclude_closing"])
num_raw = _sum_terms(db, entity_id, period_from, period_to,
cal["varcost_terms"], exclude_closing=cal["exclude_closing"])
den_raw = _sum_field(db, entity_id, period_from, period_to,
cal["revenue_field"], cal["revenue_filter"],
exclude_closing=cal["exclude_closing"])
@@ -256,7 +298,7 @@ def compute_margin_rate(db, entity_id: int, period_from: str, period_to: str,
info["reason"] = f"{cal['margin_label']}不可得:{cal['revenue_filter'][1]} 累计缺数或为 0"
return info
if num_w <= 0:
info["reason"] = f"{cal['margin_label']}不可得:{cal['varcost_filter'][1]} 累计缺数或为 0"
info["reason"] = f"{cal['margin_label']}不可得:变动成本累计缺数或为 0"
return info
info["available"] = True
info["rebate_pct"] = round(num_w / den_w * 100.0, 2)
@@ -264,17 +306,39 @@ def compute_margin_rate(db, entity_id: int, period_from: str, period_to: str,
def compute_rebate_rate(db, entity_id: int, period_from: str, period_to: str) -> dict:
"""实测累计渠补率(2026-10-02 财务裁定口径)—— 酣客(entity1) 专用薄封装。
"""实测累计**渠补率**(F_BEP_REBATE,2026-10-02 口径)—— 酣客(entity1) 专用。
渠补率(实测) = Σ(571103 借方) ÷ Σ(5001 贷方) × 100,期间 = 年初至当期(YTD),保留 2 位小数。
· 571103 = 渠补/捐赠支出(损益类费用科目)⇒ 本期发生额落**借方**;
· 5001 = 主营业务收入 ⇒ 本期发生额落**贷方**;
· 行域 = carry_forward=0(与 _sum_field 一致,排除期间损益结转腿)。
· 行域 = carry_forward=0(排除期间损益结转腿)。
保留本函数名/键名以兼容既有调用方与单测;通用实现见 compute_margin_rate。
⚠️ ⑤ 口径统一(2026-10-03)后:本函数只算**渠补口径**,是 F_BEP_REBATE 的单一事实源;
保本公式所用的**变动成本率**(销货成本+税金及附加+渠补−厂补)见 compute_margin_rate。
博海(rebate_terms=None)无渠补科目 ⇒ 返回 available=False(F_BEP_REBATE=NULL)。
"""
return compute_margin_rate(db, entity_id, period_from, period_to,
ENTITY_CALIBERS.get(entity_id))
cal = ENTITY_CALIBERS.get(entity_id)
if not cal or not cal.get("rebate_terms"):
return {"available": False, "rebate_pct": None, "rebate_sum_w": 0.0,
"sales_sum_w": 0.0, "label": "实测渠补率",
"reason": f"{cal['name'] if cal else entity_id} 无渠补科目"}
num_raw = _sum_terms(db, entity_id, period_from, period_to,
cal["rebate_terms"], exclude_closing=cal["exclude_closing"])
den_raw = _sum_field(db, entity_id, period_from, period_to,
cal["revenue_field"], cal["revenue_filter"],
exclude_closing=cal["exclude_closing"])
num_w, den_w = num_raw / 10000.0, den_raw / 10000.0
info = {"rebate_sum_w": round(num_w, 2), "sales_sum_w": round(den_w, 2),
"rebate_pct": None, "available": False, "reason": "", "label": "实测渠补率"}
if den_w <= 0:
info["reason"] = "渠补率不可得:Σ5001贷累计缺数或为 0"
return info
if num_w <= 0:
info["reason"] = "渠补率不可得:Σ571103借累计缺数或为 0"
return info
info["available"] = True
info["rebate_pct"] = round(num_w / den_w * 100.0, 2)
return info
def _month_sales(db, entity_id: int, period: str, caliber: dict = None) -> float:
@@ -460,9 +524,11 @@ def run_derive(db, entity_id: int, period: str, rebate_rate_pct: float = None,
dep_avg = dep_sum_w / months
cash_admin_avg = admin_avg - dep_avg # 现金口径固定成本(剔除折旧纸面费用)
# 2. 变动成本率:默认逐期实测累计(不再取政策常量;常量仅对照,仅 entity1 有)
# 2. 变动成本率(⑤ 后=销货成本+税金及附加+渠补−厂补 完整口径):默认逐期实测累计
rebate_info = compute_margin_rate(db, entity_id, period_from, period_to, cal)
calc_pct = rebate_info["rebate_pct"]
# ⑤:渠补率(e1 专用;e2 无 ⇒ available=False)。F_BEP_REBATE 专用,独立于上面变动成本率。
rebate_kpi_info = compute_rebate_rate(db, entity_id, period_from, period_to)
if rebate_rate_pct is not None:
rebate_info = dict(rebate_info, available=True, rebate_pct=round(float(rebate_rate_pct), 2),
reason="人工覆盖(--rebate-rate)")
@@ -484,7 +550,8 @@ def run_derive(db, entity_id: int, period: str, rebate_rate_pct: float = None,
period, cal["margin_label"], rebate_pct)
return _fail_closed_cm_non_positive(db, entity_id, period, months, rebate_info, cal,
kpis, write_kpi, sales_avg=sales_avg,
admin_avg=admin_avg, dep_avg=dep_avg)
admin_avg=admin_avg, dep_avg=dep_avg,
rebate_kpi_info=rebate_kpi_info)
# 2c. fail-closed ③(2026-10-03,同族补充):固定成本退化 ⇒ 保本点不适用
# 边际贡献率 > 0 但分子(固定成本)退化时,公式给出 保本额≈0 / 覆盖率趋于无穷,
@@ -498,7 +565,8 @@ def run_derive(db, entity_id: int, period: str, rebate_rate_pct: float = None,
return _fail_closed_cm_non_positive(db, entity_id, period, months, rebate_info, cal,
kpis, write_kpi, sales_avg=sales_avg,
admin_avg=admin_avg, dep_avg=dep_avg, guard="fixed",
cash_admin_avg=cash_admin_avg)
cash_admin_avg=cash_admin_avg,
rebate_kpi_info=rebate_kpi_info)
# 3. 派生计算(万元 / %)——账面3条路径不变;现金口径在账面基础上剔除折旧
bep = admin_avg / (cm_pct / 100.0)
@@ -513,7 +581,9 @@ def run_derive(db, entity_id: int, period: str, rebate_rate_pct: float = None,
"F_BEP_GAP": round(gap, 1),
"F_BEP_REVENUE_CASH": round(cash_bep, 1),
"F_BEP_COVER_CASH": round(cash_cover, 1),
"F_BEP_REBATE": round(rebate_pct, 2),
"F_BEP_VC_RATE": round(rebate_pct, 2), # 变动成本率(⑤ 保本分子口径)
"F_BEP_REBATE": (round(rebate_kpi_info["rebate_pct"], 2)
if rebate_kpi_info["available"] else None), # 实测渠补率(e1;e2=NULL)
}
# 4. upsert kpi_values (source_type='derived',幂等)
@@ -526,15 +596,20 @@ def run_derive(db, entity_id: int, period: str, rebate_rate_pct: float = None,
if kpi is None: # 定义缺失(仅可能为 F_BEP_REBATE,见上方告警)
written[code] = "no-definition"
continue
if code == REBATE_KPI:
if entity_id == 1:
remark = (f"实测渠补率(YTD累计): Σ571103借方 {rebate_info['rebate_sum_w']:.2f}万 ÷ "
f"Σ5001贷方 {rebate_info['sales_sum_w']:.2f}万 × 100 = {rebate_pct:.2f}%"
f"(政策常量 {POLICY_REBATE_RATE_PCT:.2f}% 仅供对照,不参与计算)")
if code == VC_RATE_KPI:
remark = (f"变动成本率(YTD累计): {cal['margin_desc']} = "
f"{rebate_info['rebate_sum_w']:.2f}万 ÷ {rebate_info['sales_sum_w']:.2f}万 "
f"× 100 = {rebate_pct:.2f}%(⑤口径统一:销货成本+税金及附加+渠补−厂补;"
f"保本额 = 固定成本月均 ÷ (1−变动成本率))")
elif code == REBATE_KPI:
if rebate_kpi_info["available"]:
rr = rebate_kpi_info["rebate_pct"]
remark = (f"实测渠补率(YTD累计): Σ571103借方 {rebate_kpi_info['rebate_sum_w']:.2f}万 ÷ "
f"Σ5001贷方 {rebate_kpi_info['sales_sum_w']:.2f}万 × 100 = {rr:.2f}%"
f"(政策常量 {POLICY_REBATE_RATE_PCT:.2f}% 仅供对照;⑤ 后**不再充当变动成本率**,"
f"变动成本率见 F_BEP_VC_RATE)")
else:
remark = (f"{cal['margin_label']}(YTD累计): {cal['margin_desc']} = "
f"{rebate_info['rebate_sum_w']:.2f}万 ÷ {rebate_info['sales_sum_w']:.2f}万 "
f"× 100 = {rebate_pct:.2f}%({cal['name']}口径,无渠补科目)")
remark = f"{cal['name']}无渠补科目(实测渠补率不适用);⑤ 后变动成本率见 F_BEP_VC_RATE"
elif code in CASH_CODES:
if entity_id == 1:
remark = (f"现金口径: 管理费月均{admin_avg:.2f}万-折旧月均{dep_avg:.2f}万"
@@ -560,9 +635,11 @@ def run_derive(db, entity_id: int, period: str, rebate_rate_pct: float = None,
is_new = existing is None
if existing:
old_value = float(existing.actual_value) if existing.actual_value is not None else None
new_value = float(values[code])
value_changed = old_value is None or abs(old_value - new_value) > 1e-9
existing.actual_value = values[code]
nv = values[code]
new_value = float(nv) if nv is not None else None
value_changed = ((old_value is None) != (new_value is None)
or (old_value is not None and abs(old_value - new_value) > 1e-9))
existing.actual_value = nv
existing.source_batch = batch
if value_changed:
existing.remark = (f"{remark}|值已更新(batch={batch}, "
@@ -651,8 +728,10 @@ def run_derive(db, entity_id: int, period: str, rebate_rate_pct: float = None,
"rebate_sum_w": rebate_info["rebate_sum_w"],
"rebate_sales_base_w": rebate_info["sales_sum_w"],
"rebate_actual_pct": rebate_pct,
"vc_rate_pct": rebate_pct,
"rebate_kpi_pct": (rebate_kpi_info["rebate_pct"] if rebate_kpi_info["available"] else None),
"rebate_policy_pct": POLICY_REBATE_RATE_PCT,
"rebate_source": rebate_info.get("reason") or "YTD实测累计(Σ571103借方/Σ5001贷方)",
"rebate_source": rebate_info.get("reason") or "YTD实测累计(⑤完整口径)",
"rebate_calc_pct": round(calc_pct, 2) if calc_pct is not None else None,
"cm_pct": round(cm_pct, 2),
"values": values,
@@ -734,7 +813,8 @@ def _fail_closed_cm_non_positive(db, entity_id: int, period: str, months: int,
rebate_info: dict, cal: dict, kpis: dict, write_kpi: bool,
sales_avg: float = None, admin_avg: float = None,
dep_avg: float = None, guard: str = "cm",
cash_admin_avg: float = None) -> dict:
cash_admin_avg: float = None,
rebate_kpi_info: dict = None) -> dict:
"""fail-closed ② 落库:保本点**不适用**(2026-10-03 财务裁定)。
五条保本派生值(REVENUE/COVER/GAP/REVENUE_CASH/COVER_CASH)写
@@ -758,14 +838,16 @@ def _fail_closed_cm_non_positive(db, entity_id: int, period: str, months: int,
detail = (f"边际贡献非正,保本点不适用({cal['margin_label']} {rebate_pct:.2f}% ≥ 100%,"
f"边际贡献率 {cm_pct:.2f}% ⇒ 每增一元销售不产生正贡献,保本点无经济意义;"
f"fail-closed,禁写 0.0)")
if entity_id == 1:
rebate_remark = (f"实测渠补率(YTD累计): Σ571103借方 {rebate_info['rebate_sum_w']:.2f}万 ÷ "
f"Σ5001贷方 {rebate_info['sales_sum_w']:.2f}万 × 100 = {rebate_pct:.2f}%"
f"(政策常量 {POLICY_REBATE_RATE_PCT:.2f}% 仅供对照,不参与计算)")
vc_rate_remark = (f"变动成本率(YTD累计): {cal['margin_desc']} = "
f"{rebate_info['rebate_sum_w']:.2f}万 ÷ {rebate_info['sales_sum_w']:.2f}万 "
f"× 100 = {rebate_pct:.2f}%(⑤口径统一;保本点因边际贡献非正/固定成本退化不适用)")
if rebate_kpi_info and rebate_kpi_info.get("available"):
rebate_remark = (f"实测渠补率(YTD累计): Σ571103借方 {rebate_kpi_info['rebate_sum_w']:.2f}万 ÷ "
f"Σ5001贷方 {rebate_kpi_info['sales_sum_w']:.2f}万 × 100 = "
f"{rebate_kpi_info['rebate_pct']:.2f}%(政策常量 {POLICY_REBATE_RATE_PCT:.2f}% 仅供对照;"
f"⑤ 后不再充当变动成本率)")
else:
rebate_remark = (f"{cal['margin_label']}(YTD累计): {cal['margin_desc']} = "
f"{rebate_info['rebate_sum_w']:.2f}万 ÷ {rebate_info['sales_sum_w']:.2f}万 "
f"× 100 = {rebate_pct:.2f}%({cal['name']}口径,无渠补科目)")
rebate_remark = f"{cal['name']}无渠补科目(实测渠补率不适用);变动成本率见 F_BEP_VC_RATE"
batch = f"bep-{datetime.now().strftime('%Y%m%d%H%M%S')}"
written = {}
changed = []
@@ -775,9 +857,16 @@ def _fail_closed_cm_non_positive(db, entity_id: int, period: str, months: int,
if kpi is None:
written[code] = "no-definition"
continue
is_rebate = (code == REBATE_KPI)
new_val = round(float(rebate_pct), 2) if is_rebate else None
rm = rebate_remark if is_rebate else detail
if code == VC_RATE_KPI:
new_val = round(float(rebate_pct), 2) # 变动成本率可测 ⇒ 照常落库
rm = vc_rate_remark
elif code == REBATE_KPI:
new_val = (round(float(rebate_kpi_info["rebate_pct"]), 2)
if rebate_kpi_info and rebate_kpi_info.get("available") else None)
rm = rebate_remark
else:
new_val = None
rm = detail
existing = db.query(KPIValue).filter(
KPIValue.kpi_id == kpi.id,
KPIValue.period == period,
@@ -0,0 +1,39 @@
-- CMA BEP 变动成本率派生KPI定义 — F_BEP_VC_RATE(2026-10-03 ⑤ 口径统一)
-- 依据: 任总 2026-10-03 18:00 DM「统一」+ 任务 finance-20261003-cvp-fix-and-bohai-coverage-fullstack §追加⑤
-- 口径: 变动成本率 = 变动成本 ÷ 收入基数(YTD 累计,2位小数)
-- · 酣客(e1): 变动成本 = Σ5401借(销货成本)+Σ5403借(税金及附加)+Σ571103借(渠补)−Σ530103贷(厂补)
-- · 博海(e2): 变动成本 = Σ6401借(主营业务成本)
-- 保本额 = 固定成本月均 ÷ (1 − 变动成本率)
-- 说明: F_BEP_REBATE(实测渠补率/博海主营成本率) 保留,⑤ 后**不再充当变动成本率**
-- 幂等: NOT EXISTS 守卫,可安全重跑
INSERT INTO kpi_definitions
(entity_id, kpi_code, kpi_name, dimension, category, formula, formula_desc,
data_source_type, data_source, data_owner, frequency, unit, target_value,
target_calc_type, threshold_green, threshold_yellow, threshold_red,
kpi_level, status, bot_source, epic, created_by)
SELECT 1, 'F_BEP_VC_RATE', '变动成本率', 'finance', 'profitability',
'round((sum(5401借)+sum(5403借)+sum(571103借)-sum(530103贷))/sum(5001贷)*100,2)',
'变动成本率(YTD累计,⑤完整口径)=(Σ5401借+Σ5403借+Σ571103借−Σ530103贷)÷Σ5001贷; 供保本点卡面单一事实源; 缺数期不出值(fail-closed)',
'derived', 'BEP派生器 kpi_bep_deriver.py(voucher_details 5401/5403/571103/530103/5001 累计)', '财务部', 'monthly', '%', 0.00,
'ratio', NULL, NULL, NULL,
'strategic', 'active', 'finance-bot', 'Epic2', 1
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM kpi_definitions WHERE entity_id = 1 AND kpi_code = 'F_BEP_VC_RATE'
);
INSERT INTO kpi_definitions
(entity_id, kpi_code, kpi_name, dimension, category, formula, formula_desc,
data_source_type, data_source, data_owner, frequency, unit, target_value,
target_calc_type, threshold_green, threshold_yellow, threshold_red,
kpi_level, status, bot_source, epic, created_by)
SELECT 2, 'F_BEP_VC_RATE', '变动成本率(主营业务成本率)', 'finance', 'profitability',
'round(sum(6401借)/sum(6001贷)*100,2)',
'变动成本率(实测,YTD累计)=Σ6401借方÷Σ6001贷方(剔结转账腿); 博海无渠补科目; 供保本点卡面单一事实源, 无阈值',
'derived', 'BEP派生器 kpi_bep_deriver.py(voucher_details 6401/6001 累计)', '财务部', 'monthly', '%', 0,
'ratio', NULL, NULL, NULL,
'strategic', 'active', 'finance-bot', 'Epic2', 1
FROM DUAL
WHERE NOT EXISTS (
SELECT 1 FROM kpi_definitions WHERE entity_id = 2 AND kpi_code = 'F_BEP_VC_RATE'
);