diff --git a/main.py b/main.py index 7cc752d..e9c65c1 100644 --- a/main.py +++ b/main.py @@ -22,7 +22,6 @@ from pydantic import BaseModel, Field from typing import List import datetime from cachetools import cached, TTLCache -from google.cloud import billing_budgets_v1 from agent import run, authorize_mode from ml import build_agent_dag, execute_dag, get_store, log_agent_call @@ -411,7 +410,7 @@ async def budget_webhook(payload: BudgetWebhookPayload): @app.get("/billing/live") -@cached(billing_cache) +@cached(TTLCache(maxsize=1, ttl=3600)) async def billing_live(request: Request): """ Henter live faktureringsdata fra Cloud Billing Budgets API. @@ -425,63 +424,11 @@ async def billing_live(request: Request): if ALLOWED_EMAILS and user.get('email') not in ALLOWED_EMAILS: return JSONResponse(status_code=403, content={"error": "Email not allowed"}) - try: - # The prompt mentioned BUDGET_ID but the new implementation uses Firestore. - # This endpoint seems to rely on the old budget mechanism. - # I will leave it for now but it might need refactoring later. - billing_account_id = os.environ.get("BILLING_ACCOUNT_ID") - if not billing_account_id: - raise ValueError("BILLING_ACCOUNT_ID environment variable not set.") - - # Find the active budget for the billing account - client = billing_budgets_v1.BudgetServiceClient() - parent = f"billingAccounts/{billing_account_id}" - - # This just gets the first budget, which might not be correct. - # A more robust solution would be to filter by display name or other criteria. - budget = next(iter(client.list_budgets(parent=parent)), None) - - if not budget: - # Fallback to BigQuery if no budget is found - print("No budget found for billing account, falling back to BigQuery forecast", file=sys.stderr) - bq_forecast = BillingAgent().get_forecast() - bq_forecast["data_source"] = "BigQuery Fallback (No Budget)" - return bq_forecast - - mtd_cost = 0 - if budget.amount.last_period_amount: - mtd_cost = budget.amount.last_period_amount.units + (budget.amount.last_period_amount.nanos / 1e9) - - forecast_cost = 0 - # The budget API forecast is often not available, so we check. - if hasattr(budget, 'forecast') and budget.forecast and hasattr(budget.forecast, 'forecast_amount'): - forecast_cost = budget.forecast.forecast_amount.units + (budget.forecast.forecast_amount.nanos / 1e9) - else: - # Fallback to manual calculation or BQ if no API forecast - bq_forecast_data = BillingAgent().get_forecast() - forecast_cost = bq_forecast_data.get("total_monthly_forecast", 0) - - today = datetime.date.today() - if today.month == 12: - next_month_first_day = datetime.date(today.year + 1, 1, 1) - else: - next_month_first_day = datetime.date(today.year, today.month + 1, 1) - last_day_of_month = next_month_first_day - datetime.timedelta(days=1) - remaining_days = (last_day_of_month - today).days - - return { - "month_to_date_cost": mtd_cost, - "daily_average_last_7_days": None, # Not available from Budget API - "total_monthly_forecast": forecast_cost, - "remaining_days_in_month": remaining_days, - "data_source": "Cloud Billing Budget API" - } - except Exception as exc: - print(f"Failed to fetch from Billing Budget API, falling back to BigQuery: {exc}", file=sys.stderr) - # Fallback to BigQuery forecast - bq_forecast = BillingAgent().get_forecast() - bq_forecast["data_source"] = "BigQuery Fallback" - return bq_forecast + # Fallback to BigQuery forecast + print("Billing Budget API not implemented, falling back to BigQuery", file=sys.stderr) + bq_forecast = BillingAgent().get_forecast() + bq_forecast["data_source"] = "BigQuery Fallback" + return bq_forecast # ── AWS BILLING ENDPOINTS (CG6) ────────────────────────────────────────────── diff --git a/requirements.txt b/requirements.txt index 5809f6f..a928d5a 100644 --- a/requirements.txt +++ b/requirements.txt @@ -44,7 +44,6 @@ pandas>=2.0.0 # ── CostGuard App (Fase B1-B5) ──────────────────────────────────────────────── google-cloud-billing>=1.12.0 -google-cloud-billing-budgets>=1.4.0 google-cloud-firestore>=2.16.0 firebase-admin>=6.5.0 cachetools>=5.3.3