● Zion Boggan
repos/Sightline/backend/app/api/routes/reports.py
zionboggan.com ↗
51 lines · python
History for this file →
1
from __future__ import annotations
2
 
3
from fastapi import APIRouter, Depends, HTTPException, Response
4
from sqlalchemy import select
5
from sqlalchemy.orm import Session
6
 
7
from app.api.deps import Perm, get_db, require
8
from app.models import AuditLog, Report, User
9
from app.schemas import ReportRequest
10
from app.services.reporting import (
11
    build_report, render_csv_timeline, render_json, render_markdown,
12
)
13
 
14
router = APIRouter(tags=["reports"])
15
 
16
 
17
@router.post("/investigations/{inv_id}/reports")
18
def create_report(inv_id: str, payload: ReportRequest, db: Session = Depends(get_db),
19
                  user: User = Depends(require(Perm.EXPORT))):
20
    try:
21
        report = build_report(db, inv_id, payload.sections)
22
    except ValueError as e:
23
        raise HTTPException(404, str(e))
24
    rec = Report(investigation_id=inv_id, title=payload.title or report["title"],
25
                 format=payload.format, sections=report["sections"], created_by=user.id)
26
    db.add(rec)
27
    db.flush()
28
    db.add(AuditLog(actor_user_id=user.id, action="report.create",
29
                    entity_type="report", entity_id=rec.id, meta={"format": payload.format}))
30
    db.commit()
31
    db.refresh(rec)
32
    return {"report_id": rec.id, "format": payload.format, "report": report}
33
 
34
 
35
@router.get("/reports/{report_id}/download")
36
def download_report(report_id: str, format: str = "markdown", db: Session = Depends(get_db),
37
                    _: User = Depends(require(Perm.EXPORT))):
38
    rec = db.get(Report, report_id)
39
    if not rec:
40
        raise HTTPException(404, "report not found")
41
    report = {"title": rec.title, "investigation_id": rec.investigation_id, "sections": rec.sections}
42
    if format == "json":
43
        return Response(render_json(report), media_type="application/json")
44
    if format == "csv":
45
        return Response(render_csv_timeline(report), media_type="text/csv",
46
                        headers={"Content-Disposition": f"attachment; filename=report_{report_id}.csv"})
47
    if format == "pdf":
48
        from app.services.report_pdf import render_pdf
49
        return Response(render_pdf(report), media_type="application/pdf",
50
                        headers={"Content-Disposition": f"attachment; filename=report_{report_id}.pdf"})
51
    return Response(render_markdown(report), media_type="text/markdown")