refactor: improve societe info handling and add sqlite lock retry docs
This commit is contained in:
parent
3f1dce918d
commit
30ffc7a493
1 changed files with 49 additions and 9 deletions
|
|
@ -74,6 +74,11 @@ def _register_sage_font():
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
# ============================================================================
|
||||||
|
# HELPERS POUR GESTION DES LOCKS SQLite
|
||||||
|
# ============================================================================
|
||||||
|
|
||||||
|
|
||||||
async def execute_with_retry(
|
async def execute_with_retry(
|
||||||
session,
|
session,
|
||||||
operation,
|
operation,
|
||||||
|
|
@ -81,6 +86,17 @@ async def execute_with_retry(
|
||||||
base_delay: float = 0.1,
|
base_delay: float = 0.1,
|
||||||
max_delay: float = 2.0,
|
max_delay: float = 2.0,
|
||||||
):
|
):
|
||||||
|
"""
|
||||||
|
Exécute une opération async avec retry en cas de lock SQLite.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
session: Session SQLAlchemy async
|
||||||
|
operation: Coroutine à exécuter
|
||||||
|
max_retries: Nombre max de tentatives
|
||||||
|
base_delay: Délai initial entre les tentatives (secondes)
|
||||||
|
max_delay: Délai maximum entre les tentatives
|
||||||
|
"""
|
||||||
|
import sqlite3
|
||||||
from sqlalchemy.exc import OperationalError
|
from sqlalchemy.exc import OperationalError
|
||||||
|
|
||||||
last_exception = None
|
last_exception = None
|
||||||
|
|
@ -107,7 +123,7 @@ async def execute_with_retry(
|
||||||
else:
|
else:
|
||||||
# Autre erreur OperationalError, ne pas retry
|
# Autre erreur OperationalError, ne pas retry
|
||||||
raise
|
raise
|
||||||
except Exception:
|
except Exception as e:
|
||||||
# Autres exceptions, ne pas retry
|
# Autres exceptions, ne pas retry
|
||||||
raise
|
raise
|
||||||
|
|
||||||
|
|
@ -148,6 +164,13 @@ class EmailQueue:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def enqueue(self, email_log_id: str, delay_seconds: float = 0):
|
def enqueue(self, email_log_id: str, delay_seconds: float = 0):
|
||||||
|
"""
|
||||||
|
Ajoute un email à la queue avec un délai optionnel.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
email_log_id: ID de l'email log
|
||||||
|
delay_seconds: Délai avant traitement (pour éviter les conflits)
|
||||||
|
"""
|
||||||
if delay_seconds > 0:
|
if delay_seconds > 0:
|
||||||
timer = threading.Timer(delay_seconds, lambda: self.queue.put(email_log_id))
|
timer = threading.Timer(delay_seconds, lambda: self.queue.put(email_log_id))
|
||||||
timer.daemon = True
|
timer.daemon = True
|
||||||
|
|
@ -377,9 +400,13 @@ class EmailQueue:
|
||||||
societe_info = None
|
societe_info = None
|
||||||
try:
|
try:
|
||||||
societe_info = self.sage_client.lire_informations_societe()
|
societe_info = self.sage_client.lire_informations_societe()
|
||||||
logger.debug(
|
# Log selon le type (dict ou objet)
|
||||||
f"Infos société récupérées: {societe_info.raison_sociale if societe_info else 'N/A'}"
|
if societe_info:
|
||||||
)
|
if isinstance(societe_info, dict):
|
||||||
|
raison = societe_info.get("raison_sociale", "N/A")
|
||||||
|
else:
|
||||||
|
raison = getattr(societe_info, "raison_sociale", "N/A")
|
||||||
|
logger.debug(f"Infos société récupérées: {raison}")
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning(f"Impossible de récupérer les infos société: {e}")
|
logger.warning(f"Impossible de récupérer les infos société: {e}")
|
||||||
|
|
||||||
|
|
@ -441,10 +468,17 @@ class SagePDFGenerator:
|
||||||
self.use_sage_font = _sage_font_registered
|
self.use_sage_font = _sage_font_registered
|
||||||
|
|
||||||
def _get_societe_field(self, field: str, default: str = "") -> str:
|
def _get_societe_field(self, field: str, default: str = "") -> str:
|
||||||
"""Récupère un champ de la société avec fallback."""
|
"""Récupère un champ de la société avec fallback (supporte dict et objet)."""
|
||||||
if self.societe_info is None:
|
if self.societe_info is None:
|
||||||
return default
|
return default
|
||||||
return getattr(self.societe_info, field, default) or default
|
|
||||||
|
# Support dict ou objet Pydantic
|
||||||
|
if isinstance(self.societe_info, dict):
|
||||||
|
value = self.societe_info.get(field)
|
||||||
|
else:
|
||||||
|
value = getattr(self.societe_info, field, None)
|
||||||
|
|
||||||
|
return value if value is not None else default
|
||||||
|
|
||||||
def _get_societe_name(self) -> str:
|
def _get_societe_name(self) -> str:
|
||||||
"""Retourne la raison sociale de la société."""
|
"""Retourne la raison sociale de la société."""
|
||||||
|
|
@ -1029,10 +1063,16 @@ class SagePDFGenerator:
|
||||||
# Forme juridique et capital si disponibles
|
# Forme juridique et capital si disponibles
|
||||||
if self.societe_info:
|
if self.societe_info:
|
||||||
forme = self._get_societe_field("forme_juridique", "")
|
forme = self._get_societe_field("forme_juridique", "")
|
||||||
capital = getattr(self.societe_info, "capital", 0)
|
capital = self._get_societe_field("capital", 0)
|
||||||
if forme and capital > 0:
|
# Convertir en float si c'est une string
|
||||||
|
if isinstance(capital, str):
|
||||||
|
try:
|
||||||
|
capital = float(capital)
|
||||||
|
except (ValueError, TypeError):
|
||||||
|
capital = 0
|
||||||
|
if forme and capital and float(capital) > 0:
|
||||||
legal_parts.append(
|
legal_parts.append(
|
||||||
f"{forme} au capital de {capital:,.0f} €".replace(",", " ")
|
f"{forme} au capital de {float(capital):,.0f} €".replace(",", " ")
|
||||||
)
|
)
|
||||||
|
|
||||||
# Dessiner les informations légales
|
# Dessiner les informations légales
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue