101 lines
3.8 KiB
Python
101 lines
3.8 KiB
Python
# diag_diana_resp_ago11.py
|
|
# NUEVO grafico (por FECHA DE RESPUESTA): leads que DIANA RESPONDIO el 11/08/2026,
|
|
# sin importar cuando se asignaron. Muestra asignacion, respuesta y minutos.
|
|
from datetime import datetime, timedelta, date
|
|
from data_manager_v2 import DataManager
|
|
|
|
ANO, MES, DIA_RESP = 2026, 8, 11 # dia de RESPUESTA
|
|
NOMBRE = "DIANA"
|
|
|
|
dm = DataManager()
|
|
asig = dm.traer_asignacion_respuesta()
|
|
act_rows = dm.traer_actividad_asesores()
|
|
|
|
uid2name = {}
|
|
for r in asig:
|
|
if r.get("user_id") is not None:
|
|
uid2name[r["user_id"]] = r.get("user_name") or ""
|
|
|
|
from collections import defaultdict
|
|
act = defaultdict(lambda: defaultdict(int))
|
|
for a in act_rows:
|
|
uid=a.get("user_id"); ts=a.get("created_at")
|
|
if uid not in uid2name or not isinstance(ts,datetime): continue
|
|
nom=uid2name[uid].upper(); d=ts.date(); h=ts.hour+ts.minute/60.0; key=(nom,d)
|
|
if d.weekday()==6: continue
|
|
if d.weekday()==5:
|
|
if 9<=h<13: act[key]["sab_manana"]+=1
|
|
elif 14<=h<18: act[key]["sab_tarde"]+=1
|
|
else:
|
|
if 13<=h<18: act[key]["tarde"]+=1
|
|
elif 18<=h<22: act[key]["noche"]+=1
|
|
|
|
def turno_dia(nom,d):
|
|
if d.weekday()==6: return None
|
|
fr=act.get((nom,d))
|
|
if not fr: return None
|
|
if d.weekday()==5:
|
|
m=fr.get("sab_manana",0); t=fr.get("sab_tarde",0)
|
|
if m==0 and t==0: return None
|
|
return [(9,13)] if m>=t else [(14,18)]
|
|
t=fr.get("tarde",0); n=fr.get("noche",0)
|
|
if t==0 and n==0: return None
|
|
return [(9,13),(18,22)] if n>t else [(9,13),(14,18)]
|
|
|
|
def es_t1(nom,d):
|
|
fr=act.get((nom,d))
|
|
if not fr or d.weekday()>=5: return False
|
|
t=fr.get("tarde",0); n=fr.get("noche",0)
|
|
return (not (n>t)) and (t>0 or n>0)
|
|
|
|
def _dt(d,hh): return datetime(d.year,d.month,d.day)+timedelta(hours=hh)
|
|
|
|
def mins_laborales(nom,t1,t2):
|
|
if not isinstance(t1,datetime) or not isinstance(t2,datetime) or t2<=t1: return 0
|
|
total=0.0; cur=t1; s=0
|
|
while cur<t2 and s<60:
|
|
d=cur.date(); bl=turno_dia(nom,d)
|
|
if not bl: cur=_dt(d,24); s+=1; continue
|
|
for (hi,hf) in bl:
|
|
ini=_dt(d,hi); fin=_dt(d,hf)
|
|
if t2<=ini: break
|
|
if cur>=fin: continue
|
|
a=max(cur,ini); b=min(t2,fin)
|
|
if b>a: total+=(b-a).total_seconds()/60.0
|
|
cur=fin
|
|
if cur>=t2: break
|
|
if cur.date()==d: cur=_dt(d,24); s+=1
|
|
return round(total)
|
|
|
|
# filtrar Diana + RESPUESTA el 11
|
|
filas=[]
|
|
for r in asig:
|
|
if NOMBRE not in (r.get("user_name") or "").upper(): continue
|
|
t1=r.get("created_at"); t2=r.get("respuesta_fecha")
|
|
if not isinstance(t1,datetime) or not isinstance(t2,datetime): continue # sin respuesta -> fuera
|
|
if t2.year==ANO and t2.month==MES and t2.day==DIA_RESP:
|
|
filas.append(r)
|
|
|
|
print(f"\n=== DIANA — leads RESPONDIDOS el {DIA_RESP:02d}/{MES:02d}/{ANO} (grafico por fecha respuesta) ===\n")
|
|
print(f"Total respondidos ese dia: {len(filas)}\n")
|
|
print(f"{'#':3} {'telefono':13} {'asignado':17} {'respondio':17} {'min':>5} nota")
|
|
print("-"*74)
|
|
suma=0
|
|
for i,r in enumerate(sorted(filas, key=lambda x: x['respuesta_fecha']),1):
|
|
t1=r['created_at']; t2=r['respuesta_fecha']; tel=r.get('telefono','')
|
|
d1=t1.date(); h=t1.hour+t1.minute/60.0
|
|
refri = es_t1((r.get('user_name') or '').upper(), d1) and (13<=h<15)
|
|
if refri:
|
|
dif=(t2-t1).total_seconds()/60.0
|
|
m=round(dif-45) if dif>45 else round(dif)
|
|
if m<0: m=0
|
|
nota=" refrig(-45)"
|
|
else:
|
|
m=mins_laborales((r.get('user_name') or '').upper(),t1,t2); nota=""
|
|
# marca si se asigno OTRO dia
|
|
if t1.date()!=t2.date(): nota += f" (asignado {t1.strftime('%d/%m')})"
|
|
suma+=m
|
|
print(f"{i:3} {tel:13} {t1.strftime('%d/%m %H:%M'):17} {t2.strftime('%d/%m %H:%M'):17} {m:>5}{nota}")
|
|
print("-"*74)
|
|
print(f"Promedio del dia {DIA_RESP} (por fecha respuesta): {round(suma/len(filas)) if filas else 0} min")
|