Initial commit - dashboard leads
This commit is contained in:
150
backend/export_base_junta.py
Normal file
150
backend/export_base_junta.py
Normal file
@@ -0,0 +1,150 @@
|
||||
# backend/export_base_junta.py
|
||||
"""
|
||||
Une los leads de Postgre (Fact_Leads_Procesados, mapa de campañas) + Supabase,
|
||||
deduplica por teléfono quedándose con el MÁS ANTIGUO (desempate: Pauta_wsp_face),
|
||||
y exporta un Excel con: Telefono, Canal, Fecha Creada.
|
||||
|
||||
Uso: py -3.12 export_base_junta.py
|
||||
"""
|
||||
import os
|
||||
from datetime import datetime
|
||||
from dotenv import load_dotenv
|
||||
from data_manager_v2 import DataManager
|
||||
|
||||
load_dotenv()
|
||||
|
||||
# Canal preferido en caso de empate de fecha
|
||||
CANAL_PREFERIDO = "Pauta_wsp_face"
|
||||
|
||||
|
||||
def _norm_tel(v):
|
||||
s = str(v or "")
|
||||
for x in ("+51", "+", " ", "-", "(", ")"):
|
||||
s = s.replace(x, "")
|
||||
return s.strip()
|
||||
|
||||
|
||||
def _txt(v):
|
||||
"""Texto en MAYÚSCULAS; '-' o vacío → ''."""
|
||||
s = str(v or "").strip()
|
||||
if s == "-":
|
||||
s = ""
|
||||
return s.upper()
|
||||
|
||||
|
||||
def _to_dt(v):
|
||||
if v is None:
|
||||
return None
|
||||
if isinstance(v, datetime):
|
||||
return v
|
||||
s = str(v)[:19]
|
||||
for fmt in ("%Y-%m-%d %H:%M:%S", "%Y-%m-%dT%H:%M:%S", "%Y-%m-%d", "%d/%m/%Y", "%d-%m-%Y"):
|
||||
try:
|
||||
return datetime.strptime(s[:len(fmt) + 2] if "%H" in fmt else s[:10], fmt)
|
||||
except Exception:
|
||||
pass
|
||||
return None
|
||||
|
||||
|
||||
def traer_postgre(dm):
|
||||
"""Mismos leads que Fact_Leads_Procesados (mapa de campañas): tel, fecha, canal(origen)."""
|
||||
filas = dm.traer_leads_chatwoot() # ya aplica el mapa de campañas y trae 'origen'
|
||||
out = []
|
||||
for f in filas:
|
||||
tel = _norm_tel(f.get("telefono"))
|
||||
if not tel:
|
||||
continue
|
||||
out.append({
|
||||
"telefono": tel,
|
||||
"fecha": _to_dt(f.get("fecha_creada")),
|
||||
"canal": _txt(f.get("origen")),
|
||||
"sede": _txt(f.get("sede")),
|
||||
"programa": _txt(f.get("programa")),
|
||||
"codigo": _txt(f.get("codigo")),
|
||||
})
|
||||
return out
|
||||
|
||||
|
||||
def traer_supabase(dm):
|
||||
"""Lee la tabla de Supabase con columnas: telefono, fechacreada, canal."""
|
||||
try:
|
||||
from supabase import create_client
|
||||
url = os.getenv("SUPABASE_URL", "")
|
||||
key = os.getenv("SUPABASE_KEY", "")
|
||||
if not url or not key:
|
||||
print("⚠️ Falta SUPABASE_URL / SUPABASE_KEY en .env — se omite Supabase")
|
||||
return []
|
||||
sb = create_client(url, key)
|
||||
tabla = os.getenv("SUPABASE_TABLA_LEADS", "leads") # ajustar nombre real si difiere
|
||||
res = sb.table(tabla).select("Telefono,Fechacreada,Canal,Sede,Programa,Codigo").execute()
|
||||
out = []
|
||||
for r in (res.data or []):
|
||||
tel = _norm_tel(r.get("Telefono"))
|
||||
if not tel:
|
||||
continue
|
||||
out.append({
|
||||
"telefono": tel,
|
||||
"fecha": _to_dt(r.get("Fechacreada")),
|
||||
"canal": _txt(r.get("Canal")),
|
||||
"sede": _txt(r.get("Sede")),
|
||||
"programa": _txt(r.get("Programa")),
|
||||
"codigo": _txt(r.get("Codigo")),
|
||||
})
|
||||
return out
|
||||
except Exception as e:
|
||||
print(f"⚠️ Error leyendo Supabase: {e}")
|
||||
return []
|
||||
|
||||
|
||||
def main():
|
||||
dm = DataManager()
|
||||
print("Trayendo Postgre (Fact_Leads_Procesados)...")
|
||||
pg = traer_postgre(dm)
|
||||
print(f" Postgre: {len(pg)} filas")
|
||||
print("Trayendo Supabase...")
|
||||
sup = traer_supabase(dm)
|
||||
print(f" Supabase: {len(sup)} filas")
|
||||
|
||||
todos = pg + sup
|
||||
print(f"Total combinado (con repetidos): {len(todos)}")
|
||||
|
||||
# Dedup por teléfono: quedarse con el MÁS ANTIGUO.
|
||||
# Desempate (misma fecha): preferir CANAL_PREFERIDO.
|
||||
FUTURO = datetime(9999, 1, 1)
|
||||
mejor = {}
|
||||
for r in todos:
|
||||
tel = r["telefono"]
|
||||
f = r["fecha"] or FUTURO
|
||||
actual = mejor.get(tel)
|
||||
if actual is None:
|
||||
mejor[tel] = r
|
||||
continue
|
||||
fa = actual["fecha"] or FUTURO
|
||||
if f < fa:
|
||||
mejor[tel] = r
|
||||
elif f == fa:
|
||||
# empate de fecha → preferir el canal preferido
|
||||
if r["canal"] == CANAL_PREFERIDO and actual["canal"] != CANAL_PREFERIDO:
|
||||
mejor[tel] = r
|
||||
|
||||
final = list(mejor.values())
|
||||
print(f"Teléfonos únicos (sin repetir): {len(final)}")
|
||||
|
||||
# Exportar a Excel
|
||||
import openpyxl
|
||||
wb = openpyxl.Workbook()
|
||||
ws = wb.active
|
||||
ws.title = "Base_Junta"
|
||||
ws.append(["Telefono", "Canal", "Fecha Creada", "Sede", "Programa", "Codigo"])
|
||||
for r in sorted(final, key=lambda x: (x["fecha"] or FUTURO)):
|
||||
fecha = r["fecha"].strftime("%d/%m/%Y") if r["fecha"] and r["fecha"] != FUTURO else ""
|
||||
ws.append([r["telefono"], r["canal"], fecha,
|
||||
r.get("sede", ""), r.get("programa", ""), r.get("codigo", "")])
|
||||
salida = os.path.join(os.path.dirname(__file__), "base_junta.xlsx")
|
||||
wb.save(salida)
|
||||
print(f"\n✅ Exportado: {salida}")
|
||||
print(f" Filas: {len(final)}")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user