"""Start processing (background) and poll status/progress.""" from __future__ import annotations from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException from sqlalchemy.orm import Session as OrmSession from ...db import models from ...services.jobs import run_processing from ..deps import db_dep, get_session_or_404, session_dict router = APIRouter(prefix="/api/sessions", tags=["processing"]) @router.post("/{session_id}/process") def start_processing(session_id: int, background: BackgroundTasks, db: OrmSession = Depends(db_dep)) -> dict: s = get_session_or_404(session_id, db) if s.month_end_date is None: raise HTTPException(400, "Set the month-end date before processing.") valid_files = db.query(models.SessionFile).filter( models.SessionFile.session_id == session_id).all() if not valid_files: raise HTTPException(400, "Upload at least one file before processing.") if any(f.status == "invalid" for f in valid_files): raise HTTPException(400, "One or more files failed validation; fix them before processing.") if s.status == "processing": raise HTTPException(409, "Already processing.") s.status = "processing" s.progress_stage = "Queued" s.progress_pct = 0.0 s.error = "" db.commit() background.add_task(run_processing, session_id) return {"started": True, "session_id": session_id} @router.get("/{session_id}/status") def status(session_id: int, db: OrmSession = Depends(db_dep)) -> dict: s = get_session_or_404(session_id, db) return { "status": s.status, "stage": s.progress_stage, "pct": s.progress_pct, "rows_done": s.progress_rows_done, "rows_total": s.progress_rows_total, "eta_seconds": s.eta_seconds, "error": s.error, "session": session_dict(s), }