Unification for document's schemas
This commit is contained in:
parent
e7bdf2d6a2
commit
8850c7c266
9 changed files with 107 additions and 121 deletions
100
api.py
100
api.py
|
|
@ -78,7 +78,7 @@ from core.sage_context import (
|
|||
get_gateway_context_for_user,
|
||||
GatewayContext,
|
||||
)
|
||||
|
||||
from utils.generic_functions import _preparer_lignes_document
|
||||
|
||||
if os.path.exists("/app"):
|
||||
LOGS_DIR = FilePath("/app/logs")
|
||||
|
|
@ -526,19 +526,15 @@ async def creer_devis(devis: DevisRequest):
|
|||
devis.date_livraison.isoformat() if devis.date_livraison else None
|
||||
),
|
||||
"reference": devis.reference,
|
||||
"lignes": [
|
||||
{
|
||||
"article_code": ligne.article_code,
|
||||
"quantite": ligne.quantite,
|
||||
"remise_pourcentage": ligne.remise_pourcentage,
|
||||
}
|
||||
for ligne in devis.lignes
|
||||
],
|
||||
"lignes": _preparer_lignes_document(devis.lignes),
|
||||
}
|
||||
|
||||
resultat = sage_client.creer_devis(devis_data)
|
||||
|
||||
logger.info(f"Devis créé: {resultat.get('numero_devis')}")
|
||||
logger.info(
|
||||
f"✅ Devis créé: {resultat.get('numero_devis')} "
|
||||
f"({resultat.get('total_ttc')}€ TTC)"
|
||||
)
|
||||
|
||||
return Devis(
|
||||
id=resultat["numero_devis"],
|
||||
|
|
@ -550,7 +546,7 @@ async def creer_devis(devis: DevisRequest):
|
|||
)
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur création devis: {e}")
|
||||
logger.error(f"❌ Erreur création devis: {e}")
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
|
|
@ -613,19 +609,15 @@ async def creer_commande(
|
|||
commande.date_livraison.isoformat() if commande.date_livraison else None
|
||||
),
|
||||
"reference": commande.reference,
|
||||
"lignes": [
|
||||
{
|
||||
"article_code": ligne.article_code,
|
||||
"quantite": ligne.quantite,
|
||||
"remise_pourcentage": ligne.remise_pourcentage,
|
||||
}
|
||||
for ligne in commande.lignes
|
||||
],
|
||||
"lignes": _preparer_lignes_document(commande.lignes),
|
||||
}
|
||||
|
||||
resultat = sage_client.creer_commande(commande_data)
|
||||
|
||||
logger.info(f"Commande créée: {resultat.get('numero_commande')}")
|
||||
logger.info(
|
||||
f"✅ Commande créée: {resultat.get('numero_commande')} "
|
||||
f"({resultat.get('total_ttc')}€ TTC)"
|
||||
)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
|
|
@ -637,14 +629,15 @@ async def creer_commande(
|
|||
"total_ht": resultat["total_ht"],
|
||||
"total_ttc": resultat["total_ttc"],
|
||||
"nb_lignes": resultat["nb_lignes"],
|
||||
"reference": commande.reference,
|
||||
"reference": resultat.get("reference"),
|
||||
"date_livraison": resultat.get("date_livraison"),
|
||||
},
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur création commande: {e}")
|
||||
logger.error(f"❌ Erreur création commande: {e}")
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
|
|
@ -1798,19 +1791,15 @@ async def creer_facture(
|
|||
facture.date_livraison.isoformat() if facture.date_livraison else None
|
||||
),
|
||||
"reference": facture.reference,
|
||||
"lignes": [
|
||||
{
|
||||
"article_code": ligne.article_code,
|
||||
"quantite": ligne.quantite,
|
||||
"remise_pourcentage": ligne.remise_pourcentage,
|
||||
}
|
||||
for ligne in facture.lignes
|
||||
],
|
||||
"lignes": _preparer_lignes_document(facture.lignes),
|
||||
}
|
||||
|
||||
resultat = sage_client.creer_facture(facture_data)
|
||||
|
||||
logger.info(f"Facture créée: {resultat.get('numero_facture')}")
|
||||
logger.info(
|
||||
f"✅ Facture créée: {resultat.get('numero_facture')} "
|
||||
f"({resultat.get('total_ttc')}€ TTC)"
|
||||
)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
|
|
@ -1822,14 +1811,15 @@ async def creer_facture(
|
|||
"total_ht": resultat["total_ht"],
|
||||
"total_ttc": resultat["total_ttc"],
|
||||
"nb_lignes": resultat["nb_lignes"],
|
||||
"reference": facture.reference,
|
||||
"reference": resultat.get("reference"),
|
||||
"date_livraison": resultat.get("date_livraison"),
|
||||
},
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur création facture: {e}")
|
||||
logger.error(f"❌ Erreur création facture: {e}")
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
|
|
@ -2324,19 +2314,15 @@ async def creer_avoir(avoir: AvoirCreate, session: AsyncSession = Depends(get_se
|
|||
avoir.date_livraison.isoformat() if avoir.date_livraison else None
|
||||
),
|
||||
"reference": avoir.reference,
|
||||
"lignes": [
|
||||
{
|
||||
"article_code": ligne.article_code,
|
||||
"quantite": ligne.quantite,
|
||||
"remise_pourcentage": ligne.remise_pourcentage,
|
||||
}
|
||||
for ligne in avoir.lignes
|
||||
],
|
||||
"lignes": _preparer_lignes_document(avoir.lignes),
|
||||
}
|
||||
|
||||
resultat = sage_client.creer_avoir(avoir_data)
|
||||
|
||||
logger.info(f"Avoir créé: {resultat.get('numero_avoir')}")
|
||||
logger.info(
|
||||
f"✅ Avoir créé: {resultat.get('numero_avoir')} "
|
||||
f"({resultat.get('total_ttc')}€ TTC)"
|
||||
)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
|
|
@ -2348,14 +2334,15 @@ async def creer_avoir(avoir: AvoirCreate, session: AsyncSession = Depends(get_se
|
|||
"total_ht": resultat["total_ht"],
|
||||
"total_ttc": resultat["total_ttc"],
|
||||
"nb_lignes": resultat["nb_lignes"],
|
||||
"reference": avoir.reference,
|
||||
"reference": resultat.get("reference"),
|
||||
"date_livraison": resultat.get("date_livraison"),
|
||||
},
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur création avoir: {e}")
|
||||
logger.error(f"❌ Erreur création avoir: {e}")
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
|
|
@ -2434,6 +2421,12 @@ async def lire_livraison(numero: str):
|
|||
async def creer_livraison(
|
||||
livraison: LivraisonCreate, session: AsyncSession = Depends(get_session)
|
||||
):
|
||||
"""
|
||||
Crée un bon de livraison dans Sage 100
|
||||
|
||||
- Le prix_unitaire_ht est optionnel (utilise le prix Sage si non fourni)
|
||||
- La remise_pourcentage est appliquée après le prix
|
||||
"""
|
||||
try:
|
||||
livraison_data = {
|
||||
"client_id": livraison.client_id,
|
||||
|
|
@ -2448,19 +2441,15 @@ async def creer_livraison(
|
|||
else None
|
||||
),
|
||||
"reference": livraison.reference,
|
||||
"lignes": [
|
||||
{
|
||||
"article_code": ligne.article_code,
|
||||
"quantite": ligne.quantite,
|
||||
"remise_pourcentage": ligne.remise_pourcentage,
|
||||
}
|
||||
for ligne in livraison.lignes
|
||||
],
|
||||
"lignes": _preparer_lignes_document(livraison.lignes),
|
||||
}
|
||||
|
||||
resultat = sage_client.creer_livraison(livraison_data)
|
||||
|
||||
logger.info(f"Livraison créée: {resultat.get('numero_livraison')}")
|
||||
logger.info(
|
||||
f"✅ Livraison créée: {resultat.get('numero_livraison')} "
|
||||
f"({resultat.get('total_ttc')}€ TTC)"
|
||||
)
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
|
|
@ -2469,17 +2458,18 @@ async def creer_livraison(
|
|||
"numero_livraison": resultat["numero_livraison"],
|
||||
"client_id": livraison.client_id,
|
||||
"date_livraison": resultat["date_livraison"],
|
||||
"date_livraison_prevue": resultat.get("date_livraison_prevue"),
|
||||
"total_ht": resultat["total_ht"],
|
||||
"total_ttc": resultat["total_ttc"],
|
||||
"nb_lignes": resultat["nb_lignes"],
|
||||
"reference": livraison.reference,
|
||||
"reference": resultat.get("reference"),
|
||||
},
|
||||
}
|
||||
|
||||
except HTTPException:
|
||||
raise
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur création livraison: {e}")
|
||||
logger.error(f"❌ Erreur création livraison: {e}")
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +1,14 @@
|
|||
from pydantic import BaseModel, Field, field_validator
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import List, Optional
|
||||
from datetime import date
|
||||
|
||||
|
||||
class LigneAvoir(BaseModel):
|
||||
article_code: str
|
||||
quantite: float
|
||||
remise_pourcentage: Optional[float] = 0.0
|
||||
|
||||
@field_validator("article_code", mode="before")
|
||||
def strip_insecables(cls, v):
|
||||
return v.replace("\xa0", "").strip()
|
||||
|
||||
from schemas.documents.ligne_document import LigneDocument
|
||||
|
||||
class AvoirCreate(BaseModel):
|
||||
client_id: str
|
||||
date_avoir: Optional[date] = None
|
||||
date_livraison: Optional[date] = None
|
||||
lignes: List[LigneAvoir]
|
||||
lignes: List[LigneDocument]
|
||||
reference: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
|
|
@ -41,7 +32,7 @@ class AvoirCreate(BaseModel):
|
|||
class AvoirUpdate(BaseModel):
|
||||
date_avoir: Optional[date] = None
|
||||
date_livraison: Optional[date] = None
|
||||
lignes: Optional[List[LigneAvoir]] = None
|
||||
lignes: Optional[List[LigneDocument]] = None
|
||||
statut: Optional[int] = Field(None, ge=0, le=6)
|
||||
reference: Optional[str] = None
|
||||
|
||||
|
|
|
|||
|
|
@ -1,23 +1,14 @@
|
|||
from pydantic import BaseModel, Field, field_validator
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import List, Optional
|
||||
from datetime import date
|
||||
|
||||
|
||||
class LigneCommande(BaseModel):
|
||||
article_code: str
|
||||
quantite: float
|
||||
remise_pourcentage: Optional[float] = 0.0
|
||||
|
||||
@field_validator("article_code", mode="before")
|
||||
def strip_insecables(cls, v):
|
||||
return v.replace("\xa0", "").strip()
|
||||
|
||||
from schemas.documents.ligne_document import LigneDocument
|
||||
|
||||
class CommandeCreate(BaseModel):
|
||||
client_id: str
|
||||
date_commande: Optional[date] = None
|
||||
date_livraison: Optional[date] = None
|
||||
lignes: List[LigneCommande]
|
||||
lignes: List[LigneDocument]
|
||||
reference: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
|
|
@ -41,7 +32,7 @@ class CommandeCreate(BaseModel):
|
|||
class CommandeUpdate(BaseModel):
|
||||
date_commande: Optional[date] = None
|
||||
date_livraison: Optional[date] = None
|
||||
lignes: Optional[List[LigneCommande]] = None
|
||||
lignes: Optional[List[LigneDocument]] = None
|
||||
statut: Optional[int] = Field(None, ge=0, le=6)
|
||||
reference: Optional[str] = None
|
||||
|
||||
|
|
|
|||
|
|
@ -1,16 +1,8 @@
|
|||
from pydantic import BaseModel, Field, field_validator
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import List, Optional
|
||||
from datetime import date
|
||||
|
||||
|
||||
class LigneDevis(BaseModel):
|
||||
article_code: str
|
||||
quantite: float
|
||||
remise_pourcentage: Optional[float] = 0.0
|
||||
|
||||
@field_validator("article_code", mode="before")
|
||||
def strip_insecables(cls, v):
|
||||
return v.replace("\xa0", "").strip()
|
||||
from schemas.documents.ligne_document import LigneDocument
|
||||
|
||||
|
||||
class DevisRequest(BaseModel):
|
||||
|
|
@ -18,7 +10,7 @@ class DevisRequest(BaseModel):
|
|||
date_devis: Optional[date] = None
|
||||
date_livraison: Optional[date] = None
|
||||
reference: Optional[str] = None
|
||||
lignes: List[LigneDevis]
|
||||
lignes: List[LigneDocument]
|
||||
|
||||
|
||||
class Devis(BaseModel):
|
||||
|
|
@ -35,8 +27,8 @@ class DevisUpdate(BaseModel):
|
|||
|
||||
date_devis: Optional[date] = None
|
||||
date_livraison: Optional[date] = None
|
||||
lignes: Optional[List[LigneDocument]] = None
|
||||
reference: Optional[str] = None
|
||||
lignes: Optional[List[LigneDevis]] = None
|
||||
statut: Optional[int] = Field(None, ge=0, le=6)
|
||||
|
||||
class Config:
|
||||
|
|
|
|||
|
|
@ -1,23 +1,14 @@
|
|||
from pydantic import BaseModel, Field, field_validator
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import List, Optional
|
||||
from datetime import date
|
||||
|
||||
|
||||
class LigneFacture(BaseModel):
|
||||
article_code: str
|
||||
quantite: float
|
||||
remise_pourcentage: Optional[float] = 0.0
|
||||
|
||||
@field_validator("article_code", mode="before")
|
||||
def strip_insecables(cls, v):
|
||||
return v.replace("\xa0", "").strip()
|
||||
|
||||
from schemas.documents.ligne_document import LigneDocument
|
||||
|
||||
class FactureCreate(BaseModel):
|
||||
client_id: str
|
||||
date_facture: Optional[date] = None
|
||||
date_livraison: Optional[date] = None
|
||||
lignes: List[LigneFacture]
|
||||
lignes: List[LigneDocument]
|
||||
reference: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
|
|
@ -41,7 +32,7 @@ class FactureCreate(BaseModel):
|
|||
class FactureUpdate(BaseModel):
|
||||
date_facture: Optional[date] = None
|
||||
date_livraison: Optional[date] = None
|
||||
lignes: Optional[List[LigneFacture]] = None
|
||||
lignes: Optional[List[LigneDocument]] = None
|
||||
statut: Optional[int] = Field(None, ge=0, le=6)
|
||||
reference: Optional[str] = None
|
||||
|
||||
|
|
|
|||
25
schemas/documents/ligne_document.py
Normal file
25
schemas/documents/ligne_document.py
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
from pydantic import BaseModel, field_validator
|
||||
from typing import Optional
|
||||
|
||||
|
||||
class LigneDocument(BaseModel):
|
||||
article_code: str
|
||||
quantite: float
|
||||
prix_unitaire_ht: Optional[float] = None
|
||||
remise_pourcentage: Optional[float] = 0.0
|
||||
|
||||
@field_validator("article_code", mode="before")
|
||||
def strip_insecables(cls, v):
|
||||
return v.replace("\xa0", "").strip()
|
||||
|
||||
@field_validator("quantite")
|
||||
def validate_quantite(cls, v):
|
||||
if v <= 0:
|
||||
raise ValueError("La quantité doit être positive")
|
||||
return v
|
||||
|
||||
@field_validator("remise_pourcentage")
|
||||
def validate_remise(cls, v):
|
||||
if v is not None and (v < 0 or v > 100):
|
||||
raise ValueError("La remise doit être entre 0 et 100")
|
||||
return v
|
||||
|
|
@ -1,23 +1,15 @@
|
|||
from pydantic import BaseModel, Field, field_validator
|
||||
from pydantic import BaseModel, Field
|
||||
from typing import List, Optional
|
||||
from datetime import date
|
||||
|
||||
|
||||
class LigneLivraison(BaseModel):
|
||||
article_code: str
|
||||
quantite: float
|
||||
remise_pourcentage: Optional[float] = 0.0
|
||||
|
||||
@field_validator("article_code", mode="before")
|
||||
def strip_insecables(cls, v):
|
||||
return v.replace("\xa0", "").strip()
|
||||
from schemas.documents.ligne_document import LigneDocument
|
||||
|
||||
|
||||
class LivraisonCreate(BaseModel):
|
||||
client_id: str
|
||||
date_livraison: Optional[date] = None
|
||||
date_livraison_prevue: Optional[date] = None
|
||||
lignes: List[LigneLivraison]
|
||||
lignes: List[LigneDocument]
|
||||
reference: Optional[str] = None
|
||||
|
||||
class Config:
|
||||
|
|
@ -41,7 +33,7 @@ class LivraisonCreate(BaseModel):
|
|||
class LivraisonUpdate(BaseModel):
|
||||
date_livraison: Optional[date] = None
|
||||
date_livraison_prevue: Optional[date] = None
|
||||
lignes: Optional[List[LigneLivraison]] = None
|
||||
lignes: Optional[List[LigneDocument]] = None
|
||||
statut: Optional[int] = Field(None, ge=0, le=6)
|
||||
reference: Optional[str] = None
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
from pydantic import BaseModel, Field, field_validator
|
||||
from typing import List, Optional
|
||||
from schemas.tiers.contact import Contact
|
||||
from typing import Optional
|
||||
from schemas.tiers.tiers import TiersDetails
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
from typing import Dict
|
||||
from typing import Dict, List
|
||||
from config.config import settings
|
||||
import logging
|
||||
|
||||
|
|
@ -264,3 +264,18 @@ async def universign_statut(transaction_id: str) -> Dict:
|
|||
except Exception as e:
|
||||
logger.error(f"Erreur statut Universign: {e}")
|
||||
return {"statut": "ERREUR", "error": str(e)}
|
||||
|
||||
|
||||
def _preparer_lignes_document(lignes: List) -> List[Dict]:
|
||||
return [
|
||||
{
|
||||
"article_code": ligne.article_code,
|
||||
"quantite": ligne.quantite,
|
||||
"prix_unitaire_ht": ligne.prix_unitaire_ht,
|
||||
"remise_pourcentage": ligne.remise_pourcentage or 0.0,
|
||||
}
|
||||
for ligne in lignes
|
||||
]
|
||||
|
||||
|
||||
__all__ = ["_preparer_lignes_document"]
|
||||
|
|
|
|||
Loading…
Reference in a new issue