Added create client logics
This commit is contained in:
parent
cc56821c70
commit
2e96cec20d
2 changed files with 271 additions and 0 deletions
188
main.py
188
main.py
|
|
@ -76,6 +76,19 @@ class StatutRequest(BaseModel):
|
|||
nouveau_statut: int
|
||||
|
||||
|
||||
class ClientCreateRequest(BaseModel):
|
||||
intitule: str = Field(..., description="Nom du client (CT_Intitule)")
|
||||
compte_collectif: str = Field("411000", description="Compte général rattaché")
|
||||
num: Optional[str] = Field(None, description="Laisser vide pour numérotation auto")
|
||||
adresse: Optional[str] = None
|
||||
code_postal: Optional[str] = None
|
||||
ville: Optional[str] = None
|
||||
pays: Optional[str] = None
|
||||
email: Optional[str] = None
|
||||
telephone: Optional[str] = None
|
||||
siret: Optional[str] = None
|
||||
tva_intra: Optional[str] = None
|
||||
|
||||
# =====================================================
|
||||
# SÉCURITÉ
|
||||
# =====================================================
|
||||
|
|
@ -185,6 +198,20 @@ def client_get(req: CodeRequest):
|
|||
raise HTTPException(500, str(e))
|
||||
|
||||
|
||||
@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
|
||||
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}")
|
||||
raise HTTPException(400, str(e))
|
||||
except Exception as e:
|
||||
logger.error(f"Erreur technique création client: {e}")
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
# =====================================================
|
||||
# ENDPOINTS - ARTICLES
|
||||
# =====================================================
|
||||
|
|
@ -2566,6 +2593,167 @@ def livraison_get(req: CodeRequest):
|
|||
logger.error(f"Erreur lecture livraison: {e}")
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
# À ajouter dans main.py (Windows Gateway)
|
||||
|
||||
@app.get("/sage/diagnostic/fournisseurs-detection", dependencies=[Depends(verify_token)])
|
||||
def diagnostiquer_detection_fournisseurs():
|
||||
"""
|
||||
🔍 DIAGNOSTIC : Découvre comment identifier les fournisseurs dans votre Sage
|
||||
|
||||
Teste plusieurs méthodes :
|
||||
- CT_Type = 1 (méthode classique)
|
||||
- CT_Qualite (méthode moderne : 0=Aucune, 1=Client, 2=Fournisseur, 3=Client+Fournisseur)
|
||||
- CT_TypeTiers
|
||||
- Présence dans FactoryFournisseur
|
||||
"""
|
||||
try:
|
||||
if not sage or not sage.cial:
|
||||
raise HTTPException(503, "Service Sage indisponible")
|
||||
|
||||
with sage._com_context(), sage._lock_com:
|
||||
factory_client = sage.cial.CptaApplication.FactoryClient
|
||||
|
||||
resultats = {
|
||||
"methodes_detectees": [],
|
||||
"tiers_analyses": [],
|
||||
"recommandation": None
|
||||
}
|
||||
|
||||
# Scanner les 50 premiers tiers
|
||||
index = 1
|
||||
while index <= 50:
|
||||
try:
|
||||
persist = factory_client.List(index)
|
||||
if persist is None:
|
||||
break
|
||||
|
||||
tiers = sage._cast_client(persist)
|
||||
if not tiers:
|
||||
index += 1
|
||||
continue
|
||||
|
||||
analyse = {
|
||||
"index": index,
|
||||
"numero": getattr(tiers, "CT_Num", ""),
|
||||
"intitule": getattr(tiers, "CT_Intitule", ""),
|
||||
"ct_type": getattr(tiers, "CT_Type", None),
|
||||
"ct_prospect": getattr(tiers, "CT_Prospect", None),
|
||||
"methodes_identifiees": []
|
||||
}
|
||||
|
||||
# Méthode 1 : CT_Qualite (la plus courante aujourd'hui)
|
||||
try:
|
||||
qualite = getattr(tiers, "CT_Qualite", None)
|
||||
if qualite is not None:
|
||||
analyse["ct_qualite"] = qualite
|
||||
analyse["ct_qualite_libelle"] = {
|
||||
0: "Aucune",
|
||||
1: "Client uniquement",
|
||||
2: "Fournisseur uniquement",
|
||||
3: "Client ET Fournisseur"
|
||||
}.get(qualite, f"Inconnu ({qualite})")
|
||||
|
||||
if qualite in [2, 3]:
|
||||
analyse["methodes_identifiees"].append("CT_Qualite (2 ou 3)")
|
||||
except:
|
||||
pass
|
||||
|
||||
# Méthode 2 : CT_TypeTiers
|
||||
try:
|
||||
type_tiers = getattr(tiers, "CT_TypeTiers", None)
|
||||
if type_tiers is not None:
|
||||
analyse["ct_type_tiers"] = type_tiers
|
||||
except:
|
||||
pass
|
||||
|
||||
# Méthode 3 : Vérifier si accessible via FactoryFournisseur
|
||||
try:
|
||||
factory_fourn = sage.cial.CptaApplication.FactoryFournisseur
|
||||
persist_fourn = factory_fourn.ReadNumero(analyse["numero"])
|
||||
|
||||
if persist_fourn:
|
||||
analyse["methodes_identifiees"].append("FactoryFournisseur.ReadNumero()")
|
||||
analyse["accessible_via_factory_fournisseur"] = True
|
||||
except:
|
||||
analyse["accessible_via_factory_fournisseur"] = False
|
||||
|
||||
# Méthode 4 : CT_Type = 1 (ancienne méthode)
|
||||
if analyse["ct_type"] == 1:
|
||||
analyse["methodes_identifiees"].append("CT_Type = 1")
|
||||
|
||||
resultats["tiers_analyses"].append(analyse)
|
||||
index += 1
|
||||
|
||||
except Exception as e:
|
||||
logger.debug(f"Erreur analyse tiers {index}: {e}")
|
||||
index += 1
|
||||
|
||||
# Analyser les méthodes détectées
|
||||
fournisseurs_via_qualite = [
|
||||
t for t in resultats["tiers_analyses"]
|
||||
if t.get("ct_qualite") in [2, 3]
|
||||
]
|
||||
|
||||
fournisseurs_via_type = [
|
||||
t for t in resultats["tiers_analyses"]
|
||||
if t.get("ct_type") == 1
|
||||
]
|
||||
|
||||
fournisseurs_via_factory = [
|
||||
t for t in resultats["tiers_analyses"]
|
||||
if t.get("accessible_via_factory_fournisseur") == True
|
||||
]
|
||||
|
||||
resultats["statistiques"] = {
|
||||
"total_tiers_scannes": len(resultats["tiers_analyses"]),
|
||||
"fournisseurs_via_ct_qualite": len(fournisseurs_via_qualite),
|
||||
"fournisseurs_via_ct_type": len(fournisseurs_via_type),
|
||||
"fournisseurs_via_factory": len(fournisseurs_via_factory)
|
||||
}
|
||||
|
||||
# Exemples de fournisseurs détectés
|
||||
if fournisseurs_via_qualite:
|
||||
resultats["exemples_fournisseurs_qualite"] = fournisseurs_via_qualite[:5]
|
||||
|
||||
if fournisseurs_via_factory:
|
||||
resultats["exemples_fournisseurs_factory"] = fournisseurs_via_factory[:5]
|
||||
|
||||
# Recommandation
|
||||
if fournisseurs_via_qualite:
|
||||
resultats["recommandation"] = {
|
||||
"methode": "CT_Qualite",
|
||||
"condition": "CT_Qualite IN (2, 3)",
|
||||
"description": "Votre Sage utilise le champ CT_Qualite pour distinguer clients/fournisseurs"
|
||||
}
|
||||
elif fournisseurs_via_factory:
|
||||
resultats["recommandation"] = {
|
||||
"methode": "FactoryFournisseur",
|
||||
"condition": "Accessible via FactoryFournisseur.ReadNumero()",
|
||||
"description": "Utilisez FactoryFournisseur au lieu de FactoryClient"
|
||||
}
|
||||
elif fournisseurs_via_type:
|
||||
resultats["recommandation"] = {
|
||||
"methode": "CT_Type",
|
||||
"condition": "CT_Type = 1",
|
||||
"description": "Méthode classique (rare aujourd'hui)"
|
||||
}
|
||||
else:
|
||||
resultats["recommandation"] = {
|
||||
"methode": "AUCUNE",
|
||||
"description": "Aucun fournisseur détecté dans les 50 premiers tiers",
|
||||
"suggestion": "Vérifiez si des fournisseurs existent dans Sage, ou augmentez le scan"
|
||||
}
|
||||
|
||||
logger.info(f"[DIAG] Fournisseurs détectés: {resultats['statistiques']}")
|
||||
|
||||
return {
|
||||
"success": True,
|
||||
"diagnostic": resultats
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"[DIAG] Erreur diagnostic fournisseurs: {e}", exc_info=True)
|
||||
raise HTTPException(500, str(e))
|
||||
|
||||
# =====================================================
|
||||
# LANCEMENT
|
||||
|
|
|
|||
|
|
@ -2370,3 +2370,86 @@ class SageConnector:
|
|||
except Exception as e:
|
||||
logger.error(f"❌ Erreur lecture livraison {numero}: {e}")
|
||||
return None
|
||||
|
||||
# =========================================================================
|
||||
# CREATION CLIENT (US-A8 ?)
|
||||
# =========================================================================
|
||||
|
||||
def creer_client(self, client_data: Dict) -> Dict:
|
||||
"""
|
||||
Crée un nouveau client dans Sage via CptaApplication.FactoryClient
|
||||
"""
|
||||
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é)
|
||||
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
|
||||
|
||||
# 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"]
|
||||
|
||||
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 ---
|
||||
try:
|
||||
client.Telecom.Telephone = client_data.get("telephone", "")
|
||||
client.Telecom.EMail = client_data.get("email", "")
|
||||
except Exception as e:
|
||||
logger.warning(f"Erreur remplissage telecom: {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
|
||||
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}")
|
||||
|
||||
return {
|
||||
"numero": num_final,
|
||||
"intitule": client.CT_Intitule,
|
||||
"compte_collectif": getattr(client, "CT_CompteA", "")
|
||||
}
|
||||
|
||||
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)}")
|
||||
Loading…
Reference in a new issue