d582f15681
- Implemented tests for import polling functionality, ensuring correct behavior for active and terminal import statuses. - Created tests for the login page, validating user interactions and error handling. - Added unit tests for money utility functions, covering parsing, formatting, and summation of monetary values. - Developed tests for query keys, ensuring proper scoping and invalidation roots. chore: setup testing environment and configuration - Added setup file for testing with Vitest and Testing Library. - Configured TypeScript and Vite for the frontend project. - Created Docker and Nginx configurations for local development and production environments. - Established a PostgreSQL initialization script for setting up application roles. docs: add README and environment configuration for infra - Included README for the infra directory, detailing local development setup and service descriptions. - Created an example environment configuration file for local development with placeholders for sensitive information.
61 lines
1.9 KiB
Python
61 lines
1.9 KiB
Python
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"'},
|
|
)
|