refactor(schemas): rename response and request models to simpler names

This commit is contained in:
Fanilo-Nantenaina 2026-01-03 11:11:28 +03:00
parent e3b0f7e44a
commit 306c71b43d
16 changed files with 194 additions and 553 deletions

206
api.py
View file

@ -23,10 +23,10 @@ from database import (
async_session_factory,
get_session,
EmailLog,
StatutEmail as StatutEmailEnum,
StatutEmail as StatutEmailDB,
WorkflowLog,
SignatureLog,
StatutSignature as StatutSignatureEnum,
StatutSignature as StatutSignatureDB,
)
from email_queue import email_queue
from sage_client import sage_client, SageGatewayClient
@ -34,45 +34,44 @@ from sage_client import sage_client, SageGatewayClient
from schemas import (
TiersDetails,
BaremeRemiseResponse,
UserResponse,
ClientCreateRequest,
Users,
ClientCreate,
ClientDetails,
ClientUpdateRequest,
FournisseurCreateAPIRequest,
ClientUpdate,
FournisseurCreate,
FournisseurDetails,
FournisseurUpdateRequest,
FournisseurUpdate,
Contact,
AvoirCreateRequest,
AvoirUpdateRequest,
CommandeCreateRequest,
CommandeUpdateRequest,
AvoirCreate,
AvoirUpdate,
CommandeCreate,
CommandeUpdate,
DevisRequest,
DevisResponse,
DevisUpdateRequest,
Devis,
DevisUpdate,
TypeDocument,
TypeDocumentSQL,
StatutEmail,
EmailEnvoiRequest,
FactureCreateRequest,
FactureUpdateRequest,
LivraisonCreateRequest,
LivraisonUpdateRequest,
SignatureRequest,
EmailEnvoi,
FactureCreate,
FactureUpdate,
LivraisonCreate,
LivraisonUpdate,
Signature,
StatutSignature,
ArticleCreateRequest,
ArticleResponse,
ArticleUpdateRequest,
EntreeStockRequest,
SortieStockRequest,
MouvementStockResponse,
RelanceDevisRequest,
FamilleResponse,
FamilleCreateRequest,
ArticleCreate,
Article,
ArticleUpdate,
EntreeStock,
SortieStock,
MouvementStock,
RelanceDevis,
Familles,
FamilleCreate,
ContactCreate,
ContactUpdate,
)
from utils.normalization import normaliser_type_tiers
from routes.sage_gateway import router as sage_gateway_router
from core.sage_context import (
get_sage_client_for_user,
@ -80,6 +79,7 @@ from core.sage_context import (
GatewayContext,
)
if os.path.exists("/app"):
LOGS_DIR = FilePath("/app/logs")
else:
@ -264,7 +264,7 @@ async def universign_envoyer(
corps_html=corps,
document_ids=doc_id,
type_document=doc_data.get("type_doc"),
statut=StatutEmailEnum.EN_ATTENTE,
statut=StatutEmailDB.EN_ATTENTE,
date_creation=datetime.now(),
nb_tentatives=0,
)
@ -347,7 +347,7 @@ async def lire_client_detail(code: str):
@app.put("/clients/{code}", tags=["Clients"])
async def modifier_client(
code: str,
client_update: ClientUpdateRequest,
client_update: ClientUpdate,
session: AsyncSession = Depends(get_session),
):
try:
@ -373,7 +373,7 @@ async def modifier_client(
@app.post("/clients", status_code=201, tags=["Clients"])
async def ajouter_client(
client: ClientCreateRequest, session: AsyncSession = Depends(get_session)
client: ClientCreate, session: AsyncSession = Depends(get_session)
):
try:
nouveau_client = sage_client.creer_client(client.model_dump(mode="json"))
@ -394,11 +394,11 @@ async def ajouter_client(
raise HTTPException(status, str(e))
@app.get("/articles", response_model=List[ArticleResponse], tags=["Articles"])
@app.get("/articles", response_model=List[Article], tags=["Articles"])
async def rechercher_articles(query: Optional[str] = Query(None)):
try:
articles = sage_client.lister_articles(filtre=query or "")
return [ArticleResponse(**a) for a in articles]
return [Article(**a) for a in articles]
except Exception as e:
logger.error(f"Erreur recherche articles: {e}")
raise HTTPException(500, str(e))
@ -406,11 +406,11 @@ async def rechercher_articles(query: Optional[str] = Query(None)):
@app.post(
"/articles",
response_model=ArticleResponse,
response_model=Article,
status_code=status.HTTP_201_CREATED,
tags=["Articles"],
)
async def creer_article(article: ArticleCreateRequest):
async def creer_article(article: ArticleCreate):
try:
if not article.reference or not article.designation:
raise HTTPException(
@ -428,7 +428,7 @@ async def creer_article(article: ArticleCreateRequest):
f"Article créé: {resultat.get('reference')} (stock: {resultat.get('stock_reel', 0)})"
)
return ArticleResponse(**resultat)
return Article(**resultat)
except ValueError as e:
logger.warning(f"Erreur métier création article: {e}")
@ -445,10 +445,10 @@ async def creer_article(article: ArticleCreateRequest):
)
@app.put("/articles/{reference}", response_model=ArticleResponse, tags=["Articles"])
@app.put("/articles/{reference}", response_model=Article, tags=["Articles"])
async def modifier_article(
reference: str = Path(..., description="Référence de l'article à modifier"),
article: ArticleUpdateRequest = Body(...),
article: ArticleUpdate = Body(...),
):
try:
article_data = article.dict(exclude_unset=True)
@ -471,7 +471,7 @@ async def modifier_article(
logger.info(f"Article {reference} modifié ({len(article_data)} champs)")
return ArticleResponse(**resultat)
return Article(**resultat)
except ValueError as e:
logger.warning(f"Erreur métier modification article: {e}")
@ -488,7 +488,7 @@ async def modifier_article(
)
@app.get("/articles/{reference}", response_model=ArticleResponse, tags=["Articles"])
@app.get("/articles/{reference}", response_model=Article, tags=["Articles"])
async def lire_article(
reference: str = Path(..., description="Référence de l'article"),
):
@ -504,7 +504,7 @@ async def lire_article(
logger.info(f"Article {reference} lu: {article.get('designation', '')}")
return ArticleResponse(**article)
return Article(**article)
except HTTPException:
raise
@ -516,7 +516,7 @@ async def lire_article(
)
@app.post("/devis", response_model=DevisResponse, status_code=201, tags=["Devis"])
@app.post("/devis", response_model=Devis, status_code=201, tags=["Devis"])
async def creer_devis(devis: DevisRequest):
try:
devis_data = {
@ -540,7 +540,7 @@ async def creer_devis(devis: DevisRequest):
logger.info(f"Devis créé: {resultat.get('numero_devis')}")
return DevisResponse(
return Devis(
id=resultat["numero_devis"],
client_id=devis.client_id,
date_devis=resultat["date_devis"],
@ -557,7 +557,7 @@ async def creer_devis(devis: DevisRequest):
@app.put("/devis/{id}", tags=["Devis"])
async def modifier_devis(
id: str,
devis_update: DevisUpdateRequest,
devis_update: DevisUpdate,
session: AsyncSession = Depends(get_session),
):
try:
@ -601,7 +601,7 @@ async def modifier_devis(
@app.post("/commandes", status_code=201, tags=["Commandes"])
async def creer_commande(
commande: CommandeCreateRequest, session: AsyncSession = Depends(get_session)
commande: CommandeCreate, session: AsyncSession = Depends(get_session)
):
try:
commande_data = {
@ -651,7 +651,7 @@ async def creer_commande(
@app.put("/commandes/{id}", tags=["Commandes"])
async def modifier_commande(
id: str,
commande_update: CommandeUpdateRequest,
commande_update: CommandeUpdate,
session: AsyncSession = Depends(get_session),
):
try:
@ -803,7 +803,7 @@ async def telecharger_document_pdf(
@app.post("/devis/{id}/envoyer", tags=["Devis"])
async def envoyer_devis_email(
id: str, request: EmailEnvoiRequest, session: AsyncSession = Depends(get_session)
id: str, request: EmailEnvoi, session: AsyncSession = Depends(get_session)
):
try:
tous_destinataires = [request.destinataire] + request.cc + request.cci
@ -817,7 +817,7 @@ async def envoyer_devis_email(
corps_html=request.corps_html,
document_ids=id,
type_document=TypeDocument.DEVIS,
statut=StatutEmailEnum.EN_ATTENTE,
statut=StatutEmailDB.EN_ATTENTE,
date_creation=datetime.now(),
nb_tentatives=0,
)
@ -1089,7 +1089,7 @@ def normaliser_type_doc(type_doc: int) -> int:
@app.post("/signature/universign/send", tags=["Signatures"])
async def envoyer_signature_optimise(
demande: SignatureRequest, session: AsyncSession = Depends(get_session)
demande: Signature, session: AsyncSession = Depends(get_session)
):
try:
doc = sage_client.lire_document(
@ -1135,7 +1135,7 @@ async def envoyer_signature_optimise(
signer_url=resultat["signer_url"],
email_signataire=demande.email_signataire,
nom_signataire=demande.nom_signataire,
statut=StatutSignatureEnum.ENVOYE,
statut=StatutSignatureDB.ENVOYE,
date_envoi=datetime.now(),
)
@ -1191,7 +1191,7 @@ async def webhook_universign(
return {"status": "not_found"}
if event_type == "transaction.completed":
signature_log.statut = StatutSignatureEnum.SIGNE
signature_log.statut = StatutSignatureDB.SIGNE
signature_log.date_signature = datetime.now()
logger.info(f"Signature confirmée: {signature_log.document_id}")
@ -1229,7 +1229,7 @@ async def webhook_universign(
corps_html=corps,
document_ids=signature_log.document_id,
type_document=signature_log.type_document,
statut=StatutEmailEnum.EN_ATTENTE,
statut=StatutEmailDB.EN_ATTENTE,
date_creation=datetime.now(),
nb_tentatives=0,
)
@ -1242,11 +1242,11 @@ async def webhook_universign(
)
elif event_type == "transaction.refused":
signature_log.statut = StatutSignatureEnum.REFUSE
signature_log.statut = StatutSignatureDB.REFUSE
logger.warning(f"Signature refusée: {signature_log.document_id}")
elif event_type == "transaction.expired":
signature_log.statut = StatutSignatureEnum.EXPIRE
signature_log.statut = StatutSignatureDB.EXPIRE
logger.warning(f"⏰ Transaction expirée: {signature_log.document_id}")
await session.commit()
@ -1271,7 +1271,7 @@ async def relancer_signatures_automatique(session: AsyncSession = Depends(get_se
query = select(SignatureLog).where(
SignatureLog.statut.in_(
[StatutSignatureEnum.EN_ATTENTE, StatutSignatureEnum.ENVOYE]
[StatutSignatureDB.EN_ATTENTE, StatutSignatureDB.ENVOYE]
),
SignatureLog.date_envoi < date_limite,
SignatureLog.nb_relances < 3, # Max 3 relances
@ -1288,7 +1288,7 @@ async def relancer_signatures_automatique(session: AsyncSession = Depends(get_se
jours_restants = 30 - nb_jours # Lien expire après 30 jours
if jours_restants <= 0:
signature.statut = StatutSignatureEnum.EXPIRE
signature.statut = StatutSignatureDB.EXPIRE
continue
template = templates_signature_email["relance_signature"]
@ -1325,7 +1325,7 @@ async def relancer_signatures_automatique(session: AsyncSession = Depends(get_se
corps_html=corps,
document_ids=signature.document_id,
type_document=signature.type_document,
statut=StatutEmailEnum.EN_ATTENTE,
statut=StatutEmailDB.EN_ATTENTE,
date_creation=datetime.now(),
nb_tentatives=0,
)
@ -1394,7 +1394,7 @@ async def lister_signatures(
query = select(SignatureLog).order_by(SignatureLog.date_envoi.desc())
if statut:
statut_db = StatutSignatureEnum[statut.value]
statut_db = StatutSignatureDB[statut.value]
query = query.where(SignatureLog.statut == statut_db)
query = query.limit(limit)
@ -1437,15 +1437,15 @@ async def statut_signature_detail(
if statut_universign.get("statut") != "ERREUR":
statut_map = {
"EN_ATTENTE": StatutSignatureEnum.EN_ATTENTE,
"ENVOYE": StatutSignatureEnum.ENVOYE,
"SIGNE": StatutSignatureEnum.SIGNE,
"REFUSE": StatutSignatureEnum.REFUSE,
"EXPIRE": StatutSignatureEnum.EXPIRE,
"EN_ATTENTE": StatutSignatureDB.EN_ATTENTE,
"ENVOYE": StatutSignatureDB.ENVOYE,
"SIGNE": StatutSignatureDB.SIGNE,
"REFUSE": StatutSignatureDB.REFUSE,
"EXPIRE": StatutSignatureDB.EXPIRE,
}
nouveau_statut = statut_map.get(
statut_universign["statut"], StatutSignatureEnum.EN_ATTENTE
statut_universign["statut"], StatutSignatureDB.EN_ATTENTE
)
signature_log.statut = nouveau_statut
@ -1478,7 +1478,7 @@ async def statut_signature_detail(
async def rafraichir_statuts_signatures(session: AsyncSession = Depends(get_session)):
query = select(SignatureLog).where(
SignatureLog.statut.in_(
[StatutSignatureEnum.EN_ATTENTE, StatutSignatureEnum.ENVOYE]
[StatutSignatureDB.EN_ATTENTE, StatutSignatureDB.ENVOYE]
)
)
@ -1492,9 +1492,9 @@ async def rafraichir_statuts_signatures(session: AsyncSession = Depends(get_sess
if statut_universign.get("statut") != "ERREUR":
statut_map = {
"SIGNE": StatutSignatureEnum.SIGNE,
"REFUSE": StatutSignatureEnum.REFUSE,
"EXPIRE": StatutSignatureEnum.EXPIRE,
"SIGNE": StatutSignatureDB.SIGNE,
"REFUSE": StatutSignatureDB.REFUSE,
"EXPIRE": StatutSignatureDB.EXPIRE,
}
nouveau = statut_map.get(statut_universign["statut"])
@ -1524,7 +1524,7 @@ async def rafraichir_statuts_signatures(session: AsyncSession = Depends(get_sess
@app.post("/devis/{id}/signer", tags=["Devis"])
async def envoyer_devis_signature(
id: str, request: SignatureRequest, session: AsyncSession = Depends(get_session)
id: str, request: Signature, session: AsyncSession = Depends(get_session)
):
try:
devis = sage_client.lire_devis(id)
@ -1548,7 +1548,7 @@ async def envoyer_devis_signature(
signer_url=resultat["signer_url"],
email_signataire=request.email_signataire,
nom_signataire=request.nom_signataire,
statut=StatutSignatureEnum.ENVOYE,
statut=StatutSignatureDB.ENVOYE,
date_envoi=datetime.now(),
)
@ -1594,7 +1594,7 @@ async def envoyer_emails_lot(
corps_html=batch.corps_html,
document_ids=",".join(batch.document_ids) if batch.document_ids else None,
type_document=batch.type_document,
statut=StatutEmailEnum.EN_ATTENTE,
statut=StatutEmailDB.EN_ATTENTE,
date_creation=datetime.now(),
nb_tentatives=0,
)
@ -1663,7 +1663,7 @@ async def valider_remise(
@app.post("/devis/{id}/relancer-signature", tags=["Devis"])
async def relancer_devis_signature(
id: str, relance: RelanceDevisRequest, session: AsyncSession = Depends(get_session)
id: str, relance: RelanceDevis, session: AsyncSession = Depends(get_session)
):
try:
devis = sage_client.lire_devis(id)
@ -1694,7 +1694,7 @@ async def relancer_devis_signature(
signer_url=resultat["signer_url"],
email_signataire=contact["email"],
nom_signataire=contact["nom"] or contact["client_intitule"],
statut=StatutSignatureEnum.ENVOYE,
statut=StatutSignatureDB.ENVOYE,
date_envoi=datetime.now(),
est_relance=True,
nb_relances=1,
@ -1786,7 +1786,7 @@ class RelanceFactureRequest(BaseModel):
@app.post("/factures", status_code=201, tags=["Factures"])
async def creer_facture(
facture: FactureCreateRequest, session: AsyncSession = Depends(get_session)
facture: FactureCreate, session: AsyncSession = Depends(get_session)
):
try:
facture_data = {
@ -1836,7 +1836,7 @@ async def creer_facture(
@app.put("/factures/{id}", tags=["Factures"])
async def modifier_facture(
id: str,
facture_update: FactureUpdateRequest,
facture_update: FactureUpdate,
session: AsyncSession = Depends(get_session),
):
try:
@ -1940,7 +1940,7 @@ async def relancer_facture(
corps_html=corps,
document_ids=id,
type_document=TypeDocument.FACTURE,
statut=StatutEmailEnum.EN_ATTENTE,
statut=StatutEmailDB.EN_ATTENTE,
date_creation=datetime.now(),
nb_tentatives=0,
)
@ -1979,7 +1979,7 @@ async def journal_emails(
query = select(EmailLog)
if statut:
query = query.where(EmailLog.statut == StatutEmailEnum[statut.value])
query = query.where(EmailLog.statut == StatutEmailDB[statut.value])
if destinataire:
query = query.where(EmailLog.destinataire.contains(destinataire))
@ -2012,7 +2012,7 @@ async def exporter_logs_csv(
):
query = select(EmailLog)
if statut:
query = query.where(EmailLog.statut == StatutEmailEnum[statut.value])
query = query.where(EmailLog.statut == StatutEmailDB[statut.value])
query = query.order_by(EmailLog.date_creation.desc())
@ -2226,7 +2226,7 @@ async def rechercher_fournisseurs(query: Optional[str] = Query(None)):
@app.post("/fournisseurs", status_code=201, tags=["Fournisseurs"])
async def ajouter_fournisseur(
fournisseur: FournisseurCreateAPIRequest,
fournisseur: FournisseurCreate,
session: AsyncSession = Depends(get_session),
):
try:
@ -2254,7 +2254,7 @@ async def ajouter_fournisseur(
)
async def modifier_fournisseur(
code: str,
fournisseur_update: FournisseurUpdateRequest,
fournisseur_update: FournisseurUpdate,
session: AsyncSession = Depends(get_session),
):
try:
@ -2315,9 +2315,7 @@ async def lire_avoir(numero: str):
@app.post("/avoirs", status_code=201, tags=["Avoirs"])
async def creer_avoir(
avoir: AvoirCreateRequest, session: AsyncSession = Depends(get_session)
):
async def creer_avoir(avoir: AvoirCreate, session: AsyncSession = Depends(get_session)):
try:
avoir_data = {
"client_id": avoir.client_id,
@ -2364,7 +2362,7 @@ async def creer_avoir(
@app.put("/avoirs/{id}", tags=["Avoirs"])
async def modifier_avoir(
id: str,
avoir_update: AvoirUpdateRequest,
avoir_update: AvoirUpdate,
session: AsyncSession = Depends(get_session),
):
try:
@ -2434,7 +2432,7 @@ async def lire_livraison(numero: str):
@app.post("/livraisons", status_code=201, tags=["Livraisons"])
async def creer_livraison(
livraison: LivraisonCreateRequest, session: AsyncSession = Depends(get_session)
livraison: LivraisonCreate, session: AsyncSession = Depends(get_session)
):
try:
livraison_data = {
@ -2488,7 +2486,7 @@ async def creer_livraison(
@app.put("/livraisons/{id}", tags=["Livraisons"])
async def modifier_livraison(
id: str,
livraison_update: LivraisonUpdateRequest,
livraison_update: LivraisonUpdate,
session: AsyncSession = Depends(get_session),
):
try:
@ -2694,7 +2692,7 @@ async def commande_vers_livraison(
@app.get(
"/familles",
response_model=List[FamilleResponse],
response_model=List[Familles],
tags=["Familles"],
summary="Liste toutes les familles d'articles",
)
@ -2706,7 +2704,7 @@ async def lister_familles(
logger.info(f"{len(familles)} famille(s) retournée(s)")
return [FamilleResponse(**f) for f in familles]
return [Familles(**f) for f in familles]
except Exception as e:
logger.error(f"Erreur liste familles: {e}", exc_info=True)
@ -2718,7 +2716,7 @@ async def lister_familles(
@app.get(
"/familles/{code}",
response_model=FamilleResponse,
response_model=Familles,
tags=["Familles"],
summary="Lecture d'une famille par son code",
)
@ -2737,7 +2735,7 @@ async def lire_famille(
logger.info(f"Famille {code} lue: {famille.get('intitule', '')}")
return FamilleResponse(**famille)
return Familles(**famille)
except HTTPException:
raise
@ -2751,12 +2749,12 @@ async def lire_famille(
@app.post(
"/familles",
response_model=FamilleResponse,
response_model=Familles,
status_code=status.HTTP_201_CREATED,
tags=["Familles"],
summary="Création d'une famille d'articles",
)
async def creer_famille(famille: FamilleCreateRequest):
async def creer_famille(famille: FamilleCreate):
try:
if not famille.code or not famille.intitule:
raise HTTPException(
@ -2772,7 +2770,7 @@ async def creer_famille(famille: FamilleCreateRequest):
logger.info(f"Famille créée: {resultat.get('code')}")
return FamilleResponse(**resultat)
return Familles(**resultat)
except ValueError as e:
logger.warning(f"Erreur métier création famille: {e}")
@ -2791,12 +2789,12 @@ async def creer_famille(famille: FamilleCreateRequest):
@app.post(
"/stock/entree",
response_model=MouvementStockResponse,
response_model=MouvementStock,
status_code=status.HTTP_201_CREATED,
tags=["Stock"],
summary="ENTRÉE EN STOCK : Ajoute des articles dans le stock",
)
async def creer_entree_stock(entree: EntreeStockRequest):
async def creer_entree_stock(entree: EntreeStock):
try:
entree_data = entree.dict()
if entree_data.get("date_entree"):
@ -2808,7 +2806,7 @@ async def creer_entree_stock(entree: EntreeStockRequest):
logger.info(f"Entrée stock créée: {resultat.get('numero')}")
return MouvementStockResponse(**resultat)
return MouvementStock(**resultat)
except ValueError as e:
logger.warning(f"Erreur métier entrée stock: {e}")
@ -2824,12 +2822,12 @@ async def creer_entree_stock(entree: EntreeStockRequest):
@app.post(
"/stock/sortie",
response_model=MouvementStockResponse,
response_model=MouvementStock,
status_code=status.HTTP_201_CREATED,
tags=["Stock"],
summary="SORTIE DE STOCK : Retire des articles du stock",
)
async def creer_sortie_stock(sortie: SortieStockRequest):
async def creer_sortie_stock(sortie: SortieStock):
try:
sortie_data = sortie.dict()
if sortie_data.get("date_sortie"):
@ -2841,7 +2839,7 @@ async def creer_sortie_stock(sortie: SortieStockRequest):
logger.info(f"Sortie stock créée: {resultat.get('numero')}")
return MouvementStockResponse(**resultat)
return MouvementStock(**resultat)
except ValueError as e:
logger.warning(f"Erreur métier sortie stock: {e}")
@ -2857,7 +2855,7 @@ async def creer_sortie_stock(sortie: SortieStockRequest):
@app.get(
"/stock/mouvement/{numero}",
response_model=MouvementStockResponse,
response_model=MouvementStock,
tags=["Stock"],
summary="Lecture d'un mouvement de stock",
)
@ -2876,7 +2874,7 @@ async def lire_mouvement_stock(
logger.info(f"Mouvement {numero} lu")
return MouvementStockResponse(**mouvement)
return MouvementStock(**mouvement)
except HTTPException:
raise
@ -2907,7 +2905,7 @@ async def statistiques_familles():
)
@app.get("/debug/users", response_model=List[UserResponse], tags=["Debug"])
@app.get("/debug/users", response_model=List[Users], tags=["Debug"])
async def lister_utilisateurs_debug(
session: AsyncSession = Depends(get_session),
limit: int = Query(100, le=1000),
@ -2934,7 +2932,7 @@ async def lister_utilisateurs_debug(
users_response = []
for user in users:
users_response.append(
UserResponse(
Users(
id=user.id,
email=user.email,
nom=user.nom,

View file

@ -12,7 +12,7 @@ from schemas import (
SageGatewayCreate,
SageGatewayUpdate,
SageGatewayResponse,
SageGatewayListResponse,
SageGatewayList,
SageGatewayHealthCheck,
SageGatewayTestRequest,
SageGatewayStatsResponse,
@ -41,7 +41,7 @@ async def create_gateway(
return SageGatewayResponse(**gateway_response_from_model(gateway))
@router.get("", response_model=SageGatewayListResponse)
@router.get("", response_model=SageGatewayList)
async def list_gateways(
include_deleted: bool = Query(False, description="Inclure les gateways supprimées"),
session: AsyncSession = Depends(get_session),
@ -54,7 +54,7 @@ async def list_gateways(
items = [SageGatewayResponse(**gateway_response_from_model(g)) for g in gateways]
return SageGatewayListResponse(
return SageGatewayList(
items=items,
total=len(items),
active_gateway=SageGatewayResponse(**gateway_response_from_model(active))

View file

@ -1,52 +1,52 @@
from schemas.tiers.tiers import TiersDetails, TypeTiersInt
from schemas.tiers.type_tiers import TypeTiers
from schemas.schema_mixte import BaremeRemiseResponse
from schemas.user import UserResponse
from schemas.user import Users
from schemas.tiers.clients import (
ClientCreateRequest,
ClientCreate,
ClientDetails,
ClientResponse,
ClientUpdateRequest,
ClientUpdate,
)
from schemas.tiers.contact import Contact, ContactCreate, ContactUpdate
from schemas.tiers.fournisseurs import (
FournisseurCreateAPIRequest,
FournisseurCreate,
FournisseurDetails,
FournisseurUpdateRequest,
FournisseurUpdate,
)
from schemas.documents.avoirs import AvoirCreateRequest, AvoirUpdateRequest
from schemas.documents.commandes import CommandeCreateRequest, CommandeUpdateRequest
from schemas.documents.avoirs import AvoirCreate, AvoirUpdate
from schemas.documents.commandes import CommandeCreate, CommandeUpdate
from schemas.documents.devis import (
DevisRequest,
DevisResponse,
DevisUpdateRequest,
RelanceDevisRequest,
Devis,
DevisUpdate,
RelanceDevis,
)
from schemas.documents.documents import TypeDocument, TypeDocumentSQL
from schemas.documents.email import StatutEmail, EmailEnvoiRequest
from schemas.documents.factures import FactureCreateRequest, FactureUpdateRequest
from schemas.documents.livraisons import LivraisonCreateRequest, LivraisonUpdateRequest
from schemas.documents.universign import SignatureRequest, StatutSignature
from schemas.documents.email import StatutEmail, EmailEnvoi
from schemas.documents.factures import FactureCreate, FactureUpdate
from schemas.documents.livraisons import LivraisonCreate, LivraisonUpdate
from schemas.documents.universign import Signature, StatutSignature
from schemas.articles.articles import (
ArticleCreateRequest,
ArticleResponse,
ArticleUpdateRequest,
ArticleListResponse,
EntreeStockRequest,
SortieStockRequest,
MouvementStockResponse,
ArticleCreate,
Article,
ArticleUpdate,
ArticleList,
EntreeStock,
SortieStock,
MouvementStock,
)
from schemas.articles.famille_article import (
FamilleResponse,
FamilleCreateRequest,
FamilleListResponse,
Familles,
FamilleCreate,
FamilleList,
)
from schemas.sage.sage_gateway import (
SageGatewayCreate,
SageGatewayUpdate,
SageGatewayResponse,
SageGatewayListResponse,
SageGatewayList,
SageGatewayHealthCheck,
SageGatewayTestRequest,
SageGatewayStatsResponse,
@ -57,50 +57,50 @@ __all__ = [
"TiersDetails",
"TypeTiers",
"BaremeRemiseResponse",
"UserResponse",
"ClientCreateRequest",
"Users",
"ClientCreate",
"ClientDetails",
"ClientResponse",
"ClientUpdateRequest",
"FournisseurCreateAPIRequest",
"ClientUpdate",
"FournisseurCreate",
"FournisseurDetails",
"FournisseurUpdateRequest",
"FournisseurUpdate",
"Contact",
"AvoirCreateRequest",
"AvoirUpdateRequest",
"CommandeCreateRequest",
"CommandeUpdateRequest",
"AvoirCreate",
"AvoirUpdate",
"CommandeCreate",
"CommandeUpdate",
"DevisRequest",
"DevisResponse",
"DevisUpdateRequest",
"Devis",
"DevisUpdate",
"TypeDocument",
"TypeDocumentSQL",
"StatutEmail",
"EmailEnvoiRequest",
"FactureCreateRequest",
"FactureUpdateRequest",
"LivraisonCreateRequest",
"LivraisonUpdateRequest",
"SignatureRequest",
"EmailEnvoi",
"FactureCreate",
"FactureUpdate",
"LivraisonCreate",
"LivraisonUpdate",
"Signature",
"StatutSignature",
"TypeTiersInt",
"ArticleCreateRequest",
"ArticleResponse",
"ArticleUpdateRequest",
"ArticleListResponse",
"EntreeStockRequest",
"SortieStockRequest",
"MouvementStockResponse",
"RelanceDevisRequest",
"FamilleResponse",
"FamilleCreateRequest",
"FamilleListResponse",
"ArticleCreate",
"Article",
"ArticleUpdate",
"ArticleList",
"EntreeStock",
"SortieStock",
"MouvementStock",
"RelanceDevis",
"Familles",
"FamilleCreate",
"FamilleList",
"ContactCreate",
"ContactUpdate",
"SageGatewayCreate",
"SageGatewayUpdate",
"SageGatewayResponse",
"SageGatewayListResponse",
"SageGatewayList",
"SageGatewayHealthCheck",
"SageGatewayTestRequest",
"SageGatewayStatsResponse",

View file

@ -1,6 +1,6 @@
from pydantic import BaseModel, Field, validator, field_validator
from typing import List, Optional
from datetime import date, datetime
from datetime import date
from utils import (
NomenclatureType,
@ -10,364 +10,7 @@ from utils import (
normalize_string_field,
)
class EmplacementStockModel(BaseModel):
"""Détail du stock dans un emplacement spécifique"""
depot: str = Field(..., description="Numéro du dépôt (DE_No)")
emplacement: str = Field(..., description="Code emplacement (DP_No)")
qte_stockee: float = Field(0.0, description="Quantité stockée (AE_QteSto)")
qte_preparee: float = Field(0.0, description="Quantité préparée (AE_QtePrepa)")
qte_a_controler: float = Field(
0.0, description="Quantité à contrôler (AE_QteAControler)"
)
date_creation: Optional[datetime] = Field(None, description="Date création")
date_modification: Optional[datetime] = Field(None, description="Date modification")
depot_num: Optional[str] = Field(None, description="Numéro dépôt")
depot_nom: Optional[str] = Field(None, description="Nom du dépôt (DE_Intitule)")
depot_code: Optional[str] = Field(None, description="Code dépôt (DE_Code)")
depot_adresse: Optional[str] = Field(None, description="Adresse (DE_Adresse)")
depot_complement: Optional[str] = Field(None, description="Complément adresse")
depot_code_postal: Optional[str] = Field(None, description="Code postal")
depot_ville: Optional[str] = Field(None, description="Ville")
depot_contact: Optional[str] = Field(None, description="Contact")
depot_est_principal: Optional[bool] = Field(
None, description="Dépôt principal (DE_Principal)"
)
depot_categorie_compta: Optional[int] = Field(
None, description="Catégorie comptable"
)
depot_region: Optional[str] = Field(None, description="Région")
depot_pays: Optional[str] = Field(None, description="Pays")
depot_email: Optional[str] = Field(None, description="Email")
depot_telephone: Optional[str] = Field(None, description="Téléphone")
depot_fax: Optional[str] = Field(None, description="Fax")
depot_emplacement_defaut: Optional[str] = Field(
None, description="Emplacement par défaut"
)
depot_exclu: Optional[bool] = Field(None, description="Dépôt exclu")
emplacement_code: Optional[str] = Field(
None, description="Code emplacement (DP_Code)"
)
emplacement_libelle: Optional[str] = Field(
None, description="Libellé emplacement (DP_Intitule)"
)
emplacement_zone: Optional[str] = Field(None, description="Zone (DP_Zone)")
emplacement_type: Optional[int] = Field(
None, description="Type emplacement (DP_Type)"
)
class Config:
json_schema_extra = {
"example": {
"depot": "01",
"emplacement": "A1-01",
"qte_stockee": 100.0,
"qte_preparee": 5.0,
"depot_nom": "Dépôt principal",
"depot_ville": "Paris",
"emplacement_libelle": "Allée A, Niveau 1, Case 01",
"emplacement_zone": "Zone A",
}
}
class GammeArticleModel(BaseModel):
"""Gamme d'un article (taille, couleur, etc.)"""
numero_gamme: int = Field(..., description="Numéro de gamme (AG_No)")
enumere: str = Field(..., description="Code énuméré (EG_Enumere)")
type_gamme: int = Field(0, description="Type de gamme (AG_Type)")
date_creation: Optional[datetime] = Field(None, description="Date création")
date_modification: Optional[datetime] = Field(None, description="Date modification")
ligne: Optional[int] = Field(None, description="Ligne énuméré (EG_Ligne)")
borne_sup: Optional[float] = Field(
None, description="Borne supérieure (EG_BorneSup)"
)
gamme_nom: Optional[str] = Field(
None, description="Nom de la gamme (P_GAMME.G_Intitule)"
)
class Config:
json_schema_extra = {
"example": {
"numero_gamme": 1,
"enumere": "001",
"type_gamme": 0,
"ligne": 1,
"gamme_nom": "Taille",
}
}
class TarifClientModel(BaseModel):
"""Tarif spécifique pour un client ou catégorie tarifaire"""
categorie: int = Field(..., description="Catégorie tarifaire (AC_Categorie)")
client_num: Optional[str] = Field(None, description="Numéro client (CT_Num)")
prix_vente: float = Field(0.0, description="Prix de vente HT (AC_PrixVen)")
coefficient: float = Field(0.0, description="Coefficient (AC_Coef)")
prix_ttc: float = Field(0.0, description="Prix TTC (AC_PrixTTC)")
arrondi: float = Field(0.0, description="Arrondi (AC_Arrondi)")
qte_montant: float = Field(0.0, description="Quantité montant (AC_QteMont)")
enumere_gamme: int = Field(0, description="Énuméré gamme (EG_Champ)")
prix_devise: float = Field(0.0, description="Prix en devise (AC_PrixDev)")
devise: int = Field(0, description="Code devise (AC_Devise)")
remise: float = Field(0.0, description="Remise (AC_Remise)")
mode_calcul: int = Field(0, description="Mode de calcul (AC_Calcul)")
type_remise: int = Field(0, description="Type de remise (AC_TypeRem)")
ref_client: Optional[str] = Field(
None, description="Référence client (AC_RefClient)"
)
coef_nouveau: float = Field(0.0, description="Nouveau coefficient (AC_CoefNouv)")
prix_vente_nouveau: float = Field(
0.0, description="Nouveau prix vente (AC_PrixVenNouv)"
)
prix_devise_nouveau: float = Field(
0.0, description="Nouveau prix devise (AC_PrixDevNouv)"
)
remise_nouvelle: float = Field(0.0, description="Nouvelle remise (AC_RemiseNouv)")
date_application: Optional[datetime] = Field(
None, description="Date application (AC_DateApplication)"
)
date_creation: Optional[datetime] = Field(None, description="Date création")
date_modification: Optional[datetime] = Field(None, description="Date modification")
class Config:
json_schema_extra = {
"example": {
"categorie": 1,
"client_num": "CLI001",
"prix_vente": 110.00,
"coefficient": 1.294,
"remise": 12.0,
}
}
class ComposantModel(BaseModel):
"""Composant/Opération de nomenclature"""
operation: str = Field(..., description="Code opération (AT_Operation)")
code_ressource: Optional[str] = Field(None, description="Code ressource (RP_Code)")
temps: float = Field(0.0, description="Temps nécessaire (AT_Temps)")
type: int = Field(0, description="Type composant (AT_Type)")
description: Optional[str] = Field(None, description="Description (AT_Description)")
ordre: int = Field(0, description="Ordre d'exécution (AT_Ordre)")
gamme_1_comp: int = Field(0, description="Gamme 1 composant (AG_No1Comp)")
gamme_2_comp: int = Field(0, description="Gamme 2 composant (AG_No2Comp)")
type_ressource: int = Field(0, description="Type ressource (AT_TypeRessource)")
chevauche: int = Field(0, description="Chevauchement (AT_Chevauche)")
demarre: int = Field(0, description="Démarrage (AT_Demarre)")
operation_chevauche: Optional[str] = Field(
None, description="Opération chevauchée (AT_OperationChevauche)"
)
valeur_chevauche: float = Field(
0.0, description="Valeur chevauchement (AT_ValeurChevauche)"
)
type_chevauche: int = Field(0, description="Type chevauchement (AT_TypeChevauche)")
date_creation: Optional[datetime] = Field(None, description="Date création")
date_modification: Optional[datetime] = Field(None, description="Date modification")
class Config:
json_schema_extra = {
"example": {
"operation": "OP010",
"code_ressource": "RES01",
"temps": 15.5,
"description": "Montage pièce A",
"ordre": 10,
}
}
class ComptaArticleModel(BaseModel):
"""Comptabilité spécifique d'un article"""
champ: int = Field(..., description="Champ (ACP_Champ)")
compte_general: Optional[str] = Field(
None, description="Compte général (ACP_ComptaCPT_CompteG)"
)
compte_auxiliaire: Optional[str] = Field(
None, description="Compte auxiliaire (ACP_ComptaCPT_CompteA)"
)
taxe_1: Optional[str] = Field(None, description="Taxe 1 (ACP_ComptaCPT_Taxe1)")
taxe_2: Optional[str] = Field(None, description="Taxe 2 (ACP_ComptaCPT_Taxe2)")
taxe_3: Optional[str] = Field(None, description="Taxe 3 (ACP_ComptaCPT_Taxe3)")
taxe_date_1: Optional[datetime] = Field(None, description="Date taxe 1")
taxe_date_2: Optional[datetime] = Field(None, description="Date taxe 2")
taxe_date_3: Optional[datetime] = Field(None, description="Date taxe 3")
taxe_anc_1: Optional[str] = Field(None, description="Ancienne taxe 1")
taxe_anc_2: Optional[str] = Field(None, description="Ancienne taxe 2")
taxe_anc_3: Optional[str] = Field(None, description="Ancienne taxe 3")
type_facture: int = Field(0, description="Type de facture (ACP_TypeFacture)")
date_creation: Optional[datetime] = Field(None, description="Date création")
date_modification: Optional[datetime] = Field(None, description="Date modification")
class Config:
json_schema_extra = {
"example": {
"champ": 1,
"compte_general": "707100",
"taxe_1": "TVA20",
"type_facture": 0,
}
}
class FournisseurArticleModel(BaseModel):
"""Fournisseur d'un article"""
fournisseur_num: str = Field(..., description="Numéro fournisseur (CT_Num)")
ref_fournisseur: Optional[str] = Field(
None, description="Référence fournisseur (AF_RefFourniss)"
)
prix_achat: float = Field(0.0, description="Prix d'achat (AF_PrixAch)")
unite: Optional[str] = Field(None, description="Unité (AF_Unite)")
conversion: float = Field(0.0, description="Conversion (AF_Conversion)")
delai_appro: int = Field(0, description="Délai approvisionnement (AF_DelaiAppro)")
garantie: int = Field(0, description="Garantie (AF_Garantie)")
colisage: int = Field(0, description="Colisage (AF_Colisage)")
qte_mini: float = Field(0.0, description="Quantité minimum (AF_QteMini)")
qte_montant: float = Field(0.0, description="Quantité montant (AF_QteMont)")
enumere_gamme: int = Field(0, description="Énuméré gamme (EG_Champ)")
est_principal: bool = Field(
False, description="Fournisseur principal (AF_Principal)"
)
prix_devise: float = Field(0.0, description="Prix devise (AF_PrixDev)")
devise: int = Field(0, description="Code devise (AF_Devise)")
remise: float = Field(0.0, description="Remise (AF_Remise)")
conversion_devise: float = Field(0.0, description="Conversion devise (AF_ConvDiv)")
type_remise: int = Field(0, description="Type remise (AF_TypeRem)")
code_barre_fournisseur: Optional[str] = Field(
None, description="Code-barres fournisseur (AF_CodeBarre)"
)
prix_achat_nouveau: float = Field(
0.0, description="Nouveau prix achat (AF_PrixAchNouv)"
)
prix_devise_nouveau: float = Field(
0.0, description="Nouveau prix devise (AF_PrixDevNouv)"
)
remise_nouvelle: float = Field(0.0, description="Nouvelle remise (AF_RemiseNouv)")
date_application: Optional[datetime] = Field(
None, description="Date application (AF_DateApplication)"
)
date_creation: Optional[datetime] = Field(None, description="Date création")
date_modification: Optional[datetime] = Field(None, description="Date modification")
class Config:
json_schema_extra = {
"example": {
"fournisseur_num": "F001",
"ref_fournisseur": "REF-FOURN-001",
"prix_achat": 85.00,
"delai_appro": 15,
"est_principal": True,
}
}
class ReferenceEnumereeModel(BaseModel):
"""Référence énumérée (article avec gammes)"""
gamme_1: int = Field(0, description="Gamme 1 (AG_No1)")
gamme_2: int = Field(0, description="Gamme 2 (AG_No2)")
reference_enumeree: str = Field(..., description="Référence énumérée (AE_Ref)")
prix_achat: float = Field(0.0, description="Prix achat (AE_PrixAch)")
code_barre: Optional[str] = Field(None, description="Code-barres (AE_CodeBarre)")
prix_achat_nouveau: float = Field(
0.0, description="Nouveau prix achat (AE_PrixAchNouv)"
)
edi_code: Optional[str] = Field(None, description="Code EDI (AE_EdiCode)")
en_sommeil: bool = Field(False, description="En sommeil (AE_Sommeil)")
date_creation: Optional[datetime] = Field(None, description="Date création")
date_modification: Optional[datetime] = Field(None, description="Date modification")
class Config:
json_schema_extra = {
"example": {
"gamme_1": 1,
"gamme_2": 3,
"reference_enumeree": "ART001-T1-C3",
"prix_achat": 85.00,
}
}
class MediaArticleModel(BaseModel):
"""Média attaché à un article (photo, document, etc.)"""
commentaire: Optional[str] = Field(None, description="Commentaire (ME_Commentaire)")
fichier: Optional[str] = Field(None, description="Nom fichier (ME_Fichier)")
type_mime: Optional[str] = Field(None, description="Type MIME (ME_TypeMIME)")
origine: int = Field(0, description="Origine (ME_Origine)")
ged_id: Optional[str] = Field(None, description="ID GED (ME_GedId)")
date_creation: Optional[datetime] = Field(None, description="Date création")
date_modification: Optional[datetime] = Field(None, description="Date modification")
class Config:
json_schema_extra = {
"example": {
"commentaire": "Photo produit principale",
"fichier": "ART001_photo1.jpg",
"type_mime": "image/jpeg",
}
}
class PrixGammeModel(BaseModel):
"""Prix spécifique par combinaison de gammes"""
gamme_1: int = Field(0, description="Gamme 1 (AG_No1)")
gamme_2: int = Field(0, description="Gamme 2 (AG_No2)")
prix_net: float = Field(0.0, description="Prix net (AR_PUNet)")
cout_standard: float = Field(0.0, description="Coût standard (AR_CoutStd)")
date_creation: Optional[datetime] = Field(None, description="Date création")
date_modification: Optional[datetime] = Field(None, description="Date modification")
class Config:
json_schema_extra = {
"example": {
"gamme_1": 1,
"gamme_2": 3,
"prix_net": 125.50,
"cout_standard": 82.30,
}
}
class ArticleResponse(BaseModel):
class Article(BaseModel):
"""Article complet avec tous les enrichissements disponibles"""
reference: str = Field(..., description="Référence article (AR_Ref)")
@ -763,11 +406,11 @@ class ArticleResponse(BaseModel):
}
class ArticleListResponse(BaseModel):
class ArticleList(BaseModel):
"""Réponse pour une liste d'articles"""
total: int = Field(..., description="Nombre total d'articles")
articles: List[ArticleResponse] = Field(..., description="Liste des articles")
articles: List[Article] = Field(..., description="Liste des articles")
filtre_applique: Optional[str] = Field(
None, description="Filtre de recherche appliqué"
)
@ -780,7 +423,7 @@ class ArticleListResponse(BaseModel):
)
class ArticleCreateRequest(BaseModel):
class ArticleCreate(BaseModel):
"""Schéma pour création d'article"""
reference: str = Field(..., max_length=18, description="Référence article")
@ -796,7 +439,7 @@ class ArticleCreateRequest(BaseModel):
description: Optional[str] = Field(None, description="Description")
class ArticleUpdateRequest(BaseModel):
class ArticleUpdate(BaseModel):
"""Schéma pour modification d'article"""
designation: Optional[str] = Field(None, max_length=69)
@ -810,7 +453,7 @@ class ArticleUpdateRequest(BaseModel):
description: Optional[str] = Field(None)
class MouvementStockLigneRequest(BaseModel):
class MouvementStockLigne(BaseModel):
article_ref: str = Field(..., description="Référence de l'article")
quantite: float = Field(..., gt=0, description="Quantité (>0)")
depot_code: Optional[str] = Field(None, description="Code du dépôt (ex: '01')")
@ -864,7 +507,7 @@ class MouvementStockLigneRequest(BaseModel):
return v
class EntreeStockRequest(BaseModel):
class EntreeStock(BaseModel):
"""Création d'un bon d'entrée en stock"""
date_entree: Optional[date] = Field(
@ -874,7 +517,7 @@ class EntreeStockRequest(BaseModel):
depot_code: Optional[str] = Field(
None, description="Dépôt principal (si applicable)"
)
lignes: List[MouvementStockLigneRequest] = Field(
lignes: List[MouvementStockLigne] = Field(
..., min_items=1, description="Lignes du mouvement"
)
commentaire: Optional[str] = Field(None, description="Commentaire général")
@ -899,7 +542,7 @@ class EntreeStockRequest(BaseModel):
}
class SortieStockRequest(BaseModel):
class SortieStock(BaseModel):
"""Création d'un bon de sortie de stock"""
date_sortie: Optional[date] = Field(
@ -909,7 +552,7 @@ class SortieStockRequest(BaseModel):
depot_code: Optional[str] = Field(
None, description="Dépôt principal (si applicable)"
)
lignes: List[MouvementStockLigneRequest] = Field(
lignes: List[MouvementStockLigne] = Field(
..., min_items=1, description="Lignes du mouvement"
)
commentaire: Optional[str] = Field(None, description="Commentaire général")
@ -933,7 +576,7 @@ class SortieStockRequest(BaseModel):
}
class MouvementStockResponse(BaseModel):
class MouvementStock(BaseModel):
"""Réponse pour un mouvement de stock"""
article_ref: str = Field(..., description="Numéro d'article")

View file

@ -2,7 +2,7 @@ from pydantic import BaseModel, Field
from typing import Optional
class FamilleCreateRequest(BaseModel):
class FamilleCreate(BaseModel):
"""Schéma pour création de famille d'articles"""
code: str = Field(..., max_length=18, description="Code famille (max 18 car)")
@ -27,7 +27,7 @@ class FamilleCreateRequest(BaseModel):
}
class FamilleResponse(BaseModel):
class Familles(BaseModel):
"""Modèle complet d'une famille avec données comptables et fournisseur"""
code: str = Field(..., description="Code famille")
@ -236,10 +236,10 @@ class FamilleResponse(BaseModel):
}
class FamilleListResponse(BaseModel):
class FamilleList(BaseModel):
"""Réponse pour la liste des familles"""
familles: list[FamilleResponse]
familles: list[Familles]
total: int
filtre: Optional[str] = None
inclure_totaux: bool = True

View file

@ -13,7 +13,7 @@ class LigneAvoir(BaseModel):
return v.replace("\xa0", "").strip()
class AvoirCreateRequest(BaseModel):
class AvoirCreate(BaseModel):
client_id: str
date_avoir: Optional[date] = None
date_livraison: Optional[date] = None
@ -38,7 +38,7 @@ class AvoirCreateRequest(BaseModel):
}
class AvoirUpdateRequest(BaseModel):
class AvoirUpdate(BaseModel):
date_avoir: Optional[date] = None
date_livraison: Optional[date] = None
lignes: Optional[List[LigneAvoir]] = None

View file

@ -13,7 +13,7 @@ class LigneCommande(BaseModel):
return v.replace("\xa0", "").strip()
class CommandeCreateRequest(BaseModel):
class CommandeCreate(BaseModel):
client_id: str
date_commande: Optional[date] = None
date_livraison: Optional[date] = None
@ -38,7 +38,7 @@ class CommandeCreateRequest(BaseModel):
}
class CommandeUpdateRequest(BaseModel):
class CommandeUpdate(BaseModel):
date_commande: Optional[date] = None
date_livraison: Optional[date] = None
lignes: Optional[List[LigneCommande]] = None

View file

@ -21,7 +21,7 @@ class DevisRequest(BaseModel):
lignes: List[LigneDevis]
class DevisResponse(BaseModel):
class Devis(BaseModel):
id: str
client_id: str
date_devis: str
@ -30,7 +30,7 @@ class DevisResponse(BaseModel):
nb_lignes: int
class DevisUpdateRequest(BaseModel):
class DevisUpdate(BaseModel):
"""Modèle pour modification d'un devis existant"""
date_devis: Optional[date] = None
@ -58,6 +58,6 @@ class DevisUpdateRequest(BaseModel):
}
class RelanceDevisRequest(BaseModel):
class RelanceDevis(BaseModel):
doc_id: str
message_personnalise: Optional[str] = None

View file

@ -13,7 +13,7 @@ class StatutEmail(str, Enum):
BOUNCE = "BOUNCE"
class EmailEnvoiRequest(BaseModel):
class EmailEnvoi(BaseModel):
destinataire: EmailStr
cc: Optional[List[EmailStr]] = []
cci: Optional[List[EmailStr]] = []

View file

@ -13,7 +13,7 @@ class LigneFacture(BaseModel):
return v.replace("\xa0", "").strip()
class FactureCreateRequest(BaseModel):
class FactureCreate(BaseModel):
client_id: str
date_facture: Optional[date] = None
date_livraison: Optional[date] = None
@ -38,7 +38,7 @@ class FactureCreateRequest(BaseModel):
}
class FactureUpdateRequest(BaseModel):
class FactureUpdate(BaseModel):
date_facture: Optional[date] = None
date_livraison: Optional[date] = None
lignes: Optional[List[LigneFacture]] = None

View file

@ -13,7 +13,7 @@ class LigneLivraison(BaseModel):
return v.replace("\xa0", "").strip()
class LivraisonCreateRequest(BaseModel):
class LivraisonCreate(BaseModel):
client_id: str
date_livraison: Optional[date] = None
date_livraison_prevue: Optional[date] = None
@ -38,7 +38,7 @@ class LivraisonCreateRequest(BaseModel):
}
class LivraisonUpdateRequest(BaseModel):
class LivraisonUpdate(BaseModel):
date_livraison: Optional[date] = None
date_livraison_prevue: Optional[date] = None
lignes: Optional[List[LigneLivraison]] = None

View file

@ -11,7 +11,7 @@ class StatutSignature(str, Enum):
EXPIRE = "EXPIRE"
class SignatureRequest(BaseModel):
class Signature(BaseModel):
doc_id: str
type_doc: TypeDocument
email_signataire: EmailStr

View file

@ -110,7 +110,7 @@ class SageGatewayResponse(BaseModel):
from_attributes = True
class SageGatewayListResponse(BaseModel):
class SageGatewayList(BaseModel):
items: List[SageGatewayResponse]
total: int

View file

@ -277,7 +277,7 @@ class ClientDetails(BaseModel):
}
class ClientCreateRequest(BaseModel):
class ClientCreate(BaseModel):
intitule: str = Field(
..., max_length=69, description="Nom du client (CT_Intitule) - OBLIGATOIRE"
)
@ -679,7 +679,7 @@ class ClientCreateRequest(BaseModel):
}
class ClientUpdateRequest(BaseModel):
class ClientUpdate(BaseModel):
intitule: Optional[str] = Field(None, max_length=69)
qualite: Optional[str] = Field(None, max_length=17)
classement: Optional[str] = Field(None, max_length=17)

View file

@ -267,7 +267,7 @@ class FournisseurDetails(BaseModel):
}
class FournisseurCreateAPIRequest(BaseModel):
class FournisseurCreate(BaseModel):
intitule: str = Field(
..., min_length=1, max_length=69, description="Raison sociale du fournisseur"
)
@ -304,7 +304,7 @@ class FournisseurCreateAPIRequest(BaseModel):
}
class FournisseurUpdateRequest(BaseModel):
class FournisseurUpdate(BaseModel):
intitule: Optional[str] = Field(None, min_length=1, max_length=69)
adresse: Optional[str] = Field(None, max_length=35)
code_postal: Optional[str] = Field(None, max_length=9)

View file

@ -2,7 +2,7 @@ from pydantic import BaseModel
from typing import Optional
class UserResponse(BaseModel):
class Users(BaseModel):
id: str
email: str
nom: str