96 lines
3.3 KiB
Python
96 lines
3.3 KiB
Python
# check_choque_campania.py
|
|
# Revisa si una campaña NUEVA chocaría (duplicaría leads) contra las existentes.
|
|
# Regla de choque (igual que el JOIN LIKE del dashboard):
|
|
# - una frase es sub-cadena de la otra (contención de texto), Y
|
|
# - los rangos de fecha se solapan.
|
|
# Un mensaje que caiga en ambas frases + ambas fechas => 2 filas => lead duplicado.
|
|
#
|
|
# Edita NUEVA abajo y ejecuta: python check_choque_campania.py
|
|
import os, requests
|
|
from datetime import date
|
|
from dotenv import load_dotenv
|
|
load_dotenv()
|
|
|
|
# ── CAMPAÑA NUEVA A PROBAR (edita aquí) ──
|
|
NUEVA = {
|
|
"frase": "🎟️ Me interesa el programa de Aire Acondicionado",
|
|
"inicio": "2026-08-10",
|
|
"fin": "2026-10-10",
|
|
}
|
|
# ─────────────────────────────────────────
|
|
|
|
URL = os.getenv("CARTERA_URL") or os.getenv("SUPABASE_PAUTA_URL", "")
|
|
KEY = os.getenv("CARTERA_KEY") or os.getenv("SUPABASE_PAUTA_KEY", "")
|
|
TABLA = os.getenv("SUPABASE_TABLA_CAMPANIAS", "campanias")
|
|
HEAD = {"apikey": KEY, "Authorization": f"Bearer {KEY}"}
|
|
assert URL and KEY, "Falta CARTERA_URL / CARTERA_KEY en .env"
|
|
|
|
|
|
def traer_todo():
|
|
filas, paso, desde = [], 1000, 0
|
|
while True:
|
|
hdr = dict(HEAD); hdr["Range-Unit"] = "items"; hdr["Range"] = f"{desde}-{desde+paso-1}"
|
|
r = requests.get(f"{URL}/rest/v1/{TABLA}", params={"select": "*", "order": "id"},
|
|
headers=hdr, timeout=60)
|
|
r.raise_for_status()
|
|
data = r.json()
|
|
if not data:
|
|
break
|
|
filas.extend(data); desde += len(data)
|
|
if len(data) < paso:
|
|
break
|
|
return filas
|
|
|
|
|
|
def _d(s):
|
|
try:
|
|
return date.fromisoformat(str(s)[:10])
|
|
except Exception:
|
|
return None
|
|
|
|
|
|
def _solapan(i1, f1, i2, f2):
|
|
if not (i1 and f1 and i2 and f2):
|
|
return False
|
|
return i1 <= f2 and i2 <= f1 # rangos [i1,f1] y [i2,f2] se cruzan
|
|
|
|
|
|
def _norm(t):
|
|
return " ".join(str(t or "").lower().split())
|
|
|
|
|
|
filas = traer_todo()
|
|
ni, nf = _norm(NUEVA["frase"]), None
|
|
n_ini, n_fin = _d(NUEVA["inicio"]), _d(NUEVA["fin"])
|
|
|
|
print("\n" + "="*90)
|
|
print(f"CAMPAÑA NUEVA: \"{NUEVA['frase']}\"")
|
|
print(f"FECHAS: {NUEVA['inicio']} → {NUEVA['fin']}")
|
|
print("="*90)
|
|
|
|
choques = []
|
|
for f in filas:
|
|
fr = _norm(f.get("frase_busqueda"))
|
|
if not fr:
|
|
continue
|
|
ei, ef = _d(f.get("fecha_inicio")), _d(f.get("fecha_fin"))
|
|
contiene = (fr in ni) or (ni in fr) # una es sub-cadena de la otra
|
|
fechas = _solapan(n_ini, n_fin, ei, ef)
|
|
if contiene and fechas:
|
|
choques.append((f, fr))
|
|
|
|
if not choques:
|
|
print("\n✅ SIN CHOQUES. Ninguna campaña existente comparte texto contenido")
|
|
print(" y fechas solapadas. Tu campaña NO duplicaría leads.\n")
|
|
else:
|
|
print(f"\n⚠️ {len(choques)} CHOQUE(S) DETECTADO(S) — estas campañas duplicarían leads:\n")
|
|
for f, fr in choques:
|
|
rel = "existente ⊂ nueva" if fr in ni else "nueva ⊂ existente"
|
|
print(f" id {f.get('id')} cod {f.get('codigo')} [{rel}]")
|
|
print(f" frase: \"{f.get('frase_busqueda')}\"")
|
|
print(f" fechas: {str(f.get('fecha_inicio'))[:10]} → {str(f.get('fecha_fin'))[:10]}")
|
|
print()
|
|
print(" Un mensaje que contenga ambas frases dentro de estas fechas se")
|
|
print(" contaría 2 veces (2 códigos de pauta para el mismo lead).\n")
|
|
print("="*90)
|