OptiQ / api /routes /roi.py
mohammademad2003's picture
first commit
7477316
"""
ROI Calculator endpoint — Calculate return on investment for OptiQ deployment.
"""
from __future__ import annotations
from fastapi import APIRouter, Depends
from pydantic import BaseModel, Field
from config import CFG
from api.auth import optional_auth, FirebaseUser
router = APIRouter()
# OptiQ pricing tiers (from README)
PRICING = {
"saas": {
"name": "SaaS Subscription",
"price_per_feeder_month": 200,
"price_per_feeder_year": 2400,
"description": "Pay-as-you-go pricing. Best for small deployments.",
},
"revenue_share": {
"name": "Revenue Share",
"share_pct": 15,
"description": "No upfront cost. Pay 15% of verified savings.",
},
"enterprise": {
"name": "Enterprise License",
"annual_fee": 500000,
"max_feeders": 1000,
"price_per_feeder_year": 500,
"description": "Flat annual fee for up to 1,000 feeders.",
},
}
# Impact per feeder (from README benchmarks)
PER_FEEDER_IMPACT = {
"loss_reduction_pct": 31.15,
"energy_saved_kwh_year": 553020,
"co2_saved_tonnes_year": 26.3,
"cost_saved_subsidised_year": 16591, # at $0.03/kWh
"cost_saved_real_year": 44242, # at $0.08/kWh
}
class ROIRequest(BaseModel):
number_of_feeders: int = Field(ge=1, le=100000, description="Number of feeders to deploy")
pricing_model: str = Field(default="saas", description="Pricing model: saas, revenue_share, or enterprise")
use_real_cost: bool = Field(default=True, description="Use real electricity cost (True) or subsidised (False)")
@router.post("/roi")
def calculate_roi(req: ROIRequest, user: FirebaseUser = Depends(optional_auth)):
"""Calculate ROI for OptiQ deployment.
Returns annual savings, OptiQ cost, and net profit for the given number of feeders.
"""
n = req.number_of_feeders
impact = PER_FEEDER_IMPACT
# Calculate savings per feeder
if req.use_real_cost:
savings_per_feeder = impact["cost_saved_real_year"]
electricity_rate = 0.08
else:
savings_per_feeder = impact["cost_saved_subsidised_year"]
electricity_rate = 0.03
total_savings = savings_per_feeder * n
total_energy_saved = impact["energy_saved_kwh_year"] * n
total_co2_saved = impact["co2_saved_tonnes_year"] * n
# Calculate OptiQ cost based on pricing model
pricing = PRICING[req.pricing_model]
if req.pricing_model == "saas":
optiq_cost = pricing["price_per_feeder_year"] * n
effective_price_per_feeder = pricing["price_per_feeder_year"]
elif req.pricing_model == "revenue_share":
optiq_cost = total_savings * (pricing["share_pct"] / 100)
effective_price_per_feeder = optiq_cost / n if n > 0 else 0
else: # enterprise
if n <= pricing["max_feeders"]:
optiq_cost = pricing["annual_fee"]
else:
# Additional feeders at $500/feeder/year
optiq_cost = pricing["annual_fee"] + (n - pricing["max_feeders"]) * pricing["price_per_feeder_year"]
effective_price_per_feeder = optiq_cost / n if n > 0 else 0
net_profit = total_savings - optiq_cost
roi_pct = (net_profit / optiq_cost * 100) if optiq_cost > 0 else float("inf")
savings_to_cost_ratio = total_savings / optiq_cost if optiq_cost > 0 else float("inf")
payback_months = (optiq_cost / (total_savings / 12)) if total_savings > 0 else float("inf")
return {
"number_of_feeders": n,
"pricing_model": req.pricing_model,
"pricing_details": pricing,
"electricity_rate_usd_kwh": electricity_rate,
"per_feeder": {
"energy_saved_kwh_year": impact["energy_saved_kwh_year"],
"co2_saved_tonnes_year": impact["co2_saved_tonnes_year"],
"cost_saved_usd_year": savings_per_feeder,
"loss_reduction_pct": impact["loss_reduction_pct"],
},
"annual_totals": {
"energy_saved_mwh": round(total_energy_saved / 1000, 2),
"energy_saved_gwh": round(total_energy_saved / 1_000_000, 4),
"co2_saved_tonnes": round(total_co2_saved, 2),
"utility_savings_usd": round(total_savings, 2),
"optiq_cost_usd": round(optiq_cost, 2),
"net_profit_usd": round(net_profit, 2),
},
"metrics": {
"roi_pct": round(roi_pct, 1) if roi_pct != float("inf") else "∞",
"savings_to_cost_ratio": round(savings_to_cost_ratio, 1) if savings_to_cost_ratio != float("inf") else "∞",
"payback_months": round(payback_months, 1) if payback_months != float("inf") else 0,
"effective_price_per_feeder_year": round(effective_price_per_feeder, 2),
},
"equivalents": {
"trees_planted": int(total_co2_saved * 1000 / 21),
"cars_removed": round(total_co2_saved / 4.6, 0),
"homes_powered": int(total_energy_saved / 10000), # Average home ~10 MWh/year
},
}
@router.get("/roi/pricing")
def get_pricing(user: FirebaseUser = Depends(optional_auth)):
"""Get available pricing models."""
return {
"pricing_models": PRICING,
"per_feeder_impact": PER_FEEDER_IMPACT,
"factors": {
"egypt_emission_factor_kg_kwh": CFG.egypt.emission_factor,
"electricity_price_subsidised": CFG.egypt.electricity_price_subsidised,
"electricity_price_real": CFG.egypt.electricity_price_real,
},
}
@router.get("/roi/comparison")
def compare_pricing(number_of_feeders: int = 100, user: FirebaseUser = Depends(optional_auth)):
"""Compare all pricing models for a given number of feeders."""
results = {}
for model in PRICING.keys():
req = ROIRequest(number_of_feeders=number_of_feeders, pricing_model=model)
results[model] = calculate_roi(req, user)
# Find best model
best_model = max(
results.keys(),
key=lambda m: results[m]["annual_totals"]["net_profit_usd"]
)
return {
"number_of_feeders": number_of_feeders,
"comparison": results,
"recommended": best_model,
"recommendation_reason": f"{PRICING[best_model]['name']} offers the highest net profit for {number_of_feeders} feeders",
}