diff --git a/api.py b/api.py index 7604f58..a439a8c 100644 --- a/api.py +++ b/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": """ @@ -1557,7 +1557,7 @@ templates_signature_email = {

- 📝 Signature Électronique Requise + Signature Électronique Requise

@@ -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": """ @@ -1686,7 +1686,7 @@ templates_signature_email = {

- ✅ Document Signé avec Succès + Document Signé avec Succès

@@ -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))