Files
cma-management/backend/scripts/sql/dupont_kpi_defs_20261003.sql
T
Hermes CI Fix 38a6de9325
ci/woodpecker/push/main Pipeline failed
feat(dupont): period-basis design (cumulative flow x average stock, optional annualize, identity guard)
Task: finance-20261003-dupont-period-basis-design-fullstack (P1; proposer wecom-finance)
Basis ruling: finance 2026-10-03 (Boss 09:49 CST DM approval of the design task)

- /reports/dupont accepts period/start/end/annualize (default YTD), returns
  period_start/period_end/basis/annualized metadata; identity guard
  |ROE - npm x turnover x multiplier| <= 0.05 pp, else identity_broken (no values).
- new app/utils/dupont_basis.py = single source of truth (window resolve, flow
  cumulative via voucher_details, stock average via subject_balances level=1,
  fail-closed basis_fallback, pure calc + identity check).
- scripts/kpi_dupont_deriver.py (idempotent derived writer, dry-run/check/write),
  scripts/apply_dupont_kpi_defs.py + sql/dupont_kpi_defs_20261003.sql (seed:
  F_ASSET_TOTAL/F_EQUITY_TOTAL/F_EQUITY_MULTIPLIER as derived; F_ASSET_TURNOVER
  manual -> derived). Seed already applied under approval 296cc1fd.
- scripts/verify_dupont_period_basis.py: read-only acceptance battery A1-A9
  (independent SQL recompute). BEFORE (base tree) 1/10 PASS -> AFTER 10/13 PASS;
  remaining 3 need the deriver value write (approval-gated).
- frontend DupontAnalysis.vue: period selector (YTD default) + annualize switch
  + caliber metadata bar + identity_broken alert.

No DDL. No ERP direct connection (old register_dupont_kpis.py caliber dropped).
2026-10-04 13:35:25 +08:00

