Finance-Accounts/ar-aging-app/backend/app/api/routes/processing.py

49 lines
2.0 KiB
Python

"""Start processing (background) and poll status/progress."""
from __future__ import annotations
from fastapi import APIRouter, BackgroundTasks, Depends, HTTPException, Request
from sqlalchemy.orm import Session as OrmSession
from ...db import models
from ...services.audit import record as audit
from ...services.jobs import run_processing
from ..deps import db_dep, ensure_editable, 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, request: Request,
db: OrmSession = Depends(db_dep)) -> dict:
s = get_session_or_404(session_id, db)
ensure_editable(s)
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 = ""
audit(db, request, "process_run", session=s,
detail=f"{len(valid_files)} file(s)")
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),
}