validation method par SQL, dangereux actuellement mais "seem" functionnal

This commit is contained in:
fanilo 2026-01-15 12:22:04 +01:00
parent 6b4b603aee
commit 5c80a5e912

View file

@ -293,113 +293,70 @@ def introspecter_validation(connector, numero_facture: str = None) -> Dict:
def valider_facture(connector, numero_facture: str) -> Dict: def valider_facture(connector, numero_facture: str) -> Dict:
""" """
Valide via late binding forcé + invocation COM correcte Valide une facture via SQL direct
Contourne les règles métier Sage - à utiliser avec précaution
""" """
import win32com.client logger.info(f"🔒 Validation facture {numero_facture} (SQL direct)")
import win32com.client.dynamic
import pythoncom
if not connector.cial: # Vérifications préalables
raise RuntimeError("Connexion Sage non établie") with connector._get_sql_connection() as conn:
cursor = conn.cursor()
logger.info(f"🔒 Validation facture {numero_facture} (v5)") # Vérifier que la facture existe et peut être validée
cursor.execute(
"""
SELECT DO_Valide, DO_Statut, DO_TotalTTC, DO_MontantRegle
FROM F_DOCENTETE
WHERE DO_Piece = ? AND DO_Type = 6
""",
(numero_facture,),
)
with connector._com_context(), connector._lock_com: row = cursor.fetchone()
factory = connector.cial.FactoryDocumentVente if not row:
if not factory.ExistPiece(60, numero_facture):
raise ValueError(f"Facture {numero_facture} introuvable") raise ValueError(f"Facture {numero_facture} introuvable")
persist = factory.ReadPiece(60, numero_facture) valide_avant, statut, total_ttc, montant_regle = row
doc = win32com.client.CastTo(persist, "IBODocumentVente3")
doc.Read()
# Lecture via getattr if valide_avant == 1:
valide_avant = getattr(doc, "DO_Valide", None)
imprim_avant = getattr(doc, "DO_Imprim", None)
logger.info(f" Avant: DO_Imprim={imprim_avant}, DO_Valide={valide_avant}")
if valide_avant == True:
return {"numero_facture": numero_facture, "deja_valide": True} return {"numero_facture": numero_facture, "deja_valide": True}
oleobj = doc._oleobj_ if statut == 6: # Annulé
raise ValueError("Facture annulée, validation impossible")
# Explorer les DISPID # Valider via SQL
type_info = oleobj.GetTypeInfo() cursor.execute(
type_attr = type_info.GetTypeAttr() """
UPDATE F_DOCENTETE
SET DO_Valide = 1, DO_Imprim = 1
WHERE DO_Piece = ? AND DO_Type = 6
""",
(numero_facture,),
)
dispids = {} conn.commit()
for i in range(type_attr.cFuncs):
func_desc = type_info.GetFuncDesc(i)
names = type_info.GetNames(func_desc.memid)
if names:
name = names[0]
if name in ("DO_Valide", "DO_Imprim"):
invkind = func_desc.invkind
logger.info(
f" {name}: memid={func_desc.memid}, invkind={invkind}, cParams={func_desc.cParamsOpt}"
)
dispids[name] = {
"memid": func_desc.memid,
"invkind": invkind,
"cParams": func_desc.cParamsOpt,
}
logger.info(f" DISPIDs trouvés: {dispids}") # Vérifier
cursor.execute(
"""
SELECT DO_Valide, DO_Imprim
FROM F_DOCENTETE
WHERE DO_Piece = ? AND DO_Type = 6
""",
(numero_facture,),
)
errors = [] valide_apres, imprim_apres = cursor.fetchone()
# Méthode A: Invoke PROPERTYPUT logger.info(f" SQL: DO_Valide={valide_apres}, DO_Imprim={imprim_apres}")
if "DO_Valide" in dispids:
memid = dispids["DO_Valide"]["memid"]
try:
oleobj.Invoke(memid, 0, pythoncom.DISPATCH_PROPERTYPUT, False, True)
doc.Write()
logger.info(f" ✅ Méthode A: Invoke PROPERTYPUT OK")
except Exception as e:
errors.append(f"Invoke PROPERTYPUT: {e}")
logger.warning(f" Méthode A échouée: {e}")
# Méthode B: DumbDispatch
try:
raw_dispatch = win32com.client.dynamic.DumbDispatch(oleobj)
raw_dispatch.DO_Valide = True
doc.Write()
logger.info(f" ✅ Méthode B: DumbDispatch OK")
except Exception as e:
errors.append(f"DumbDispatch: {e}")
logger.warning(f" Méthode B échouée: {e}")
# Méthode C: Dispatch dynamique combiné
try:
if "DO_Valide" in dispids:
memid = dispids["DO_Valide"]["memid"]
oleobj.Invoke(
memid,
0,
pythoncom.DISPATCH_PROPERTYPUT | pythoncom.DISPATCH_METHOD,
False,
True,
)
doc.Write()
logger.info(f" ✅ Méthode C: Combined flags OK")
except Exception as e:
errors.append(f"Combined flags: {e}")
logger.warning(f" Méthode C échouée: {e}")
# Vérification
doc.Read()
valide_apres = getattr(doc, "DO_Valide", None)
imprim_apres = getattr(doc, "DO_Imprim", None)
logger.info(f" Après: DO_Imprim={imprim_apres}, DO_Valide={valide_apres}")
return { return {
"numero_facture": numero_facture, "numero_facture": numero_facture,
"avant": {"DO_Imprim": imprim_avant, "DO_Valide": valide_avant}, "methode": "SQL_DIRECT",
"apres": {"DO_Imprim": imprim_apres, "DO_Valide": valide_apres}, "DO_Valide": valide_apres == 1,
"dispids": dispids, "DO_Imprim": imprim_apres == 1,
"errors": errors, "success": valide_apres == 1,
"success": valide_apres == True, "warning": "Validation SQL directe - règles métier Sage contournées",
} }