106 lines
7.7 KiB
SQL
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
-- CMA 杜邦分析「区间取值」KPI 定义收敛 — 2026-10-03
-- 任务: finance-20261003-dupont-period-basis-design-fullstack(部署目标 cma-backend · cma-frontend)
-- 口径: 财务Bot 2026-10-03 裁定(任总 09:49 CST DM「立」)—— 详见任务件 §二
-- 动作:
-- ① 新增 F_ASSET_TOTAL(总资产)/ F_EQUITY_TOTAL(净资产)/ F_EQUITY_MULTIPLIER(权益乘数)
-- 为 derived KPI(**两账套**:entity 1 酣客 / entity 2 博海)
-- ② F_ASSET_TURNOVER 由 manual → derived(口径=区间营业收入 ÷ 平均总资产,由派生器出数)
-- 单一事实源: app/utils/dupont_basis.py(口径/取数/计算)+ scripts/kpi_dupont_deriver.py(落值)
-- 幂等: 条件 INSERT(NOT EXISTS)+ 条件 UPDATE,可安全重跑
-- ⚠️ 取数源: CMA 库内 subject_balances(存量 level=1)+ voucher_details(流量),
-- **不用**旧脚本 register_dupont_kpis.py 的 ERP 直连近似口径(缺应收/存货)
-- ── ① entity 1(酣客,旧准则科目:权益 3xxx)────────────────────────────
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, kpi_level, status, bot_source, created_by, data_source_config)
SELECT 1, 'F_ASSET_TOTAL', '总资产', 'finance', 'asset_efficiency',
'期末总资产 = SUM(subject_balances.cb_dr-cb_cr) WHERE level=1 AND subject_code LIKE ''1%''',
'总资产期末余额(万元),一级科目(level=1)防跨层双计;来源 CMA 库内 subject_balances。'
'杜邦恒等式需用**平均**口径,见 F_EQUITY_MULTIPLIER 与 /reports/dupont 的 basis=average',
'derived', '杜邦派生器 kpi_dupont_deriver.py(subject_balances level=1)',
'财务部', 'monthly', '万元', 0.00, 'accumulate', 'strategic', 'active', 'finance-bot', 1,
'{"params": {"asset_prefix": "1", "equity_prefixes": ["3"], "revenue_codes": ["5001"], "net_profit_mode": "carry_forward"}, "param_note": "账套科目体系口径,读取入口 app/utils/dupont_basis.py load_dupont_params"}'
FROM DUAL WHERE NOT EXISTS (
SELECT 1 FROM kpi_definitions WHERE entity_id = 1 AND kpi_code = 'F_ASSET_TOTAL');
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, kpi_level, status, bot_source, created_by)
SELECT 1, 'F_EQUITY_TOTAL', '净资产', 'finance', 'asset_efficiency',
'期末净资产 = SUM(subject_balances.cb_cr-cb_dr) WHERE level=1 AND subject_code LIKE ''3%''',
'净资产期末余额(万元)= 所有者权益合计;一级科目(level=1)。来源 CMA 库内 subject_balances',
'derived', '杜邦派生器 kpi_dupont_deriver.py(subject_balances level=1)',
'财务部', 'monthly', '万元', 0.00, 'accumulate', 'strategic', 'active', 'finance-bot', 1
FROM DUAL WHERE NOT EXISTS (
SELECT 1 FROM kpi_definitions WHERE entity_id = 1 AND kpi_code = 'F_EQUITY_TOTAL');
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, created_by)
SELECT 1, 'F_EQUITY_MULTIPLIER', '权益乘数', 'finance', 'asset_efficiency',
'平均总资产 / 平均净资产((期初+期末)/2,level=1)',
'权益乘数=平均总资产÷平均净资产;**平均口径** = 区间(期初+期末)/2,与 /reports/dupont '
'同区间;期初缺失显式回落期末并标注 basis_fallback(禁静默)',
'derived', '杜邦派生器 kpi_dupont_deriver.py(subject_balances level=1)',
'财务部', 'monthly', '倍', 2.00, 'ratio', '<=2', '<=3', '>3',
'strategic', 'active', 'finance-bot', 1
FROM DUAL WHERE NOT EXISTS (
SELECT 1 FROM kpi_definitions WHERE entity_id = 1 AND kpi_code = 'F_EQUITY_MULTIPLIER');
-- ── ① entity 2(博海,新 30 号准则科目:权益 4xxx,损益 6xxx)────────────
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, kpi_level, status, bot_source, created_by, data_source_config)
SELECT 2, 'F_ASSET_TOTAL', '总资产', 'finance', 'asset_efficiency',
'期末总资产 = SUM(subject_balances.cb_dr-cb_cr) WHERE level=1 AND subject_code LIKE ''1%''',
'总资产期末余额(万元),一级科目(level=1)防跨层双计;来源 CMA 库内 subject_balances',
'derived', '杜邦派生器 kpi_dupont_deriver.py(subject_balances level=1)',
'财务部', 'monthly', '万元', 0.00, 'accumulate', 'strategic', 'active', 'finance-bot', 1,
'{"params": {"asset_prefix": "1", "equity_prefixes": ["4"], "revenue_codes": ["6001", "6051", "6052"], "net_profit_mode": "pnl_net"}, "param_note": "博海用新30号准则科目体系(权益 4xxx / 损益 6xxx),读取入口 app/utils/dupont_basis.py"}'
FROM DUAL WHERE NOT EXISTS (
SELECT 1 FROM kpi_definitions WHERE entity_id = 2 AND kpi_code = 'F_ASSET_TOTAL');
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, kpi_level, status, bot_source, created_by)
SELECT 2, 'F_EQUITY_TOTAL', '净资产', 'finance', 'asset_efficiency',
'期末净资产 = SUM(subject_balances.cb_cr-cb_dr) WHERE level=1 AND subject_code LIKE ''4%''',
'净资产期末余额(万元)= 所有者权益合计(新30号准则 4xxx);一级科目(level=1)',
'derived', '杜邦派生器 kpi_dupont_deriver.py(subject_balances level=1)',
'财务部', 'monthly', '万元', 0.00, 'accumulate', 'strategic', 'active', 'finance-bot', 1
FROM DUAL WHERE NOT EXISTS (
SELECT 1 FROM kpi_definitions WHERE entity_id = 2 AND kpi_code = 'F_EQUITY_TOTAL');
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, created_by)
SELECT 2, 'F_EQUITY_MULTIPLIER', '权益乘数', 'finance', 'asset_efficiency',
'平均总资产 / 平均净资产((期初+期末)/2,level=1)',
'权益乘数=平均总资产÷平均净资产;**平均口径** = 区间(期初+期末)/2,与 /reports/dupont 同区间',
'derived', '杜邦派生器 kpi_dupont_deriver.py(subject_balances level=1)',
'财务部', 'monthly', '倍', 2.00, 'ratio', '<=2', '<=3', '>3',
'strategic', 'active', 'finance-bot', 1
FROM DUAL WHERE NOT EXISTS (
SELECT 1 FROM kpi_definitions WHERE entity_id = 2 AND kpi_code = 'F_EQUITY_MULTIPLIER');
-- ── ② F_ASSET_TURNOVER: manual → derived(两账套)─────────────────────
-- 值型阈值不改;只改「谁出数 + 口径文本」,避免单位/量级语义被顺手改动
UPDATE kpi_definitions
SET data_source_type = 'derived',
data_source = '杜邦派生器 kpi_dupont_deriver.py(subject_balances + voucher_details)',
formula = '营业收入 / 平均总资产',
formula_desc = '总资产周转率 = 区间**累计**营业收入 ÷ 区间**平均**总资产((期初+期末)/2,level=1);'
'单月口径该值天然很小(≠年化),跨期比较请在 /reports/dupont 用 annualize=true(×12/月数)',
updated_at = NOW()
WHERE entity_id IN (1, 2) AND kpi_code = 'F_ASSET_TURNOVER'
AND (data_source_type IS NULL OR data_source_type <> 'derived');