From 215763b679d0565ed1453cc7395794e090de071b Mon Sep 17 00:00:00 2001 From: Fanilo-Nantenaina Date: Mon, 22 Dec 2025 11:11:12 +0300 Subject: [PATCH] Trying to make universign functionnal --- api.py | 175 ++++++++++++++++++++++++--------------------------------- 1 file changed, 74 insertions(+), 101 deletions(-) diff --git a/api.py b/api.py index e8e8f82..a0072de 100644 --- a/api.py +++ b/api.py @@ -1432,20 +1432,18 @@ async def universign_envoyer_avec_email( logger.info(f"🔐 DĂ©marrage processus Universign pour {email}") logger.info(f"📌 Document: {doc_id} ({doc_data.get('type_label')})") - - # ======================================== - # VÉRIFICATION : PDF valide ? - # ======================================== + + # VĂ©rification PDF 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") # ======================================== # ÉTAPE 1 : CrĂ©er la transaction # ======================================== - logger.info(f"📝 ÉTAPE 1/7 : CrĂ©ation transaction") - + logger.info(f"📝 ÉTAPE 1/6 : CrĂ©ation transaction") + response = requests.post( f"{api_url}/transactions", auth=auth, @@ -1455,19 +1453,19 @@ async def universign_envoyer_avec_email( }, timeout=30, ) - + if response.status_code != 200: 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}") # ======================================== # ÉTAPE 2 : Upload du fichier PDF # ======================================== - logger.info(f"📄 ÉTAPE 2/7 : Upload PDF") - + logger.info(f"📄 ÉTAPE 2/6 : Upload PDF") + files = { "file": ( f"{doc_data.get('type_label', 'Document')}_{doc_id}.pdf", @@ -1475,146 +1473,133 @@ async def universign_envoyer_avec_email( "application/pdf", ) } - + response = requests.post( - f"{api_url}/files", - auth=auth, - files=files, + f"{api_url}/files", + auth=auth, + files=files, timeout=60, ) - + if response.status_code not in [200, 201]: logger.error(f"❌ Erreur upload: {response.text}") raise Exception(f"Erreur upload fichier: {response.status_code}") - + file_id = response.json().get("id") - - if not file_id: - logger.error(f"❌ Pas de file_id retournĂ©") - raise Exception("Upload rĂ©ussi mais file_id manquant") - logger.info(f"✅ Fichier uploadĂ©: {file_id}") # ======================================== - # ÉTAPE 3 : Ajouter le document (form-data) + # ÉTAPE 3 : Ajouter le document # ======================================== - logger.info(f"📋 ÉTAPE 3/7 : Ajout document Ă  transaction") - + logger.info(f"📋 ÉTAPE 3/6 : Ajout document Ă  transaction") + response = requests.post( f"{api_url}/transactions/{transaction_id}/documents", auth=auth, - data={"document": file_id}, # ✅ UTILISER data= (form-data) + data={"document": file_id}, timeout=30, ) - + if response.status_code not in [200, 201]: 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}") # ======================================== - # ÉTAPE 4 : CrĂ©er le signataire + # ÉTAPE 4 : CrĂ©er le champ de signature # ======================================== - logger.info(f"đŸ‘€ ÉTAPE 4/7 : CrĂ©ation signataire") - - nom_parts = nom.split() - first_name = nom_parts[0] if len(nom_parts) > 0 else nom - last_name = " ".join(nom_parts[1:]) if len(nom_parts) > 1 else "" - - response = requests.post( - f"{api_url}/transactions/{transaction_id}/signers", - auth=auth, - data={ # ✅ UTILISER data= (form-data) - "email": email, - "firstName": first_name, - "lastName": last_name, - }, - timeout=30, - ) - - if response.status_code not in [200, 201]: - logger.error(f"❌ Erreur crĂ©ation signataire: {response.text}") - raise Exception(f"Erreur crĂ©ation signataire: {response.status_code}") - - signer_id = response.json().get("id") - logger.info(f"✅ Signataire créé: {signer_id}") - - # ======================================== - # ÉTAPE 5 : CrĂ©er le champ de signature - # ======================================== - logger.info(f"✍ ÉTAPE 5/7 : CrĂ©ation champ signature") - + logger.info(f"✍ ÉTAPE 4/6 : CrĂ©ation champ signature") + response = requests.post( f"{api_url}/transactions/{transaction_id}/documents/{document_id}/fields", auth=auth, - data={ # ✅ UTILISER data= (form-data) + data={ "type": "signature", - "page": "1", - "signer": signer_id, + # Laisser Universign positionner automatiquement }, timeout=30, ) - + if response.status_code not in [200, 201]: 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}") + # ======================================== + # ÉTAPE 5 : Lier le signataire au champ (ancien endpoint) + # ======================================== + logger.info(f"đŸ‘€ ÉTAPE 5/6 : Liaison signataire au champ") + + response = requests.post( + f"{api_url}/transactions/{transaction_id}/signatures", # ✅ /signatures pas /signers + auth=auth, + data={ + "signer": email, + "field": field_id, + }, + timeout=30, + ) + + if response.status_code not in [200, 201]: + logger.error(f"❌ Erreur liaison signataire: {response.text}") + raise Exception(f"Erreur liaison signataire: {response.status_code}") + + logger.info(f"✅ Signataire liĂ©: {email}") + # ======================================== # ÉTAPE 6 : DĂ©marrer la transaction # ======================================== - logger.info(f"🚀 ÉTAPE 6/7 : DĂ©marrage transaction") - + logger.info(f"🚀 ÉTAPE 6/6 : DĂ©marrage transaction") + response = requests.post( - f"{api_url}/transactions/{transaction_id}/start", auth=auth, timeout=30 + f"{api_url}/transactions/{transaction_id}/start", + auth=auth, + timeout=30 ) - + if response.status_code not in [200, 201]: 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") # ======================================== - # ÉTAPE 7 : RĂ©cupĂ©rer l'URL de signature + # RĂ©cupĂ©rer l'URL de signature # ======================================== - logger.info(f"🔗 ÉTAPE 7/7 : RĂ©cupĂ©ration URL") - + logger.info(f"🔗 RĂ©cupĂ©ration URL de signature") + signer_url = "" - - # Chercher dans la rĂ©ponse du /start - if final_data.get("signers"): + + # Chercher dans actions + if final_data.get("actions"): + for action in final_data["actions"]: + if action.get("url"): + signer_url = action["url"] + break + + # Sinon chercher dans signers + if not signer_url and final_data.get("signers"): for signer in final_data["signers"]: if signer.get("email") == email: signer_url = signer.get("url", "") break - # Si pas trouvĂ©e, interroger le signataire directement if not signer_url: - response = requests.get( - f"{api_url}/transactions/{transaction_id}/signers/{signer_id}", - auth=auth, - timeout=10, - ) - if response.status_code == 200: - signer_url = response.json().get("url", "") - - if not signer_url: - logger.error(f"❌ URL de signature introuvable") + 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 avec succĂšs") + logger.info(f"✅ URL rĂ©cupĂ©rĂ©e") # ======================================== # CrĂ©er l'email de notification # ======================================== - logger.info(f"📧 PrĂ©paration email de notification") - + logger.info(f"📧 PrĂ©paration email") + template = templates_signature_email["demande_signature"] type_labels = { @@ -1642,7 +1627,6 @@ async def universign_envoyer_avec_email( sujet = sujet.replace(f"{{{{{var}}}}}", str(valeur)) corps = corps.replace(f"{{{{{var}}}}}", str(valeur)) - # CrĂ©er log email email_log = EmailLog( id=str(uuid.uuid4()), destinataire=email, @@ -1658,11 +1642,10 @@ async def universign_envoyer_avec_email( session.add(email_log) await session.flush() - # Enqueue l'email email_queue.enqueue(email_log.id) logger.info(f"✅ Email mis en file pour {email}") - logger.info(f"🎉 Processus Universign terminĂ© avec succĂšs") + logger.info(f"🎉 Processus terminĂ© avec succĂšs") return { "transaction_id": transaction_id, @@ -1672,16 +1655,6 @@ async def universign_envoyer_avec_email( "email_sent": True, } - except requests.exceptions.HTTPError as e: - logger.error(f"❌ Erreur HTTP Universign: {e}") - if e.response: - logger.error(f"Status: {e.response.status_code}") - logger.error(f"Body: {e.response.text}") - return { - "error": f"Erreur Universign: {e.response.status_code if e.response else 'Unknown'} - {e.response.text if e.response else str(e)}", - "statut": "ERREUR", - "email_sent": False, - } except Exception as e: logger.error(f"❌ Erreur Universign: {e}", exc_info=True) return {