""" Routes d'administration """ from fastapi import APIRouter, Depends, HTTPException from sqlalchemy.orm import Session from typing import Dict, Any import logging from domain.database import get_db, Document, ProcessingLog from domain.models import DocumentStatus logger = logging.getLogger(__name__) router = APIRouter() @router.get("/stats") async def get_statistics(db: Session = Depends(get_db)): """ Statistiques générales du système """ try: # Statistiques des documents total_documents = db.query(Document).count() status_counts = {} for status in DocumentStatus: count = db.query(Document).filter(Document.status == status.value).count() status_counts[status.value] = count # Statistiques des étapes de traitement processing_stats = db.query( ProcessingLog.step_name, ProcessingLog.status, db.func.count(ProcessingLog.id).label('count') ).group_by( ProcessingLog.step_name, ProcessingLog.status ).all() # Statistiques par étude etude_stats = db.query( Document.etude_id, db.func.count(Document.id).label('count') ).group_by(Document.etude_id).all() return { "documents": { "total": total_documents, "by_status": status_counts }, "processing": [ { "step": stat.step_name, "status": stat.status, "count": stat.count } for stat in processing_stats ], "etudes": [ { "etude_id": stat.etude_id, "document_count": stat.count } for stat in etude_stats ] } except Exception as e: logger.error(f"Erreur lors de la récupération des statistiques: {e}") raise HTTPException(status_code=500, detail=str(e)) @router.post("/documents/{document_id}/retry") async def retry_document_processing( document_id: str, db: Session = Depends(get_db) ): """ Relancer le traitement d'un document """ document = db.query(Document).filter(Document.id == document_id).first() if not document: raise HTTPException(status_code=404, detail="Document non trouvé") if document.status not in [DocumentStatus.FAILED.value, DocumentStatus.MANUAL_REVIEW.value]: raise HTTPException( status_code=400, detail="Le document ne peut être relancé que s'il est en échec ou en révision manuelle" ) # Réinitialisation du statut document.status = DocumentStatus.PENDING.value document.processing_steps = {} document.errors = [] db.commit() # Relance du traitement from tasks.enqueue import enqueue_import meta = { "id_dossier": document.id_dossier, "source": document.source, "etude_id": document.etude_id, "utilisateur_id": document.utilisateur_id, "filename": document.filename, "mime": document.mime_type, "received_at": int(time.time()) } enqueue_import(document_id, meta) logger.info(f"Retraitement lancé pour le document {document_id}") return {"message": "Retraitement lancé avec succès"} @router.post("/documents/{document_id}/manual-review") async def mark_for_manual_review( document_id: str, db: Session = Depends(get_db) ): """ Marquer un document pour révision manuelle """ document = db.query(Document).filter(Document.id == document_id).first() if not document: raise HTTPException(status_code=404, detail="Document non trouvé") document.status = DocumentStatus.MANUAL_REVIEW.value document.manual_review = True db.commit() logger.info(f"Document {document_id} marqué pour révision manuelle") return {"message": "Document marqué pour révision manuelle"} @router.get("/processing-logs/{document_id}") async def get_processing_logs( document_id: str, db: Session = Depends(get_db) ): """ Récupération des logs de traitement d'un document """ logs = db.query(ProcessingLog).filter( ProcessingLog.document_id == document_id ).order_by(ProcessingLog.started_at.desc()).all() return [ { "id": log.id, "step_name": log.step_name, "status": log.status, "started_at": log.started_at, "completed_at": log.completed_at, "duration": log.duration, "error_message": log.error_message, "metadata": log.metadata } for log in logs ]