import uuid from fastapi import APIRouter, Response from app.dependencies import Context, Csrf, Db from app.exports import service from app.exports.tasks import enqueue_export router = APIRouter(prefix="/exports", tags=["data"]) @router.post("", status_code=202) def request_export(db: Db, context: Context, _csrf: Csrf) -> dict: job = service.request_export(db, space_id=context.space.id, user_id=context.user.id) db.commit() try: enqueue_export(job.id, context.space.id) except Exception as exc: from app.db.session import set_space_context from app.errors import AppError set_space_context(db, context.space.id) job = service.get_export(db, space_id=context.space.id, export_id=job.id) job.status = "failed" job.error_code = "EXPORT_QUEUE_FAILED" db.commit() raise AppError( "Export queue is unavailable", code="EXPORT_QUEUE_FAILED", status_code=503, ) from exc return { "id": job.id, "status": job.status, "downloadUrl": None, "createdAt": job.created_at, } @router.get("/{export_id}") def export_status(export_id: uuid.UUID, db: Db, context: Context) -> dict: job = service.get_export(db, space_id=context.space.id, export_id=export_id) return { "id": job.id, "status": job.status, "downloadUrl": f"/api/v1/exports/{job.id}/download" if job.status == "ready" else None, "createdAt": job.created_at, "expiresAt": job.expires_at, "errorCode": job.error_code, } @router.get("/{export_id}/download") def download(export_id: uuid.UUID, db: Db, context: Context) -> Response: raw = service.consume_export(db, space_id=context.space.id, export_id=export_id) return Response( raw, media_type="application/zip", headers={"Content-Disposition": 'attachment; filename="finance-export.zip"'}, )