feat(workflow): add direct quote-to-invoice and order-to-delivery endpoints
This commit is contained in:
parent
57d1f313f4
commit
5a6a721f16
1 changed files with 180 additions and 0 deletions
180
api.py
180
api.py
|
|
@ -3170,6 +3170,186 @@ async def livraison_vers_facture(id: str, session: AsyncSession = Depends(get_se
|
|||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
@app.post("/workflow/devis/{id}/to-facture", tags=["US-A2"])
|
||||
async def devis_vers_facture_direct(id: str, session: AsyncSession = Depends(get_session)):
|
||||
"""
|
||||
🔧 Transformation Devis → Facture (DIRECT, sans commande)
|
||||
|
||||
✅ Utilise les VRAIS types Sage (0 → 60)
|
||||
✅ Met à jour le statut du devis source à 5 (Transformé)
|
||||
|
||||
**Workflow raccourci** : Permet de facturer directement depuis un devis
|
||||
sans passer par la création d'une commande.
|
||||
|
||||
**Cas d'usage** :
|
||||
- Prestations de services facturées directement
|
||||
- Petites commandes sans besoin de suivi intermédiaire
|
||||
- Ventes au comptoir
|
||||
|
||||
Args:
|
||||
id: Numéro du devis source
|
||||
|
||||
Returns:
|
||||
Informations de la facture créée
|
||||
"""
|
||||
try:
|
||||
# Étape 1: Vérifier que le devis n'a pas déjà été transformé
|
||||
devis_existant = sage_client.lire_devis(id)
|
||||
if not devis_existant:
|
||||
raise HTTPException(404, f"Devis {id} introuvable")
|
||||
|
||||
statut_devis = devis_existant.get("statut", 0)
|
||||
if statut_devis == 5:
|
||||
raise HTTPException(
|
||||
400,
|
||||
f"Le devis {id} a déjà été transformé (statut=5). "
|
||||
f"Vérifiez les documents déjà créés depuis ce devis."
|
||||
)
|
||||
|
||||
# Étape 2: Transformation
|
||||
resultat = sage_client.transformer_document(
|
||||
numero_source=id,
|
||||
type_source=settings.SAGE_TYPE_DEVIS, # = 0
|
||||
type_cible=settings.SAGE_TYPE_FACTURE, # = 60
|
||||
)
|
||||
|
||||
# Étape 3: Mettre à jour le statut du devis à 5 (Transformé)
|
||||
try:
|
||||
sage_client.changer_statut_devis(id, nouveau_statut=5)
|
||||
logger.info(f"✅ Statut devis {id} mis à jour: 5 (Transformé)")
|
||||
except Exception as e:
|
||||
logger.warning(f"⚠️ Impossible de mettre à jour le statut du devis {id}: {e}")
|
||||
# On continue même si la MAJ statut échoue
|
||||
|
||||
# Étape 4: Logger la transformation
|
||||
workflow_log = WorkflowLog(
|
||||
id=str(uuid.uuid4()),
|
||||
document_source=id,
|
||||
type_source=TypeDocument.DEVIS,
|
||||
document_cible=resultat.get("document_cible", ""),
|
||||
type_cible=TypeDocument.FACTURE,
|
||||
nb_lignes=resultat.get("nb_lignes", 0),
|
||||
date_transformation=datetime.now(),
|
||||
succes=True,
|
||||
)
|
||||
|
||||
session.add(workflow_log)
|
||||
await session.commit()
|
||||
|
||||
logger.info(
|
||||
f"✅ Transformation DIRECTE: Devis {id} → Facture {resultat['document_cible']}"
|
||||
)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"workflow": "devis_to_facture_direct",
|
||||
"document_source": id,
|
||||
"document_cible": resultat["document_cible"],
|
||||
"nb_lignes": resultat["nb_lignes"],
|
||||
"statut_devis_mis_a_jour": True,
|
||||
"message": f"Facture {resultat['document_cible']} créée directement depuis le devis {id}",
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Erreur transformation devis→facture: {e}", exc_info=True)
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
@app.post("/workflow/commande/{id}/to-livraison", tags=["US-A2"])
|
||||
async def commande_vers_livraison(id: str, session: AsyncSession = Depends(get_session)):
|
||||
"""
|
||||
🔧 Transformation Commande → Bon de livraison
|
||||
|
||||
✅ Utilise les VRAIS types Sage (10 → 30)
|
||||
|
||||
**Workflow typique** : Après validation d'une commande, génère
|
||||
le bon de livraison pour préparer l'expédition.
|
||||
|
||||
**Cas d'usage** :
|
||||
- Préparation d'une expédition
|
||||
- Génération du bordereau de livraison
|
||||
- Suivi logistique
|
||||
|
||||
**Workflow complet** :
|
||||
1. Devis → Commande (via `/workflow/devis/{id}/to-commande`)
|
||||
2. **Commande → Livraison** (cette route)
|
||||
3. Livraison → Facture (via `/workflow/livraison/{id}/to-facture`)
|
||||
|
||||
Args:
|
||||
id: Numéro de la commande source
|
||||
|
||||
Returns:
|
||||
Informations du bon de livraison créé
|
||||
"""
|
||||
try:
|
||||
# Étape 1: Vérifier que la commande existe
|
||||
commande_existante = sage_client.lire_document(
|
||||
id,
|
||||
settings.SAGE_TYPE_BON_COMMANDE
|
||||
)
|
||||
|
||||
if not commande_existante:
|
||||
raise HTTPException(404, f"Commande {id} introuvable")
|
||||
|
||||
statut_commande = commande_existante.get("statut", 0)
|
||||
if statut_commande == 5:
|
||||
raise HTTPException(
|
||||
400,
|
||||
f"La commande {id} a déjà été transformée (statut=5). "
|
||||
f"Un bon de livraison existe probablement déjà."
|
||||
)
|
||||
|
||||
if statut_commande == 6:
|
||||
raise HTTPException(
|
||||
400,
|
||||
f"La commande {id} est annulée (statut=6) et ne peut pas être transformée."
|
||||
)
|
||||
|
||||
# Étape 2: Transformation
|
||||
resultat = sage_client.transformer_document(
|
||||
numero_source=id,
|
||||
type_source=settings.SAGE_TYPE_BON_COMMANDE, # = 10
|
||||
type_cible=settings.SAGE_TYPE_BON_LIVRAISON, # = 30
|
||||
)
|
||||
|
||||
# Étape 3: Logger la transformation
|
||||
workflow_log = WorkflowLog(
|
||||
id=str(uuid.uuid4()),
|
||||
document_source=id,
|
||||
type_source=TypeDocument.BON_COMMANDE,
|
||||
document_cible=resultat.get("document_cible", ""),
|
||||
type_cible=TypeDocument.BON_LIVRAISON,
|
||||
nb_lignes=resultat.get("nb_lignes", 0),
|
||||
date_transformation=datetime.now(),
|
||||
succes=True,
|
||||
)
|
||||
|
||||
session.add(workflow_log)
|
||||
await session.commit()
|
||||
|
||||
logger.info(
|
||||
f"✅ Transformation: Commande {id} → Livraison {resultat['document_cible']}"
|
||||
)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"workflow": "commande_to_livraison",
|
||||
"document_source": id,
|
||||
"document_cible": resultat["document_cible"],
|
||||
"nb_lignes": resultat["nb_lignes"],
|
||||
"message": f"Bon de livraison {resultat['document_cible']} créé depuis la commande {id}",
|
||||
"next_step": f"Utilisez /workflow/livraison/{resultat['document_cible']}/to-facture pour créer la facture",
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"❌ Erreur transformation commande→livraison: {e}", exc_info=True)
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
@app.get("/debug/users", response_model=List[UserResponse], tags=["Debug"])
|
||||
async def lister_utilisateurs_debug(
|
||||
session: AsyncSession = Depends(get_session),
|
||||
|
|
|
|||
Loading…
Reference in a new issue