"""Refreshes the local `plan_cache` table from the live AER APIs. Run periodically (see scheduler/jobs.py) rather than per page-load: pulling every configured retailer's full plan list, plus a detail call per plan, is too slow and too polite-unfriendly to a public government API to do on every request. """ from __future__ import annotations import logging from app.aer.client import AERClient from app.costing.aer_mapper import map_aer_plan from app.db.repositories import upsert_plan from app.db.session import get_session _LOGGER = logging.getLogger(__name__) def refresh_plan_cache(distributor_filter: str | None = None) -> int: """Fetches every retailer's current electricity plans and upserts them into `plan_cache`. If `distributor_filter` is given (case-insensitive substring), only plans available in that distributor's area are kept, since fetching plan *detail* is the slow part and most retailers serve many distributor areas we don't care about.""" client = AERClient() count = 0 for list_entry in client.fetch_all_plans(): distributors = list_entry.get("geography", {}).get("distributors", []) if distributor_filter and not any(distributor_filter.lower() in d.lower() for d in distributors): continue try: detail = client.fetch_plan_detail(list_entry["brand"], list_entry["planId"]) plan = map_aer_plan(list_entry, detail) except Exception: _LOGGER.exception("Failed to fetch/parse plan %s from %s", list_entry.get("planId"), list_entry.get("brand")) continue with get_session() as session: upsert_plan(session, plan, raw_detail=detail) count += 1 return count