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,
|
async_session_factory,
|
||||||
get_session,
|
get_session,
|
||||||
EmailLog,
|
EmailLog,
|
||||||
StatutEmail as StatutEmailEnum,
|
StatutEmail as StatutEmailDB,
|
||||||
WorkflowLog,
|
WorkflowLog,
|
||||||
SignatureLog,
|
SignatureLog,
|
||||||
StatutSignature as StatutSignatureEnum,
|
StatutSignature as StatutSignatureDB,
|
||||||
)
|
)
|
||||||
from email_queue import email_queue
|
from email_queue import email_queue
|
||||||
from sage_client import sage_client, SageGatewayClient
|
from sage_client import sage_client, SageGatewayClient
|
||||||
|
|
@ -34,45 +34,44 @@ from sage_client import sage_client, SageGatewayClient
|
||||||
from schemas import (
|
from schemas import (
|
||||||
TiersDetails,
|
TiersDetails,
|
||||||
BaremeRemiseResponse,
|
BaremeRemiseResponse,
|
||||||
UserResponse,
|
Users,
|
||||||
ClientCreateRequest,
|
ClientCreate,
|
||||||
ClientDetails,
|
ClientDetails,
|
||||||
ClientUpdateRequest,
|
ClientUpdate,
|
||||||
FournisseurCreateAPIRequest,
|
FournisseurCreate,
|
||||||
FournisseurDetails,
|
FournisseurDetails,
|
||||||
FournisseurUpdateRequest,
|
FournisseurUpdate,
|
||||||
Contact,
|
Contact,
|
||||||
AvoirCreateRequest,
|
AvoirCreate,
|
||||||
AvoirUpdateRequest,
|
AvoirUpdate,
|
||||||
CommandeCreateRequest,
|
CommandeCreate,
|
||||||
CommandeUpdateRequest,
|
CommandeUpdate,
|
||||||
DevisRequest,
|
DevisRequest,
|
||||||
DevisResponse,
|
Devis,
|
||||||
DevisUpdateRequest,
|
DevisUpdate,
|
||||||
TypeDocument,
|
TypeDocument,
|
||||||
TypeDocumentSQL,
|
TypeDocumentSQL,
|
||||||
StatutEmail,
|
StatutEmail,
|
||||||
EmailEnvoiRequest,
|
EmailEnvoi,
|
||||||
FactureCreateRequest,
|
FactureCreate,
|
||||||
FactureUpdateRequest,
|
FactureUpdate,
|
||||||
LivraisonCreateRequest,
|
LivraisonCreate,
|
||||||
LivraisonUpdateRequest,
|
LivraisonUpdate,
|
||||||
SignatureRequest,
|
Signature,
|
||||||
StatutSignature,
|
StatutSignature,
|
||||||
ArticleCreateRequest,
|
ArticleCreate,
|
||||||
ArticleResponse,
|
Article,
|
||||||
ArticleUpdateRequest,
|
ArticleUpdate,
|
||||||
EntreeStockRequest,
|
EntreeStock,
|
||||||
SortieStockRequest,
|
SortieStock,
|
||||||
MouvementStockResponse,
|
MouvementStock,
|
||||||
RelanceDevisRequest,
|
RelanceDevis,
|
||||||
FamilleResponse,
|
Familles,
|
||||||
FamilleCreateRequest,
|
FamilleCreate,
|
||||||
ContactCreate,
|
ContactCreate,
|
||||||
ContactUpdate,
|
ContactUpdate,
|
||||||
)
|
)
|
||||||
from utils.normalization import normaliser_type_tiers
|
from utils.normalization import normaliser_type_tiers
|
||||||
|
|
||||||
from routes.sage_gateway import router as sage_gateway_router
|
from routes.sage_gateway import router as sage_gateway_router
|
||||||
from core.sage_context import (
|
from core.sage_context import (
|
||||||
get_sage_client_for_user,
|
get_sage_client_for_user,
|
||||||
|
|
@ -80,6 +79,7 @@ from core.sage_context import (
|
||||||
GatewayContext,
|
GatewayContext,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
if os.path.exists("/app"):
|
if os.path.exists("/app"):
|
||||||
LOGS_DIR = FilePath("/app/logs")
|
LOGS_DIR = FilePath("/app/logs")
|
||||||
else:
|
else:
|
||||||
|
|
@ -264,7 +264,7 @@ async def universign_envoyer(
|
||||||
corps_html=corps,
|
corps_html=corps,
|
||||||
document_ids=doc_id,
|
document_ids=doc_id,
|
||||||
type_document=doc_data.get("type_doc"),
|
type_document=doc_data.get("type_doc"),
|
||||||
statut=StatutEmailEnum.EN_ATTENTE,
|
statut=StatutEmailDB.EN_ATTENTE,
|
||||||
date_creation=datetime.now(),
|
date_creation=datetime.now(),
|
||||||
nb_tentatives=0,
|
nb_tentatives=0,
|
||||||
)
|
)
|
||||||
|
|
@ -347,7 +347,7 @@ async def lire_client_detail(code: str):
|
||||||
@app.put("/clients/{code}", tags=["Clients"])
|
@app.put("/clients/{code}", tags=["Clients"])
|
||||||
async def modifier_client(
|
async def modifier_client(
|
||||||
code: str,
|
code: str,
|
||||||
client_update: ClientUpdateRequest,
|
client_update: ClientUpdate,
|
||||||
session: AsyncSession = Depends(get_session),
|
session: AsyncSession = Depends(get_session),
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
|
|
@ -373,7 +373,7 @@ async def modifier_client(
|
||||||
|
|
||||||
@app.post("/clients", status_code=201, tags=["Clients"])
|
@app.post("/clients", status_code=201, tags=["Clients"])
|
||||||
async def ajouter_client(
|
async def ajouter_client(
|
||||||
client: ClientCreateRequest, session: AsyncSession = Depends(get_session)
|
client: ClientCreate, session: AsyncSession = Depends(get_session)
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
nouveau_client = sage_client.creer_client(client.model_dump(mode="json"))
|
nouveau_client = sage_client.creer_client(client.model_dump(mode="json"))
|
||||||
|
|
@ -394,11 +394,11 @@ async def ajouter_client(
|
||||||
raise HTTPException(status, str(e))
|
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)):
|
async def rechercher_articles(query: Optional[str] = Query(None)):
|
||||||
try:
|
try:
|
||||||
articles = sage_client.lister_articles(filtre=query or "")
|
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:
|
except Exception as e:
|
||||||
logger.error(f"Erreur recherche articles: {e}")
|
logger.error(f"Erreur recherche articles: {e}")
|
||||||
raise HTTPException(500, str(e))
|
raise HTTPException(500, str(e))
|
||||||
|
|
@ -406,11 +406,11 @@ async def rechercher_articles(query: Optional[str] = Query(None)):
|
||||||
|
|
||||||
@app.post(
|
@app.post(
|
||||||
"/articles",
|
"/articles",
|
||||||
response_model=ArticleResponse,
|
response_model=Article,
|
||||||
status_code=status.HTTP_201_CREATED,
|
status_code=status.HTTP_201_CREATED,
|
||||||
tags=["Articles"],
|
tags=["Articles"],
|
||||||
)
|
)
|
||||||
async def creer_article(article: ArticleCreateRequest):
|
async def creer_article(article: ArticleCreate):
|
||||||
try:
|
try:
|
||||||
if not article.reference or not article.designation:
|
if not article.reference or not article.designation:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -428,7 +428,7 @@ async def creer_article(article: ArticleCreateRequest):
|
||||||
f"Article créé: {resultat.get('reference')} (stock: {resultat.get('stock_reel', 0)})"
|
f"Article créé: {resultat.get('reference')} (stock: {resultat.get('stock_reel', 0)})"
|
||||||
)
|
)
|
||||||
|
|
||||||
return ArticleResponse(**resultat)
|
return Article(**resultat)
|
||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logger.warning(f"Erreur métier création article: {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(
|
async def modifier_article(
|
||||||
reference: str = Path(..., description="Référence de l'article à modifier"),
|
reference: str = Path(..., description="Référence de l'article à modifier"),
|
||||||
article: ArticleUpdateRequest = Body(...),
|
article: ArticleUpdate = Body(...),
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
article_data = article.dict(exclude_unset=True)
|
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)")
|
logger.info(f"Article {reference} modifié ({len(article_data)} champs)")
|
||||||
|
|
||||||
return ArticleResponse(**resultat)
|
return Article(**resultat)
|
||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logger.warning(f"Erreur métier modification article: {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(
|
async def lire_article(
|
||||||
reference: str = Path(..., description="Référence de l'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', '')}")
|
logger.info(f"Article {reference} lu: {article.get('designation', '')}")
|
||||||
|
|
||||||
return ArticleResponse(**article)
|
return Article(**article)
|
||||||
|
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
raise
|
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):
|
async def creer_devis(devis: DevisRequest):
|
||||||
try:
|
try:
|
||||||
devis_data = {
|
devis_data = {
|
||||||
|
|
@ -540,7 +540,7 @@ async def creer_devis(devis: DevisRequest):
|
||||||
|
|
||||||
logger.info(f"Devis créé: {resultat.get('numero_devis')}")
|
logger.info(f"Devis créé: {resultat.get('numero_devis')}")
|
||||||
|
|
||||||
return DevisResponse(
|
return Devis(
|
||||||
id=resultat["numero_devis"],
|
id=resultat["numero_devis"],
|
||||||
client_id=devis.client_id,
|
client_id=devis.client_id,
|
||||||
date_devis=resultat["date_devis"],
|
date_devis=resultat["date_devis"],
|
||||||
|
|
@ -557,7 +557,7 @@ async def creer_devis(devis: DevisRequest):
|
||||||
@app.put("/devis/{id}", tags=["Devis"])
|
@app.put("/devis/{id}", tags=["Devis"])
|
||||||
async def modifier_devis(
|
async def modifier_devis(
|
||||||
id: str,
|
id: str,
|
||||||
devis_update: DevisUpdateRequest,
|
devis_update: DevisUpdate,
|
||||||
session: AsyncSession = Depends(get_session),
|
session: AsyncSession = Depends(get_session),
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
|
|
@ -601,7 +601,7 @@ async def modifier_devis(
|
||||||
|
|
||||||
@app.post("/commandes", status_code=201, tags=["Commandes"])
|
@app.post("/commandes", status_code=201, tags=["Commandes"])
|
||||||
async def creer_commande(
|
async def creer_commande(
|
||||||
commande: CommandeCreateRequest, session: AsyncSession = Depends(get_session)
|
commande: CommandeCreate, session: AsyncSession = Depends(get_session)
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
commande_data = {
|
commande_data = {
|
||||||
|
|
@ -651,7 +651,7 @@ async def creer_commande(
|
||||||
@app.put("/commandes/{id}", tags=["Commandes"])
|
@app.put("/commandes/{id}", tags=["Commandes"])
|
||||||
async def modifier_commande(
|
async def modifier_commande(
|
||||||
id: str,
|
id: str,
|
||||||
commande_update: CommandeUpdateRequest,
|
commande_update: CommandeUpdate,
|
||||||
session: AsyncSession = Depends(get_session),
|
session: AsyncSession = Depends(get_session),
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
|
|
@ -803,7 +803,7 @@ async def telecharger_document_pdf(
|
||||||
|
|
||||||
@app.post("/devis/{id}/envoyer", tags=["Devis"])
|
@app.post("/devis/{id}/envoyer", tags=["Devis"])
|
||||||
async def envoyer_devis_email(
|
async def envoyer_devis_email(
|
||||||
id: str, request: EmailEnvoiRequest, session: AsyncSession = Depends(get_session)
|
id: str, request: EmailEnvoi, session: AsyncSession = Depends(get_session)
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
tous_destinataires = [request.destinataire] + request.cc + request.cci
|
tous_destinataires = [request.destinataire] + request.cc + request.cci
|
||||||
|
|
@ -817,7 +817,7 @@ async def envoyer_devis_email(
|
||||||
corps_html=request.corps_html,
|
corps_html=request.corps_html,
|
||||||
document_ids=id,
|
document_ids=id,
|
||||||
type_document=TypeDocument.DEVIS,
|
type_document=TypeDocument.DEVIS,
|
||||||
statut=StatutEmailEnum.EN_ATTENTE,
|
statut=StatutEmailDB.EN_ATTENTE,
|
||||||
date_creation=datetime.now(),
|
date_creation=datetime.now(),
|
||||||
nb_tentatives=0,
|
nb_tentatives=0,
|
||||||
)
|
)
|
||||||
|
|
@ -1089,7 +1089,7 @@ def normaliser_type_doc(type_doc: int) -> int:
|
||||||
|
|
||||||
@app.post("/signature/universign/send", tags=["Signatures"])
|
@app.post("/signature/universign/send", tags=["Signatures"])
|
||||||
async def envoyer_signature_optimise(
|
async def envoyer_signature_optimise(
|
||||||
demande: SignatureRequest, session: AsyncSession = Depends(get_session)
|
demande: Signature, session: AsyncSession = Depends(get_session)
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
doc = sage_client.lire_document(
|
doc = sage_client.lire_document(
|
||||||
|
|
@ -1135,7 +1135,7 @@ async def envoyer_signature_optimise(
|
||||||
signer_url=resultat["signer_url"],
|
signer_url=resultat["signer_url"],
|
||||||
email_signataire=demande.email_signataire,
|
email_signataire=demande.email_signataire,
|
||||||
nom_signataire=demande.nom_signataire,
|
nom_signataire=demande.nom_signataire,
|
||||||
statut=StatutSignatureEnum.ENVOYE,
|
statut=StatutSignatureDB.ENVOYE,
|
||||||
date_envoi=datetime.now(),
|
date_envoi=datetime.now(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -1191,7 +1191,7 @@ async def webhook_universign(
|
||||||
return {"status": "not_found"}
|
return {"status": "not_found"}
|
||||||
|
|
||||||
if event_type == "transaction.completed":
|
if event_type == "transaction.completed":
|
||||||
signature_log.statut = StatutSignatureEnum.SIGNE
|
signature_log.statut = StatutSignatureDB.SIGNE
|
||||||
signature_log.date_signature = datetime.now()
|
signature_log.date_signature = datetime.now()
|
||||||
|
|
||||||
logger.info(f"Signature confirmée: {signature_log.document_id}")
|
logger.info(f"Signature confirmée: {signature_log.document_id}")
|
||||||
|
|
@ -1229,7 +1229,7 @@ async def webhook_universign(
|
||||||
corps_html=corps,
|
corps_html=corps,
|
||||||
document_ids=signature_log.document_id,
|
document_ids=signature_log.document_id,
|
||||||
type_document=signature_log.type_document,
|
type_document=signature_log.type_document,
|
||||||
statut=StatutEmailEnum.EN_ATTENTE,
|
statut=StatutEmailDB.EN_ATTENTE,
|
||||||
date_creation=datetime.now(),
|
date_creation=datetime.now(),
|
||||||
nb_tentatives=0,
|
nb_tentatives=0,
|
||||||
)
|
)
|
||||||
|
|
@ -1242,11 +1242,11 @@ async def webhook_universign(
|
||||||
)
|
)
|
||||||
|
|
||||||
elif event_type == "transaction.refused":
|
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}")
|
logger.warning(f"Signature refusée: {signature_log.document_id}")
|
||||||
|
|
||||||
elif event_type == "transaction.expired":
|
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}")
|
logger.warning(f"⏰ Transaction expirée: {signature_log.document_id}")
|
||||||
|
|
||||||
await session.commit()
|
await session.commit()
|
||||||
|
|
@ -1271,7 +1271,7 @@ async def relancer_signatures_automatique(session: AsyncSession = Depends(get_se
|
||||||
|
|
||||||
query = select(SignatureLog).where(
|
query = select(SignatureLog).where(
|
||||||
SignatureLog.statut.in_(
|
SignatureLog.statut.in_(
|
||||||
[StatutSignatureEnum.EN_ATTENTE, StatutSignatureEnum.ENVOYE]
|
[StatutSignatureDB.EN_ATTENTE, StatutSignatureDB.ENVOYE]
|
||||||
),
|
),
|
||||||
SignatureLog.date_envoi < date_limite,
|
SignatureLog.date_envoi < date_limite,
|
||||||
SignatureLog.nb_relances < 3, # Max 3 relances
|
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
|
jours_restants = 30 - nb_jours # Lien expire après 30 jours
|
||||||
|
|
||||||
if jours_restants <= 0:
|
if jours_restants <= 0:
|
||||||
signature.statut = StatutSignatureEnum.EXPIRE
|
signature.statut = StatutSignatureDB.EXPIRE
|
||||||
continue
|
continue
|
||||||
|
|
||||||
template = templates_signature_email["relance_signature"]
|
template = templates_signature_email["relance_signature"]
|
||||||
|
|
@ -1325,7 +1325,7 @@ async def relancer_signatures_automatique(session: AsyncSession = Depends(get_se
|
||||||
corps_html=corps,
|
corps_html=corps,
|
||||||
document_ids=signature.document_id,
|
document_ids=signature.document_id,
|
||||||
type_document=signature.type_document,
|
type_document=signature.type_document,
|
||||||
statut=StatutEmailEnum.EN_ATTENTE,
|
statut=StatutEmailDB.EN_ATTENTE,
|
||||||
date_creation=datetime.now(),
|
date_creation=datetime.now(),
|
||||||
nb_tentatives=0,
|
nb_tentatives=0,
|
||||||
)
|
)
|
||||||
|
|
@ -1394,7 +1394,7 @@ async def lister_signatures(
|
||||||
query = select(SignatureLog).order_by(SignatureLog.date_envoi.desc())
|
query = select(SignatureLog).order_by(SignatureLog.date_envoi.desc())
|
||||||
|
|
||||||
if statut:
|
if statut:
|
||||||
statut_db = StatutSignatureEnum[statut.value]
|
statut_db = StatutSignatureDB[statut.value]
|
||||||
query = query.where(SignatureLog.statut == statut_db)
|
query = query.where(SignatureLog.statut == statut_db)
|
||||||
|
|
||||||
query = query.limit(limit)
|
query = query.limit(limit)
|
||||||
|
|
@ -1437,15 +1437,15 @@ async def statut_signature_detail(
|
||||||
|
|
||||||
if statut_universign.get("statut") != "ERREUR":
|
if statut_universign.get("statut") != "ERREUR":
|
||||||
statut_map = {
|
statut_map = {
|
||||||
"EN_ATTENTE": StatutSignatureEnum.EN_ATTENTE,
|
"EN_ATTENTE": StatutSignatureDB.EN_ATTENTE,
|
||||||
"ENVOYE": StatutSignatureEnum.ENVOYE,
|
"ENVOYE": StatutSignatureDB.ENVOYE,
|
||||||
"SIGNE": StatutSignatureEnum.SIGNE,
|
"SIGNE": StatutSignatureDB.SIGNE,
|
||||||
"REFUSE": StatutSignatureEnum.REFUSE,
|
"REFUSE": StatutSignatureDB.REFUSE,
|
||||||
"EXPIRE": StatutSignatureEnum.EXPIRE,
|
"EXPIRE": StatutSignatureDB.EXPIRE,
|
||||||
}
|
}
|
||||||
|
|
||||||
nouveau_statut = statut_map.get(
|
nouveau_statut = statut_map.get(
|
||||||
statut_universign["statut"], StatutSignatureEnum.EN_ATTENTE
|
statut_universign["statut"], StatutSignatureDB.EN_ATTENTE
|
||||||
)
|
)
|
||||||
|
|
||||||
signature_log.statut = nouveau_statut
|
signature_log.statut = nouveau_statut
|
||||||
|
|
@ -1478,7 +1478,7 @@ async def statut_signature_detail(
|
||||||
async def rafraichir_statuts_signatures(session: AsyncSession = Depends(get_session)):
|
async def rafraichir_statuts_signatures(session: AsyncSession = Depends(get_session)):
|
||||||
query = select(SignatureLog).where(
|
query = select(SignatureLog).where(
|
||||||
SignatureLog.statut.in_(
|
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":
|
if statut_universign.get("statut") != "ERREUR":
|
||||||
statut_map = {
|
statut_map = {
|
||||||
"SIGNE": StatutSignatureEnum.SIGNE,
|
"SIGNE": StatutSignatureDB.SIGNE,
|
||||||
"REFUSE": StatutSignatureEnum.REFUSE,
|
"REFUSE": StatutSignatureDB.REFUSE,
|
||||||
"EXPIRE": StatutSignatureEnum.EXPIRE,
|
"EXPIRE": StatutSignatureDB.EXPIRE,
|
||||||
}
|
}
|
||||||
|
|
||||||
nouveau = statut_map.get(statut_universign["statut"])
|
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"])
|
@app.post("/devis/{id}/signer", tags=["Devis"])
|
||||||
async def envoyer_devis_signature(
|
async def envoyer_devis_signature(
|
||||||
id: str, request: SignatureRequest, session: AsyncSession = Depends(get_session)
|
id: str, request: Signature, session: AsyncSession = Depends(get_session)
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
devis = sage_client.lire_devis(id)
|
devis = sage_client.lire_devis(id)
|
||||||
|
|
@ -1548,7 +1548,7 @@ async def envoyer_devis_signature(
|
||||||
signer_url=resultat["signer_url"],
|
signer_url=resultat["signer_url"],
|
||||||
email_signataire=request.email_signataire,
|
email_signataire=request.email_signataire,
|
||||||
nom_signataire=request.nom_signataire,
|
nom_signataire=request.nom_signataire,
|
||||||
statut=StatutSignatureEnum.ENVOYE,
|
statut=StatutSignatureDB.ENVOYE,
|
||||||
date_envoi=datetime.now(),
|
date_envoi=datetime.now(),
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -1594,7 +1594,7 @@ async def envoyer_emails_lot(
|
||||||
corps_html=batch.corps_html,
|
corps_html=batch.corps_html,
|
||||||
document_ids=",".join(batch.document_ids) if batch.document_ids else None,
|
document_ids=",".join(batch.document_ids) if batch.document_ids else None,
|
||||||
type_document=batch.type_document,
|
type_document=batch.type_document,
|
||||||
statut=StatutEmailEnum.EN_ATTENTE,
|
statut=StatutEmailDB.EN_ATTENTE,
|
||||||
date_creation=datetime.now(),
|
date_creation=datetime.now(),
|
||||||
nb_tentatives=0,
|
nb_tentatives=0,
|
||||||
)
|
)
|
||||||
|
|
@ -1663,7 +1663,7 @@ async def valider_remise(
|
||||||
|
|
||||||
@app.post("/devis/{id}/relancer-signature", tags=["Devis"])
|
@app.post("/devis/{id}/relancer-signature", tags=["Devis"])
|
||||||
async def relancer_devis_signature(
|
async def relancer_devis_signature(
|
||||||
id: str, relance: RelanceDevisRequest, session: AsyncSession = Depends(get_session)
|
id: str, relance: RelanceDevis, session: AsyncSession = Depends(get_session)
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
devis = sage_client.lire_devis(id)
|
devis = sage_client.lire_devis(id)
|
||||||
|
|
@ -1694,7 +1694,7 @@ async def relancer_devis_signature(
|
||||||
signer_url=resultat["signer_url"],
|
signer_url=resultat["signer_url"],
|
||||||
email_signataire=contact["email"],
|
email_signataire=contact["email"],
|
||||||
nom_signataire=contact["nom"] or contact["client_intitule"],
|
nom_signataire=contact["nom"] or contact["client_intitule"],
|
||||||
statut=StatutSignatureEnum.ENVOYE,
|
statut=StatutSignatureDB.ENVOYE,
|
||||||
date_envoi=datetime.now(),
|
date_envoi=datetime.now(),
|
||||||
est_relance=True,
|
est_relance=True,
|
||||||
nb_relances=1,
|
nb_relances=1,
|
||||||
|
|
@ -1786,7 +1786,7 @@ class RelanceFactureRequest(BaseModel):
|
||||||
|
|
||||||
@app.post("/factures", status_code=201, tags=["Factures"])
|
@app.post("/factures", status_code=201, tags=["Factures"])
|
||||||
async def creer_facture(
|
async def creer_facture(
|
||||||
facture: FactureCreateRequest, session: AsyncSession = Depends(get_session)
|
facture: FactureCreate, session: AsyncSession = Depends(get_session)
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
facture_data = {
|
facture_data = {
|
||||||
|
|
@ -1836,7 +1836,7 @@ async def creer_facture(
|
||||||
@app.put("/factures/{id}", tags=["Factures"])
|
@app.put("/factures/{id}", tags=["Factures"])
|
||||||
async def modifier_facture(
|
async def modifier_facture(
|
||||||
id: str,
|
id: str,
|
||||||
facture_update: FactureUpdateRequest,
|
facture_update: FactureUpdate,
|
||||||
session: AsyncSession = Depends(get_session),
|
session: AsyncSession = Depends(get_session),
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
|
|
@ -1940,7 +1940,7 @@ async def relancer_facture(
|
||||||
corps_html=corps,
|
corps_html=corps,
|
||||||
document_ids=id,
|
document_ids=id,
|
||||||
type_document=TypeDocument.FACTURE,
|
type_document=TypeDocument.FACTURE,
|
||||||
statut=StatutEmailEnum.EN_ATTENTE,
|
statut=StatutEmailDB.EN_ATTENTE,
|
||||||
date_creation=datetime.now(),
|
date_creation=datetime.now(),
|
||||||
nb_tentatives=0,
|
nb_tentatives=0,
|
||||||
)
|
)
|
||||||
|
|
@ -1979,7 +1979,7 @@ async def journal_emails(
|
||||||
query = select(EmailLog)
|
query = select(EmailLog)
|
||||||
|
|
||||||
if statut:
|
if statut:
|
||||||
query = query.where(EmailLog.statut == StatutEmailEnum[statut.value])
|
query = query.where(EmailLog.statut == StatutEmailDB[statut.value])
|
||||||
|
|
||||||
if destinataire:
|
if destinataire:
|
||||||
query = query.where(EmailLog.destinataire.contains(destinataire))
|
query = query.where(EmailLog.destinataire.contains(destinataire))
|
||||||
|
|
@ -2012,7 +2012,7 @@ async def exporter_logs_csv(
|
||||||
):
|
):
|
||||||
query = select(EmailLog)
|
query = select(EmailLog)
|
||||||
if statut:
|
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())
|
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"])
|
@app.post("/fournisseurs", status_code=201, tags=["Fournisseurs"])
|
||||||
async def ajouter_fournisseur(
|
async def ajouter_fournisseur(
|
||||||
fournisseur: FournisseurCreateAPIRequest,
|
fournisseur: FournisseurCreate,
|
||||||
session: AsyncSession = Depends(get_session),
|
session: AsyncSession = Depends(get_session),
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
|
|
@ -2254,7 +2254,7 @@ async def ajouter_fournisseur(
|
||||||
)
|
)
|
||||||
async def modifier_fournisseur(
|
async def modifier_fournisseur(
|
||||||
code: str,
|
code: str,
|
||||||
fournisseur_update: FournisseurUpdateRequest,
|
fournisseur_update: FournisseurUpdate,
|
||||||
session: AsyncSession = Depends(get_session),
|
session: AsyncSession = Depends(get_session),
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
|
|
@ -2315,9 +2315,7 @@ async def lire_avoir(numero: str):
|
||||||
|
|
||||||
|
|
||||||
@app.post("/avoirs", status_code=201, tags=["Avoirs"])
|
@app.post("/avoirs", status_code=201, tags=["Avoirs"])
|
||||||
async def creer_avoir(
|
async def creer_avoir(avoir: AvoirCreate, session: AsyncSession = Depends(get_session)):
|
||||||
avoir: AvoirCreateRequest, session: AsyncSession = Depends(get_session)
|
|
||||||
):
|
|
||||||
try:
|
try:
|
||||||
avoir_data = {
|
avoir_data = {
|
||||||
"client_id": avoir.client_id,
|
"client_id": avoir.client_id,
|
||||||
|
|
@ -2364,7 +2362,7 @@ async def creer_avoir(
|
||||||
@app.put("/avoirs/{id}", tags=["Avoirs"])
|
@app.put("/avoirs/{id}", tags=["Avoirs"])
|
||||||
async def modifier_avoir(
|
async def modifier_avoir(
|
||||||
id: str,
|
id: str,
|
||||||
avoir_update: AvoirUpdateRequest,
|
avoir_update: AvoirUpdate,
|
||||||
session: AsyncSession = Depends(get_session),
|
session: AsyncSession = Depends(get_session),
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
|
|
@ -2434,7 +2432,7 @@ async def lire_livraison(numero: str):
|
||||||
|
|
||||||
@app.post("/livraisons", status_code=201, tags=["Livraisons"])
|
@app.post("/livraisons", status_code=201, tags=["Livraisons"])
|
||||||
async def creer_livraison(
|
async def creer_livraison(
|
||||||
livraison: LivraisonCreateRequest, session: AsyncSession = Depends(get_session)
|
livraison: LivraisonCreate, session: AsyncSession = Depends(get_session)
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
livraison_data = {
|
livraison_data = {
|
||||||
|
|
@ -2488,7 +2486,7 @@ async def creer_livraison(
|
||||||
@app.put("/livraisons/{id}", tags=["Livraisons"])
|
@app.put("/livraisons/{id}", tags=["Livraisons"])
|
||||||
async def modifier_livraison(
|
async def modifier_livraison(
|
||||||
id: str,
|
id: str,
|
||||||
livraison_update: LivraisonUpdateRequest,
|
livraison_update: LivraisonUpdate,
|
||||||
session: AsyncSession = Depends(get_session),
|
session: AsyncSession = Depends(get_session),
|
||||||
):
|
):
|
||||||
try:
|
try:
|
||||||
|
|
@ -2694,7 +2692,7 @@ async def commande_vers_livraison(
|
||||||
|
|
||||||
@app.get(
|
@app.get(
|
||||||
"/familles",
|
"/familles",
|
||||||
response_model=List[FamilleResponse],
|
response_model=List[Familles],
|
||||||
tags=["Familles"],
|
tags=["Familles"],
|
||||||
summary="Liste toutes les familles d'articles",
|
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)")
|
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:
|
except Exception as e:
|
||||||
logger.error(f"Erreur liste familles: {e}", exc_info=True)
|
logger.error(f"Erreur liste familles: {e}", exc_info=True)
|
||||||
|
|
@ -2718,7 +2716,7 @@ async def lister_familles(
|
||||||
|
|
||||||
@app.get(
|
@app.get(
|
||||||
"/familles/{code}",
|
"/familles/{code}",
|
||||||
response_model=FamilleResponse,
|
response_model=Familles,
|
||||||
tags=["Familles"],
|
tags=["Familles"],
|
||||||
summary="Lecture d'une famille par son code",
|
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', '')}")
|
logger.info(f"Famille {code} lue: {famille.get('intitule', '')}")
|
||||||
|
|
||||||
return FamilleResponse(**famille)
|
return Familles(**famille)
|
||||||
|
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
raise
|
raise
|
||||||
|
|
@ -2751,12 +2749,12 @@ async def lire_famille(
|
||||||
|
|
||||||
@app.post(
|
@app.post(
|
||||||
"/familles",
|
"/familles",
|
||||||
response_model=FamilleResponse,
|
response_model=Familles,
|
||||||
status_code=status.HTTP_201_CREATED,
|
status_code=status.HTTP_201_CREATED,
|
||||||
tags=["Familles"],
|
tags=["Familles"],
|
||||||
summary="Création d'une famille d'articles",
|
summary="Création d'une famille d'articles",
|
||||||
)
|
)
|
||||||
async def creer_famille(famille: FamilleCreateRequest):
|
async def creer_famille(famille: FamilleCreate):
|
||||||
try:
|
try:
|
||||||
if not famille.code or not famille.intitule:
|
if not famille.code or not famille.intitule:
|
||||||
raise HTTPException(
|
raise HTTPException(
|
||||||
|
|
@ -2772,7 +2770,7 @@ async def creer_famille(famille: FamilleCreateRequest):
|
||||||
|
|
||||||
logger.info(f"Famille créée: {resultat.get('code')}")
|
logger.info(f"Famille créée: {resultat.get('code')}")
|
||||||
|
|
||||||
return FamilleResponse(**resultat)
|
return Familles(**resultat)
|
||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logger.warning(f"Erreur métier création famille: {e}")
|
logger.warning(f"Erreur métier création famille: {e}")
|
||||||
|
|
@ -2791,12 +2789,12 @@ async def creer_famille(famille: FamilleCreateRequest):
|
||||||
|
|
||||||
@app.post(
|
@app.post(
|
||||||
"/stock/entree",
|
"/stock/entree",
|
||||||
response_model=MouvementStockResponse,
|
response_model=MouvementStock,
|
||||||
status_code=status.HTTP_201_CREATED,
|
status_code=status.HTTP_201_CREATED,
|
||||||
tags=["Stock"],
|
tags=["Stock"],
|
||||||
summary="ENTRÉE EN STOCK : Ajoute des articles dans le 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:
|
try:
|
||||||
entree_data = entree.dict()
|
entree_data = entree.dict()
|
||||||
if entree_data.get("date_entree"):
|
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')}")
|
logger.info(f"Entrée stock créée: {resultat.get('numero')}")
|
||||||
|
|
||||||
return MouvementStockResponse(**resultat)
|
return MouvementStock(**resultat)
|
||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logger.warning(f"Erreur métier entrée stock: {e}")
|
logger.warning(f"Erreur métier entrée stock: {e}")
|
||||||
|
|
@ -2824,12 +2822,12 @@ async def creer_entree_stock(entree: EntreeStockRequest):
|
||||||
|
|
||||||
@app.post(
|
@app.post(
|
||||||
"/stock/sortie",
|
"/stock/sortie",
|
||||||
response_model=MouvementStockResponse,
|
response_model=MouvementStock,
|
||||||
status_code=status.HTTP_201_CREATED,
|
status_code=status.HTTP_201_CREATED,
|
||||||
tags=["Stock"],
|
tags=["Stock"],
|
||||||
summary="SORTIE DE STOCK : Retire des articles du 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:
|
try:
|
||||||
sortie_data = sortie.dict()
|
sortie_data = sortie.dict()
|
||||||
if sortie_data.get("date_sortie"):
|
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')}")
|
logger.info(f"Sortie stock créée: {resultat.get('numero')}")
|
||||||
|
|
||||||
return MouvementStockResponse(**resultat)
|
return MouvementStock(**resultat)
|
||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logger.warning(f"Erreur métier sortie stock: {e}")
|
logger.warning(f"Erreur métier sortie stock: {e}")
|
||||||
|
|
@ -2857,7 +2855,7 @@ async def creer_sortie_stock(sortie: SortieStockRequest):
|
||||||
|
|
||||||
@app.get(
|
@app.get(
|
||||||
"/stock/mouvement/{numero}",
|
"/stock/mouvement/{numero}",
|
||||||
response_model=MouvementStockResponse,
|
response_model=MouvementStock,
|
||||||
tags=["Stock"],
|
tags=["Stock"],
|
||||||
summary="Lecture d'un mouvement de stock",
|
summary="Lecture d'un mouvement de stock",
|
||||||
)
|
)
|
||||||
|
|
@ -2876,7 +2874,7 @@ async def lire_mouvement_stock(
|
||||||
|
|
||||||
logger.info(f"Mouvement {numero} lu")
|
logger.info(f"Mouvement {numero} lu")
|
||||||
|
|
||||||
return MouvementStockResponse(**mouvement)
|
return MouvementStock(**mouvement)
|
||||||
|
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
raise
|
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(
|
async def lister_utilisateurs_debug(
|
||||||
session: AsyncSession = Depends(get_session),
|
session: AsyncSession = Depends(get_session),
|
||||||
limit: int = Query(100, le=1000),
|
limit: int = Query(100, le=1000),
|
||||||
|
|
@ -2934,7 +2932,7 @@ async def lister_utilisateurs_debug(
|
||||||
users_response = []
|
users_response = []
|
||||||
for user in users:
|
for user in users:
|
||||||
users_response.append(
|
users_response.append(
|
||||||
UserResponse(
|
Users(
|
||||||
id=user.id,
|
id=user.id,
|
||||||
email=user.email,
|
email=user.email,
|
||||||
nom=user.nom,
|
nom=user.nom,
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ from schemas import (
|
||||||
SageGatewayCreate,
|
SageGatewayCreate,
|
||||||
SageGatewayUpdate,
|
SageGatewayUpdate,
|
||||||
SageGatewayResponse,
|
SageGatewayResponse,
|
||||||
SageGatewayListResponse,
|
SageGatewayList,
|
||||||
SageGatewayHealthCheck,
|
SageGatewayHealthCheck,
|
||||||
SageGatewayTestRequest,
|
SageGatewayTestRequest,
|
||||||
SageGatewayStatsResponse,
|
SageGatewayStatsResponse,
|
||||||
|
|
@ -41,7 +41,7 @@ async def create_gateway(
|
||||||
return SageGatewayResponse(**gateway_response_from_model(gateway))
|
return SageGatewayResponse(**gateway_response_from_model(gateway))
|
||||||
|
|
||||||
|
|
||||||
@router.get("", response_model=SageGatewayListResponse)
|
@router.get("", response_model=SageGatewayList)
|
||||||
async def list_gateways(
|
async def list_gateways(
|
||||||
include_deleted: bool = Query(False, description="Inclure les gateways supprimées"),
|
include_deleted: bool = Query(False, description="Inclure les gateways supprimées"),
|
||||||
session: AsyncSession = Depends(get_session),
|
session: AsyncSession = Depends(get_session),
|
||||||
|
|
@ -54,7 +54,7 @@ async def list_gateways(
|
||||||
|
|
||||||
items = [SageGatewayResponse(**gateway_response_from_model(g)) for g in gateways]
|
items = [SageGatewayResponse(**gateway_response_from_model(g)) for g in gateways]
|
||||||
|
|
||||||
return SageGatewayListResponse(
|
return SageGatewayList(
|
||||||
items=items,
|
items=items,
|
||||||
total=len(items),
|
total=len(items),
|
||||||
active_gateway=SageGatewayResponse(**gateway_response_from_model(active))
|
active_gateway=SageGatewayResponse(**gateway_response_from_model(active))
|
||||||
|
|
|
||||||
|
|
@ -1,52 +1,52 @@
|
||||||
from schemas.tiers.tiers import TiersDetails, TypeTiersInt
|
from schemas.tiers.tiers import TiersDetails, TypeTiersInt
|
||||||
from schemas.tiers.type_tiers import TypeTiers
|
from schemas.tiers.type_tiers import TypeTiers
|
||||||
from schemas.schema_mixte import BaremeRemiseResponse
|
from schemas.schema_mixte import BaremeRemiseResponse
|
||||||
from schemas.user import UserResponse
|
from schemas.user import Users
|
||||||
from schemas.tiers.clients import (
|
from schemas.tiers.clients import (
|
||||||
ClientCreateRequest,
|
ClientCreate,
|
||||||
ClientDetails,
|
ClientDetails,
|
||||||
ClientResponse,
|
ClientResponse,
|
||||||
ClientUpdateRequest,
|
ClientUpdate,
|
||||||
)
|
)
|
||||||
from schemas.tiers.contact import Contact, ContactCreate, ContactUpdate
|
from schemas.tiers.contact import Contact, ContactCreate, ContactUpdate
|
||||||
from schemas.tiers.fournisseurs import (
|
from schemas.tiers.fournisseurs import (
|
||||||
FournisseurCreateAPIRequest,
|
FournisseurCreate,
|
||||||
FournisseurDetails,
|
FournisseurDetails,
|
||||||
FournisseurUpdateRequest,
|
FournisseurUpdate,
|
||||||
)
|
)
|
||||||
from schemas.documents.avoirs import AvoirCreateRequest, AvoirUpdateRequest
|
from schemas.documents.avoirs import AvoirCreate, AvoirUpdate
|
||||||
from schemas.documents.commandes import CommandeCreateRequest, CommandeUpdateRequest
|
from schemas.documents.commandes import CommandeCreate, CommandeUpdate
|
||||||
from schemas.documents.devis import (
|
from schemas.documents.devis import (
|
||||||
DevisRequest,
|
DevisRequest,
|
||||||
DevisResponse,
|
Devis,
|
||||||
DevisUpdateRequest,
|
DevisUpdate,
|
||||||
RelanceDevisRequest,
|
RelanceDevis,
|
||||||
)
|
)
|
||||||
from schemas.documents.documents import TypeDocument, TypeDocumentSQL
|
from schemas.documents.documents import TypeDocument, TypeDocumentSQL
|
||||||
from schemas.documents.email import StatutEmail, EmailEnvoiRequest
|
from schemas.documents.email import StatutEmail, EmailEnvoi
|
||||||
from schemas.documents.factures import FactureCreateRequest, FactureUpdateRequest
|
from schemas.documents.factures import FactureCreate, FactureUpdate
|
||||||
from schemas.documents.livraisons import LivraisonCreateRequest, LivraisonUpdateRequest
|
from schemas.documents.livraisons import LivraisonCreate, LivraisonUpdate
|
||||||
from schemas.documents.universign import SignatureRequest, StatutSignature
|
from schemas.documents.universign import Signature, StatutSignature
|
||||||
from schemas.articles.articles import (
|
from schemas.articles.articles import (
|
||||||
ArticleCreateRequest,
|
ArticleCreate,
|
||||||
ArticleResponse,
|
Article,
|
||||||
ArticleUpdateRequest,
|
ArticleUpdate,
|
||||||
ArticleListResponse,
|
ArticleList,
|
||||||
EntreeStockRequest,
|
EntreeStock,
|
||||||
SortieStockRequest,
|
SortieStock,
|
||||||
MouvementStockResponse,
|
MouvementStock,
|
||||||
)
|
)
|
||||||
from schemas.articles.famille_article import (
|
from schemas.articles.famille_article import (
|
||||||
FamilleResponse,
|
Familles,
|
||||||
FamilleCreateRequest,
|
FamilleCreate,
|
||||||
FamilleListResponse,
|
FamilleList,
|
||||||
)
|
)
|
||||||
|
|
||||||
from schemas.sage.sage_gateway import (
|
from schemas.sage.sage_gateway import (
|
||||||
SageGatewayCreate,
|
SageGatewayCreate,
|
||||||
SageGatewayUpdate,
|
SageGatewayUpdate,
|
||||||
SageGatewayResponse,
|
SageGatewayResponse,
|
||||||
SageGatewayListResponse,
|
SageGatewayList,
|
||||||
SageGatewayHealthCheck,
|
SageGatewayHealthCheck,
|
||||||
SageGatewayTestRequest,
|
SageGatewayTestRequest,
|
||||||
SageGatewayStatsResponse,
|
SageGatewayStatsResponse,
|
||||||
|
|
@ -57,50 +57,50 @@ __all__ = [
|
||||||
"TiersDetails",
|
"TiersDetails",
|
||||||
"TypeTiers",
|
"TypeTiers",
|
||||||
"BaremeRemiseResponse",
|
"BaremeRemiseResponse",
|
||||||
"UserResponse",
|
"Users",
|
||||||
"ClientCreateRequest",
|
"ClientCreate",
|
||||||
"ClientDetails",
|
"ClientDetails",
|
||||||
"ClientResponse",
|
"ClientResponse",
|
||||||
"ClientUpdateRequest",
|
"ClientUpdate",
|
||||||
"FournisseurCreateAPIRequest",
|
"FournisseurCreate",
|
||||||
"FournisseurDetails",
|
"FournisseurDetails",
|
||||||
"FournisseurUpdateRequest",
|
"FournisseurUpdate",
|
||||||
"Contact",
|
"Contact",
|
||||||
"AvoirCreateRequest",
|
"AvoirCreate",
|
||||||
"AvoirUpdateRequest",
|
"AvoirUpdate",
|
||||||
"CommandeCreateRequest",
|
"CommandeCreate",
|
||||||
"CommandeUpdateRequest",
|
"CommandeUpdate",
|
||||||
"DevisRequest",
|
"DevisRequest",
|
||||||
"DevisResponse",
|
"Devis",
|
||||||
"DevisUpdateRequest",
|
"DevisUpdate",
|
||||||
"TypeDocument",
|
"TypeDocument",
|
||||||
"TypeDocumentSQL",
|
"TypeDocumentSQL",
|
||||||
"StatutEmail",
|
"StatutEmail",
|
||||||
"EmailEnvoiRequest",
|
"EmailEnvoi",
|
||||||
"FactureCreateRequest",
|
"FactureCreate",
|
||||||
"FactureUpdateRequest",
|
"FactureUpdate",
|
||||||
"LivraisonCreateRequest",
|
"LivraisonCreate",
|
||||||
"LivraisonUpdateRequest",
|
"LivraisonUpdate",
|
||||||
"SignatureRequest",
|
"Signature",
|
||||||
"StatutSignature",
|
"StatutSignature",
|
||||||
"TypeTiersInt",
|
"TypeTiersInt",
|
||||||
"ArticleCreateRequest",
|
"ArticleCreate",
|
||||||
"ArticleResponse",
|
"Article",
|
||||||
"ArticleUpdateRequest",
|
"ArticleUpdate",
|
||||||
"ArticleListResponse",
|
"ArticleList",
|
||||||
"EntreeStockRequest",
|
"EntreeStock",
|
||||||
"SortieStockRequest",
|
"SortieStock",
|
||||||
"MouvementStockResponse",
|
"MouvementStock",
|
||||||
"RelanceDevisRequest",
|
"RelanceDevis",
|
||||||
"FamilleResponse",
|
"Familles",
|
||||||
"FamilleCreateRequest",
|
"FamilleCreate",
|
||||||
"FamilleListResponse",
|
"FamilleList",
|
||||||
"ContactCreate",
|
"ContactCreate",
|
||||||
"ContactUpdate",
|
"ContactUpdate",
|
||||||
"SageGatewayCreate",
|
"SageGatewayCreate",
|
||||||
"SageGatewayUpdate",
|
"SageGatewayUpdate",
|
||||||
"SageGatewayResponse",
|
"SageGatewayResponse",
|
||||||
"SageGatewayListResponse",
|
"SageGatewayList",
|
||||||
"SageGatewayHealthCheck",
|
"SageGatewayHealthCheck",
|
||||||
"SageGatewayTestRequest",
|
"SageGatewayTestRequest",
|
||||||
"SageGatewayStatsResponse",
|
"SageGatewayStatsResponse",
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from pydantic import BaseModel, Field, validator, field_validator
|
from pydantic import BaseModel, Field, validator, field_validator
|
||||||
from typing import List, Optional
|
from typing import List, Optional
|
||||||
from datetime import date, datetime
|
from datetime import date
|
||||||
|
|
||||||
from utils import (
|
from utils import (
|
||||||
NomenclatureType,
|
NomenclatureType,
|
||||||
|
|
@ -10,364 +10,7 @@ from utils import (
|
||||||
normalize_string_field,
|
normalize_string_field,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
class Article(BaseModel):
|
||||||
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):
|
|
||||||
"""Article complet avec tous les enrichissements disponibles"""
|
"""Article complet avec tous les enrichissements disponibles"""
|
||||||
|
|
||||||
reference: str = Field(..., description="Référence article (AR_Ref)")
|
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"""
|
"""Réponse pour une liste d'articles"""
|
||||||
|
|
||||||
total: int = Field(..., description="Nombre total 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(
|
filtre_applique: Optional[str] = Field(
|
||||||
None, description="Filtre de recherche appliqué"
|
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"""
|
"""Schéma pour création d'article"""
|
||||||
|
|
||||||
reference: str = Field(..., max_length=18, description="Référence 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")
|
description: Optional[str] = Field(None, description="Description")
|
||||||
|
|
||||||
|
|
||||||
class ArticleUpdateRequest(BaseModel):
|
class ArticleUpdate(BaseModel):
|
||||||
"""Schéma pour modification d'article"""
|
"""Schéma pour modification d'article"""
|
||||||
|
|
||||||
designation: Optional[str] = Field(None, max_length=69)
|
designation: Optional[str] = Field(None, max_length=69)
|
||||||
|
|
@ -810,7 +453,7 @@ class ArticleUpdateRequest(BaseModel):
|
||||||
description: Optional[str] = Field(None)
|
description: Optional[str] = Field(None)
|
||||||
|
|
||||||
|
|
||||||
class MouvementStockLigneRequest(BaseModel):
|
class MouvementStockLigne(BaseModel):
|
||||||
article_ref: str = Field(..., description="Référence de l'article")
|
article_ref: str = Field(..., description="Référence de l'article")
|
||||||
quantite: float = Field(..., gt=0, description="Quantité (>0)")
|
quantite: float = Field(..., gt=0, description="Quantité (>0)")
|
||||||
depot_code: Optional[str] = Field(None, description="Code du dépôt (ex: '01')")
|
depot_code: Optional[str] = Field(None, description="Code du dépôt (ex: '01')")
|
||||||
|
|
@ -864,7 +507,7 @@ class MouvementStockLigneRequest(BaseModel):
|
||||||
return v
|
return v
|
||||||
|
|
||||||
|
|
||||||
class EntreeStockRequest(BaseModel):
|
class EntreeStock(BaseModel):
|
||||||
"""Création d'un bon d'entrée en stock"""
|
"""Création d'un bon d'entrée en stock"""
|
||||||
|
|
||||||
date_entree: Optional[date] = Field(
|
date_entree: Optional[date] = Field(
|
||||||
|
|
@ -874,7 +517,7 @@ class EntreeStockRequest(BaseModel):
|
||||||
depot_code: Optional[str] = Field(
|
depot_code: Optional[str] = Field(
|
||||||
None, description="Dépôt principal (si applicable)"
|
None, description="Dépôt principal (si applicable)"
|
||||||
)
|
)
|
||||||
lignes: List[MouvementStockLigneRequest] = Field(
|
lignes: List[MouvementStockLigne] = Field(
|
||||||
..., min_items=1, description="Lignes du mouvement"
|
..., min_items=1, description="Lignes du mouvement"
|
||||||
)
|
)
|
||||||
commentaire: Optional[str] = Field(None, description="Commentaire général")
|
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"""
|
"""Création d'un bon de sortie de stock"""
|
||||||
|
|
||||||
date_sortie: Optional[date] = Field(
|
date_sortie: Optional[date] = Field(
|
||||||
|
|
@ -909,7 +552,7 @@ class SortieStockRequest(BaseModel):
|
||||||
depot_code: Optional[str] = Field(
|
depot_code: Optional[str] = Field(
|
||||||
None, description="Dépôt principal (si applicable)"
|
None, description="Dépôt principal (si applicable)"
|
||||||
)
|
)
|
||||||
lignes: List[MouvementStockLigneRequest] = Field(
|
lignes: List[MouvementStockLigne] = Field(
|
||||||
..., min_items=1, description="Lignes du mouvement"
|
..., min_items=1, description="Lignes du mouvement"
|
||||||
)
|
)
|
||||||
commentaire: Optional[str] = Field(None, description="Commentaire général")
|
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"""
|
"""Réponse pour un mouvement de stock"""
|
||||||
|
|
||||||
article_ref: str = Field(..., description="Numéro d'article")
|
article_ref: str = Field(..., description="Numéro d'article")
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ from pydantic import BaseModel, Field
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
class FamilleCreateRequest(BaseModel):
|
class FamilleCreate(BaseModel):
|
||||||
"""Schéma pour création de famille d'articles"""
|
"""Schéma pour création de famille d'articles"""
|
||||||
|
|
||||||
code: str = Field(..., max_length=18, description="Code famille (max 18 car)")
|
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"""
|
"""Modèle complet d'une famille avec données comptables et fournisseur"""
|
||||||
|
|
||||||
code: str = Field(..., description="Code famille")
|
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"""
|
"""Réponse pour la liste des familles"""
|
||||||
|
|
||||||
familles: list[FamilleResponse]
|
familles: list[Familles]
|
||||||
total: int
|
total: int
|
||||||
filtre: Optional[str] = None
|
filtre: Optional[str] = None
|
||||||
inclure_totaux: bool = True
|
inclure_totaux: bool = True
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ class LigneAvoir(BaseModel):
|
||||||
return v.replace("\xa0", "").strip()
|
return v.replace("\xa0", "").strip()
|
||||||
|
|
||||||
|
|
||||||
class AvoirCreateRequest(BaseModel):
|
class AvoirCreate(BaseModel):
|
||||||
client_id: str
|
client_id: str
|
||||||
date_avoir: Optional[date] = None
|
date_avoir: Optional[date] = None
|
||||||
date_livraison: 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_avoir: Optional[date] = None
|
||||||
date_livraison: Optional[date] = None
|
date_livraison: Optional[date] = None
|
||||||
lignes: Optional[List[LigneAvoir]] = None
|
lignes: Optional[List[LigneAvoir]] = None
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ class LigneCommande(BaseModel):
|
||||||
return v.replace("\xa0", "").strip()
|
return v.replace("\xa0", "").strip()
|
||||||
|
|
||||||
|
|
||||||
class CommandeCreateRequest(BaseModel):
|
class CommandeCreate(BaseModel):
|
||||||
client_id: str
|
client_id: str
|
||||||
date_commande: Optional[date] = None
|
date_commande: Optional[date] = None
|
||||||
date_livraison: 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_commande: Optional[date] = None
|
||||||
date_livraison: Optional[date] = None
|
date_livraison: Optional[date] = None
|
||||||
lignes: Optional[List[LigneCommande]] = None
|
lignes: Optional[List[LigneCommande]] = None
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ class DevisRequest(BaseModel):
|
||||||
lignes: List[LigneDevis]
|
lignes: List[LigneDevis]
|
||||||
|
|
||||||
|
|
||||||
class DevisResponse(BaseModel):
|
class Devis(BaseModel):
|
||||||
id: str
|
id: str
|
||||||
client_id: str
|
client_id: str
|
||||||
date_devis: str
|
date_devis: str
|
||||||
|
|
@ -30,7 +30,7 @@ class DevisResponse(BaseModel):
|
||||||
nb_lignes: int
|
nb_lignes: int
|
||||||
|
|
||||||
|
|
||||||
class DevisUpdateRequest(BaseModel):
|
class DevisUpdate(BaseModel):
|
||||||
"""Modèle pour modification d'un devis existant"""
|
"""Modèle pour modification d'un devis existant"""
|
||||||
|
|
||||||
date_devis: Optional[date] = None
|
date_devis: Optional[date] = None
|
||||||
|
|
@ -58,6 +58,6 @@ class DevisUpdateRequest(BaseModel):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class RelanceDevisRequest(BaseModel):
|
class RelanceDevis(BaseModel):
|
||||||
doc_id: str
|
doc_id: str
|
||||||
message_personnalise: Optional[str] = None
|
message_personnalise: Optional[str] = None
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ class StatutEmail(str, Enum):
|
||||||
BOUNCE = "BOUNCE"
|
BOUNCE = "BOUNCE"
|
||||||
|
|
||||||
|
|
||||||
class EmailEnvoiRequest(BaseModel):
|
class EmailEnvoi(BaseModel):
|
||||||
destinataire: EmailStr
|
destinataire: EmailStr
|
||||||
cc: Optional[List[EmailStr]] = []
|
cc: Optional[List[EmailStr]] = []
|
||||||
cci: Optional[List[EmailStr]] = []
|
cci: Optional[List[EmailStr]] = []
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ class LigneFacture(BaseModel):
|
||||||
return v.replace("\xa0", "").strip()
|
return v.replace("\xa0", "").strip()
|
||||||
|
|
||||||
|
|
||||||
class FactureCreateRequest(BaseModel):
|
class FactureCreate(BaseModel):
|
||||||
client_id: str
|
client_id: str
|
||||||
date_facture: Optional[date] = None
|
date_facture: Optional[date] = None
|
||||||
date_livraison: 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_facture: Optional[date] = None
|
||||||
date_livraison: Optional[date] = None
|
date_livraison: Optional[date] = None
|
||||||
lignes: Optional[List[LigneFacture]] = None
|
lignes: Optional[List[LigneFacture]] = None
|
||||||
|
|
|
||||||
|
|
@ -13,7 +13,7 @@ class LigneLivraison(BaseModel):
|
||||||
return v.replace("\xa0", "").strip()
|
return v.replace("\xa0", "").strip()
|
||||||
|
|
||||||
|
|
||||||
class LivraisonCreateRequest(BaseModel):
|
class LivraisonCreate(BaseModel):
|
||||||
client_id: str
|
client_id: str
|
||||||
date_livraison: Optional[date] = None
|
date_livraison: Optional[date] = None
|
||||||
date_livraison_prevue: 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: Optional[date] = None
|
||||||
date_livraison_prevue: Optional[date] = None
|
date_livraison_prevue: Optional[date] = None
|
||||||
lignes: Optional[List[LigneLivraison]] = None
|
lignes: Optional[List[LigneLivraison]] = None
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,7 @@ class StatutSignature(str, Enum):
|
||||||
EXPIRE = "EXPIRE"
|
EXPIRE = "EXPIRE"
|
||||||
|
|
||||||
|
|
||||||
class SignatureRequest(BaseModel):
|
class Signature(BaseModel):
|
||||||
doc_id: str
|
doc_id: str
|
||||||
type_doc: TypeDocument
|
type_doc: TypeDocument
|
||||||
email_signataire: EmailStr
|
email_signataire: EmailStr
|
||||||
|
|
|
||||||
|
|
@ -110,7 +110,7 @@ class SageGatewayResponse(BaseModel):
|
||||||
from_attributes = True
|
from_attributes = True
|
||||||
|
|
||||||
|
|
||||||
class SageGatewayListResponse(BaseModel):
|
class SageGatewayList(BaseModel):
|
||||||
|
|
||||||
items: List[SageGatewayResponse]
|
items: List[SageGatewayResponse]
|
||||||
total: int
|
total: int
|
||||||
|
|
|
||||||
|
|
@ -277,7 +277,7 @@ class ClientDetails(BaseModel):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
class ClientCreateRequest(BaseModel):
|
class ClientCreate(BaseModel):
|
||||||
intitule: str = Field(
|
intitule: str = Field(
|
||||||
..., max_length=69, description="Nom du client (CT_Intitule) - OBLIGATOIRE"
|
..., 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)
|
intitule: Optional[str] = Field(None, max_length=69)
|
||||||
qualite: Optional[str] = Field(None, max_length=17)
|
qualite: Optional[str] = Field(None, max_length=17)
|
||||||
classement: 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(
|
intitule: str = Field(
|
||||||
..., min_length=1, max_length=69, description="Raison sociale du fournisseur"
|
..., 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)
|
intitule: Optional[str] = Field(None, min_length=1, max_length=69)
|
||||||
adresse: Optional[str] = Field(None, max_length=35)
|
adresse: Optional[str] = Field(None, max_length=35)
|
||||||
code_postal: Optional[str] = Field(None, max_length=9)
|
code_postal: Optional[str] = Field(None, max_length=9)
|
||||||
|
|
|
||||||
|
|
@ -2,7 +2,7 @@ from pydantic import BaseModel
|
||||||
from typing import Optional
|
from typing import Optional
|
||||||
|
|
||||||
|
|
||||||
class UserResponse(BaseModel):
|
class Users(BaseModel):
|
||||||
id: str
|
id: str
|
||||||
email: str
|
email: str
|
||||||
nom: str
|
nom: str
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue