diff --git a/api.py b/api.py index 542a8f6..04f7e9a 100644 --- a/api.py +++ b/api.py @@ -127,257 +127,115 @@ class ClientResponse(BaseModel): class ClientDetails(BaseModel): """ Modèle de réponse client complet (GET /clients/{code}) - Aligné avec tous les champs gérés par creer_client et lister_tous_clients + Strictement aligné avec les champs retournés par lister_tous_clients """ + # IDENTIFICATION (9 champs) numero: Optional[str] = Field(None, description="Code client (CT_Num)") - intitule: Optional[str] = Field( - None, description="Raison sociale ou Nom complet (CT_Intitule)" - ) - type_tiers: Optional[str] = Field( - None, - description="Type : 'client', 'prospect', 'fournisseur' ou 'client_fournisseur'", - ) - qualite: Optional[str] = Field( - None, - description="Qualité Sage : CLI (Client), FOU (Fournisseur), PRO (Prospect)", - ) - classement: Optional[str] = Field( - None, description="Code de classement personnalisé (CT_Classement)" - ) - raccourci: Optional[str] = Field( - None, description="Code raccourci (7 car. max) (CT_Raccourci)" - ) - - est_prospect: Optional[bool] = Field( - None, description="True si prospect (CT_Prospect=1)" - ) - est_fournisseur: Optional[bool] = Field( - None, description="True si fournisseur (CT_Type=1 ou CT_Qualite contient FOU)" - ) - est_actif: Optional[bool] = Field(None, description="True si actif (CT_Sommeil=0)") - est_en_sommeil: Optional[bool] = Field( - None, description="True si en sommeil (CT_Sommeil=1)" - ) - - civilite: Optional[str] = Field(None, description="M., Mme, Mlle (CT_Civilite)") - nom: Optional[str] = Field(None, description="Nom de famille (CT_Nom)") - prenom: Optional[str] = Field(None, description="Prénom (CT_Prenom)") - nom_complet: Optional[str] = Field( - None, description="Nom complet formaté : 'Civilité Prénom Nom'" - ) - contact: Optional[str] = Field( - None, description="Nom du contact principal (CT_Contact)" - ) + 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)") + # ADRESSE (7 champs) + 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)" - ) + 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)") + # TELECOM (6 champs - pas de portable dans le SQL) telephone: Optional[str] = Field(None, description="Téléphone fixe (CT_Telephone)") - portable: Optional[str] = Field(None, description="Téléphone mobile") 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)" - ) - - forme_juridique: Optional[str] = Field( - None, - description="Forme juridique (SA, SARL, SAS, EI, etc.) (CT_SvFormeJuri)", - ) - est_entreprise: Optional[bool] = Field( - None, description="True si entreprise (forme_juridique renseignée)" - ) - est_particulier: Optional[bool] = Field( - None, description="True si particulier (pas de forme juridique)" - ) - siret: Optional[str] = Field(None, description="N° SIRET 14 chiffres (CT_Siret)") - siren: Optional[str] = Field( - None, description="N° SIREN 9 chiffres (extrait du 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)") + facebook: Optional[str] = Field(None, description="Profil Facebook (CT_Facebook)") + linkedin: Optional[str] = Field(None, description="Profil LinkedIn (CT_LinkedIn)") + # TAUX (4 champs) 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)") - secteur: Optional[str] = Field( - None, description="Secteur d'activité (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)" - ) + # STATISTIQUES (10 champs - utiliser les noms exacts du SQL) + 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)") - effectif: Optional[str] = Field( - None, description="Nombre d'employés (CT_SvEffectif)" - ) - ca_annuel: Optional[float] = Field( - None, description="Chiffre d'affaires annuel (CT_SvCA)" - ) - commercial_code: Optional[int] = Field( - None, description="Code du commercial rattaché (CO_No)" - ) - commercial_nom: Optional[str] = Field(None, description="Nom du commercial") - langue: Optional[int] = Field( - None, description="Code langue (0=Français, 1=Anglais...) (CT_Langue)" - ) + # COMMERCIAL (4 champs) + 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)") - categorie_tarifaire: Optional[int] = Field( - None, description="Catégorie tarifaire (N_CatTarif)" - ) - categorie_comptable: Optional[int] = Field( - None, description="Catégorie comptable (N_CatCompta)" - ) - compte_general: Optional[str] = Field( - None, description="Compte général principal (CG_NumPrinc)" - ) + # FACTURATION (11 champs) + 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)") - lettrage_auto: Optional[bool] = Field( - None, description="Lettrage automatique (CT_Lettrage)" - ) - type_facture: Optional[int] = Field( - None, description="Type de facture (0=Facture, 1=BL facturant) (CT_Facture)" - ) - 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)" - ) - 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)" - ) + # LOGISTIQUE (4 champs) + 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)") - priorite_livraison: Optional[int] = Field( - None, description="Priorité de livraison (CT_PrioriteLivr)" - ) - livraison_partielle: Optional[int] = Field( - None, description="Autoriser livraison partielle (CT_LivrPartielle)" - ) - delai_transport: Optional[int] = Field( - None, description="Délai de transport (jours) (CT_DelaiTransport)" - ) - delai_appro: Optional[int] = Field( - None, description="Délai d'approvisionnement (jours) (CT_DelaiAppro)" - ) + # COMMENTAIRE (1 champ) + commentaire: Optional[str] = Field(None, description="Commentaire libre (CT_Commentaire)") - commentaire: Optional[str] = Field( - None, description="Commentaire libre (CT_Commentaire)" - ) + # ANALYTIQUE (1 champ) + section_analytique: Optional[str] = Field(None, description="Section analytique (CA_Num)") - section_analytique: Optional[str] = Field( - None, description="Section analytique (CA_Num)" - ) + # ORGANISATION / SURVEILLANCE (10 champs) + 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)") - mode_reglement_code: Optional[int] = Field( - None, description="Code mode de règlement (MR_No)" - ) - surveillance_active: Optional[bool] = Field( - None, description="Surveillance financière active (CT_Surveillance)" - ) - coface: Optional[str] = Field( - None, description="Code Coface (25 car.) (CT_Coface)" - ) - 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 surveillance (CT_SvObjetMaj)" - ) - sv_resultat: Optional[float] = Field( - None, description="Résultat financier (CT_SvResultat)" - ) - - date_creation: Optional[str] = Field(None, description="Date de création") - date_modification: Optional[str] = Field( - None, description="Date de dernière modification (CT_DateMAJ)" - ) - - @field_validator("type_tiers", mode="before") - @classmethod - def convertir_type_tiers(cls, v): - if v is None: - return None - if isinstance(v, int): - mapping = { - 0: "client", - 1: "fournisseur", - 2: "prospect", - } - return mapping.get(v) - return v + # COMPTE GENERAL ET CATEGORIES (3 champs) + 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)") class Config: json_schema_extra = { "example": { "numero": "CLI000001", "intitule": "SARL EXEMPLE", - "type_tiers": "client", + "type_tiers": 0, "qualite": "CLI", "classement": "A", "raccourci": "EXEMPL", - "est_entreprise": True, - "est_actif": True, - "forme_juridique": "SARL", + "siret": "12345678901234", + "tva_intra": "FR12345678901", + "code_naf": "6201Z", "contact": "Jean Dupont", "adresse": "123 Rue de la Paix", "complement": "Bâtiment B", @@ -386,41 +244,63 @@ class ClientDetails(BaseModel): "region": "Île-de-France", "pays": "France", "telephone": "0123456789", - "portable": "0612345678", + "telecopie": "0123456788", "email": "contact@exemple.fr", "site_web": "https://www.exemple.fr", "facebook": "https://facebook.com/exemple", "linkedin": "https://linkedin.com/company/exemple", - "siret": "12345678901234", - "siren": "123456789", - "tva_intra": "FR12345678901", - "code_naf": "6201Z", - "secteur": "Informatique", - "effectif": "50-99", - "ca_annuel": 2500000.0, - "commercial_code": 1, - "langue": 0, - "categorie_tarifaire": 0, - "categorie_comptable": 0, - "compte_general": "4110000", - "lettrage_auto": True, - "type_facture": 1, - "controle_encours": 1, - "exclure_relance": False, + "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", - "date_creation": "2024-01-15T10:30:00", - "date_modification": "2024-12-20T14:22:00", + "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): """ Modèle de réponse pour un article Sage