import argparse import os import sqlite3 import sys import sys as _sys, os as _os _sys.path.insert(0, _os.path.dirname(_os.path.dirname(_os.path.abspath(__file__)))) from paths import DB_PATH as DB_PATH BRAND_LOCATION_ID = "GbKkBpCmKu2QmloKFHy3" TRACKED_STATUSES = ("open", "won", "lost", "abandoned") def parse_args(): parser = argparse.ArgumentParser( description="Resume oportunidades por sucursal y estado usando la base SQLite local." ) parser.add_argument("--location", help="ID de una sucursal especifica") parser.add_argument("--include-main", action="store_true", help="Incluye la cuenta de marca principal") parser.add_argument("--include-demo", action="store_true", help="Incluye cuentas cuyo nombre contiene 'demo'") parser.add_argument("--show-empty", action="store_true", help="Muestra sucursales sin oportunidades") return parser.parse_args() def status_key(status): return (status or "open").strip().lower() or "open" def build_accounts_query(args): where = [] params = [] if args.location: where.append("a.location_id = ?") params.append(args.location) elif not args.include_main: where.append("a.location_id != ?") params.append(BRAND_LOCATION_ID) if not args.include_demo: where.append("LOWER(a.nombre) NOT LIKE ?") params.append("%demo%") sql = """ SELECT a.location_id, a.nombre, a.type FROM accounts a """ if where: sql += " WHERE " + " AND ".join(where) sql += " ORDER BY a.nombre COLLATE NOCASE" return sql, params def summarize(args): if not os.path.exists(DB_PATH): print(f"Error: La base de datos local no existe en {DB_PATH}.") print("Ejecuta primero la sincronizacion global desde el dashboard.") sys.exit(1) conn = sqlite3.connect(DB_PATH) conn.row_factory = sqlite3.Row try: accounts_sql, account_params = build_accounts_query(args) accounts = conn.execute(accounts_sql, account_params).fetchall() if not accounts: print("No se encontraron sucursales con los filtros indicados.") return 0 summaries = [] unknown_statuses = {} totals = {status: 0 for status in TRACKED_STATUSES} totals["other"] = 0 totals["total"] = 0 for account in accounts: rows = conn.execute( """ SELECT status, COUNT(*) AS count FROM opportunities WHERE location_id = ? GROUP BY status """, (account["location_id"],), ).fetchall() counts = {status: 0 for status in TRACKED_STATUSES} other = 0 for row in rows: key = status_key(row["status"]) count = row["count"] or 0 if key in counts: counts[key] += count else: other += count unknown_statuses[key] = unknown_statuses.get(key, 0) + count total = sum(counts.values()) + other if total == 0 and not args.show_empty: continue for status in TRACKED_STATUSES: totals[status] += counts[status] totals["other"] += other totals["total"] += total summaries.append({ "name": account["nombre"], "location_id": account["location_id"], "type": account["type"], "counts": counts, "other": other, "total": total, }) print("=== RESUMEN GLOBAL DE OPORTUNIDADES POR SUCURSAL ===") print("Fuente: SQLite local (ultima sincronizacion del dashboard)") print(f"Cuentas incluidas: {len(summaries)}") print(f"Marca incluida: {'si' if args.include_main else 'no'}") print(f"Demos incluidas: {'si' if args.include_demo else 'no'}") if args.location: print(f"Filtro location: {args.location}") print() header = f"{'Sucursal':<36} {'Abiertas':>9} {'Ganadas':>9} {'Perdidas':>9} {'Abandon.':>9} {'Otros':>7} {'Total':>7}" print(header) print("-" * len(header)) for item in summaries: counts = item["counts"] name = item["name"][:36] print( f"{name:<36} {counts['open']:>9} {counts['won']:>9} " f"{counts['lost']:>9} {counts['abandoned']:>9} {item['other']:>7} {item['total']:>7}" ) print("-" * len(header)) print( f"{'TOTAL':<36} {totals['open']:>9} {totals['won']:>9} " f"{totals['lost']:>9} {totals['abandoned']:>9} {totals['other']:>7} {totals['total']:>7}" ) if unknown_statuses: print("\nEstados no estandar encontrados:") for status, count in sorted(unknown_statuses.items(), key=lambda item: item[0]): print(f" {status}: {count}") return 0 finally: conn.close() if __name__ == "__main__": if sys.platform == "win32": try: sys.stdout.reconfigure(encoding="utf-8") except AttributeError: pass sys.exit(summarize(parse_args()))