From e8558e207b8ced11de0158e3d85fc8b7c3fffe96 Mon Sep 17 00:00:00 2001 From: Fanilo-Nantenaina Date: Fri, 5 Dec 2025 19:37:48 +0300 Subject: [PATCH] Modified create client context --- main.py | 5 +- sage_connector.py | 114 ++++++++++++++++++++++++++-------------------- 2 files changed, 69 insertions(+), 50 deletions(-) diff --git a/main.py b/main.py index d009574..bea9c35 100644 --- a/main.py +++ b/main.py @@ -198,18 +198,21 @@ def client_get(req: CodeRequest): raise HTTPException(500, str(e)) +# DANS main.py @app.post("/sage/clients/create", dependencies=[Depends(verify_token)]) def create_client_endpoint(req: ClientCreateRequest): """Création d'un client dans Sage""" try: - # Transformation du modèle Pydantic en dict pour le connecteur + # L'appel au connecteur est fait ici resultat = sage.creer_client(req.dict()) return {"success": True, "data": resultat} except ValueError as e: logger.warning(f"Erreur métier création client: {e}") + # Erreur métier (ex: doublon) -> 400 Bad Request raise HTTPException(400, str(e)) except Exception as e: logger.error(f"Erreur technique création client: {e}") + # Erreur technique (ex: COM) -> 500 Internal Server Error raise HTTPException(500, str(e)) # ===================================================== diff --git a/sage_connector.py b/sage_connector.py index e7ac1cc..70c4353 100644 --- a/sage_connector.py +++ b/sage_connector.py @@ -2377,79 +2377,95 @@ class SageConnector: def creer_client(self, client_data: Dict) -> Dict: """ - Crée un nouveau client dans Sage via CptaApplication.FactoryClient + Crée un nouveau client dans Sage 100c via l'API COM, + en utilisant CreateNew() pour obtenir l'objet concret. """ if not self.cial: raise RuntimeError("Connexion Sage non établie") try: with self._com_context(), self._lock_com: - # 1. Accès à la Factory Client (Module Comptabilité) + # 1. Accès à la Factory Client (CptaApplication si Tiers) factory_client = self.cial.CptaApplication.FactoryClient - # 2. Création de l'objet en mémoire - client = factory_client.Create() # Ou CreateNew() selon version, Create() est plus standard + # CORRECTION CRITIQUE: Utiliser CreateNew() pour obtenir l'objet Tiers concret + client = factory_client.CreateNew() - # 3. Remplissage des Champs OBLIGATOIRES - # Si 'num' est fourni, on l'utilise, sinon Sage utilisera la souche par défaut - if client_data.get("num"): - client.CT_Num = client_data["num"] + # 2. Remplissage des Champs OBLIGATOIRES (Conformes F_COMPTET) + # CT_Num (Numéro de compte) + num_prop = client_data.get("num", "") + if num_prop: + # S'assurer que le numéro est en majuscule (conforme Alpha Majuscule) + client.CT_Num = num_prop.upper() + + # CT_Intitule - Si cette ligne échoue, l'objet créé n'est pas bon. client.CT_Intitule = client_data["intitule"] client.CT_Type = 0 # 0 = Client - - # Compte Collectif (Obligatoire, ex: 411000) - if client_data.get("compte_collectif"): - client.CT_CompteA = client_data["compte_collectif"] - - # 4. Remplissage des Champs OPTIONNELS - # --- Adresse principale --- - try: - client.Adresse.Adresse = client_data.get("adresse", "") - client.Adresse.CodePostal = client_data.get("code_postal", "") - client.Adresse.Ville = client_data.get("ville", "") - client.Adresse.Pays = client_data.get("pays", "") - except Exception as e: - logger.warning(f"Erreur remplissage adresse: {e}") - # --- Contact / Télécom --- + # CORRECTION : Utiliser CT_CompteG (mappé à CG_NumPrinc) + if client_data.get("compte_collectif"): + client.CT_CompteG = client_data["compte_collectif"] + + # Initialisation des champs obligatoires (N_...) + client.N_CatTarif = 1 + client.N_CatCompta = 1 + client.N_Period = 1 + client.N_Expedition = 1 + client.N_Condition = 1 + client.N_Risque = 1 + + # CT_NumPayeur doit être défini, souvent égal à CT_Num + client.CT_NumPayeur = client.CT_Num + + # 3. CHAMPS OPTIONNELS + + # --- Adresse principale (Accès via sous-objet Adresse) --- + # Ajout d'une gestion d'erreur sur l'accès aux sous-objets car ils peuvent varier try: - client.Telecom.Telephone = client_data.get("telephone", "") - client.Telecom.EMail = client_data.get("email", "") + if client_data.get("adresse"): client.Adresse.Adresse = client_data["adresse"] + if client_data.get("code_postal"): client.Adresse.CodePostal = client_data["code_postal"] + if client_data.get("ville"): client.Adresse.Ville = client_data["ville"] + if client_data.get("pays"): client.Adresse.Pays = client_data["pays"] except Exception as e: - logger.warning(f"Erreur remplissage telecom: {e}") + logger.warning(f"Impossible de définir l'adresse: {e}") + + # --- Contact / Télécom (Accès via sous-objet Telecom) --- + try: + if client_data.get("telephone"): client.Telecom.Telephone = client_data["telephone"] + if client_data.get("email"): client.Telecom.EMail = client_data["email"] + except Exception as e: + logger.warning(f"Impossible de définir les télécoms: {e}") # --- Identifiants --- - if client_data.get("siret"): - try: client.CT_Siret = client_data["siret"] - except: pass - - if client_data.get("tva_intra"): - try: client.CT_Identifiant = client_data["tva_intra"] - except: pass - - # 5. Écriture en base + if client_data.get("siret"): client.CT_Siret = client_data["siret"] + if client_data.get("tva_intra"): client.CT_Identifiant = client_data["tva_intra"] + + # 4. Écriture en base client.Write() - # Récupération du numéro généré (surtout si auto-incrément) num_final = client.CT_Num - - # Mise à jour du cache local immédiate pour qu'il soit trouvable tout de suite - with self._lock_clients: - self._cache_clients.append(self._extraire_client(client)) - self._cache_clients_dict[num_final] = self._extraire_client(client) - - logger.info(f"✅ Client créé avec succès : {num_final} - {client.CT_Intitule}") + logger.info(f"✅ Client créé et conforme: {num_final} - {client.CT_Intitule}") return { "numero": num_final, "intitule": client.CT_Intitule, - "compte_collectif": getattr(client, "CT_CompteA", "") + "compte_collectif": getattr(client, "CT_CompteG", "") } except Exception as e: - logger.error(f"❌ Erreur création client : {e}", exc_info=True) - # Gestion d'erreur spécifique pour les doublons - if "doublon" in str(e).lower() or "existe déjà" in str(e).lower(): - raise ValueError(f"Le client ou le numéro existe déjà.") - raise RuntimeError(f"Erreur technique Sage: {str(e)}") \ No newline at end of file + logger.error(f"❌ Erreur création client: {e}", exc_info=True) + # Gestion d'erreur remontant l'erreur COM détaillée (si disponible) + error_message = str(e) + if self.cial: + try: + err = self.cial.LastError + if err: + error_message = f"Erreur Sage: {err.Description}" + if "doublon" in err.Description.lower(): + raise ValueError(f"Ce client ou ce numéro existe déjà. {error_message}") + except: + pass + + # Le connecteur lève maintenant un RuntimeError clair + raise RuntimeError(f"Erreur technique Sage: {error_message}") \ No newline at end of file