refactor(document): Made status changes to be "global"

This commit is contained in:
Fanilo-Nantenaina 2025-12-30 11:56:18 +03:00
parent bad6f3b44b
commit c89db29963
3 changed files with 85 additions and 44 deletions

89
api.py
View file

@ -817,39 +817,76 @@ async def envoyer_devis_email(
logger.error(f"Erreur envoi email: {e}")
raise HTTPException(500, str(e))
@app.put("/devis/{id}/statut", tags=["Devis"])
async def changer_statut_devis(
id: str,
@app.put("/document/{type_doc}/{numero}/statut", tags=["Documents"])
async def changer_statut_document(
type_doc: int = Path(
...,
description="Type de document (0=Devis, 10=Commande, 30=Livraison, 60=Facture, 50=Avoir)",
),
numero: str = Path(..., description="Numéro du document"),
nouveau_statut: int = Query(
..., ge=0, le=6, description="0=Brouillon, 2=Accepté, 5=Transformé, 6=Annulé"
..., ge=0, le=6, description="0=Saisi, 1=Confirmé, 2=Accepté"
),
):
document_type = 0
try:
devis_existant = sage_client.lire_devis(id)
if not devis_existant:
raise HTTPException(404, f"Devis {id} introuvable")
match type_doc:
case 0:
document_type = TypeDocumentSQL.DEVIS
case 10 | 1:
document_type = TypeDocumentSQL.BON_COMMANDE
case 20 | 2:
document_type = TypeDocumentSQL.PREPARATION
case 30 | 3:
document_type = TypeDocumentSQL.BON_LIVRAISON
case 40 | 4:
document_type = TypeDocumentSQL.BON_RETOUR
case 50 | 5:
document_type = TypeDocumentSQL.BON_AVOIR
case 60 | 6:
document_type = TypeDocumentSQL.FACTURE
case _:
raise HTTPException(
400,
f"Type de document invalide: {type_doc}. "
f"Types valides: {list(settings.__dict__.values())}",
)
statut_actuel = devis_existant.get("statut", 0)
document_existant = sage_client.lire_document(numero, document_type)
if not document_existant:
raise HTTPException(404, f"Document {numero} introuvable")
if statut_actuel == 5:
raise HTTPException(
400,
f"Le devis {id} a déjà été transformé et ne peut plus changer de statut",
)
statut_actuel = document_existant.get("statut", 0)
if statut_actuel == 6:
raise HTTPException(
400, f"Le devis {id} est annulé et ne peut plus changer de statut"
)
match type_doc:
case 0:
if statut_actuel >= 2:
statuts_devis = {2: "accepté", 3: "perdu", 4: "archivé"}
raise HTTPException(
400,
f"Le devis {numero} est {statuts_devis.get(statut_actuel, 'verrouillé')} "
f"et ne peut plus changer de statut",
)
resultat = sage_client.changer_statut_devis(id, nouveau_statut)
case 10 | 1 | 30 | 3 | 60 | 6 | 50 | 5:
if statut_actuel >= 2:
type_names = {10: "commande", 1: "commande", 30: "livraison",
3: "livraison", 60: "facture", 6: "facture",
50: "avoir", 5: "avoir"}
raise HTTPException(
400,
f"Le document {numero} ({type_names.get(type_doc, 'document')}) "
f"ne peut plus changer de statut (statut actuel: {statut_actuel})",
)
logger.info(f"Statut devis {id} changé: {statut_actuel}{nouveau_statut}")
resultat = sage_client.changer_statut_document(numero, nouveau_statut)
logger.info(f"Statut document {numero} changé: {statut_actuel}{nouveau_statut}")
return {
"success": True,
"devis_id": id,
"document_id": numero,
"type_document": type_doc,
"statut_ancien": resultat.get("statut_ancien", statut_actuel),
"statut_nouveau": resultat.get("statut_nouveau", nouveau_statut),
"message": f"Statut mis à jour: {statut_actuel}{nouveau_statut}",
@ -858,10 +895,9 @@ async def changer_statut_devis(
except HTTPException:
raise
except Exception as e:
logger.error(f"Erreur changement statut devis {id}: {e}")
logger.error(f"Erreur changement statut document {numero}: {e}")
raise HTTPException(500, str(e))
@app.get("/commandes/{id}", tags=["Commandes"])
async def lire_commande(id: str):
try:
@ -3053,7 +3089,12 @@ async def modifier_contact(numero: str, contact_numero: int, contact: ContactUpd
raise HTTPException(400, "Aucune modification fournie")
resultat = sage_client.modifier_contact(numero, contact_numero, updates)
return Contact(**resultat)
if isinstance(resultat, dict) and "data" in resultat:
contact_data = resultat["data"]
else:
contact_data = resultat
return Contact(**contact_data)
except HTTPException:
raise

View file

@ -24,12 +24,12 @@ def debug_log(message: str, level: str = "INFO"):
if ULTRA_DEBUG:
timestamp = datetime.now().strftime("%H:%M:%S.%f")[:-3]
prefix = {
"INFO": "🔍",
"SUCCESS": "",
"ERROR": "",
"WARN": "⚠️",
"STEP": "📍",
"DATA": "📦"
"INFO": "[INFO]",
"SUCCESS": "[SUCCESS]",
"ERROR": "[ERROR]",
"WARN": "[WARN]",
"STEP": "[STEP]",
"DATA": "[DATA]"
}.get(level, "")
logger.info(f"{prefix} [{timestamp}] {message}")
@ -56,15 +56,15 @@ class EmailQueue:
worker.start()
self.workers.append(worker)
logger.info(f" Queue email démarrée avec {num_workers} worker(s)")
logger.info(f" Queue email démarrée avec {num_workers} worker(s)")
def stop(self):
logger.info("🛑 Arrêt de la queue email...")
logger.info("Arrêt de la queue email...")
self.running = False
try:
self.queue.join()
logger.info(" Queue email arrêtée proprement")
logger.info(" Queue email arrêtée proprement")
except:
logger.warning("⚠️ Timeout lors de l'arrêt de la queue")
@ -93,7 +93,7 @@ class EmailQueue:
except queue.Empty:
continue
except Exception as e:
logger.error(f" Erreur worker {worker_name}: {e}", exc_info=True)
logger.error(f" Erreur worker {worker_name}: {e}", exc_info=True)
try:
self.queue.task_done()
except:
@ -109,7 +109,7 @@ class EmailQueue:
debug_log(f"═══ DÉBUT TRAITEMENT EMAIL {email_log_id} ═══", "STEP")
if not self.session_factory:
logger.error(" session_factory non configuré")
logger.error(" session_factory non configuré")
return
async with self.session_factory() as session:
@ -119,7 +119,7 @@ class EmailQueue:
email_log = result.scalar_one_or_none()
if not email_log:
logger.error(f" Email log {email_log_id} introuvable en DB")
logger.error(f" Email log {email_log_id} introuvable en DB")
return
debug_log(f"Email trouvé en DB:", "DATA")
@ -401,13 +401,13 @@ class EmailQueue:
def _generate_pdf(self, doc_id: str, type_doc: int) -> bytes:
if not self.sage_client:
logger.error(" sage_client non configuré")
logger.error(" sage_client non configuré")
raise Exception("sage_client non disponible")
try:
doc = self.sage_client.lire_document(doc_id, type_doc)
except Exception as e:
logger.error(f" Erreur récupération document {doc_id}: {e}")
logger.error(f" Erreur récupération document {doc_id}: {e}")
raise Exception(f"Document {doc_id} inaccessible")
if not doc:
@ -468,7 +468,7 @@ class EmailQueue:
y = height - 3 * cm
pdf.setFont("Helvetica", 9)
# FIX: Gérer les valeurs None correctement
# FIX: Gérer les valeurs None correctement
designation = (
ligne.get("designation")
or ligne.get("designation_article")
@ -512,7 +512,7 @@ class EmailQueue:
pdf.save()
buffer.seek(0)
logger.info(f" PDF généré: {doc_id}.pdf")
logger.info(f" PDF généré: {doc_id}.pdf")
return buffer.read()

View file

@ -94,10 +94,10 @@ class SageGatewayClient:
payload["statut"] = statut
return self._post("/sage/devis/list", payload).get("data", [])
def changer_statut_devis(self, numero: str, nouveau_statut: int) -> Dict:
def changer_statut_document(self, numero: str, nouveau_statut: int) -> Dict:
try:
r = requests.post(
f"{self.url}/sage/devis/statut",
f"{self.url}/sage/document/statut",
params={
"numero": numero,
"nouveau_statut": nouveau_statut,