validation method par SQL, dangereux actuellement mais "seem" functionnal
This commit is contained in:
parent
6b4b603aee
commit
5c80a5e912
1 changed files with 47 additions and 90 deletions
|
|
@ -293,113 +293,70 @@ def introspecter_validation(connector, numero_facture: str = None) -> 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
|
||||
import win32com.client.dynamic
|
||||
import pythoncom
|
||||
logger.info(f"🔒 Validation facture {numero_facture} (SQL direct)")
|
||||
|
||||
if not connector.cial:
|
||||
raise RuntimeError("Connexion Sage non établie")
|
||||
# Vérifications préalables
|
||||
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:
|
||||
factory = connector.cial.FactoryDocumentVente
|
||||
|
||||
if not factory.ExistPiece(60, numero_facture):
|
||||
row = cursor.fetchone()
|
||||
if not row:
|
||||
raise ValueError(f"Facture {numero_facture} introuvable")
|
||||
|
||||
persist = factory.ReadPiece(60, numero_facture)
|
||||
doc = win32com.client.CastTo(persist, "IBODocumentVente3")
|
||||
doc.Read()
|
||||
valide_avant, statut, total_ttc, montant_regle = row
|
||||
|
||||
# Lecture via getattr
|
||||
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:
|
||||
if valide_avant == 1:
|
||||
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
|
||||
type_info = oleobj.GetTypeInfo()
|
||||
type_attr = type_info.GetTypeAttr()
|
||||
# Valider via SQL
|
||||
cursor.execute(
|
||||
"""
|
||||
UPDATE F_DOCENTETE
|
||||
SET DO_Valide = 1, DO_Imprim = 1
|
||||
WHERE DO_Piece = ? AND DO_Type = 6
|
||||
""",
|
||||
(numero_facture,),
|
||||
)
|
||||
|
||||
dispids = {}
|
||||
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,
|
||||
}
|
||||
conn.commit()
|
||||
|
||||
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
|
||||
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}")
|
||||
logger.info(f" SQL: DO_Valide={valide_apres}, DO_Imprim={imprim_apres}")
|
||||
|
||||
return {
|
||||
"numero_facture": numero_facture,
|
||||
"avant": {"DO_Imprim": imprim_avant, "DO_Valide": valide_avant},
|
||||
"apres": {"DO_Imprim": imprim_apres, "DO_Valide": valide_apres},
|
||||
"dispids": dispids,
|
||||
"errors": errors,
|
||||
"success": valide_apres == True,
|
||||
"methode": "SQL_DIRECT",
|
||||
"DO_Valide": valide_apres == 1,
|
||||
"DO_Imprim": imprim_apres == 1,
|
||||
"success": valide_apres == 1,
|
||||
"warning": "Validation SQL directe - règles métier Sage contournées",
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue