Reverted delocalized function
This commit is contained in:
parent
ffa45347bb
commit
d0db0e4077
1 changed files with 150 additions and 1 deletions
151
api.py
151
api.py
|
|
@ -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:
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue