Files
foodlinkk-command-center/cockpit/app/routes/reports.py
T

79 lines
2.7 KiB
Python
Raw Normal View History

from pathlib import Path
from fastapi import APIRouter, HTTPException, Query, Request
from fastapi.responses import JSONResponse, PlainTextResponse, Response
from fastapi.templating import Jinja2Templates
from app.db import fetch_all
from app.services.reports_export import EXPORT_DATASETS, export_all_json, fetch_dataset, list_datasets, to_csv
router = APIRouter(prefix="/reports", tags=["reports"])
BASE_DIR = Path(__file__).resolve().parent.parent.parent
templates = Jinja2Templates(directory=str(BASE_DIR / "templates"))
def _iso_rows(rows: list) -> list:
for row in rows:
for key, val in list(row.items()):
if hasattr(val, "isoformat"):
row[key] = val.isoformat()
return rows
@router.get("")
async def reports_page(request: Request):
briefings, events = [], []
try:
briefings = _iso_rows(fetch_all(
"SELECT id, content, generated_by, created_at FROM daily_briefings ORDER BY created_at DESC LIMIT 20"
))
except Exception:
briefings = []
try:
events = _iso_rows(fetch_all(
"""SELECT id, agent_name, event_type, title, status, created_at FROM agent_events
WHERE event_type IN ('briefing','report','herman_chat') ORDER BY created_at DESC LIMIT 50"""
))
except Exception:
events = []
datasets = list_datasets()
return templates.TemplateResponse(
"reports.html",
{
"request": request,
"page_title": "Reports & Export",
"briefings": briefings,
"report_events": events,
"datasets": datasets,
},
)
@router.get("/api/datasets")
async def reports_datasets():
return JSONResponse({"items": list_datasets()})
@router.get("/api/export/{name}")
async def reports_export_one(name: str, format: str = Query("csv", pattern="^(csv|json)$"), limit: int = Query(10000, ge=1, le=50000)):
if name not in EXPORT_DATASETS:
raise HTTPException(404, "Dataset not found")
try:
rows = fetch_dataset(name, limit)
except Exception as exc:
raise HTTPException(500, str(exc)) from exc
if format == "json":
return JSONResponse({"dataset": name, "count": len(rows), "items": rows})
csv_text = to_csv(rows)
return PlainTextResponse(
csv_text,
media_type="text/csv",
headers={"Content-Disposition": f'attachment; filename="foodlinkk_{name}.csv"'},
)
@router.get("/api/export-all")
async def reports_export_all(format: str = Query("json", pattern="^(json)$"), limit: int = Query(3000, ge=100, le=10000)):
bundle = export_all_json(limit)
return JSONResponse(bundle, headers={"Content-Disposition": 'attachment; filename="foodlinkk_full_export.json"'})