"""Generate and download the Accounts Receivable Aging workbook.""" from __future__ import annotations import os from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException from fastapi.responses import FileResponse from sqlalchemy.orm import Session as OrmSession from ...db import models from ...services.jobs import run_export, run_summary_export from ..deps import db_dep, get_session_or_404 router = APIRouter(prefix="/api/sessions", tags=["export"]) @router.post("/{session_id}/export") def start_export(session_id: int, background: BackgroundTasks, kind: str = "full", db: OrmSession = Depends(db_dep)) -> dict: """kind='summary' → compact Finance pack (fast); kind='full' → complete audit workbook.""" if kind not in ("full", "summary"): raise HTTPException(400, "kind must be 'full' or 'summary'.") s = get_session_or_404(session_id, db) if s.status not in ("processed", "exporting", "completed"): raise HTTPException(400, "Process the session before exporting.") if s.status == "exporting": raise HTTPException(409, "Export already in progress.") # Flip status synchronously so the frontend starts polling immediately. s.status = "exporting" s.progress_stage = "Queued for export" s.progress_pct = 0.0 s.progress_rows_done = 0 s.progress_rows_total = 0 s.eta_seconds = 0 s.error = "" db.commit() background.add_task(run_summary_export if kind == "summary" else run_export, session_id) return {"started": True, "kind": kind} @router.get("/{session_id}/exports") def list_exports(session_id: int, db: OrmSession = Depends(db_dep)) -> list[dict]: get_session_or_404(session_id, db) rows = db.query(models.ExportRecord).filter( models.ExportRecord.session_id == session_id).order_by( models.ExportRecord.generated_at.desc()).all() return [{"id": r.id, "kind": r.kind or "full", "sha256": r.sha256, "size_bytes": r.size_bytes, "generated_at": r.generated_at.isoformat() if r.generated_at else None, "available": bool(r.path and os.path.exists(r.path))} for r in rows] @router.get("/{session_id}/export/download") def download_export(session_id: int, kind: str = "full", db: OrmSession = Depends(db_dep)): get_session_or_404(session_id, db) q = db.query(models.ExportRecord).filter(models.ExportRecord.session_id == session_id) if kind in ("full", "summary"): q = q.filter(models.ExportRecord.kind == kind) r = q.order_by(models.ExportRecord.generated_at.desc()).first() if not r or not r.path or not os.path.exists(r.path): raise HTTPException(404, "No export available; generate it first.") return FileResponse( r.path, filename=os.path.basename(r.path), media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", )