Files
Aissa 5d60d33db1 Platform bundle: marketing publish, IT ops, packaging, agents mesh.
Volledige Foodlinkk Command Center uitbreiding met social automatisering,
reclamefolder filters, Proxmox monitoring en documentatie.
2026-06-09 00:41:27 +00:00

94 lines
3.1 KiB
Python

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}