diff --git a/sage_connector.py b/sage_connector.py index c778837..840517f 100644 --- a/sage_connector.py +++ b/sage_connector.py @@ -108,7 +108,7 @@ from utils.documents.validations import ( devalider_facture as _devalider, get_statut_validation as _get_statut, introspecter_validation as _introspect, - explorer_impression_validation as _introspect_doc, + explorer_toutes_interfaces_validation as _introspect_doc, ) logger = logging.getLogger(__name__) diff --git a/utils/documents/validations.py b/utils/documents/validations.py index c12eee0..b2c3fcc 100644 --- a/utils/documents/validations.py +++ b/utils/documents/validations.py @@ -292,10 +292,6 @@ def introspecter_validation(connector, numero_facture: str = None) -> Dict: def valider_facture(connector, numero_facture: str) -> Dict: - """ - Valide une facture via SQL direct - ⚠️ Contourne les règles métier Sage - à utiliser avec précaution - """ logger.info(f"🔒 Validation facture {numero_facture} (SQL direct)") # Vérifications préalables @@ -328,7 +324,7 @@ def valider_facture(connector, numero_facture: str) -> Dict: cursor.execute( """ UPDATE F_DOCENTETE - SET DO_Valide = 1, DO_Imprim = 1 + SET DO_Valide = 1, DO_Imprim = 0 WHERE DO_Piece = ? AND DO_Type = 6 """, (numero_facture,), @@ -536,118 +532,73 @@ def _valider_document_com(connector, numero_facture: str, valider: bool = True) raise RuntimeError(f"Échec {action}: {'; '.join(erreurs[:5])}") -def explorer_impression_validation(connector, numero_facture: str) -> Dict: - """Explorer les méthodes d'impression/validation pour les factures""" - result = {"numero_facture": numero_facture} +def explorer_toutes_interfaces_validation(connector, numero_facture: str) -> Dict: + """Explorer TOUTES les interfaces possibles pour trouver un setter DO_Valide""" + import win32com.client + import pythoncom + + result = {"numero_facture": numero_facture, "interfaces": {}} with connector._com_context(), connector._lock_com: factory = connector.cial.FactoryDocumentVente persist = factory.ReadPiece(60, numero_facture) - doc = win32com.client.CastTo(persist, "IBODocumentVente3") - doc.Read() - # 1. CreateProcess_Document SANS paramètre - try: - process = connector.cial.CreateProcess_Document() - attrs = [a for a in dir(process) if not a.startswith("_")] - result["CreateProcess_Document_no_param"] = { - "attrs": attrs, - "print_related": [ - a - for a in attrs - if any( - x in a.lower() - for x in ["print", "imprim", "edit", "model", "bgc", "valid"] - ) - ], - } - - # Essayer d'assigner le document - if "Document" in attrs: - try: - process.Document = doc - result["CreateProcess_Document_no_param"]["Document_assigned"] = ( - True - ) - except Exception as e: - result["CreateProcess_Document_no_param"]["Document_error"] = str(e) - - if "SetDocument" in attrs: - try: - process.SetDocument(doc) - result["CreateProcess_Document_no_param"]["SetDocument_ok"] = True - except Exception as e: - result["CreateProcess_Document_no_param"]["SetDocument_error"] = ( - str(e) - ) - - except Exception as e: - result["CreateProcess_Document_no_param_error"] = str(e) - - # 2. CreateProcess_Document avec type (60 = facture) - try: - process = connector.cial.CreateProcess_Document(60) - attrs = [a for a in dir(process) if not a.startswith("_")] - result["CreateProcess_Document_type60"] = {"attrs": attrs} - except Exception as e: - result["CreateProcess_Document_type60_error"] = str(e) - - # 3. Explorer TOUS les CreateProcess - cial_attrs = [a for a in dir(connector.cial) if "CreateProcess" in a] - result["all_createprocess"] = cial_attrs - - # 4. Chercher spécifiquement impression/validation - for proc_name in cial_attrs: - if any( - x in proc_name.lower() - for x in ["imprim", "print", "edit", "valid", "confirm"] - ): - try: - proc = getattr(connector.cial, proc_name)() - proc_attrs = [a for a in dir(proc) if not a.startswith("_")] - result[proc_name] = { - "attrs": proc_attrs, - "has_modele": [ - a - for a in proc_attrs - if "model" in a.lower() or "bgc" in a.lower() - ], - "has_document": "Document" in proc_attrs - or "SetDocument" in proc_attrs, - } - except Exception as e: - result[proc_name] = {"error": str(e)} - - # 5. Explorer le document pour méthodes Print/Imprimer - doc_attrs = [a for a in dir(doc) if not a.startswith("_")] - result["doc_print_methods"] = [ - a - for a in doc_attrs - if any(x in a.lower() for x in ["print", "imprim", "edit", "valid"]) + # Liste des interfaces à tester + interfaces = [ + "IBODocumentVente3", + "IBODocument3", + "IBIPersistObject", + "IBIDocument", + "IPMDocument", + "IDispatch", ] - # 6. Chercher IPMDocument (Process Manager) - try: - pm = win32com.client.CastTo(persist, "IPMDocument") - pm_attrs = [a for a in dir(pm) if not a.startswith("_")] - result["IPMDocument"] = { - "attrs": pm_attrs, - "print_related": [ - a - for a in pm_attrs - if any( - x in a.lower() - for x in ["print", "imprim", "edit", "valid", "process"] - ) - ], - } - except Exception as e: - result["IPMDocument_error"] = str(e) + for iface_name in interfaces: + try: + obj = win32com.client.CastTo(persist, iface_name) + if hasattr(obj, "Read"): + obj.Read() - # 7. Chemin du modèle BGC - result["modele_bgc_path"] = ( - r"C:\Users\Public\Documents\Sage\Entreprise 100c\fr-FR\Documents standards\Gestion commerciale\Ventes\Facture client.bgc" - ) + oleobj = obj._oleobj_ + type_info = oleobj.GetTypeInfo() + type_attr = type_info.GetTypeAttr() + + props = {} + for i in range(type_attr.cFuncs): + func_desc = type_info.GetFuncDesc(i) + names = type_info.GetNames(func_desc.memid) + if names and names[0] in ( + "DO_Valide", + "DO_Imprim", + "Valider", + "Validate", + "Lock", + ): + props[names[0]] = { + "memid": func_desc.memid, + "invkind": func_desc.invkind, + # invkind: 1=METHOD, 2=GET, 4=PUT, 8=PUTREF + "has_setter": (func_desc.invkind & 4) == 4, + } + + result["interfaces"][iface_name] = { + "success": True, + "properties": props, + } + + except Exception as e: + result["interfaces"][iface_name] = {"error": str(e)[:100]} + + # Explorer aussi FactoryDocumentVente pour des méthodes de validation + try: + factory_attrs = [a for a in dir(factory) if not a.startswith("_")] + result["factory_methods"] = [ + a + for a in factory_attrs + if any(x in a.lower() for x in ["valid", "lock", "confirm", "imprim"]) + ] + except: + pass return result