fix: 预算年度分解幂等加固+数据质量七规则测试

- auto-decompose批量聚合只取年度行(period=YYYY-00)排除月度行,修复重复点击执行分解年底预算滚雪球
- 同一KPI多个version年度行时只取一行(优先请求version),避免多版本叠加总额虚高
- 新增tests/test_data_quality.py: 财务七规则(governance-check)3用例全过
This commit is contained in:
Hermes CI Fix
2026-08-30 10:27:01 +08:00
parent 974ec48564
commit 5b920df8a0
2 changed files with 155 additions and 5 deletions
+14 -5
View File
@@ -197,18 +197,26 @@ def auto_decompose_budget(
# ── 批量模式:不传kpi_id → 分解该年所有有年度预算的KPI ──
if not kpi_id:
# 找该年已存在的年度预算period=YYYY-00 或已按月填的KPI汇总
# 优先用 budget_plans 中该年的预算作为年度总额
# 只取年度行period=YYYY-00)作为年度总额,避免把月度行也加进来导致滚雪球(非幂等bug修复
year_budget_rows = db.query(BudgetPlan).filter(
BudgetPlan.entity_id == 1,
BudgetPlan.budget_year == year,
BudgetPlan.period == f"{year}-00",
BudgetPlan.status == "active",
).all()
# 按KPI聚合年度预算总额
kpi_annual = {}
# 按KPI聚合年度预算总额——同一KPI存在多个version年度行时只取一行
# (优先匹配请求version,否则取第一条),避免多版本叠加导致总额虚高(幂等加固)
from collections import defaultdict
per_kpi = defaultdict(list)
for r in year_budget_rows:
kpi_annual[r.kpi_id] = kpi_annual.get(r.kpi_id, 0) + (r.budget_value or 0)
per_kpi[r.kpi_id].append(r)
kpi_annual = {}
kpi_version_used = {}
for kid, rows in per_kpi.items():
chosen = next((r for r in rows if r.version == version), rows[0])
kpi_annual[kid] = chosen.budget_value or 0
kpi_version_used[kid] = chosen.version
if not kpi_annual:
raise HTTPException(400, "该年度没有可分解的预算,请先在预算执行中录入年度预算")
@@ -268,6 +276,7 @@ def auto_decompose_budget(
"kpi_code": kpi.kpi_code,
"kpi_name": kpi.kpi_name,
"annual_budget": round(annual, 2),
"version_used": kpi_version_used.get(kid),
"method": "equal" if not weights else "weighted",
"monthly": monthly,
"monthly_count": 12,