96 lines
4.0 KiB
Python
96 lines
4.0 KiB
Python
from __future__ import annotations
|
|
|
|
from civilplan_mcp.models import ProjectDomain
|
|
from civilplan_mcp.tools._base import wrap_response
|
|
|
|
|
|
def analyze_feasibility(
|
|
*,
|
|
land_area_m2: float,
|
|
land_price_per_m2: float,
|
|
land_price_multiplier: float = 1.3,
|
|
construction_cost_total: float,
|
|
other_costs_million: float = 0,
|
|
revenue_type: str,
|
|
building_floor_area_m2: float,
|
|
sale_price_per_m2: float | None = None,
|
|
monthly_rent_per_m2: float | None = None,
|
|
vacancy_rate_pct: float = 10.0,
|
|
operating_expense_pct: float = 20.0,
|
|
equity_ratio_pct: float = 30.0,
|
|
loan_rate_pct: float = 5.5,
|
|
loan_term_years: int = 10,
|
|
construction_months: int = 24,
|
|
sale_months: int = 12,
|
|
) -> dict:
|
|
land_cost = round(land_area_m2 * land_price_per_m2 * land_price_multiplier)
|
|
soft_cost = round(construction_cost_total * 0.12 + other_costs_million * 1_000_000)
|
|
debt_ratio = 1 - (equity_ratio_pct / 100)
|
|
debt = round((land_cost + construction_cost_total + soft_cost) * debt_ratio)
|
|
equity = round((land_cost + construction_cost_total + soft_cost) - debt)
|
|
financing_cost = round(debt * (loan_rate_pct / 100) * (construction_months / 12) * 0.5)
|
|
total_investment = land_cost + construction_cost_total + soft_cost + financing_cost
|
|
|
|
if revenue_type == "임대":
|
|
gross_annual_rent = round(building_floor_area_m2 * float(monthly_rent_per_m2 or 0) * 12)
|
|
net_annual_rent = round(gross_annual_rent * (1 - vacancy_rate_pct / 100) * (1 - operating_expense_pct / 100))
|
|
stabilized_value = round(net_annual_rent / 0.06)
|
|
revenue_total = stabilized_value
|
|
elif revenue_type == "분양":
|
|
revenue_total = round(building_floor_area_m2 * float(sale_price_per_m2 or 0))
|
|
gross_annual_rent = 0
|
|
net_annual_rent = 0
|
|
stabilized_value = revenue_total
|
|
else:
|
|
revenue_total = total_investment
|
|
gross_annual_rent = 0
|
|
net_annual_rent = 0
|
|
stabilized_value = total_investment
|
|
|
|
profit = revenue_total - total_investment
|
|
monthly_payment = round(debt * ((loan_rate_pct / 100) / 12 + 1 / (loan_term_years * 12)))
|
|
dscr = round((net_annual_rent / max(monthly_payment * 12, 1)), 2) if monthly_payment else 0
|
|
irr_pct = round((profit / max(total_investment, 1)) * 100 / max((construction_months + sale_months) / 12, 1), 1)
|
|
npv_won = round(profit / 1.06)
|
|
payback_years = round(total_investment / max(net_annual_rent, 1), 1) if net_annual_rent else 0
|
|
equity_multiple = round(revenue_total / max(equity, 1), 2)
|
|
|
|
return wrap_response(
|
|
{
|
|
"cost_structure": {
|
|
"land_cost": land_cost,
|
|
"construction_cost": construction_cost_total,
|
|
"soft_cost": soft_cost,
|
|
"financing_cost": financing_cost,
|
|
"total_investment": total_investment,
|
|
},
|
|
"revenue_projection": {
|
|
"type": revenue_type,
|
|
"gross_annual_rent": gross_annual_rent,
|
|
"net_annual_rent": net_annual_rent,
|
|
"stabilized_value": stabilized_value,
|
|
},
|
|
"returns": {
|
|
"profit": profit,
|
|
"profit_margin_pct": round((profit / max(total_investment, 1)) * 100, 1),
|
|
"irr_pct": irr_pct,
|
|
"npv_won": npv_won,
|
|
"payback_years": payback_years,
|
|
"equity_multiple": equity_multiple,
|
|
},
|
|
"loan_structure": {
|
|
"equity": equity,
|
|
"debt": debt,
|
|
"monthly_payment": monthly_payment,
|
|
"dscr": dscr,
|
|
},
|
|
"sensitivity": {
|
|
"rent_down_10pct": "IRR sensitivity check required",
|
|
"rate_up_100bp": "Financing sensitivity check required",
|
|
"cost_up_10pct": "Cost sensitivity check required",
|
|
},
|
|
"verdict": "투자 검토 가능" if profit > 0 else "재검토 필요",
|
|
},
|
|
ProjectDomain.복합,
|
|
)
|