#!/usr/bin/env python3 # -*- coding: utf-8 -*- """Sincroniza y lista todos los workflows de todas las cuentas.""" import argparse import os import sys import concurrent.futures ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) if ROOT_DIR not in sys.path: sys.path.insert(0, ROOT_DIR) import sync_engine import db import error_logging import script_audit def fetch_and_save_workflows_for_location(location): location_id = location["location_id"] nombre = location["nombre"] token = location["token"] print(f"[{nombre}] Consultando workflows...") try: workflows = sync_engine.ghl_client.get_workflows(token, location_id) db.save_workflows(location_id, workflows) print(f"[{nombre}] Sincronizados {len(workflows)} workflows.") return location_id, nombre, workflows, None except Exception as e: error_id = error_logging.log_error("sync_workflows_single_location_failed", e, {"location_id": location_id}) print(f"[{nombre}] Error: {str(e)} | error_id={error_id}") return location_id, nombre, [], str(e) def main(): parser = argparse.ArgumentParser(description="Sincroniza y lista todos los workflows de todas las cuentas.") parser.add_argument("--location", help="ID de ubicación específica para sincronizar (por defecto todas)") parser.add_argument("--include-main", action="store_true", help="Incluye la cuenta de marca principal") parser.add_argument("--run-id", help="ID de auditoría para la ejecución del script") args = parser.parse_args() # Informar el inicio en la auditoría si hay run_id if args.run_id: script_audit.update_run_status(args.run_id, "running") print("=== CONTROL DE SCRIPTS: sync_workflows.py ===") print("Descripción: Obtiene todos los workflows de todas las cuentas de GHL y los almacena en SQLite.") print("----------------------------------------------------------------------") try: # Cargar todas las cuentas accounts = sync_engine.parse_accounts_csv() if not args.include_main: # Filtrar marca principal a menos que se especifique --include-main o se use una específica accounts = [acc for acc in accounts if acc["location_id"] != "GbKkBpCmKu2QmloKFHy3" or args.location == "GbKkBpCmKu2QmloKFHy3"] if args.location: accounts = [acc for acc in accounts if acc["location_id"] == args.location] if not accounts: print(f"Error: No se encontró la ubicación {args.location} en el CSV.") if args.run_id: script_audit.update_run_status(args.run_id, "failed", error_message=f"Location {args.location} not found") sys.exit(1) print(f"Se procesarán {len(accounts)} cuenta(s)...") # Ejecutar en paralelo con un máximo de 5 hilos results = [] with concurrent.futures.ThreadPoolExecutor(max_workers=5) as executor: futures = [executor.submit(fetch_and_save_workflows_for_location, acc) for acc in accounts] for future in concurrent.futures.as_completed(futures): results.append(future.result()) # Imprimir resumen de los resultados total_workflows = 0 total_active = 0 total_inactive = 0 total_draft = 0 failed_accounts = [] print("\n=== RESUMEN DE WORKFLOWS POR CUENTA ===") print(f"{'Cuenta':<40} | {'Total':<6} | {'Active':<6} | {'Inactive':<8} | {'Draft':<6} | {'Estado':<10}") print("-" * 88) for loc_id, nombre, wfs, err in results: if err: failed_accounts.append((nombre, err)) print(f"{nombre:<40} | {'-':<6} | {'-':<6} | {'-':<8} | {'-':<6} | ERROR") continue active = sum(1 for w in wfs if w.get("status") in ("active", "published")) inactive = sum(1 for w in wfs if w.get("status") == "inactive") draft = sum(1 for w in wfs if w.get("status") == "draft") total = len(wfs) total_workflows += total total_active += active total_inactive += inactive total_draft += draft print(f"{nombre:<40} | {total:<6} | {active:<6} | {inactive:<8} | {draft:<6} | OK") print("-" * 88) print(f"{'TOTAL GENERAL':<40} | {total_workflows:<6} | {total_active:<6} | {total_inactive:<8} | {total_draft:<6} |") print("----------------------------------------------------------------------") # Mostrar detalle de errores si los hubo if failed_accounts: print("\nDetalle de errores:") for name, err in failed_accounts: print(f"- {name}: {err}") # Registrar éxito en la auditoría si hay run_id if args.run_id: script_audit.update_run_status(args.run_id, "success") print("\nSincronización completada con éxito.") except Exception as e: error_id = error_logging.log_error("sync_workflows_script_failed", e) print(f"Error crítico en la ejecución del script: {e} | error_id={error_id}") if args.run_id: script_audit.update_run_status(args.run_id, "failed", error_message=str(e)) sys.exit(1) if __name__ == "__main__": main()