"""Full-system data export for Reports hub.""" from __future__ import annotations import csv import io import json from datetime import datetime, timezone from typing import Any from app.db import fetch_all EXPORT_DATASETS: dict[str, dict[str, str]] = { "clients": {"label": "CRM Klanten", "table": "clients", "order": "updated_at DESC"}, "deals": {"label": "CRM Deals", "table": "deals", "order": "updated_at DESC"}, "supermarkets": {"label": "Supermarkten", "table": "supermarkets", "order": "name ASC"}, "wholesalers": {"label": "Groothandels", "table": "wholesalers", "order": "name ASC"}, "supermarket_contacts": {"label": "Supermarkt contacten", "table": "supermarket_contacts", "order": "id ASC"}, "wholesaler_contacts": {"label": "Groothandel contacten", "table": "wholesaler_contacts", "order": "id ASC"}, "rss_items": {"label": "RSS items", "table": "rss_items", "order": "published_at DESC NULLS LAST"}, "rss_bookmarks": {"label": "RSS bookmarks", "table": "rss_bookmarks", "order": "created_at DESC"}, "agent_events": {"label": "Agent events", "table": "agent_events", "order": "created_at DESC"}, "sales_milestones": {"label": "Sales milestones", "table": "sales_milestones", "order": "created_at DESC"}, "promo_campaigns": {"label": "Promo / reclame", "table": "promo_campaigns", "order": "created_at DESC"}, "daily_briefings": {"label": "Dagrapporten", "table": "daily_briefings", "order": "created_at DESC"}, "document_analytics": {"label": "NAS documenten", "table": "document_analytics", "order": "analyzed_at DESC NULLS LAST"}, "products": {"label": "Producten", "table": "products", "order": "name ASC"}, "suppliers": {"label": "Leveranciers", "table": "suppliers", "order": "name ASC"}, } def _serialize(val: Any) -> Any: if hasattr(val, "isoformat"): return val.isoformat() if isinstance(val, (dict, list)): return json.dumps(val, default=str) if val is not None and type(val).__name__ == "Decimal": return float(val) return val def list_datasets() -> list[dict[str, Any]]: out = [] for key, meta in EXPORT_DATASETS.items(): count = 0 try: from app.db import fetch_one row = fetch_one(f"SELECT COUNT(*) AS c FROM {meta['table']}") count = int(row["c"]) if row else 0 except Exception: pass out.append({"id": key, "label": meta["label"], "count": count}) return out def fetch_dataset(name: str, limit: int = 10000) -> list[dict[str, Any]]: meta = EXPORT_DATASETS.get(name) if not meta: raise ValueError(f"Unknown dataset: {name}") rows = fetch_all(f"SELECT * FROM {meta['table']} ORDER BY {meta['order']} LIMIT %s", (limit,)) for row in rows: for k, v in list(row.items()): row[k] = _serialize(v) return rows def to_csv(rows: list[dict[str, Any]]) -> str: if not rows: return "" buf = io.StringIO() writer = csv.DictWriter(buf, fieldnames=list(rows[0].keys()), extrasaction="ignore") writer.writeheader() writer.writerows(rows) return buf.getvalue() def export_all_json(limit: int = 5000) -> dict[str, Any]: bundle: dict[str, Any] = { "exported_at": datetime.now(timezone.utc).isoformat(), "datasets": {}, } for key in EXPORT_DATASETS: try: bundle["datasets"][key] = fetch_dataset(key, limit=min(limit, 5000)) except Exception as exc: bundle["datasets"][key] = {"error": str(exc)} return bundle