feat: CMA P1+P2 Round1 — 成本法对比+杜邦分析+本量利
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -202,6 +202,68 @@ def cost_breakdown(product_code: str = Query(...),
|
||||
return get_cost_breakdown(product_code, period)
|
||||
|
||||
|
||||
@router.get("/comparison")
|
||||
def cost_method_comparison(entity: str = Query("hanke")):
|
||||
"""三种成本法对比分析:传统/变动/作业成本法 (CMA P1)"""
|
||||
if entity == "hanke":
|
||||
gross_revenue = 713 # 万
|
||||
channel_rebate_rate = 0.828
|
||||
net_revenue = round(gross_revenue * (1 - channel_rebate_rate), 2)
|
||||
weighted_cost_rate = 0.4862
|
||||
book_cost = 717 # 万
|
||||
total_expenses = 546 # 万
|
||||
non_value_added = 26 # 万
|
||||
|
||||
traditional = {
|
||||
"revenue": gross_revenue,
|
||||
"cost": book_cost,
|
||||
"gross_profit": round(gross_revenue - book_cost, 2),
|
||||
"gross_margin": round((gross_revenue - book_cost) / gross_revenue * 100, 2),
|
||||
"expenses": total_expenses,
|
||||
"net_profit": round(gross_revenue - book_cost - total_expenses, 2),
|
||||
}
|
||||
|
||||
var_cost = round(net_revenue * weighted_cost_rate, 2)
|
||||
variable = {
|
||||
"revenue": net_revenue,
|
||||
"cost": var_cost,
|
||||
"gross_profit": round(net_revenue - var_cost, 2),
|
||||
"gross_margin": round((1 - weighted_cost_rate) * 100, 2),
|
||||
"expenses": total_expenses,
|
||||
"net_profit": round(net_revenue - var_cost - total_expenses, 2),
|
||||
}
|
||||
|
||||
abc_cost = round(net_revenue * weighted_cost_rate, 2)
|
||||
abc_exp = total_expenses - non_value_added
|
||||
abc = {
|
||||
"revenue": net_revenue,
|
||||
"cost": abc_cost,
|
||||
"gross_profit": round(net_revenue - abc_cost, 2),
|
||||
"gross_margin": round((1 - weighted_cost_rate) * 100, 2),
|
||||
"expenses": abc_exp,
|
||||
"net_profit": round(net_revenue - abc_cost - abc_exp, 2),
|
||||
}
|
||||
|
||||
return {
|
||||
"entity": "hanke",
|
||||
"entity_name": "陕西酣客(白酒经销)",
|
||||
"traditional": traditional,
|
||||
"variable": variable,
|
||||
"abc": abc,
|
||||
"insights": [
|
||||
{"method": "传统成本法", "conclusion": "毛利率为负", "decision": "❌ 不赚钱,别卖了", "detail": "未剔除渠补,账面收入虚高"},
|
||||
{"method": "变动成本法", "conclusion": "毛利率18.6%", "decision": "✅ 业务能赚钱→砍费用", "detail": "剔除渠补后净收入122万,成本率48.62%"},
|
||||
{"method": "作业成本法", "conclusion": "识别非增值作业26万", "decision": "✅ 可再省", "detail": "剔除冗余招待费等非增值作业"},
|
||||
],
|
||||
"notes": {
|
||||
"net_revenue": "毛收入713万 × (1-渠补率82.8%) = 净收入122万",
|
||||
"variable_cost": "净收入122万 × 加权成本率48.62% = 成本59.3万",
|
||||
"abc_expenses": "总费用546万 - 非增值作业26万 = 520万",
|
||||
},
|
||||
}
|
||||
return {"error": "不支持的实体"}
|
||||
|
||||
|
||||
@router.get("/dashboard")
|
||||
def cost_dashboard(period: Optional[str] = Query(None)):
|
||||
"""成本分析首页—汇总数据"""
|
||||
|
||||
@@ -96,3 +96,59 @@ def api_scenario_analysis(data: dict):
|
||||
raise
|
||||
except Exception as e:
|
||||
raise HTTPException(400, f"情景模拟失败: {str(e)}")
|
||||
|
||||
|
||||
@router.post("/cvp-detailed")
|
||||
def api_cvp_detailed(data: dict):
|
||||
"""CVP本量利详细分析 — 含改善方案推演和保本图数据 (CMA P2)"""
|
||||
try:
|
||||
fixed_cost = float(data.get("fixed_cost", 617))
|
||||
variable_cost_rate = float(data.get("variable_cost_rate", 0.4862))
|
||||
unit_price = float(data.get("unit_price", 228))
|
||||
current_volume = float(data.get("current_volume", 5300))
|
||||
|
||||
contribution_margin_rate = 1 - variable_cost_rate
|
||||
breakeven_revenue = round(fixed_cost / contribution_margin_rate, 2)
|
||||
breakeven_units = round(breakeven_revenue * 10000 / unit_price, 0)
|
||||
|
||||
current_revenue = round(current_volume * unit_price / 10000, 2)
|
||||
current_profit = round(current_revenue * (1 - variable_cost_rate) - fixed_cost, 2)
|
||||
safety_margin = round((current_revenue - breakeven_revenue) / current_revenue * 100, 2) if current_revenue > 0 else 0
|
||||
|
||||
scenarios = [
|
||||
{"name": "降固定费用至300万", "fixed_cost": 300, "variable_cost_rate": variable_cost_rate,
|
||||
"breakeven_revenue": round(300 / contribution_margin_rate, 2),
|
||||
"breakeven_units": round(300 / contribution_margin_rate * 10000 / unit_price, 0)},
|
||||
{"name": "降变动成本率至30%", "fixed_cost": fixed_cost, "variable_cost_rate": 0.3,
|
||||
"breakeven_revenue": round(fixed_cost / 0.7, 2),
|
||||
"breakeven_units": round(fixed_cost / 0.7 * 10000 / unit_price, 0)},
|
||||
{"name": "两者同时改善", "fixed_cost": 300, "variable_cost_rate": 0.3,
|
||||
"breakeven_revenue": round(300 / 0.7, 2),
|
||||
"breakeven_units": round(300 / 0.7 * 10000 / unit_price, 0)},
|
||||
]
|
||||
|
||||
# 保本图数据点
|
||||
chart_data = []
|
||||
max_volume = int(max(breakeven_units * 2, current_volume * 3))
|
||||
step = max(1, int(max_volume / 20))
|
||||
for vol in range(0, int(max_volume) + step, step):
|
||||
rev = round(vol * unit_price / 10000, 2)
|
||||
tc = round(fixed_cost + rev * variable_cost_rate, 2)
|
||||
chart_data.append({"volume": vol, "revenue": rev, "total_cost": tc, "profit": round(rev - tc, 2)})
|
||||
|
||||
return {
|
||||
"fixed_cost": fixed_cost,
|
||||
"variable_cost_rate": round(variable_cost_rate * 100, 2),
|
||||
"unit_price": unit_price,
|
||||
"contribution_margin_rate": round(contribution_margin_rate * 100, 2),
|
||||
"breakeven_revenue": breakeven_revenue,
|
||||
"breakeven_units": int(breakeven_units),
|
||||
"current_revenue": current_revenue,
|
||||
"current_profit": current_profit,
|
||||
"current_volume": int(current_volume),
|
||||
"safety_margin": safety_margin,
|
||||
"scenarios": scenarios,
|
||||
"chart_data": chart_data,
|
||||
}
|
||||
except Exception as e:
|
||||
raise HTTPException(400, f"CVP详细分析失败: {str(e)}")
|
||||
|
||||
@@ -420,3 +420,76 @@ def _build_scorecard_from_kpis(db: Session, period: str) -> dict:
|
||||
"overall_score": round(total_score / dim_count, 1) if dim_count > 0 else 0,
|
||||
"dimensions": dimensions,
|
||||
}
|
||||
|
||||
|
||||
# ============================================================
|
||||
# 杜邦分析 (CMA P2)
|
||||
# ============================================================
|
||||
|
||||
@router.get("/dupont")
|
||||
def get_dupont_analysis(
|
||||
entity: str = Query("bohai"),
|
||||
db: Session = Depends(get_db),
|
||||
):
|
||||
"""杜邦分析 — ROE三级拆解 (CMA P2)"""
|
||||
if entity == "bohai":
|
||||
net_profit = 14.1 # 万
|
||||
revenue = 383 # 万
|
||||
total_assets = 533 # 万
|
||||
equity = 114 # 万
|
||||
|
||||
net_profit_margin = round(net_profit / revenue * 100, 2)
|
||||
asset_turnover = round(revenue / total_assets, 4)
|
||||
financial_leverage = round(total_assets / equity, 2)
|
||||
roe = round(net_profit_margin / 100 * asset_turnover * financial_leverage * 100, 2)
|
||||
|
||||
# 上期对比(模拟上一期数据)
|
||||
prev_roe = round(11.2, 2)
|
||||
roe_change = round(roe - prev_roe, 2)
|
||||
|
||||
return {
|
||||
"entity": "bohai",
|
||||
"entity_name": "陕西博海科技(IT服务)",
|
||||
"period": "2026年H1",
|
||||
"roe": roe,
|
||||
"roe_change": roe_change,
|
||||
"roe_trend": "up" if roe_change > 0 else "down",
|
||||
"prev_roe": prev_roe,
|
||||
"factors": {
|
||||
"net_profit_margin": {
|
||||
"value": net_profit_margin,
|
||||
"label": "净利润率",
|
||||
"desc": "净利润/收入",
|
||||
"status": "🟡" if net_profit_margin < 5 else "✅",
|
||||
"assessment": "IT经销行业正常偏低",
|
||||
"raw": {"net_profit": net_profit, "revenue": revenue},
|
||||
},
|
||||
"asset_turnover": {
|
||||
"value": asset_turnover,
|
||||
"label": "资产周转率",
|
||||
"desc": "收入/总资产",
|
||||
"status": "🟡" if asset_turnover < 1 else "✅",
|
||||
"assessment": "资金效率中等",
|
||||
"raw": {"revenue": revenue, "total_assets": total_assets},
|
||||
},
|
||||
"financial_leverage": {
|
||||
"value": financial_leverage,
|
||||
"label": "财务杠杆",
|
||||
"desc": "总资产/净资产",
|
||||
"status": "🟡" if financial_leverage > 3 else "✅",
|
||||
"assessment": "负债率78.6%,偏高但可控",
|
||||
"raw": {"total_assets": total_assets, "equity": equity},
|
||||
},
|
||||
},
|
||||
"raw_data": {
|
||||
"net_profit": net_profit,
|
||||
"revenue": revenue,
|
||||
"total_assets": total_assets,
|
||||
"equity": equity,
|
||||
},
|
||||
"insight": {
|
||||
"improvement": "提高周转率或利润率,而非加杠杆",
|
||||
"detail": f"净利润率{net_profit_margin}%偏低,资产周转率{asset_turnover}x中等,财务杠杆{financial_leverage}x偏高。改善方向:提升毛利率或加快库存周转。",
|
||||
},
|
||||
}
|
||||
return {"error": "不支持的实体"}
|
||||
|
||||
Binary file not shown.
Reference in New Issue
Block a user