""" Tâches de traitement pour le worker Cheque Scanner """ import os import sys import time import json import logging import traceback import redis from datetime import datetime from rq import get_current_job from json import JSONEncoder # Ajouter le module d'extraction au path sys.path.append('/app/shared') # Importer les fonctions d'extraction from extraction import ( extraire_infos_cheque, get_tessdata_path ) # Configuration du logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) logger = logging.getLogger("cheque_scanner_tasks") # Variables d'environnement REDIS_URL = os.getenv("REDIS_URL", "redis://redis:6379/0") DEFAULT_OCR_LANGUAGE = os.getenv("DEFAULT_OCR_LANGUAGE", "eng") ALTERNATIVE_OCR_LANGUAGE = os.getenv("ALTERNATIVE_OCR_LANGUAGE", "fra") TESSERACT_DATA_PATH = os.getenv("TESSERACT_DATA_PATH", "/usr/share/tesseract-ocr/4.00/tessdata") def update_job_status(job_id, status, message=None, progress=None, result=None, texte_brut=None, erreur=None, methode=None): """ Met à jour le statut d'une tâche dans Redis """ try: # Connexion à Redis redis_conn = redis.Redis.from_url(REDIS_URL) # Préparer les données à mettre à jour update_data = { "status": status, "updated_at": datetime.now().isoformat() } if message: update_data["message"] = message if progress: update_data["progress"] = str(progress) if result: # Utiliser json.dumps pour une sérialisation correcte update_data["result"] = json.dumps(result) if texte_brut: update_data["texte_brut"] = texte_brut if erreur: update_data["erreur"] = erreur if methode: update_data["methode"] = methode if status == "completed": update_data["completed_at"] = datetime.now().isoformat() # Mettre à jour les données dans Redis redis_conn.hset(f"job:{job_id}", mapping=update_data) logger.info(f"Statut de la tâche {job_id} mis à jour: {status}") return True except Exception as e: logger.error(f"Erreur lors de la mise à jour du statut de la tâche {job_id}: {str(e)}") return False def process_cheque_image(job_id, file_path, **kwargs): """ Traite une image de chèque pour en extraire les informations Args: job_id (str): Identifiant de la tâche file_path (str): Chemin vers l'image à traiter **kwargs: Paramètres supplémentaires (ignorés, pour compatibilité avec RQ) Returns: dict: Résultat de l'extraction """ job = get_current_job() logger.info(f"Début du traitement de l'image: {file_path} (Tâche: {job_id})") # Mettre à jour le statut update_job_status( job_id=job_id, status="processing", message="Traitement en cours", progress=10 ) try: # Vérifier que le fichier existe if not os.path.exists(file_path): raise FileNotFoundError(f"L'image {file_path} n'existe pas") # Récupérer le chemin vers tessdata tessdata_path = TESSERACT_DATA_PATH if not os.path.exists(tessdata_path): # Essayer de trouver automatiquement tessdata_path = get_tessdata_path() # Mise à jour intermédiaire update_job_status( job_id=job_id, status="processing", message="Extraction des informations en cours", progress=30 ) # Première tentative avec la langue par défaut try: logger.info(f"Tentative d'extraction avec la langue: {DEFAULT_OCR_LANGUAGE}") update_job_status( job_id=job_id, status="processing", message=f"Extraction avec langue {DEFAULT_OCR_LANGUAGE}", progress=50 ) infos, texte = extraire_infos_cheque( chemin_image=file_path, methode="hybride_avance", language=DEFAULT_OCR_LANGUAGE, tessdata=tessdata_path ) methode = "hybride_avance" except Exception as e: logger.warning(f"Échec de la première tentative: {str(e)}") # Deuxième tentative avec la langue alternative try: logger.info(f"Tentative d'extraction avec la langue: {ALTERNATIVE_OCR_LANGUAGE}") update_job_status( job_id=job_id, status="processing", message=f"Extraction avec langue {ALTERNATIVE_OCR_LANGUAGE}", progress=60 ) infos, texte = extraire_infos_cheque( chemin_image=file_path, methode="hybride_avance", language=ALTERNATIVE_OCR_LANGUAGE, tessdata=tessdata_path ) methode = "hybride_avance" except Exception as e2: logger.warning(f"Échec de la deuxième tentative: {str(e2)}") # Troisième tentative avec la méthode hybride (combinant MICR et extraction du montant en lettres) logger.info("Tentative d'extraction avec la méthode hybride (MICR + montant en lettres)") update_job_status( job_id=job_id, status="processing", message="Extraction MICR et montant en lettres", progress=70 ) infos, texte = extraire_infos_cheque( chemin_image=file_path, methode="hybride", language=DEFAULT_OCR_LANGUAGE, tessdata=tessdata_path ) methode = "hybride" # Si échec, dernière tentative avec la méthode MICR seule if not infos.get("montant") and not infos.get("code_banque"): logger.info("Tentative d'extraction avec la méthode MICR uniquement") update_job_status( job_id=job_id, status="processing", message="Extraction MICR uniquement", progress=80 ) infos, texte = extraire_infos_cheque( chemin_image=file_path, methode="micr" ) methode = "micr" # Mise à jour finale update_job_status( job_id=job_id, status="processing", message="Finalisation des résultats", progress=90 ) # Sauvegarder les résultats dans Redis update_job_status( job_id=job_id, status="completed", message="Extraction terminée avec succès", progress=100, result=infos, texte_brut=texte, methode=methode ) logger.info(f"Traitement terminé pour la tâche {job_id}") return { "job_id": job_id, "status": "completed", "result": infos, "methode": methode } except Exception as e: # Capturer l'erreur error_trace = traceback.format_exc() logger.error(f"Erreur lors du traitement de l'image: {str(e)}\n{error_trace}") # Mettre à jour le statut avec l'erreur update_job_status( job_id=job_id, status="failed", message="Échec du traitement", erreur=str(e) ) # Retourner l'erreur return { "job_id": job_id, "status": "failed", "error": str(e) }