85 lines
2.7 KiB
Python
85 lines
2.7 KiB
Python
"""
|
|
Export endpoint — CSV, JSON export of system data.
|
|
Production: add XLSX via openpyxl, PDF via reportlab.
|
|
"""
|
|
import csv
|
|
import io
|
|
import json
|
|
from datetime import datetime
|
|
|
|
from fastapi import APIRouter, Depends, Query, Response
|
|
from sqlalchemy.orm import Session
|
|
|
|
from app.api.deps import get_current_user, require_roles, get_db
|
|
from app.api.helpers import audit
|
|
from app.models import Aircraft, Organization, CertApplication, RiskAlert, Audit
|
|
|
|
router = APIRouter(prefix="/export", tags=["export"])
|
|
|
|
EXPORTABLE = {
|
|
"aircraft": Aircraft,
|
|
"organizations": Organization,
|
|
"cert_applications": CertApplication,
|
|
"risk_alerts": RiskAlert,
|
|
"audits": Audit,
|
|
}
|
|
|
|
|
|
@router.get(
|
|
"/{dataset}",
|
|
dependencies=[Depends(require_roles("admin", "authority_inspector", "operator_manager"))],
|
|
)
|
|
def export_data(
|
|
dataset: str,
|
|
format: str = Query("csv", regex="^(csv|json)$"),
|
|
limit: int = Query(5000, le=50000),
|
|
db: Session = Depends(get_db),
|
|
user=Depends(get_current_user),
|
|
):
|
|
"""Export dataset as CSV or JSON."""
|
|
model = EXPORTABLE.get(dataset)
|
|
if not model:
|
|
return Response(
|
|
content=json.dumps({"error": f"Unknown dataset: {dataset}. Available: {list(EXPORTABLE.keys())}"}),
|
|
media_type="application/json", status_code=400,
|
|
)
|
|
|
|
rows = db.query(model).limit(limit).all()
|
|
audit(db, user, "export", dataset, description=f"Exported {len(rows)} {dataset} as {format}")
|
|
db.commit()
|
|
|
|
if format == "json":
|
|
data = []
|
|
for row in rows:
|
|
d = {}
|
|
for col in row.__table__.columns:
|
|
val = getattr(row, col.name, None)
|
|
if isinstance(val, datetime):
|
|
val = val.isoformat()
|
|
d[col.name] = val
|
|
data.append(d)
|
|
return Response(
|
|
content=json.dumps(data, ensure_ascii=False, indent=2, default=str),
|
|
media_type="application/json",
|
|
headers={"Content-Disposition": f"attachment; filename={dataset}_{datetime.utcnow().strftime('%Y%m%d')}.json"},
|
|
)
|
|
|
|
# CSV
|
|
output = io.StringIO()
|
|
if rows:
|
|
cols = [col.name for col in rows[0].__table__.columns]
|
|
writer = csv.DictWriter(output, fieldnames=cols)
|
|
writer.writeheader()
|
|
for row in rows:
|
|
d = {}
|
|
for col in cols:
|
|
val = getattr(row, col, None)
|
|
d[col] = val.isoformat() if isinstance(val, datetime) else val
|
|
writer.writerow(d)
|
|
|
|
return Response(
|
|
content=output.getvalue(),
|
|
media_type="text/csv; charset=utf-8",
|
|
headers={"Content-Disposition": f"attachment; filename={dataset}_{datetime.utcnow().strftime('%Y%m%d')}.csv"},
|
|
)
|