feat(fournisseurs): add FournisseurDetails model and update endpoints
This commit is contained in:
parent
3546c58165
commit
0f06075779
1 changed files with 176 additions and 10 deletions
186
api.py
186
api.py
|
|
@ -357,6 +357,176 @@ class ClientDetails(BaseModel):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class FournisseurDetails(BaseModel):
|
||||||
|
"""
|
||||||
|
Modèle de réponse fournisseur complet (GET /fournisseurs/{code})
|
||||||
|
Strictement aligné avec ClientDetails
|
||||||
|
"""
|
||||||
|
|
||||||
|
numero: Optional[str] = Field(None, description="Code fournisseur (CT_Num)")
|
||||||
|
intitule: Optional[str] = Field(None, description="Raison sociale ou Nom complet (CT_Intitule)")
|
||||||
|
type_tiers: Optional[int] = Field(None, description="Type : 0=Client, 1=Fournisseur (CT_Type)")
|
||||||
|
qualite: Optional[str] = Field(None, description="Qualité Sage : CLI, FOU, PRO (CT_Qualite)")
|
||||||
|
classement: Optional[str] = Field(None, description="Code de classement (CT_Classement)")
|
||||||
|
raccourci: Optional[str] = Field(None, description="Code raccourci 7 car. (CT_Raccourci)")
|
||||||
|
siret: Optional[str] = Field(None, description="N° SIRET 14 chiffres (CT_Siret)")
|
||||||
|
tva_intra: Optional[str] = Field(None, description="N° TVA intracommunautaire (CT_Identifiant)")
|
||||||
|
code_naf: Optional[str] = Field(None, description="Code NAF/APE (CT_Ape)")
|
||||||
|
|
||||||
|
contact: Optional[str] = Field(None, description="Nom du contact principal (CT_Contact)")
|
||||||
|
adresse: Optional[str] = Field(None, description="Adresse ligne 1 (CT_Adresse)")
|
||||||
|
complement: Optional[str] = Field(None, description="Complément d'adresse (CT_Complement)")
|
||||||
|
code_postal: Optional[str] = Field(None, description="Code postal (CT_CodePostal)")
|
||||||
|
ville: Optional[str] = Field(None, description="Ville (CT_Ville)")
|
||||||
|
region: Optional[str] = Field(None, description="Région/État (CT_CodeRegion)")
|
||||||
|
pays: Optional[str] = Field(None, description="Pays (CT_Pays)")
|
||||||
|
|
||||||
|
telephone: Optional[str] = Field(None, description="Téléphone fixe (CT_Telephone)")
|
||||||
|
telecopie: Optional[str] = Field(None, description="Fax (CT_Telecopie)")
|
||||||
|
email: Optional[str] = Field(None, description="Email principal (CT_EMail)")
|
||||||
|
site_web: Optional[str] = Field(None, description="Site web (CT_Site)")
|
||||||
|
facebook: Optional[str] = Field(None, description="Profil Facebook (CT_Facebook)")
|
||||||
|
linkedin: Optional[str] = Field(None, description="Profil LinkedIn (CT_LinkedIn)")
|
||||||
|
|
||||||
|
taux01: Optional[float] = Field(None, description="Taux personnalisé 1 (CT_Taux01)")
|
||||||
|
taux02: Optional[float] = Field(None, description="Taux personnalisé 2 (CT_Taux02)")
|
||||||
|
taux03: Optional[float] = Field(None, description="Taux personnalisé 3 (CT_Taux03)")
|
||||||
|
taux04: Optional[float] = Field(None, description="Taux personnalisé 4 (CT_Taux04)")
|
||||||
|
|
||||||
|
statistique01: Optional[str] = Field(None, description="Statistique 1 (CT_Statistique01)")
|
||||||
|
statistique02: Optional[str] = Field(None, description="Statistique 2 (CT_Statistique02)")
|
||||||
|
statistique03: Optional[str] = Field(None, description="Statistique 3 (CT_Statistique03)")
|
||||||
|
statistique04: Optional[str] = Field(None, description="Statistique 4 (CT_Statistique04)")
|
||||||
|
statistique05: Optional[str] = Field(None, description="Statistique 5 (CT_Statistique05)")
|
||||||
|
statistique06: Optional[str] = Field(None, description="Statistique 6 (CT_Statistique06)")
|
||||||
|
statistique07: Optional[str] = Field(None, description="Statistique 7 (CT_Statistique07)")
|
||||||
|
statistique08: Optional[str] = Field(None, description="Statistique 8 (CT_Statistique08)")
|
||||||
|
statistique09: Optional[str] = Field(None, description="Statistique 9 (CT_Statistique09)")
|
||||||
|
statistique10: Optional[str] = Field(None, description="Statistique 10 (CT_Statistique10)")
|
||||||
|
|
||||||
|
encours_autorise: Optional[float] = Field(None, description="Encours maximum autorisé (CT_Encours)")
|
||||||
|
assurance_credit: Optional[float] = Field(None, description="Montant assurance crédit (CT_Assurance)")
|
||||||
|
langue: Optional[int] = Field(None, description="Code langue 0=FR, 1=EN (CT_Langue)")
|
||||||
|
commercial_code: Optional[int] = Field(None, description="Code du commercial (CO_No)")
|
||||||
|
|
||||||
|
lettrage_auto: Optional[bool] = Field(None, description="Lettrage automatique (CT_Lettrage)")
|
||||||
|
est_actif: Optional[bool] = Field(None, description="True si actif (CT_Sommeil=0)")
|
||||||
|
type_facture: Optional[int] = Field(None, description="Type facture 0=Facture, 1=BL (CT_Facture)")
|
||||||
|
est_prospect: Optional[bool] = Field(None, description="True si prospect (CT_Prospect=1)")
|
||||||
|
bl_en_facture: Optional[int] = Field(None, description="Imprimer BL en facture (CT_BLFact)")
|
||||||
|
saut_page: Optional[int] = Field(None, description="Saut de page sur documents (CT_Saut)")
|
||||||
|
validation_echeance: Optional[int] = Field(None, description="Valider les échéances (CT_ValidEch)")
|
||||||
|
controle_encours: Optional[int] = Field(None, description="Contrôler l'encours (CT_ControlEnc)")
|
||||||
|
exclure_relance: Optional[bool] = Field(None, description="Exclure des relances (CT_NotRappel)")
|
||||||
|
exclure_penalites: Optional[bool] = Field(None, description="Exclure des pénalités (CT_NotPenal)")
|
||||||
|
bon_a_payer: Optional[int] = Field(None, description="Bon à payer obligatoire (CT_BonAPayer)")
|
||||||
|
|
||||||
|
priorite_livraison: Optional[int] = Field(None, description="Priorité livraison (CT_PrioriteLivr)")
|
||||||
|
livraison_partielle: Optional[int] = Field(None, description="Livraison partielle (CT_LivrPartielle)")
|
||||||
|
delai_transport: Optional[int] = Field(None, description="Délai transport jours (CT_DelaiTransport)")
|
||||||
|
delai_appro: Optional[int] = Field(None, description="Délai appro jours (CT_DelaiAppro)")
|
||||||
|
|
||||||
|
commentaire: Optional[str] = Field(None, description="Commentaire libre (CT_Commentaire)")
|
||||||
|
|
||||||
|
section_analytique: Optional[str] = Field(None, description="Section analytique (CA_Num)")
|
||||||
|
|
||||||
|
mode_reglement_code: Optional[int] = Field(None, description="Code mode règlement (MR_No)")
|
||||||
|
surveillance_active: Optional[bool] = Field(None, description="Surveillance financière (CT_Surveillance)")
|
||||||
|
coface: Optional[str] = Field(None, description="Code Coface 25 car. (CT_Coface)")
|
||||||
|
forme_juridique: Optional[str] = Field(None, description="Forme juridique SA, SARL (CT_SvFormeJuri)")
|
||||||
|
effectif: Optional[str] = Field(None, description="Nombre d'employés (CT_SvEffectif)")
|
||||||
|
sv_regularite: Optional[str] = Field(None, description="Régularité paiements (CT_SvRegul)")
|
||||||
|
sv_cotation: Optional[str] = Field(None, description="Cotation crédit (CT_SvCotation)")
|
||||||
|
sv_objet_maj: Optional[str] = Field(None, description="Objet dernière MAJ (CT_SvObjetMaj)")
|
||||||
|
sv_chiffre_affaires: Optional[float] = Field(None, description="Chiffre d'affaires (CT_SvCA)")
|
||||||
|
sv_resultat: Optional[float] = Field(None, description="Résultat financier (CT_SvResultat)")
|
||||||
|
|
||||||
|
compte_general: Optional[str] = Field(None, description="Compte général principal (CG_NumPrinc)")
|
||||||
|
categorie_tarif: Optional[int] = Field(None, description="Catégorie tarifaire (N_CatTarif)")
|
||||||
|
categorie_compta: Optional[int] = Field(None, description="Catégorie comptable (N_CatCompta)")
|
||||||
|
|
||||||
|
contacts: Optional[List[Contact]] = Field(
|
||||||
|
default_factory=list,
|
||||||
|
description="Liste des contacts du fournisseur"
|
||||||
|
)
|
||||||
|
|
||||||
|
class Config:
|
||||||
|
json_schema_extra = {
|
||||||
|
"example": {
|
||||||
|
"numero": "FOU000001",
|
||||||
|
"intitule": "SARL FOURNISSEUR EXEMPLE",
|
||||||
|
"type_tiers": 1,
|
||||||
|
"qualite": "FOU",
|
||||||
|
"classement": "A",
|
||||||
|
"raccourci": "EXEMPL",
|
||||||
|
"siret": "12345678901234",
|
||||||
|
"tva_intra": "FR12345678901",
|
||||||
|
"code_naf": "6201Z",
|
||||||
|
"contact": "Jean Dupont",
|
||||||
|
"adresse": "123 Rue de la Paix",
|
||||||
|
"complement": "Bâtiment B",
|
||||||
|
"code_postal": "75001",
|
||||||
|
"ville": "Paris",
|
||||||
|
"region": "Île-de-France",
|
||||||
|
"pays": "France",
|
||||||
|
"telephone": "0123456789",
|
||||||
|
"telecopie": "0123456788",
|
||||||
|
"email": "contact@exemple.fr",
|
||||||
|
"site_web": "https://www.exemple.fr",
|
||||||
|
"facebook": "https://facebook.com/exemple",
|
||||||
|
"linkedin": "https://linkedin.com/company/exemple",
|
||||||
|
"taux01": 0.0,
|
||||||
|
"taux02": 0.0,
|
||||||
|
"taux03": 0.0,
|
||||||
|
"taux04": 0.0,
|
||||||
|
"statistique01": "Informatique",
|
||||||
|
"statistique02": "",
|
||||||
|
"statistique03": "",
|
||||||
|
"statistique04": "",
|
||||||
|
"statistique05": "",
|
||||||
|
"statistique06": "",
|
||||||
|
"statistique07": "",
|
||||||
|
"statistique08": "",
|
||||||
|
"statistique09": "",
|
||||||
|
"statistique10": "",
|
||||||
|
"encours_autorise": 50000.0,
|
||||||
|
"assurance_credit": 40000.0,
|
||||||
|
"langue": 0,
|
||||||
|
"commercial_code": 1,
|
||||||
|
"lettrage_auto": True,
|
||||||
|
"est_actif": True,
|
||||||
|
"type_facture": 1,
|
||||||
|
"est_prospect": False,
|
||||||
|
"bl_en_facture": 0,
|
||||||
|
"saut_page": 0,
|
||||||
|
"validation_echeance": 0,
|
||||||
|
"controle_encours": 1,
|
||||||
|
"exclure_relance": False,
|
||||||
|
"exclure_penalites": False,
|
||||||
|
"bon_a_payer": 0,
|
||||||
|
"priorite_livraison": 1,
|
||||||
|
"livraison_partielle": 1,
|
||||||
|
"delai_transport": 2,
|
||||||
|
"delai_appro": 0,
|
||||||
|
"commentaire": "Client important",
|
||||||
|
"section_analytique": "",
|
||||||
|
"mode_reglement_code": 1,
|
||||||
|
"surveillance_active": True,
|
||||||
|
"coface": "COF12345",
|
||||||
|
"forme_juridique": "SARL",
|
||||||
|
"effectif": "50-99",
|
||||||
|
"sv_regularite": "",
|
||||||
|
"sv_cotation": "",
|
||||||
|
"sv_objet_maj": "",
|
||||||
|
"sv_chiffre_affaires": 2500000.0,
|
||||||
|
"sv_resultat": 150000.0,
|
||||||
|
"compte_general": "4110000",
|
||||||
|
"categorie_tarif": 0,
|
||||||
|
"categorie_compta": 0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
class ArticleResponse(BaseModel):
|
class ArticleResponse(BaseModel):
|
||||||
"""
|
"""
|
||||||
Modèle de réponse pour un article Sage
|
Modèle de réponse pour un article Sage
|
||||||
|
|
@ -2405,7 +2575,7 @@ async def rechercher_clients(query: Optional[str] = Query(None)):
|
||||||
raise HTTPException(500, str(e))
|
raise HTTPException(500, str(e))
|
||||||
|
|
||||||
|
|
||||||
@app.get("/clients/{code}", tags=["Clients"])
|
@app.get("/clients/{code}", response_model=ClientDetails , tags=["Clients"])
|
||||||
async def lire_client_detail(code: str):
|
async def lire_client_detail(code: str):
|
||||||
try:
|
try:
|
||||||
client = sage_client.lire_client(code)
|
client = sage_client.lire_client(code)
|
||||||
|
|
@ -2413,7 +2583,7 @@ async def lire_client_detail(code: str):
|
||||||
if not client:
|
if not client:
|
||||||
raise HTTPException(404, f"Client {code} introuvable")
|
raise HTTPException(404, f"Client {code} introuvable")
|
||||||
|
|
||||||
return {"success": True, "data": client}
|
return ClientDetails(**client)
|
||||||
|
|
||||||
except HTTPException:
|
except HTTPException:
|
||||||
raise
|
raise
|
||||||
|
|
@ -4271,7 +4441,7 @@ async def lire_prospect(code: str):
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@app.get("/fournisseurs", tags=["Fournisseurs"])
|
@app.get("/fournisseurs", response_model=List[FournisseurDetails], tags=["Fournisseurs"])
|
||||||
async def rechercher_fournisseurs(query: Optional[str] = Query(None)):
|
async def rechercher_fournisseurs(query: Optional[str] = Query(None)):
|
||||||
try:
|
try:
|
||||||
fournisseurs = sage_client.lister_fournisseurs(filtre=query or "")
|
fournisseurs = sage_client.lister_fournisseurs(filtre=query or "")
|
||||||
|
|
@ -4281,7 +4451,7 @@ async def rechercher_fournisseurs(query: Optional[str] = Query(None)):
|
||||||
if len(fournisseurs) == 0:
|
if len(fournisseurs) == 0:
|
||||||
logger.warning("Aucun fournisseur retourné - vérifier la gateway Windows")
|
logger.warning("Aucun fournisseur retourné - vérifier la gateway Windows")
|
||||||
|
|
||||||
return fournisseurs
|
return [FournisseurDetails(**f) for f in fournisseurs]
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.error(f"Erreur recherche fournisseurs: {e}")
|
logger.error(f"Erreur recherche fournisseurs: {e}")
|
||||||
|
|
@ -4313,7 +4483,7 @@ async def ajouter_fournisseur(
|
||||||
raise HTTPException(500, str(e))
|
raise HTTPException(500, str(e))
|
||||||
|
|
||||||
|
|
||||||
@app.put("/fournisseurs/{code}", tags=["Fournisseurs"])
|
@app.put("/fournisseurs/{code}", response_model=FournisseurDetails, tags=["Fournisseurs"])
|
||||||
async def modifier_fournisseur(
|
async def modifier_fournisseur(
|
||||||
code: str,
|
code: str,
|
||||||
fournisseur_update: FournisseurUpdateRequest,
|
fournisseur_update: FournisseurUpdateRequest,
|
||||||
|
|
@ -4326,11 +4496,7 @@ async def modifier_fournisseur(
|
||||||
|
|
||||||
logger.info(f"Fournisseur {code} modifié avec succès")
|
logger.info(f"Fournisseur {code} modifié avec succès")
|
||||||
|
|
||||||
return {
|
return FournisseurDetails(**resultat)
|
||||||
"success": True,
|
|
||||||
"message": f"Fournisseur {code} modifié avec succès",
|
|
||||||
"fournisseur": resultat,
|
|
||||||
}
|
|
||||||
|
|
||||||
except ValueError as e:
|
except ValueError as e:
|
||||||
logger.warning(f"Erreur métier modification fournisseur {code}: {e}")
|
logger.warning(f"Erreur métier modification fournisseur {code}: {e}")
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue