refactor(schemas): rename response and request models to simpler names
This commit is contained in:
parent
e3b0f7e44a
commit
306c71b43d
16 changed files with 194 additions and 553 deletions
206
api.py
206
api.py
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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))
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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")
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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]] = []
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ class SageGatewayResponse(BaseModel):
|
|||
from_attributes = True
|
||||
|
||||
|
||||
class SageGatewayListResponse(BaseModel):
|
||||
class SageGatewayList(BaseModel):
|
||||
|
||||
items: List[SageGatewayResponse]
|
||||
total: int
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ from pydantic import BaseModel
|
|||
from typing import Optional
|
||||
|
||||
|
||||
class UserResponse(BaseModel):
|
||||
class Users(BaseModel):
|
||||
id: str
|
||||
email: str
|
||||
nom: str
|
||||
|
|
|
|||
Loading…
Reference in a new issue