Update fournisseur

This commit is contained in:
Fanilo-Nantenaina 2025-12-06 15:17:06 +03:00
parent c66280b305
commit 876e050bff
2 changed files with 242 additions and 1 deletions

37
main.py
View file

@ -107,7 +107,26 @@ class FournisseurCreateRequest(BaseModel):
siret: Optional[str] = None siret: Optional[str] = None
tva_intra: Optional[str] = None tva_intra: Optional[str] = None
class FournisseurCreateRequest(BaseModel):
intitule: str = Field(..., description="Raison sociale du fournisseur")
compte_collectif: str = Field("401000", description="Compte général rattaché")
num: Optional[str] = Field(None, description="Code fournisseur (auto si vide)")
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
class FournisseurUpdateGatewayRequest(BaseModel):
"""Modèle pour modification fournisseur côté gateway"""
code: str
fournisseur_data: Dict
# ===================================================== # =====================================================
# SÉCURITÉ # SÉCURITÉ
# ===================================================== # =====================================================
@ -2636,6 +2655,22 @@ def create_fournisseur_endpoint(req: FournisseurCreateRequest):
logger.error(f"❌ Erreur technique création fournisseur: {e}") logger.error(f"❌ Erreur technique création fournisseur: {e}")
raise HTTPException(500, str(e)) raise HTTPException(500, str(e))
@app.post("/sage/fournisseurs/update", dependencies=[Depends(verify_token)])
def modifier_fournisseur_endpoint(req: FournisseurUpdateGatewayRequest):
"""
Modification d'un fournisseur dans Sage
"""
try:
resultat = sage.modifier_fournisseur(req.code, req.fournisseur_data)
return {"success": True, "data": resultat}
except ValueError as e:
logger.warning(f"Erreur métier modification fournisseur: {e}")
raise HTTPException(404, str(e))
except Exception as e:
logger.error(f"Erreur technique modification fournisseur: {e}")
raise HTTPException(500, str(e))
@app.post("/sage/fournisseurs/get", dependencies=[Depends(verify_token)]) @app.post("/sage/fournisseurs/get", dependencies=[Depends(verify_token)])
def fournisseur_get(req: CodeRequest): def fournisseur_get(req: CodeRequest):
""" """

View file

