Files
2026-03-27 13:54:07 +01:00

115 lines
3.9 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Router Reports Dashboard e Reportistica (Fase 7).
Endpoint:
GET /reports/summary KPI + serie storica + breakdown caselle
GET /reports/export export CSV o PDF
Permessi:
- Tutti gli utenti autenticati possono accedere.
- Admin e super_admin: vedono tutto il tenant.
- Operator/Supervisor/Readonly: vedono solo le caselle su cui hanno can_read.
"""
import uuid
from datetime import datetime
from typing import Optional
from fastapi import APIRouter, Query
from fastapi.responses import Response
from app.dependencies import CurrentUser, DB
from app.schemas.reports import ReportSummaryResponse
from app.services.report_service import ReportService
router = APIRouter(prefix="/reports", tags=["Reports"])
async def _get_visible_ids(user, db) -> Optional[list[uuid.UUID]]:
"""Restituisce None per admin (nessun filtro), lista per non-admin."""
if user.is_admin:
return None
from app.services.permission_service import PermissionService
svc = PermissionService(db)
return await svc.get_visible_mailboxes(user)
# ─── GET /reports/summary ─────────────────────────────────────────────────────
@router.get("/summary", response_model=ReportSummaryResponse)
async def get_report_summary(
current_user: CurrentUser,
db: DB,
days: int = Query(7, ge=1, le=365, description="Periodo in giorni per la serie storica"),
) -> ReportSummaryResponse:
"""
Restituisce il riepilogo completo per la dashboard:
- KPI (PEC ricevute/inviate oggi, anomalie, tasso consegna, ...)
- Serie storica giornaliera per il grafico a barre
- Distribuzione stati outbound per il grafico a torta
- Statistiche per casella
"""
visible = await _get_visible_ids(current_user, db)
svc = ReportService(db)
return await svc.get_summary(
tenant_id=current_user.tenant_id,
period_days=days,
visible_mailbox_ids=visible,
)
# ─── GET /reports/export ──────────────────────────────────────────────────────
@router.get("/export")
async def export_report(
current_user: CurrentUser,
db: DB,
format: str = Query("csv", pattern="^(csv|pdf)$", description="Formato: csv o pdf"),
date_from: Optional[datetime] = Query(None, description="Data inizio (ISO 8601)"),
date_to: Optional[datetime] = Query(None, description="Data fine (ISO 8601)"),
mailbox_id: Optional[uuid.UUID] = Query(None, description="Filtra per casella specifica"),
) -> Response:
"""
Esporta i dati in formato CSV o PDF.
- CSV: lista completa dei messaggi del periodo con tutti i metadati.
- PDF: riepilogo KPI + tabella caselle (generato con reportlab).
"""
visible = await _get_visible_ids(current_user, db)
svc = ReportService(db)
now_str = datetime.now().strftime("%Y%m%d_%H%M%S")
if format == "csv":
data = await svc.export_csv(
tenant_id=current_user.tenant_id,
date_from=date_from,
date_to=date_to,
mailbox_id=mailbox_id,
visible_mailbox_ids=visible,
)
return Response(
content=data,
media_type="text/csv; charset=utf-8-sig",
headers={
"Content-Disposition": f'attachment; filename="pechub_report_{now_str}.csv"',
"Content-Length": str(len(data)),
},
)
# PDF
data = await svc.export_pdf(
tenant_id=current_user.tenant_id,
date_from=date_from,
date_to=date_to,
visible_mailbox_ids=visible,
)
return Response(
content=data,
media_type="application/pdf",
headers={
"Content-Disposition": f'attachment; filename="pechub_report_{now_str}.pdf"',
"Content-Length": str(len(data)),
},
)