Nicolas Cantu 7f96fd439d fix: Corrections finales pour le déploiement Docker
- Correction des imports dans domain/models.py (ajout des enums et modèles Pydantic)
- Correction des imports dans routes/ (documents, health, admin)
- Correction de la fonction init_db() dans app.py (suppression await)
- Correction de la configuration MinIO (suppression du protocole http://)
- Correction de la fonction get_detailed_verification_report (async)
- Correction des imports StorageManager dans tasks/notary_tasks.py
- Correction du Dockerfile worker (contexte de build et chemins)
- Suppression de la dépendance python-alto non trouvée

L'API est maintenant fonctionnelle et accessible sur http://localhost:8000
2025-09-10 17:56:10 +02:00

187 lines
5.5 KiB
Python

"""
Routes pour la gestion des documents
"""
from fastapi import APIRouter, UploadFile, File, Form, HTTPException, Depends, Query
from sqlalchemy.orm import Session
from typing import List, Optional
import uuid
import time
import logging
from domain.database import get_db
from domain.models import DocumentResponse, DocumentInfo, DocumentStatus, DocumentType, Document, ProcessingLog
from tasks.enqueue import enqueue_import
from utils.storage import store_document
logger = logging.getLogger(__name__)
router = APIRouter()
@router.post("/import", response_model=DocumentResponse)
async def import_document(
file: UploadFile = File(...),
id_dossier: str = Form(...),
source: str = Form("upload"),
etude_id: str = Form(...),
utilisateur_id: str = Form(...),
db: Session = Depends(get_db)
):
"""
Import d'un nouveau document dans le pipeline
"""
try:
# Vérification du type de fichier
if file.content_type not in [dt.value for dt in DocumentType]:
raise HTTPException(
status_code=415,
detail=f"Type de fichier non supporté: {file.content_type}"
)
# Génération d'un ID unique
doc_id = str(uuid.uuid4())
# Lecture du contenu du fichier
content = await file.read()
file_size = len(content)
# Stockage du document
storage_path = await store_document(doc_id, content, file.filename)
# Création de l'enregistrement en base
document = Document(
id=doc_id,
filename=file.filename or "unknown",
mime_type=file.content_type,
size=file_size,
status=DocumentStatus.PENDING.value,
id_dossier=id_dossier,
etude_id=etude_id,
utilisateur_id=utilisateur_id,
source=source
)
db.add(document)
db.commit()
db.refresh(document)
# Enqueue du traitement
meta = {
"id_dossier": id_dossier,
"source": source,
"etude_id": etude_id,
"utilisateur_id": utilisateur_id,
"filename": file.filename,
"mime": file.content_type,
"received_at": int(time.time())
}
enqueue_import(doc_id, meta)
logger.info(f"Document {doc_id} importé avec succès")
return DocumentResponse(
status="queued",
id_document=doc_id,
message="Document en cours de traitement"
)
except Exception as e:
logger.error(f"Erreur lors de l'import du document: {e}")
raise HTTPException(status_code=500, detail=str(e))
@router.get("/documents/{document_id}", response_model=DocumentInfo)
async def get_document(
document_id: str,
db: Session = Depends(get_db)
):
"""
Récupération des informations 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é")
return DocumentInfo(
id=document.id,
filename=document.filename,
mime_type=document.mime_type,
size=document.size,
status=DocumentStatus(document.status),
id_dossier=document.id_dossier,
etude_id=document.etude_id,
utilisateur_id=document.utilisateur_id,
created_at=document.created_at,
updated_at=document.updated_at,
processing_steps=document.processing_steps,
extracted_data=document.extracted_data,
errors=document.errors
)
@router.get("/documents", response_model=List[DocumentInfo])
async def list_documents(
etude_id: Optional[str] = Query(None),
id_dossier: Optional[str] = Query(None),
status: Optional[DocumentStatus] = Query(None),
limit: int = Query(50, le=100),
offset: int = Query(0, ge=0),
db: Session = Depends(get_db)
):
"""
Liste des documents avec filtres
"""
query = db.query(Document)
if etude_id:
query = query.filter(Document.etude_id == etude_id)
if id_dossier:
query = query.filter(Document.id_dossier == id_dossier)
if status:
query = query.filter(Document.status == status.value)
documents = query.offset(offset).limit(limit).all()
return [
DocumentInfo(
id=doc.id,
filename=doc.filename,
mime_type=doc.mime_type,
size=doc.size,
status=DocumentStatus(doc.status),
id_dossier=doc.id_dossier,
etude_id=doc.etude_id,
utilisateur_id=doc.utilisateur_id,
created_at=doc.created_at,
updated_at=doc.updated_at,
processing_steps=doc.processing_steps,
extracted_data=doc.extracted_data,
errors=doc.errors
)
for doc in documents
]
@router.delete("/documents/{document_id}")
async def delete_document(
document_id: str,
db: Session = Depends(get_db)
):
"""
Suppression 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é")
# Suppression des logs de traitement
db.query(ProcessingLog).filter(ProcessingLog.document_id == document_id).delete()
# Suppression du document
db.delete(document)
db.commit()
logger.info(f"Document {document_id} supprimé")
return {"message": "Document supprimé avec succès"}