@ -710,6 +710,212 @@ class SageConnector:
raise RuntimeError(f"Erreur technique Sage: {error_message}") raise RuntimeError(f"Erreur technique Sage: {error_message}")
def modifier_fournisseur(self, code: str, fournisseur_data: Dict) -> Dict:
"""
Modification d'un fournisseur existant dans Sage 100c
IMPORTANT: Utilise FactoryFournisseur.ReadNumero() pour charger le fournisseur
Args:
code: Code du fournisseur à modifier
fournisseur_data: Dictionnaire avec les champs à mettre à jour
Returns:
Fournisseur modifié
"""
if not self.cial:
raise RuntimeError("Connexion Sage non établie")
try:
with self._com_context(), self._lock_com:
# ========================================
# ÉTAPE 1 : CHARGER LE FOURNISSEUR EXISTANT
# ========================================
logger.info(f"🔍 Recherche fournisseur {code}...")
factory_fournisseur = self.cial.CptaApplication.FactoryFournisseur
persist = factory_fournisseur.ReadNumero(code)
if not persist:
raise ValueError(f"Fournisseur {code} introuvable")
fournisseur = self._cast_client(persist) # ✅ Réutiliser _cast_client
if not fournisseur:
raise ValueError(f"Impossible de charger le fournisseur {code}")
logger.info(f"✅ Fournisseur {code} trouvé: {getattr(fournisseur, 'CT_Intitule', '')}")
# ========================================
# ÉTAPE 2 : METTRE À JOUR LES CHAMPS FOURNIS
# ========================================
logger.info("📝 Mise à jour des champs...")
champs_modifies = []
# Intitulé
if "intitule" in fournisseur_data:
intitule = str(fournisseur_data["intitule"])[:69].strip()
fournisseur.CT_Intitule = intitule
champs_modifies.append(f"intitule='{intitule}'")
# Adresse
if any(k in fournisseur_data for k in ["adresse", "code_postal", "ville", "pays"]):
try:
adresse_obj = fournisseur.Adresse
if "adresse" in fournisseur_data:
adresse = str(fournisseur_data["adresse"])[:35].strip()
adresse_obj.Adresse = adresse
champs_modifies.append("adresse")
if "code_postal" in fournisseur_data:
cp = str(fournisseur_data["code_postal"])[:9].strip()
adresse_obj.CodePostal = cp
champs_modifies.append("code_postal")
if "ville" in fournisseur_data:
ville = str(fournisseur_data["ville"])[:35].strip()
adresse_obj.Ville = ville
champs_modifies.append("ville")
if "pays" in fournisseur_data:
pays = str(fournisseur_data["pays"])[:35].strip()
adresse_obj.Pays = pays
champs_modifies.append("pays")
except Exception as e:
logger.warning(f"⚠️ Erreur mise à jour adresse: {e}")
# Télécom
if "email" in fournisseur_data or "telephone" in fournisseur_data:
try:
telecom_obj = fournisseur.Telecom
if "email" in fournisseur_data:
email = str(fournisseur_data["email"])[:69].strip()
telecom_obj.EMail = email
champs_modifies.append("email")
if "telephone" in fournisseur_data:
tel = str(fournisseur_data["telephone"])[:21].strip()
telecom_obj.Telephone = tel
champs_modifies.append("telephone")
except Exception as e:
logger.warning(f"⚠️ Erreur mise à jour télécom: {e}")
# SIRET
if "siret" in fournisseur_data:
try:
siret = str(fournisseur_data["siret"])[:14].strip()
fournisseur.CT_Siret = siret
champs_modifies.append("siret")
except Exception as e:
logger.warning(f"⚠️ Erreur mise à jour SIRET: {e}")
# TVA Intracommunautaire
if "tva_intra" in fournisseur_data:
try:
tva = str(fournisseur_data["tva_intra"])[:25].strip()
fournisseur.CT_Identifiant = tva
champs_modifies.append("tva_intra")
except Exception as e:
logger.warning(f"⚠️ Erreur mise à jour TVA: {e}")
if not champs_modifies:
logger.warning("⚠️ Aucun champ à modifier")
# Retourner les données actuelles via extraction directe
return {
"numero": getattr(fournisseur, "CT_Num", "").strip(),
"intitule": getattr(fournisseur, "CT_Intitule", "").strip(),
"type": 1,
"est_fournisseur": True
}
logger.info(f"📝 Champs à modifier: {', '.join(champs_modifies)}")
# ========================================
# ÉTAPE 3 : ÉCRIRE LES MODIFICATIONS
# ========================================
logger.info("💾 Écriture des modifications...")
try:
fournisseur.Write()
logger.info("✅ Write() réussi !")
except Exception as e:
error_detail = str(e)
try:
sage_error = self.cial.CptaApplication.LastError
if sage_error:
error_detail = f"{sage_error.Description} (Code: {sage_error.Number})"
except:
pass
logger.error(f"❌ Erreur Write(): {error_detail}")
raise RuntimeError(f"Échec modification: {error_detail}")
# ========================================
# ÉTAPE 4 : RELIRE ET RETOURNER
# ========================================
fournisseur.Read()
logger.info(f"✅✅✅ FOURNISSEUR MODIFIÉ: {code} ({len(champs_modifies)} champs) ✅✅✅")
# Extraction directe (comme lire_fournisseur)
numero = getattr(fournisseur, "CT_Num", "").strip()
intitule = getattr(fournisseur, "CT_Intitule", "").strip()
data = {
"numero": numero,
"intitule": intitule,
"type": 1,
"est_fournisseur": True
}
# Adresse
try:
adresse_obj = getattr(fournisseur, "Adresse", None)
if adresse_obj:
data["adresse"] = getattr(adresse_obj, "Adresse", "").strip()
data["code_postal"] = getattr(adresse_obj, "CodePostal", "").strip()
data["ville"] = getattr(adresse_obj, "Ville", "").strip()
except:
data["adresse"] = ""
data["code_postal"] = ""
data["ville"] = ""
# Télécom
try:
telecom_obj = getattr(fournisseur, "Telecom", None)
if telecom_obj:
data["telephone"] = getattr(telecom_obj, "Telephone", "").strip()
data["email"] = getattr(telecom_obj, "EMail", "").strip()
except:
data["telephone"] = ""
data["email"] = ""
return data
except ValueError as e:
logger.error(f"❌ Erreur métier: {e}")
raise
except Exception as e:
logger.error(f"❌ Erreur modification fournisseur: {e}", exc_info=True)
error_message = str(e)
if self.cial:
try:
err = self.cial.CptaApplication.LastError
if err:
error_message = f"Erreur Sage: {err.Description}"
except:
pass
raise RuntimeError(f"Erreur technique Sage: {error_message}")
def lire_fournisseur(self, code): def lire_fournisseur(self, code):
""" """
NOUVEAU : Lecture d'un fournisseur par code NOUVEAU : Lecture d'un fournisseur par code