Refactored universign message function

This commit is contained in:
Fanilo-Nantenaina 2025-12-22 09:56:38 +03:00
parent 2705de7a07
commit dbdfa1e2df

142
api.py
View file

@ -1420,7 +1420,7 @@ async def universign_envoyer_avec_email(
pdf_bytes: bytes,
email: str,
nom: str,
doc_data: Dict, # Données du document (type, montant, date, etc.)
doc_data: Dict,
session: AsyncSession,
) -> Dict:
import requests
@ -1430,20 +1430,36 @@ async def universign_envoyer_avec_email(
api_url = settings.universign_api_url
auth = (api_key, "")
# ========================================
# ÉTAPE 1 : Créer la transaction
# ========================================
logger.info(f"🔐 Création transaction Universign pour {email}")
response = requests.post(
f"{api_url}/transactions",
auth=auth,
json={
"name": f"{doc_data.get('type_label', 'Document')} {doc_id}",
"language": "fr",
"profile": "default", # ✅ Ajout du profil
},
timeout=30,
)
if response.status_code != 200:
logger.error(f"❌ Erreur création transaction: {response.status_code} - {response.text}")
raise Exception(f"Erreur création transaction: {response.status_code}")
response.raise_for_status()
transaction_id = response.json().get("id")
logger.info(f"✅ Transaction Universign créée: {transaction_id}")
logger.info(f"✅ Transaction créée: {transaction_id}")
# ========================================
# ÉTAPE 2 : Upload du fichier PDF
# ========================================
logger.info(f"📄 Upload PDF ({len(pdf_bytes)} octets)")
files = {
"file": (
f"{doc_data.get('type_label', 'Document')}_{doc_id}.pdf",
@ -1451,56 +1467,138 @@ async def universign_envoyer_avec_email(
"application/pdf",
)
}
response = requests.post(f"{api_url}/files", auth=auth, files=files, timeout=30)
response = requests.post(
f"{api_url}/files",
auth=auth,
files=files,
timeout=30
)
if response.status_code != 200:
logger.error(f"❌ Erreur upload fichier: {response.status_code} - {response.text}")
raise Exception(f"Erreur upload fichier: {response.status_code}")
response.raise_for_status()
file_id = response.json().get("id")
logger.info(f"✅ Fichier uploadé: {file_id}")
# ========================================
# ÉTAPE 3 : Créer le document dans la transaction
# ========================================
logger.info(f"📋 Ajout document à la transaction")
response = requests.post(
f"{api_url}/transactions/{transaction_id}/documents",
auth=auth,
data={"document": file_id},
json={"file": file_id}, # ✅ Utiliser 'file' au lieu de 'document'
timeout=30,
)
if response.status_code != 200:
logger.error(f"❌ Erreur ajout document: {response.status_code} - {response.text}")
raise Exception(f"Erreur ajout document: {response.status_code}")
response.raise_for_status()
document_id = response.json().get("id")
logger.info(f"✅ Document ajouté: {document_id}")
# ========================================
# ÉTAPE 4 : Ajouter un champ de signature
# ========================================
logger.info(f"✍️ Ajout champ signature")
response = requests.post(
f"{api_url}/transactions/{transaction_id}/documents/{document_id}/fields",
auth=auth,
data={"type": "signature"},
json={
"type": "signature",
"page": 1, # ✅ Préciser la page
# Position optionnelle - Universign peut la placer automatiquement
# "x": 100,
# "y": 600,
},
timeout=30,
)
if response.status_code != 200:
logger.error(f"❌ Erreur ajout champ: {response.status_code} - {response.text}")
raise Exception(f"Erreur ajout champ signature: {response.status_code}")
response.raise_for_status()
field_id = response.json().get("id")
logger.info(f"✅ Champ signature créé: {field_id}")
# ========================================
# ÉTAPE 5 : Ajouter le signataire
# ========================================
logger.info(f"👤 Ajout signataire: {nom} ({email})")
response = requests.post(
f"{api_url}/transactions/{transaction_id}/signatures",
f"{api_url}/transactions/{transaction_id}/signers",
auth=auth,
data={"signer": email, "field": field_id},
json={
"email": email,
"firstName": nom.split()[0] if ' ' in nom else nom, # ✅ Prénom
"lastName": nom.split()[-1] if ' ' in nom else "", # ✅ Nom
# ✅ Lier le signataire au champ de signature
"fields": [field_id],
},
timeout=30,
)
if response.status_code != 200:
logger.error(f"❌ Erreur ajout signataire: {response.status_code} - {response.text}")
raise Exception(f"Erreur ajout signataire: {response.status_code}")
response.raise_for_status()
signer_id = response.json().get("id")
logger.info(f"✅ Signataire ajouté: {signer_id}")
# ========================================
# ÉTAPE 6 : Démarrer la transaction
# ========================================
logger.info(f"🚀 Démarrage de la transaction")
response = requests.post(
f"{api_url}/transactions/{transaction_id}/start", auth=auth, timeout=30
f"{api_url}/transactions/{transaction_id}/start",
auth=auth,
json={}, # ✅ Body vide mais présent
timeout=30
)
if response.status_code != 200:
logger.error(f"❌ Erreur démarrage transaction: {response.status_code}")
logger.error(f"Réponse complète: {response.text}")
raise Exception(f"Erreur démarrage transaction: {response.status_code} - {response.text}")
response.raise_for_status()
final_data = response.json()
signer_url = (
final_data.get("actions", [{}])[0].get("url", "")
if final_data.get("actions")
else ""
)
# ========================================
# ÉTAPE 7 : Récupérer l'URL de signature
# ========================================
signer_url = ""
if final_data.get("signers"):
for signer in final_data["signers"]:
if signer.get("email") == email:
signer_url = signer.get("url", "")
break
if not signer_url:
logger.warning("⚠️ URL de signature non trouvée dans la réponse")
raise ValueError("URL de signature non retournée par Universign")
logger.info(f"✅ Signature Universign démarrée: {transaction_id}")
logger.info(f"✅ Signature Universign prête: {transaction_id}")
# ========================================
# ÉTAPE 8 : Créer l'email de notification
# ========================================
template = templates_signature_email["demande_signature"]
# Préparer les variables
type_labels = {
0: "Devis",
10: "Commande",
@ -1519,7 +1617,6 @@ async def universign_envoyer_avec_email(
"CONTACT_EMAIL": settings.smtp_from,
}
# Remplacer les variables dans le template
sujet = template["sujet"]
corps = template["corps_html"]
@ -1556,11 +1653,18 @@ async def universign_envoyer_avec_email(
"email_sent": True,
}
except requests.exceptions.HTTPError as e:
logger.error(f"❌ Erreur HTTP Universign: {e}")
logger.error(f"Réponse: {e.response.text if e.response else 'N/A'}")
return {
"error": f"Erreur Universign: {e.response.status_code} - {e.response.text if e.response else str(e)}",
"statut": "ERREUR",
"email_sent": False,
}
except Exception as e:
logger.error(f"❌ Erreur Universign+Email: {e}")
logger.error(f"❌ Erreur Universign+Email: {e}", exc_info=True)
return {"error": str(e), "statut": "ERREUR", "email_sent": False}
async def universign_statut(transaction_id: str) -> Dict:
"""Récupération statut signature"""
import requests