Files
MP-Manager/scripts/analyze_sucursal_discrepancies.py
T
2026-05-30 14:31:19 -06:00

147 lines
6.2 KiB
Python

import os
import sys
import sqlite3
import json
# Ruta a la base de datos (un nivel arriba del script)
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 # noqa: E402
from paths import DB_PATH
_schema_cache = {}
_tokens_map = None
def get_location_token(location_id):
global _tokens_map
if _tokens_map is None:
_tokens_map = sync_engine.get_tokens_map()
return _tokens_map.get(location_id)
def get_schema_field_id(location_id, object_key, field_name):
cache_key = (location_id, object_key)
if cache_key not in _schema_cache:
token = get_location_token(location_id)
if not token:
_schema_cache[cache_key] = {}
else:
_schema_cache[cache_key] = sync_engine.ghl_client.get_object_schema(token, location_id, object_key)
return _schema_cache[cache_key].get(field_name)
def extract_custom_field_value(cf_json, field_id):
if not field_id or not cf_json:
return None
try:
cfs = json.loads(cf_json)
if isinstance(cfs, list):
for cf in cfs:
if cf.get("id") == field_id or cf.get("fieldId") == field_id:
return cf.get("value")
except Exception:
pass
return None
def analyze_discrepancies():
if not os.path.exists(DB_PATH):
print(f"Error: La base de datos local no existe en {DB_PATH}.")
print("Por favor, ejecuta la sincronización global primero desde el dashboard.")
sys.exit(1)
conn = sqlite3.connect(DB_PATH)
conn.row_factory = sqlite3.Row
try:
# 1. Obtener todas las cuentas y mapear sus IDs y nombres
accounts_rows = conn.execute("SELECT location_id, nombre FROM accounts").fetchall()
branches = {}
for r in accounts_rows:
name = r['nombre']
# Normalizar nombre de sucursal para comparación (ej. de "85932 - MP - La Viga" a "la viga")
normalized_name = name.lower()
for token in ["mp", "-", "859", "0001", "qro", "demo", "plaza"]:
normalized_name = normalized_name.replace(token, "")
normalized_name = " ".join(normalized_name.split())
branches[r['location_id']] = {
"full_name": name,
"clean_name": normalized_name
}
# 2. Consultar todas las oportunidades y sus contactos asociados
sql = """
SELECT o.id as opp_id, o.name as opp_name, o.location_id as opp_loc_id, o.status as opp_status,
c.id as contact_id, c.first_name, c.last_name, c.custom_fields_json, c.location_id as contact_loc_id
FROM opportunities o
JOIN contacts c ON o.contact_id = c.id AND o.location_id = c.location_id
"""
opps = conn.execute(sql).fetchall()
print("=== ANÁLISIS DE DISCREPANCIAS DE SUCURSAL ===")
print(f"Total de oportunidades con contactos analizadas: {len(opps)}")
print("Buscando inconsistencias entre la sucursal del contacto (campo custom) y la ubicación real de la oportunidad...\n")
print("-" * 110)
discrepancies_count = 0
missing_schema_locations = set()
for row in opps:
opp_loc_id = row['opp_loc_id']
contact_cf_json = row['custom_fields_json']
contact_loc_id = row['contact_loc_id']
# Obtener nombre de la sucursal donde vive la oportunidad
opp_branch_info = branches.get(opp_loc_id, {"full_name": "Desconocida", "clean_name": ""})
opp_branch_clean = opp_branch_info["clean_name"]
# Leer solo el campo personalizado Sucursal resuelto dinamicamente por schema.
contact_sucursal_val = None
sucursal_field_id = get_schema_field_id(contact_loc_id, "contact", "Sucursal")
if not sucursal_field_id:
missing_schema_locations.add(contact_loc_id)
else:
val = str(extract_custom_field_value(contact_cf_json, sucursal_field_id) or "").strip()
val_lower = val.lower()
for loc_id, b_info in branches.items():
b_clean = b_info["clean_name"]
if b_clean and b_clean in val_lower:
contact_sucursal_val = b_info["full_name"]
break
# Si el contacto tiene un valor de sucursal definido, pero no se parece al de la oportunidad
if contact_sucursal_val:
# Normalizar la sucursal del contacto para comparar
c_suc_clean = contact_sucursal_val.lower()
for token in ["mp", "-", "859", "0001", "qro", "demo", "plaza"]:
c_suc_clean = c_suc_clean.replace(token, "")
c_suc_clean = " ".join(c_suc_clean.split())
# Si los nombres limpios difieren, hay discrepancia
if c_suc_clean != opp_branch_clean:
discrepancies_count += 1
contact_name = f"{row['first_name'] or ''} {row['last_name'] or ''}".strip()
print(f"{discrepancies_count:02d}. Oportunidad: {row['opp_name']}")
print(f" Cliente: {contact_name} (ID: {row['contact_id']})")
print(f" Ubicación Opp: {opp_branch_info['full_name']} ({opp_loc_id})")
print(f" Campo Contact: {contact_sucursal_val}")
print(f" Estado Opp: {row['opp_status'].upper()}")
print("-" * 110)
print(f"\nAnálisis finalizado.")
if missing_schema_locations:
print(f"Locations sin campo Sucursal resuelto por schema: {len(missing_schema_locations)}")
if discrepancies_count == 0:
print("¡Felicidades! No se detectaron discrepancias de sucursal en la base de datos.")
else:
print(f"Se encontraron {discrepancies_count} discrepancias de sucursal.")
print("Se recomienda correr el script 'fix_sucursal_discrepancies.py' para corregir automáticamente.")
finally:
conn.close()
if __name__ == "__main__":
analyze_discrepancies()