feat: CMA P1+P2 Round2 — 风险矩阵+COSO+预算方法
This commit is contained in:
@@ -334,3 +334,103 @@ def get_deviation_report(
|
||||
"summary": summary,
|
||||
"items": items,
|
||||
}
|
||||
|
||||
|
||||
# ──────────────────────────────────────────────
|
||||
# 功能6: 预算方法三选一向导 (CMA P1 - 增量/零基/弹性)
|
||||
# ──────────────────────────────────────────────
|
||||
|
||||
@router.post("/method-comparison")
|
||||
def budget_method_comparison(data: dict):
|
||||
"""
|
||||
预算方法三选一对比计算
|
||||
接收: { entity: "hanke", last_month_budget: 91, current_revenue: 122, ... }
|
||||
返回三种方法的计算结果
|
||||
"""
|
||||
entity = data.get("entity", "hanke")
|
||||
last_month_budget = data.get("last_month_budget", 91) # 上月预算(万)
|
||||
current_revenue = data.get("current_revenue", 122) # 当前收入(万)
|
||||
fixed_costs = data.get("fixed_costs", {
|
||||
"rent": 15, # 房租(万)
|
||||
"labor": 40, # 人工(万)
|
||||
"entertainment": 16, # 招待费(万)
|
||||
"misc": 12, # 杂项(万)
|
||||
})
|
||||
variable_cost_rate = data.get("variable_cost_rate", 0.4862) # 变动成本率
|
||||
|
||||
# 1. 增量预算: 基于上月统一调整
|
||||
increment_rate = data.get("increment_rate", 0.05) # 5%增幅
|
||||
incremental_result = round(last_month_budget * (1 + increment_rate), 1)
|
||||
incremental_detail = f"上月{last_month_budget}万 × (1+{increment_rate*100:.0f}%) = {incremental_result}万"
|
||||
|
||||
# 2. 零基预算: 每项从零论证
|
||||
zbb_entertainment = round(fixed_costs.get("entertainment", 16) / 2, 1) # 砍半
|
||||
zbb_misc = round(fixed_costs.get("misc", 12) * 0.7, 1) # 压缩30%
|
||||
zbb_total = round(
|
||||
fixed_costs.get("rent", 15)
|
||||
+ fixed_costs.get("labor", 40)
|
||||
+ zbb_entertainment
|
||||
+ zbb_misc,
|
||||
1,
|
||||
)
|
||||
zbb_savings = round(last_month_budget - zbb_total, 1)
|
||||
zbb_detail = (
|
||||
f"房租{fixed_costs.get('rent', 15)}万(固定)+人工{fixed_costs.get('labor', 40)}万(砍不掉)"
|
||||
f"+招待{zbb_entertainment}万(砍半)+杂项{zbb_misc}万(压缩)"
|
||||
f"={zbb_total}万 ← 省{zbb_savings}万"
|
||||
)
|
||||
|
||||
# 3. 弹性预算: 根据收入水平动态调整
|
||||
flexible_fixed = round(fixed_costs.get("rent", 15) + fixed_costs.get("labor", 40) * 0.5, 1)
|
||||
flexible_variable = round(current_revenue * variable_cost_rate * 0.4, 1)
|
||||
flexible_total = round(flexible_fixed + flexible_variable, 1)
|
||||
flexible_variance = round(last_month_budget - flexible_total, 1)
|
||||
flex_detail = (
|
||||
f"收入{current_revenue}万 → 对应费用预算 = {flexible_total}万"
|
||||
f"(固定部分{flexible_fixed}万+变动部分{flexible_variable}万)"
|
||||
f",实际{last_month_budget}万 → 差异{flexible_variance}万 → {'效率问题' if flexible_variance > 0 else '节省'}"
|
||||
)
|
||||
|
||||
# 推荐方法
|
||||
recommended = "zero_based"
|
||||
|
||||
return {
|
||||
"entity": entity,
|
||||
"entity_name": "陕西酣客(白酒经销)" if entity == "hanke" else "陕西博海科技(IT服务)",
|
||||
"methods": [
|
||||
{
|
||||
"id": "incremental",
|
||||
"name": "增量预算",
|
||||
"name_en": "Incremental Budgeting",
|
||||
"result_value": incremental_result,
|
||||
"detail": incremental_detail,
|
||||
"pros": "简单快速",
|
||||
"cons": "浪费持续",
|
||||
"is_recommended": False,
|
||||
},
|
||||
{
|
||||
"id": "zero_based",
|
||||
"name": "零基预算",
|
||||
"name_en": "Zero-Based Budgeting (ZBB)",
|
||||
"result_value": zbb_total,
|
||||
"savings": zbb_savings,
|
||||
"detail": zbb_detail,
|
||||
"pros": "最合理",
|
||||
"cons": "耗时",
|
||||
"is_recommended": True,
|
||||
},
|
||||
{
|
||||
"id": "flexible",
|
||||
"name": "弹性预算",
|
||||
"name_en": "Flexible Budgeting",
|
||||
"result_value": flexible_total,
|
||||
"variance": flexible_variance,
|
||||
"detail": flex_detail,
|
||||
"pros": "动态响应",
|
||||
"cons": "需要详细分类",
|
||||
"is_recommended": False,
|
||||
},
|
||||
],
|
||||
"recommended": recommended,
|
||||
"recommended_name": "零基预算",
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user