Files
foodlinkk-command-center/cockpit/templates/api.py
T

94 lines
3.1 KiB
Python
Raw Normal View History

from datetime import date, datetime
from typing import Any, Optional
import httpx
from fastapi import APIRouter, HTTPException
from app.config import settings
from app.db import execute, fetch_all, fetch_one
from app.services.briefing import collect_briefing_data, generate_daily_briefing, serialize_stats
router = APIRouter(prefix="/api", tags=["api"])
def _stats_payload() -> dict[str, Any]:
stats: dict[str, Any] = {
"deals": 0,
"clients": 0,
"pending_approvals": 0,
"pipeline_value": 0,
}
try:
row = fetch_one("SELECT COUNT(*) AS c FROM deals")
stats["deals"] = int(row["c"]) if row else 0
except Exception:
pass
try:
row = fetch_one("SELECT COUNT(*) AS c FROM clients")
stats["clients"] = int(row["c"]) if row else 0
except Exception:
pass
try:
row = fetch_one("SELECT COUNT(*) AS c FROM agent_events WHERE status = 'needs_approval'")
stats["pending_approvals"] = int(row["c"]) if row else 0
except Exception:
pass
try:
row = fetch_one(
"SELECT COALESCE(SUM(value), 0) AS total FROM deals WHERE stage NOT IN ('won', 'lost')"
)
stats["pipeline_value"] = float(row["total"]) if row else 0
except Exception:
pass
return stats
@router.get("/herman/briefing/stats")
async def herman_briefing_stats():
"""Live stats from DB — always fresh for dashboard panels."""
return {"ok": True, "stats": serialize_stats(collect_briefing_data()), "at": datetime.utcnow().isoformat()}
@router.post("/herman/briefing")
async def herman_briefing():
try:
content, stats = await generate_daily_briefing()
except Exception as exc:
raise HTTPException(status_code=502, detail=str(exc)) from exc
return {"ok": True, "content": content, "stats": stats, "generated_at": datetime.utcnow().isoformat()}
@router.get("/herman/briefing/latest")
async def herman_briefing_latest():
try:
row = fetch_one(
"SELECT id, content, generated_by, metadata, created_at FROM daily_briefings ORDER BY created_at DESC LIMIT 1"
)
except Exception as exc:
raise HTTPException(status_code=500, detail=str(exc)) from exc
live_stats = serialize_stats(collect_briefing_data())
if not row:
return {"ok": True, "content": None, "stats": live_stats}
if row.get("created_at") and hasattr(row["created_at"], "isoformat"):
row["created_at"] = row["created_at"].isoformat()
return {"ok": True, **row, "stats": live_stats}
@router.get("/events")
async def list_events(limit: int = 50):
limit = max(1, min(limit, 200))
try:
rows = fetch_all(
"""
SELECT id, agent_name, event_type, title, body, status, created_at
FROM agent_events ORDER BY created_at DESC LIMIT %s
""",
(limit,),
)
except Exception as exc:
raise HTTPException(status_code=500, detail=str(exc)) from exc
for row in rows:
if row.get("created_at"):
row["created_at"] = row["created_at"].isoformat()
return {"events": rows}