Reverted delocalized function

This commit is contained in:
Fanilo-Nantenaina 2025-12-29 20:43:27 +03:00
parent ffa45347bb
commit d0db0e4077

151
api.py
View file

@ -75,7 +75,6 @@ from schemas import (
ContactCreate, ContactCreate,
ContactUpdate, ContactUpdate,
) )
from utils.generic_functions import universign_envoyer, universign_statut
from utils.normalization import normaliser_type_tiers from utils.normalization import normaliser_type_tiers
logging.basicConfig( logging.basicConfig(
@ -126,6 +125,156 @@ app.add_middleware(
app.include_router(auth_router) app.include_router(auth_router)
async def universign_envoyer(
doc_id: str,
pdf_bytes: bytes,
email: str,
nom: str,
doc_data: dict,
session: AsyncSession,
) -> dict:
import requests
try:
api_key = settings.universign_api_key
api_url = settings.universign_api_url
auth = (api_key, "")
logger.info(f"Démarrage processus Universign pour {email}")
if not pdf_bytes or len(pdf_bytes) == 0:
raise Exception("Le PDF généré est vide")
# ÉTAPE 1: Création transaction
response = requests.post(
f"{api_url}/transactions",
auth=auth,
json={"name": f"{doc_data.get('type_label', 'Document')} {doc_id}", "language": "fr"},
timeout=30,
)
if response.status_code != 200:
raise Exception(f"Erreur création transaction: {response.status_code}")
transaction_id = response.json().get("id")
# ÉTAPE 2: Upload PDF
files = {"file": (f"{doc_data.get('type_label', 'Document')}_{doc_id}.pdf", pdf_bytes, "application/pdf")}
response = requests.post(f"{api_url}/files", auth=auth, files=files, timeout=60)
if response.status_code not in [200, 201]:
raise Exception(f"Erreur upload fichier: {response.status_code}")
file_id = response.json().get("id")
# ÉTAPE 3: Ajout document
response = requests.post(
f"{api_url}/transactions/{transaction_id}/documents",
auth=auth, data={"document": file_id}, timeout=30
)
if response.status_code not in [200, 201]:
raise Exception(f"Erreur ajout document: {response.status_code}")
document_id = response.json().get("id")
# ÉTAPE 4: Création champ signature
response = requests.post(
f"{api_url}/transactions/{transaction_id}/documents/{document_id}/fields",
auth=auth, data={"type": "signature"}, timeout=30
)
if response.status_code not in [200, 201]:
raise Exception(f"Erreur création champ: {response.status_code}")
field_id = response.json().get("id")
# ÉTAPE 5: Liaison signataire
response = requests.post(
f"{api_url}/transactions/{transaction_id}/signatures",
auth=auth, data={"signer": email, "field": field_id}, timeout=30
)
if response.status_code not in [200, 201]:
raise Exception(f"Erreur liaison signataire: {response.status_code}")
# ÉTAPE 6: Démarrage
response = requests.post(f"{api_url}/transactions/{transaction_id}/start", auth=auth, timeout=30)
if response.status_code not in [200, 201]:
raise Exception(f"Erreur démarrage: {response.status_code}")
final_data = response.json()
# Récupération URL
signer_url = ""
if final_data.get("actions"):
for action in final_data["actions"]:
if action.get("url"):
signer_url = action["url"]
break
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
if not signer_url:
raise ValueError("URL de signature non retournée par Universign")
# Préparation email
template = templates_signature_email["demande_signature"]
type_labels = {0: "Devis", 10: "Commande", 30: "Bon de Livraison", 60: "Facture", 50: "Avoir"}
variables = {
"NOM_SIGNATAIRE": nom,
"TYPE_DOC": type_labels.get(doc_data.get("type_doc", 0), "Document"),
"NUMERO": doc_id,
"DATE": doc_data.get("date", datetime.now().strftime("%d/%m/%Y")),
"MONTANT_TTC": f"{doc_data.get('montant_ttc', 0):.2f}",
"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(
id=str(uuid.uuid4()),
destinataire=email,
sujet=sujet,
corps_html=corps,
document_ids=doc_id,
type_document=doc_data.get("type_doc"),
statut=StatutEmailEnum.EN_ATTENTE,
date_creation=datetime.now(),
nb_tentatives=0,
)
session.add(email_log)
await session.flush()
email_queue.enqueue(email_log.id)
return {
"transaction_id": transaction_id,
"signer_url": signer_url,
"statut": "ENVOYE",
"email_log_id": email_log.id,
"email_sent": True,
}
except Exception as e:
logger.error(f"Erreur Universign: {e}", exc_info=True)
return {"error": str(e), "statut": "ERREUR", "email_sent": False}
async def universign_statut(transaction_id: str) -> dict:
import requests
try:
response = requests.get(
f"{settings.universign_api_url}/transactions/{transaction_id}",
auth=(settings.universign_api_key, ""),
timeout=10,
)
if response.status_code == 200:
data = response.json()
statut_map = {"draft": "EN_ATTENTE", "started": "EN_ATTENTE", "completed": "SIGNE", "refused": "REFUSE", "expired": "EXPIRE", "canceled": "REFUSE"}
return {"statut": statut_map.get(data.get("state"), "EN_ATTENTE"), "date_signature": data.get("completed_at")}
return {"statut": "ERREUR"}
except Exception as e:
logger.error(f"Erreur statut Universign: {e}")
return {"statut": "ERREUR", "error": str(e)}
@app.get("/clients", response_model=List[ClientDetails], tags=["Clients"]) @app.get("/clients", response_model=List[ClientDetails], tags=["Clients"])
async def obtenir_clients(query: Optional[str] = Query(None)): async def obtenir_clients(query: Optional[str] = Query(None)):
try: try: