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