Files
k1nq d582f15681 feat: add tests for import polling, login page, money utilities, and query keys
- 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.
2026-09-14 09:26:33 +05:00

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"'},
)