feat(universign): add email templating for signature requests

This commit is contained in:
Fanilo-Nantenaina 2026-01-06 11:02:52 +03:00
parent ab25443f99
commit b40c998062

View file

@ -6,6 +6,7 @@ from typing import List, Optional
from datetime import datetime from datetime import datetime
from pydantic import BaseModel, EmailStr from pydantic import BaseModel, EmailStr
import logging import logging
from data.data import templates_signature_email
from email_queue import email_queue from email_queue import email_queue
from database import get_session from database import get_session
from database import ( from database import (
@ -86,13 +87,12 @@ async def create_signature(
if not pdf_bytes: if not pdf_bytes:
raise HTTPException(400, "Échec génération PDF") raise HTTPException(400, "Échec génération PDF")
# === 2. CRÉATION TRANSACTION UNIVERSIGN === # === CRÉATION TRANSACTION UNIVERSIGN ===
import requests import requests
import uuid import uuid
auth = (settings.universign_api_key, "") auth = (settings.universign_api_key, "")
# Créer la transaction
resp = requests.post( resp = requests.post(
f"{settings.universign_api_url}/transactions", f"{settings.universign_api_url}/transactions",
auth=auth, auth=auth,
@ -109,7 +109,6 @@ async def create_signature(
universign_tx_id = resp.json().get("id") universign_tx_id = resp.json().get("id")
# Upload le fichier
files = { files = {
"file": (f"{request.sage_document_id}.pdf", pdf_bytes, "application/pdf") "file": (f"{request.sage_document_id}.pdf", pdf_bytes, "application/pdf")
} }
@ -122,7 +121,6 @@ async def create_signature(
file_id = resp.json().get("id") file_id = resp.json().get("id")
# Attacher le document
resp = requests.post( resp = requests.post(
f"{settings.universign_api_url}/transactions/{universign_tx_id}/documents", f"{settings.universign_api_url}/transactions/{universign_tx_id}/documents",
auth=auth, auth=auth,
@ -135,7 +133,6 @@ async def create_signature(
document_id = resp.json().get("id") document_id = resp.json().get("id")
# Créer le champ de signature
resp = requests.post( resp = requests.post(
f"{settings.universign_api_url}/transactions/{universign_tx_id}/documents/{document_id}/fields", f"{settings.universign_api_url}/transactions/{universign_tx_id}/documents/{document_id}/fields",
auth=auth, auth=auth,
@ -148,7 +145,6 @@ async def create_signature(
field_id = resp.json().get("id") field_id = resp.json().get("id")
# Lier le signataire
resp = requests.post( resp = requests.post(
f"{settings.universign_api_url}/transactions/{universign_tx_id}/signatures", f"{settings.universign_api_url}/transactions/{universign_tx_id}/signatures",
auth=auth, auth=auth,
@ -159,7 +155,6 @@ async def create_signature(
if resp.status_code not in [200, 201]: if resp.status_code not in [200, 201]:
raise HTTPException(500, "Erreur liaison signataire") raise HTTPException(500, "Erreur liaison signataire")
# Démarrer la transaction
resp = requests.post( resp = requests.post(
f"{settings.universign_api_url}/transactions/{universign_tx_id}/start", f"{settings.universign_api_url}/transactions/{universign_tx_id}/start",
auth=auth, auth=auth,
@ -171,7 +166,6 @@ async def create_signature(
final_data = resp.json() final_data = resp.json()
# Extraire l'URL de signature
signer_url = "" signer_url = ""
if final_data.get("actions"): if final_data.get("actions"):
for action in final_data["actions"]: for action in final_data["actions"]:
@ -182,8 +176,7 @@ async def create_signature(
if not signer_url: if not signer_url:
raise HTTPException(500, "URL de signature non retournée") raise HTTPException(500, "URL de signature non retournée")
# === 3. ENREGISTREMENT LOCAL === # === ENREGISTREMENT LOCAL ===
local_id = str(uuid.uuid4()) local_id = str(uuid.uuid4())
transaction = UniversignTransaction( transaction = UniversignTransaction(
@ -199,13 +192,12 @@ async def create_signature(
document_name=request.document_name, document_name=request.document_name,
created_at=datetime.now(), created_at=datetime.now(),
sent_at=datetime.now(), sent_at=datetime.now(),
is_test=True, # Environnement .alpha is_test=True,
needs_sync=True, needs_sync=True,
) )
session.add(transaction) session.add(transaction)
# Signataire
signer = UniversignSigner( signer = UniversignSigner(
id=f"{local_id}_signer_0", id=f"{local_id}_signer_0",
transaction_id=local_id, transaction_id=local_id,
@ -216,18 +208,51 @@ async def create_signature(
) )
session.add(signer) session.add(signer)
await session.commit() await session.commit()
# === ENVOI EMAIL AVEC TEMPLATE ===
template = templates_signature_email["demande_signature"]
type_labels = {
0: "Devis",
10: "Commande",
30: "Bon de Livraison",
60: "Facture",
50: "Avoir",
}
doc_info = email_queue.sage_client.lire_document(
request.sage_document_id, request.sage_document_type.value
)
montant_ttc = f"{doc_info.get('total_ttc', 0):.2f}" if doc_info else "0.00"
date_doc = (
doc_info.get("date", datetime.now().strftime("%d/%m/%Y"))
if doc_info
else datetime.now().strftime("%d/%m/%Y")
)
variables = {
"NOM_SIGNATAIRE": request.signer_name,
"TYPE_DOC": type_labels.get(request.sage_document_type.value, "Document"),
"NUMERO": request.sage_document_id,
"DATE": date_doc,
"MONTANT_TTC": montant_ttc,
"SIGNER_URL": signer_url,
"CONTACT_EMAIL": settings.smtp_from,
}
sujet = template["sujet"]
corps = template["corps_html"]
for var, valeur in variables.items():
sujet = sujet.replace(f"{{{{{var}}}}}", str(valeur))
corps = corps.replace(f"{{{{{var}}}}}", str(valeur))
email_log = EmailLog( email_log = EmailLog(
id=str(uuid.uuid4()), id=str(uuid.uuid4()),
destinataire=request.signer_email, destinataire=request.signer_email,
sujet=f"Signature requise - {request.sage_document_type.name} {request.sage_document_id}", sujet=sujet,
corps_html=f""" corps_html=corps,
<p>Bonjour {request.signer_name},</p>
<p>Merci de signer le document suivant :</p>
<p><a href="{signer_url}">Cliquez ici pour signer</a></p>
""",
document_ids=request.sage_document_id, document_ids=request.sage_document_id,
type_document=request.sage_document_type.value, type_document=request.sage_document_type.value,
statut=StatutEmail.EN_ATTENTE, statut=StatutEmail.EN_ATTENTE,
@ -241,7 +266,6 @@ async def create_signature(
email_queue.enqueue(email_log.id) email_queue.enqueue(email_log.id)
# === RÉPONSE === # === RÉPONSE ===
return TransactionResponse( return TransactionResponse(
id=transaction.id, id=transaction.id,
transaction_id=transaction.transaction_id, transaction_id=transaction.transaction_id,