FastAPI app that pulls interval usage from Sungrow iSolarCloud (OAuth2), caches AER Consumer Data Right electricity plan data, and compares actual metered usage against every available plan to estimate real annual cost (TOU, tiered feed-in, and flat tariffs). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
39 lines
1.3 KiB
Python
39 lines
1.3 KiB
Python
from __future__ import annotations
|
|
|
|
from dataclasses import asdict
|
|
from datetime import datetime, timedelta, timezone
|
|
|
|
from fastapi import APIRouter, Query
|
|
|
|
from app.costing.compare import compare_plans
|
|
from app.db.repositories import get_current_plan, get_household_config, set_current_plan
|
|
from app.db.session import get_session
|
|
|
|
router = APIRouter(prefix="/api/plans", tags=["plans"])
|
|
|
|
|
|
@router.get("/compare")
|
|
def compare(days: int = Query(90, ge=1, le=730), limit: int = Query(50, ge=1, le=500)) -> dict:
|
|
end = datetime.now(timezone.utc)
|
|
start = end - timedelta(days=days)
|
|
result = compare_plans(start, end, limit=limit)
|
|
return {
|
|
"total_plans_considered": result.total_plans_considered,
|
|
"rows": [
|
|
{
|
|
"is_current": row.is_current,
|
|
"savings_vs_current_dollars": row.savings_vs_current_dollars,
|
|
**asdict(row.breakdown),
|
|
"annualized_total_dollars": row.breakdown.annualized_total_dollars,
|
|
"is_estimate": row.breakdown.is_estimate,
|
|
}
|
|
for row in result.rows
|
|
],
|
|
}
|
|
|
|
|
|
@router.get("/household")
|
|
def household():
|
|
with get_session() as session:
|
|
cfg = get_household_config(session)
|
|
return {"distributor": cfg.distributor, "postcode": cfg.postcode, "isolarcloud_ps_id": cfg.isolarcloud_ps_id}
|