style: remove emoji icons from log messages and comments

This commit is contained in:
Fanilo-Nantenaina 2025-12-24 16:01:41 +03:00
parent c47c2c43fb
commit 07ec8af191

220
api.py
View file

@ -267,7 +267,7 @@ class ArticleResponse(BaseModel):
"""
Modèle de réponse pour un article Sage
ENRICHI avec tous les champs disponibles
ENRICHI avec tous les champs disponibles
"""
# === IDENTIFICATION ===
@ -1339,7 +1339,7 @@ class ArticleUpdateRequest(BaseModel):
prix_vente: Optional[float] = Field(None, ge=0)
prix_achat: Optional[float] = Field(None, ge=0)
stock_reel: Optional[float] = Field(
None, ge=0, description="⚠️ Critique pour erreur 2881"
None, ge=0, description="Critique pour erreur 2881"
)
stock_mini: Optional[float] = Field(None, ge=0)
code_ean: Optional[str] = Field(None, max_length=13)
@ -1539,7 +1539,7 @@ templates_signature_email = {
"demande_signature": {
"id": "demande_signature",
"nom": "Demande de Signature Électronique",
"sujet": "📝 Signature requise - {{TYPE_DOC}} {{NUMERO}}",
"sujet": "Signature requise - {{TYPE_DOC}} {{NUMERO}}",
"corps_html": """
<!DOCTYPE html>
<html>
@ -1557,7 +1557,7 @@ templates_signature_email = {
<tr>
<td style="background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); padding: 30px; text-align: center; border-radius: 8px 8px 0 0;">
<h1 style="color: #000; margin: 0; font-size: 24px; font-weight: 600;">
📝 Signature Électronique Requise
Signature Électronique Requise
</h1>
</td>
</tr>
@ -1668,7 +1668,7 @@ templates_signature_email = {
"signature_confirmee": {
"id": "signature_confirmee",
"nom": "Confirmation de Signature",
"sujet": "Document signé - {{TYPE_DOC}} {{NUMERO}}",
"sujet": "Document signé - {{TYPE_DOC}} {{NUMERO}}",
"corps_html": """
<!DOCTYPE html>
<html>
@ -1686,7 +1686,7 @@ templates_signature_email = {
<tr>
<td style="background: linear-gradient(135deg, #48bb78 0%, #38a169 100%); padding: 30px; text-align: center; border-radius: 8px 8px 0 0;">
<h1 style="color: #ffffff; margin: 0; font-size: 24px; font-weight: 600;">
Document Signé avec Succès
Document Signé avec Succès
</h1>
</td>
</tr>
@ -1902,12 +1902,12 @@ async def universign_envoyer_avec_email(
if not pdf_bytes or len(pdf_bytes) == 0:
raise Exception("Le PDF généré est vide")
logger.info(f"PDF valide : {len(pdf_bytes)} octets")
logger.info(f"PDF valide : {len(pdf_bytes)} octets")
# ========================================
# ÉTAPE 1 : Créer la transaction
# ========================================
logger.info(f"📝 ÉTAPE 1/6 : Création transaction")
logger.info(f"ÉTAPE 1/6 : Création transaction")
response = requests.post(
f"{api_url}/transactions",
@ -1920,16 +1920,16 @@ async def universign_envoyer_avec_email(
)
if response.status_code != 200:
logger.error(f"Erreur création transaction: {response.text}")
logger.error(f"Erreur création transaction: {response.text}")
raise Exception(f"Erreur création transaction: {response.status_code}")
transaction_id = response.json().get("id")
logger.info(f"Transaction créée: {transaction_id}")
logger.info(f"Transaction créée: {transaction_id}")
# ========================================
# ÉTAPE 2 : Upload du fichier PDF
# ========================================
logger.info(f"📄 ÉTAPE 2/6 : Upload PDF")
logger.info(f"ÉTAPE 2/6 : Upload PDF")
files = {
"file": (
@ -1947,11 +1947,11 @@ async def universign_envoyer_avec_email(
)
if response.status_code not in [200, 201]:
logger.error(f"Erreur upload: {response.text}")
logger.error(f"Erreur upload: {response.text}")
raise Exception(f"Erreur upload fichier: {response.status_code}")
file_id = response.json().get("id")
logger.info(f"Fichier uploadé: {file_id}")
logger.info(f"Fichier uploadé: {file_id}")
# ========================================
# ÉTAPE 3 : Ajouter le document
@ -1966,11 +1966,11 @@ async def universign_envoyer_avec_email(
)
if response.status_code not in [200, 201]:
logger.error(f"Erreur ajout document: {response.text}")
logger.error(f"Erreur ajout document: {response.text}")
raise Exception(f"Erreur ajout document: {response.status_code}")
document_id = response.json().get("id")
logger.info(f"Document ajouté: {document_id}")
logger.info(f"Document ajouté: {document_id}")
# ========================================
# ÉTAPE 4 : Créer le champ de signature
@ -1988,11 +1988,11 @@ async def universign_envoyer_avec_email(
)
if response.status_code not in [200, 201]:
logger.error(f"Erreur création champ: {response.text}")
logger.error(f"Erreur création champ: {response.text}")
raise Exception(f"Erreur création champ: {response.status_code}")
field_id = response.json().get("id")
logger.info(f"Champ créé: {field_id}")
logger.info(f"Champ créé: {field_id}")
# ========================================
# ÉTAPE 5 : Lier le signataire au champ (ancien endpoint)
@ -2000,7 +2000,7 @@ async def universign_envoyer_avec_email(
logger.info(f"👤 ÉTAPE 5/6 : Liaison signataire au champ")
response = requests.post(
f"{api_url}/transactions/{transaction_id}/signatures", # /signatures pas /signers
f"{api_url}/transactions/{transaction_id}/signatures", # /signatures pas /signers
auth=auth,
data={
"signer": email,
@ -2010,10 +2010,10 @@ async def universign_envoyer_avec_email(
)
if response.status_code not in [200, 201]:
logger.error(f"Erreur liaison signataire: {response.text}")
logger.error(f"Erreur liaison signataire: {response.text}")
raise Exception(f"Erreur liaison signataire: {response.status_code}")
logger.info(f"Signataire lié: {email}")
logger.info(f"Signataire lié: {email}")
# ========================================
# ÉTAPE 6 : Démarrer la transaction
@ -2027,11 +2027,11 @@ async def universign_envoyer_avec_email(
)
if response.status_code not in [200, 201]:
logger.error(f"Erreur démarrage: {response.text}")
logger.error(f"Erreur démarrage: {response.text}")
raise Exception(f"Erreur démarrage: {response.status_code}")
final_data = response.json()
logger.info(f"Transaction démarrée")
logger.info(f"Transaction démarrée")
# ========================================
# Récupérer l'URL de signature
@ -2055,10 +2055,10 @@ async def universign_envoyer_avec_email(
break
if not signer_url:
logger.error(f"URL introuvable dans: {final_data}")
logger.error(f"URL introuvable dans: {final_data}")
raise ValueError("URL de signature non retournée par Universign")
logger.info(f"URL récupérée")
logger.info(f"URL récupérée")
# ========================================
# Créer l'email de notification
@ -2109,7 +2109,7 @@ async def universign_envoyer_avec_email(
email_queue.enqueue(email_log.id)
logger.info(f"Email mis en file pour {email}")
logger.info(f"Email mis en file pour {email}")
logger.info(f"🎉 Processus terminé avec succès")
return {
@ -2121,7 +2121,7 @@ async def universign_envoyer_avec_email(
}
except Exception as e:
logger.error(f"Erreur Universign: {e}", exc_info=True)
logger.error(f"Erreur Universign: {e}", exc_info=True)
return {
"error": str(e),
"statut": "ERREUR",
@ -2166,16 +2166,16 @@ async def universign_statut(transaction_id: str) -> Dict:
async def lifespan(app: FastAPI):
# Init base de données
await init_db()
logger.info("Base de données initialisée")
logger.info("Base de données initialisée")
email_queue.session_factory = async_session_factory
email_queue.sage_client = sage_client
logger.info("sage_client injecté dans email_queue")
logger.info("sage_client injecté dans email_queue")
# Démarrer queue
email_queue.start(num_workers=settings.max_email_workers)
logger.info(f"Email queue démarrée")
logger.info(f"Email queue démarrée")
yield
@ -2246,7 +2246,7 @@ async def modifier_client(
code, client_update.dict(exclude_none=True)
)
logger.info(f"Client {code} modifié avec succès")
logger.info(f"Client {code} modifié avec succès")
return {
"success": True,
@ -2269,9 +2269,9 @@ async def ajouter_client(
client: ClientCreateAPIRequest, session: AsyncSession = Depends(get_session)
):
try:
nouveau_client = sage_client.creer_client(client.dict())
nouveau_client = sage_client.creer_client(client.model_dump(mode='json'))
logger.info(f"Client créé via API: {nouveau_client.get('numero')}")
logger.info(f"Client créé via API: {nouveau_client.get('numero')}")
return jsonable_encoder({
"success": True,
@ -2313,20 +2313,20 @@ async def creer_article(article: ArticleCreateRequest):
article_data = article.dict(exclude_unset=True)
logger.info(f"📝 Création article: {article.reference} - {article.designation}")
logger.info(f"Création article: {article.reference} - {article.designation}")
# Appel à la gateway Windows
resultat = sage_client.creer_article(article_data)
logger.info(
f"Article créé: {resultat.get('reference')} (stock: {resultat.get('stock_reel', 0)})"
f"Article créé: {resultat.get('reference')} (stock: {resultat.get('stock_reel', 0)})"
)
return ArticleResponse(**resultat)
except ValueError as e:
# Erreur métier (ex: article existe déjà)
logger.warning(f"⚠️ Erreur métier création article: {e}")
logger.warning(f"Erreur métier création article: {e}")
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
except HTTPException:
@ -2334,7 +2334,7 @@ async def creer_article(article: ArticleCreateRequest):
except Exception as e:
# Erreur technique Sage
logger.error(f"Erreur technique création article: {e}", exc_info=True)
logger.error(f"Erreur technique création article: {e}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Erreur lors de la création de l'article: {str(e)}",
@ -2355,7 +2355,7 @@ async def modifier_article(
detail="Aucun champ à modifier. Fournissez au moins un champ à mettre à jour.",
)
logger.info(f"📝 Modification article {reference}: {list(article_data.keys())}")
logger.info(f"Modification article {reference}: {list(article_data.keys())}")
# Appel à la gateway Windows
resultat = sage_client.modifier_article(reference, article_data)
@ -2363,17 +2363,17 @@ async def modifier_article(
# Log spécial pour modification de stock (important pour erreur 2881)
if "stock_reel" in article_data:
logger.info(
f"📦 Stock {reference} modifié: {article_data['stock_reel']} "
f"Stock {reference} modifié: {article_data['stock_reel']} "
f"(peut résoudre erreur 2881)"
)
logger.info(f"Article {reference} modifié ({len(article_data)} champs)")
logger.info(f"Article {reference} modifié ({len(article_data)} champs)")
return ArticleResponse(**resultat)
except ValueError as e:
# Erreur métier (ex: article introuvable)
logger.warning(f"⚠️ Erreur métier modification article: {e}")
logger.warning(f"Erreur métier modification article: {e}")
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND, detail=str(e))
except HTTPException:
@ -2381,7 +2381,7 @@ async def modifier_article(
except Exception as e:
# Erreur technique Sage
logger.error(f"Erreur technique modification article: {e}", exc_info=True)
logger.error(f"Erreur technique modification article: {e}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Erreur lors de la modification de l'article: {str(e)}",
@ -2396,20 +2396,20 @@ async def lire_article(
article = sage_client.lire_article(reference)
if not article:
logger.warning(f"⚠️ Article {reference} introuvable")
logger.warning(f"Article {reference} introuvable")
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Article {reference} introuvable",
)
logger.info(f"Article {reference} lu: {article.get('designation', '')}")
logger.info(f"Article {reference} lu: {article.get('designation', '')}")
return ArticleResponse(**article)
except HTTPException:
raise
except Exception as e:
logger.error(f"Erreur lecture article {reference}: {e}", exc_info=True)
logger.error(f"Erreur lecture article {reference}: {e}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Erreur lors de la lecture de l'article: {str(e)}",
@ -2452,7 +2452,7 @@ async def creer_devis(devis: DevisRequest):
# Appel HTTP vers Windows
resultat = sage_client.creer_devis(devis_data)
logger.info(f"Devis créé: {resultat.get('numero_devis')}")
logger.info(f"Devis créé: {resultat.get('numero_devis')}")
return DevisResponse(
id=resultat["numero_devis"],
@ -2499,7 +2499,7 @@ async def modifier_devis(
# Appel à la gateway Windows
resultat = sage_client.modifier_devis(id, update_data)
logger.info(f"Devis {id} modifié avec succès")
logger.info(f"Devis {id} modifié avec succès")
return {
"success": True,
@ -2541,7 +2541,7 @@ async def creer_commande(
# Appel à la gateway Windows
resultat = sage_client.creer_commande(commande_data)
logger.info(f"Commande créée: {resultat.get('numero_commande')}")
logger.info(f"Commande créée: {resultat.get('numero_commande')}")
return {
"success": True,
@ -2595,7 +2595,7 @@ async def modifier_commande(
# Appel à la gateway Windows
resultat = sage_client.modifier_commande(id, update_data)
logger.info(f"Commande {id} modifiée avec succès")
logger.info(f"Commande {id} modifiée avec succès")
return {
"success": True,
@ -2693,7 +2693,7 @@ async def telecharger_document_pdf(
label = types_labels[type_doc]
logger.info(f"📄 Génération PDF: {label} {numero} (type={type_doc})")
logger.info(f"Génération PDF: {label} {numero} (type={type_doc})")
# Appel à sage_client pour générer le PDF
pdf_bytes = sage_client.generer_pdf_document(numero, type_doc)
@ -2701,7 +2701,7 @@ async def telecharger_document_pdf(
if not pdf_bytes:
raise HTTPException(500, f"Le PDF du document {numero} est vide")
logger.info(f"PDF généré: {len(pdf_bytes)} octets")
logger.info(f"PDF généré: {len(pdf_bytes)} octets")
# Nom de fichier formaté
filename = f"{label}_{numero}.pdf"
@ -2719,7 +2719,7 @@ async def telecharger_document_pdf(
raise
except Exception as e:
logger.error(
f"Erreur génération PDF {numero} (type {type_doc}): {e}", exc_info=True
f"Erreur génération PDF {numero} (type {type_doc}): {e}", exc_info=True
)
raise HTTPException(500, f"Erreur génération PDF: {str(e)}")
@ -2754,7 +2754,7 @@ async def envoyer_devis_email(
await session.commit()
logger.info(
f"Email devis {id} mis en file: {len(tous_destinataires)} destinataire(s)"
f"Email devis {id} mis en file: {len(tous_destinataires)} destinataire(s)"
)
return {
@ -2800,7 +2800,7 @@ async def changer_statut_devis(
resultat = sage_client.changer_statut_devis(id, nouveau_statut)
logger.info(f"Statut devis {id} changé: {statut_actuel}{nouveau_statut}")
logger.info(f"Statut devis {id} changé: {statut_actuel}{nouveau_statut}")
return {
"success": True,
@ -2870,7 +2870,7 @@ async def devis_vers_commande(id: str, session: AsyncSession = Depends(get_sessi
await session.commit()
logger.info(
f"Transformation: Devis {id} → Commande {resultat['document_cible']}"
f"Transformation: Devis {id} → Commande {resultat['document_cible']}"
)
return {
@ -2910,7 +2910,7 @@ async def commande_vers_facture(id: str, session: AsyncSession = Depends(get_ses
await session.commit()
logger.info(
f"Transformation: Commande {id} → Facture {resultat['document_cible']}"
f"Transformation: Commande {id} → Facture {resultat['document_cible']}"
)
return {
@ -3002,7 +3002,7 @@ async def envoyer_signature_optimise(
)
logger.info(
f"Signature envoyée: {demande.doc_id} (Email: {resultat['email_sent']})"
f"Signature envoyée: {demande.doc_id} (Email: {resultat['email_sent']})"
)
return {
@ -3017,7 +3017,7 @@ async def envoyer_signature_optimise(
except HTTPException:
raise
except Exception as e:
logger.error(f"Erreur signature: {e}")
logger.error(f"Erreur signature: {e}")
raise HTTPException(500, str(e))
@ -3032,7 +3032,7 @@ async def webhook_universign(
transaction_id = payload.get("transaction_id")
if not transaction_id:
logger.warning("⚠️ Webhook sans transaction_id")
logger.warning("Webhook sans transaction_id")
return {"status": "ignored"}
# Chercher la signature dans la DB
@ -3043,7 +3043,7 @@ async def webhook_universign(
signature_log = result.scalar_one_or_none()
if not signature_log:
logger.warning(f"⚠️ Transaction {transaction_id} introuvable en DB")
logger.warning(f"Transaction {transaction_id} introuvable en DB")
return {"status": "not_found"}
# =============================================
@ -3051,11 +3051,11 @@ async def webhook_universign(
# =============================================
if event_type == "transaction.completed":
# SIGNATURE RÉUSSIE
# SIGNATURE RÉUSSIE
signature_log.statut = StatutSignatureEnum.SIGNE
signature_log.date_signature = datetime.now()
logger.info(f"Signature confirmée: {signature_log.document_id}")
logger.info(f"Signature confirmée: {signature_log.document_id}")
# ENVOYER EMAIL DE CONFIRMATION
template = templates_signature_email["signature_confirmee"]
@ -3105,9 +3105,9 @@ async def webhook_universign(
)
elif event_type == "transaction.refused":
# SIGNATURE REFUSÉE
# SIGNATURE REFUSÉE
signature_log.statut = StatutSignatureEnum.REFUSE
logger.warning(f"Signature refusée: {signature_log.document_id}")
logger.warning(f"Signature refusée: {signature_log.document_id}")
elif event_type == "transaction.expired":
# ⏰ TRANSACTION EXPIRÉE
@ -3123,7 +3123,7 @@ async def webhook_universign(
}
except Exception as e:
logger.error(f"Erreur webhook Universign: {e}")
logger.error(f"Erreur webhook Universign: {e}")
return {"status": "error", "message": str(e)}
@ -3214,7 +3214,7 @@ async def relancer_signatures_automatique(session: AsyncSession = Depends(get_se
)
except Exception as e:
logger.error(f"Erreur relance signature {signature.id}: {e}")
logger.error(f"Erreur relance signature {signature.id}: {e}")
continue
await session.commit()
@ -3227,7 +3227,7 @@ async def relancer_signatures_automatique(session: AsyncSession = Depends(get_se
}
except Exception as e:
logger.error(f"Erreur relances automatiques: {e}")
logger.error(f"Erreur relances automatiques: {e}")
raise HTTPException(500, str(e))
@ -3496,7 +3496,7 @@ async def envoyer_emails_lot(
nb_documents = len(batch.document_ids) if batch.document_ids else 0
logger.info(
f"{len(batch.destinataires)} emails mis en file avec {nb_documents} docs"
f"{len(batch.destinataires)} emails mis en file avec {nb_documents} docs"
)
return {
@ -3520,12 +3520,12 @@ async def valider_remise(
autorisee = remise_pourcentage <= remise_max
if not autorisee:
message = f"⚠️ Remise trop élevée (max autorisé: {remise_max}%)"
message = f"Remise trop élevée (max autorisé: {remise_max}%)"
logger.warning(
f"Remise refusée pour {client_id}: {remise_pourcentage}% > {remise_max}%"
)
else:
message = "Remise autorisée"
message = "Remise autorisée"
return BaremeRemiseResponse(
client_id=client_id,
@ -3702,7 +3702,7 @@ async def creer_facture(
# Appel à la gateway Windows
resultat = sage_client.creer_facture(facture_data)
logger.info(f"Facture créée: {resultat.get('numero_facture')}")
logger.info(f"Facture créée: {resultat.get('numero_facture')}")
return {
"success": True,
@ -3756,7 +3756,7 @@ async def modifier_facture(
# Appel à la gateway Windows
resultat = sage_client.modifier_facture(id, update_data)
logger.info(f"Facture {id} modifiée avec succès")
logger.info(f"Facture {id} modifiée avec succès")
return {
"success": True,
@ -3852,7 +3852,7 @@ async def relancer_facture(
await session.commit()
logger.info(f"Relance facture: {id}{contact['email']}")
logger.info(f"Relance facture: {id}{contact['email']}")
return {
"success": True,
@ -4175,15 +4175,15 @@ async def rechercher_fournisseurs(query: Optional[str] = Query(None)):
try:
fournisseurs = sage_client.lister_fournisseurs(filtre=query or "")
logger.info(f"{len(fournisseurs)} fournisseurs")
logger.info(f"{len(fournisseurs)} fournisseurs")
if len(fournisseurs) == 0:
logger.warning("⚠️ Aucun fournisseur retourné - vérifier la gateway Windows")
logger.warning("Aucun fournisseur retourné - vérifier la gateway Windows")
return fournisseurs
except Exception as e:
logger.error(f"Erreur recherche fournisseurs: {e}")
logger.error(f"Erreur recherche fournisseurs: {e}")
raise HTTPException(500, str(e))
@ -4196,7 +4196,7 @@ async def ajouter_fournisseur(
# Appel à la gateway Windows via sage_client
nouveau_fournisseur = sage_client.creer_fournisseur(fournisseur.dict())
logger.info(f"Fournisseur créé via API: {nouveau_fournisseur.get('numero')}")
logger.info(f"Fournisseur créé via API: {nouveau_fournisseur.get('numero')}")
return {
"success": True,
@ -4206,12 +4206,12 @@ async def ajouter_fournisseur(
except ValueError as e:
# Erreur métier (doublon, validation)
logger.warning(f"⚠️ Erreur métier création fournisseur: {e}")
logger.warning(f"Erreur métier création fournisseur: {e}")
raise HTTPException(400, str(e))
except Exception as e:
# Erreur technique (COM, connexion)
logger.error(f"Erreur technique création fournisseur: {e}")
logger.error(f"Erreur technique création fournisseur: {e}")
raise HTTPException(500, str(e))
@ -4227,7 +4227,7 @@ async def modifier_fournisseur(
code, fournisseur_update.dict(exclude_none=True)
)
logger.info(f"Fournisseur {code} modifié avec succès")
logger.info(f"Fournisseur {code} modifié avec succès")
return {
"success": True,
@ -4313,7 +4313,7 @@ async def creer_avoir(
# Appel à la gateway Windows
resultat = sage_client.creer_avoir(avoir_data)
logger.info(f"Avoir créé: {resultat.get('numero_avoir')}")
logger.info(f"Avoir créé: {resultat.get('numero_avoir')}")
return {
"success": True,
@ -4367,7 +4367,7 @@ async def modifier_avoir(
# Appel à la gateway Windows
resultat = sage_client.modifier_avoir(id, update_data)
logger.info(f"Avoir {id} modifié avec succès")
logger.info(f"Avoir {id} modifié avec succès")
return {
"success": True,
@ -4442,7 +4442,7 @@ async def creer_livraison(
# Appel à la gateway Windows
resultat = sage_client.creer_livraison(livraison_data)
logger.info(f"Livraison créée: {resultat.get('numero_livraison')}")
logger.info(f"Livraison créée: {resultat.get('numero_livraison')}")
return {
"success": True,
@ -4496,7 +4496,7 @@ async def modifier_livraison(
# Appel à la gateway Windows
resultat = sage_client.modifier_livraison(id, update_data)
logger.info(f"Livraison {id} modifiée avec succès")
logger.info(f"Livraison {id} modifiée avec succès")
return {
"success": True,
@ -4535,7 +4535,7 @@ async def livraison_vers_facture(id: str, session: AsyncSession = Depends(get_se
await session.commit()
logger.info(
f"Transformation: Livraison {id} → Facture {resultat['document_cible']}"
f"Transformation: Livraison {id} → Facture {resultat['document_cible']}"
)
return {
@ -4591,7 +4591,7 @@ async def devis_vers_facture_direct(
await session.commit()
logger.info(
f"Transformation DIRECTE: Devis {id} → Facture {resultat['document_cible']}"
f"Transformation DIRECTE: Devis {id} → Facture {resultat['document_cible']}"
)
return {
@ -4607,7 +4607,7 @@ async def devis_vers_facture_direct(
except HTTPException:
raise
except Exception as e:
logger.error(f"Erreur transformation devis→facture: {e}", exc_info=True)
logger.error(f"Erreur transformation devis→facture: {e}", exc_info=True)
raise HTTPException(500, str(e))
@ -4659,7 +4659,7 @@ async def commande_vers_livraison(
await session.commit()
logger.info(
f"Transformation: Commande {id} → Livraison {resultat['document_cible']}"
f"Transformation: Commande {id} → Livraison {resultat['document_cible']}"
)
return {
@ -4675,7 +4675,7 @@ async def commande_vers_livraison(
except HTTPException:
raise
except Exception as e:
logger.error(f"Erreur transformation commande→livraison: {e}", exc_info=True)
logger.error(f"Erreur transformation commande→livraison: {e}", exc_info=True)
raise HTTPException(500, str(e))
@ -4691,12 +4691,12 @@ async def lister_familles(
try:
familles = sage_client.lister_familles(filtre or "")
logger.info(f"{len(familles)} famille(s) retournée(s)")
logger.info(f"{len(familles)} famille(s) retournée(s)")
return [FamilleResponse(**f) for f in familles]
except Exception as e:
logger.error(f"Erreur liste familles: {e}", exc_info=True)
logger.error(f"Erreur liste familles: {e}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Erreur lors de la récupération des familles: {str(e)}",
@ -4716,20 +4716,20 @@ async def lire_famille(
famille = sage_client.lire_famille(code)
if not famille:
logger.warning(f"⚠️ Famille {code} introuvable")
logger.warning(f"Famille {code} introuvable")
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Famille {code} introuvable",
)
logger.info(f"Famille {code} lue: {famille.get('intitule', '')}")
logger.info(f"Famille {code} lue: {famille.get('intitule', '')}")
return FamilleResponse(**famille)
except HTTPException:
raise
except Exception as e:
logger.error(f"Erreur lecture famille {code}: {e}", exc_info=True)
logger.error(f"Erreur lecture famille {code}: {e}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Erreur lors de la lecture de la famille: {str(e)}",
@ -4754,18 +4754,18 @@ async def creer_famille(famille: FamilleCreateRequest):
famille_data = famille.dict()
logger.info(f"📦 Création famille: {famille.code} - {famille.intitule}")
logger.info(f"Création famille: {famille.code} - {famille.intitule}")
# Appel à la gateway Windows
resultat = sage_client.creer_famille(famille_data)
logger.info(f"Famille créée: {resultat.get('code')}")
logger.info(f"Famille créée: {resultat.get('code')}")
return FamilleResponse(**resultat)
except ValueError as e:
# Erreur métier (ex: famille existe déjà)
logger.warning(f"⚠️ Erreur métier création famille: {e}")
logger.warning(f"Erreur métier création famille: {e}")
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
except HTTPException:
@ -4773,7 +4773,7 @@ async def creer_famille(famille: FamilleCreateRequest):
except Exception as e:
# Erreur technique Sage
logger.error(f"Erreur technique création famille: {e}", exc_info=True)
logger.error(f"Erreur technique création famille: {e}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Erreur lors de la création de la famille: {str(e)}",
@ -4794,21 +4794,21 @@ async def creer_entree_stock(entree: EntreeStockRequest):
if entree_data.get("date_entree"):
entree_data["date_entree"] = entree_data["date_entree"].isoformat()
logger.info(f"📦 Création entrée stock: {len(entree.lignes)} ligne(s)")
logger.info(f"Création entrée stock: {len(entree.lignes)} ligne(s)")
# Appel à la gateway Windows
resultat = sage_client.creer_entree_stock(entree_data)
logger.info(f"Entrée stock créée: {resultat.get('numero')}")
logger.info(f"Entrée stock créée: {resultat.get('numero')}")
return MouvementStockResponse(**resultat)
except ValueError as e:
logger.warning(f"⚠️ Erreur métier entrée stock: {e}")
logger.warning(f"Erreur métier entrée stock: {e}")
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
except Exception as e:
logger.error(f"Erreur technique entrée stock: {e}", exc_info=True)
logger.error(f"Erreur technique entrée stock: {e}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Erreur lors de la création de l'entrée: {str(e)}",
@ -4834,16 +4834,16 @@ async def creer_sortie_stock(sortie: SortieStockRequest):
# Appel à la gateway Windows
resultat = sage_client.creer_sortie_stock(sortie_data)
logger.info(f"Sortie stock créée: {resultat.get('numero')}")
logger.info(f"Sortie stock créée: {resultat.get('numero')}")
return MouvementStockResponse(**resultat)
except ValueError as e:
logger.warning(f"⚠️ Erreur métier sortie stock: {e}")
logger.warning(f"Erreur métier sortie stock: {e}")
raise HTTPException(status_code=status.HTTP_400_BAD_REQUEST, detail=str(e))
except Exception as e:
logger.error(f"Erreur technique sortie stock: {e}", exc_info=True)
logger.error(f"Erreur technique sortie stock: {e}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Erreur lors de la création de la sortie: {str(e)}",
@ -4863,20 +4863,20 @@ async def lire_mouvement_stock(
mouvement = sage_client.lire_mouvement_stock(numero)
if not mouvement:
logger.warning(f"⚠️ Mouvement {numero} introuvable")
logger.warning(f"Mouvement {numero} introuvable")
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail=f"Mouvement de stock {numero} introuvable",
)
logger.info(f"Mouvement {numero} lu")
logger.info(f"Mouvement {numero} lu")
return MouvementStockResponse(**mouvement)
except HTTPException:
raise
except Exception as e:
logger.error(f"Erreur lecture mouvement {numero}: {e}", exc_info=True)
logger.error(f"Erreur lecture mouvement {numero}: {e}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Erreur lors de la lecture du mouvement: {str(e)}",
@ -4895,7 +4895,7 @@ async def statistiques_familles():
return {"success": True, "data": stats}
except Exception as e:
logger.error(f"Erreur stats familles: {e}", exc_info=True)
logger.error(f"Erreur stats familles: {e}", exc_info=True)
raise HTTPException(
status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
detail=f"Erreur lors de la récupération des statistiques: {str(e)}",
@ -4955,7 +4955,7 @@ async def lister_utilisateurs_debug(
return users_response
except Exception as e:
logger.error(f"Erreur liste utilisateurs: {e}")
logger.error(f"Erreur liste utilisateurs: {e}")
raise HTTPException(500, str(e))
@ -4995,7 +4995,7 @@ async def statistiques_utilisateurs(session: AsyncSession = Depends(get_session)
}
except Exception as e:
logger.error(f"Erreur stats utilisateurs: {e}")
logger.error(f"Erreur stats utilisateurs: {e}")
raise HTTPException(500, str(e))