48 lines
2.0 KiB
Python
48 lines
2.0 KiB
Python
|
|
"""Export API: Excel and PDF report download."""
|
||
|
|
|
||
|
|
from io import BytesIO
|
||
|
|
from fastapi import APIRouter, Depends, HTTPException
|
||
|
|
from fastapi.responses import StreamingResponse
|
||
|
|
from sqlalchemy import select
|
||
|
|
from sqlalchemy.ext.asyncio import AsyncSession
|
||
|
|
|
||
|
|
from app.models.database import get_db
|
||
|
|
from app.models import Case, Transaction
|
||
|
|
from app.schemas import TransactionResponse
|
||
|
|
|
||
|
|
router = APIRouter()
|
||
|
|
|
||
|
|
|
||
|
|
@router.get("/{case_id}/export/excel")
|
||
|
|
async def export_excel(case_id: int, db: AsyncSession = Depends(get_db)):
|
||
|
|
from app.services.report import build_excel_report
|
||
|
|
r = await db.execute(select(Case).where(Case.id == case_id))
|
||
|
|
case = r.scalar_one_or_none()
|
||
|
|
if not case:
|
||
|
|
raise HTTPException(status_code=404, detail="Case not found")
|
||
|
|
r = await db.execute(select(Transaction).where(Transaction.case_id == case_id).order_by(Transaction.transaction_time))
|
||
|
|
txns = [TransactionResponse.model_validate(t) for t in r.scalars().all()]
|
||
|
|
data = await build_excel_report(case, txns)
|
||
|
|
return StreamingResponse(
|
||
|
|
BytesIO(data),
|
||
|
|
media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
||
|
|
headers={"Content-Disposition": f"attachment; filename=case_{case_id}_report.xlsx"},
|
||
|
|
)
|
||
|
|
|
||
|
|
|
||
|
|
@router.get("/{case_id}/export/pdf")
|
||
|
|
async def export_pdf(case_id: int, db: AsyncSession = Depends(get_db)):
|
||
|
|
from app.services.report import build_pdf_report
|
||
|
|
r = await db.execute(select(Case).where(Case.id == case_id))
|
||
|
|
case = r.scalar_one_or_none()
|
||
|
|
if not case:
|
||
|
|
raise HTTPException(status_code=404, detail="Case not found")
|
||
|
|
r = await db.execute(select(Transaction).where(Transaction.case_id == case_id).order_by(Transaction.transaction_time))
|
||
|
|
txns = [TransactionResponse.model_validate(t) for t in r.scalars().all()]
|
||
|
|
data = await build_pdf_report(case, txns)
|
||
|
|
return StreamingResponse(
|
||
|
|
BytesIO(data),
|
||
|
|
media_type="application/pdf",
|
||
|
|
headers={"Content-Disposition": f"attachment; filename=case_{case_id}_report.pdf"},
|
||
|
|
)
|