style: remove emoji icons from log messages and comments
This commit is contained in:
parent
c47c2c43fb
commit
07ec8af191
1 changed files with 111 additions and 111 deletions
222
api.py
222
api.py
|
|
@ -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())
|
||||
|
||||
logger.info(f"✅ Client créé via API: {nouveau_client.get('numero')}")
|
||||
nouveau_client = sage_client.creer_client(client.model_dump(mode='json'))
|
||||
|
||||
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))
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue