# diag_diana_8_9_10.py # Dias 8, 9 y 10 de AGOSTO 2026 de DIANA: turno detectado (o LIBRE) y tiempos. # Aplica la regla del refrigerio (13-15 turno1: diferencia directa, -45 si supera 45). from datetime import datetime, timedelta, date from data_manager_v2 import DataManager ANO, MES = 2026, 8 DIAS = [8, 9, 10] 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=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) for DIA in DIAS: d1=date(ANO,MES,DIA) filas=[] for r in asig: if NOMBRE not in (r.get("user_name") or "").upper(): continue t1=r.get("created_at") if not isinstance(t1,datetime): continue if t1.year==ANO and t1.month==MES and t1.day==DIA: filas.append(r) # turno del dia (por actividad de Diana) nom_up = (filas[0].get("user_name") or "").upper() if filas else NOMBRE tt=turno_dia(nom_up,d1) if tt is None: turno="LIBRE / DESCANSO (sin actividad ese dia)" elif tt==[(9,13),(14,18)]: turno="TURNO 1 (9-18)" elif tt==[(9,13),(18,22)]: turno="TURNO 2 (9-13 + 18-22)" else: turno=str(tt) print(f"\n{'='*66}") print(f"DIANA — {DIA:02d}/{MES:02d}/{ANO} -> {turno}") print(f"Total asignados: {len(filas)}") print(f"{'='*66}") print(f"{'#':3} {'telefono':13} {'asignado':11} {'respondio':11} {'min':>5} nota") print("-"*60) resp=0; sinr=0; suma=0 for i,r in enumerate(sorted(filas,key=lambda x:x['created_at']),1): t1=r['created_at']; t2=r.get('respuesta_fecha'); tel=r.get('telefono','') h=t1.hour+t1.minute/60.0 refri = es_t1(nom_up,d1) and (13<=h<15) if not isinstance(t2,datetime): sinr+=1 print(f"{i:3} {tel:13} {t1.strftime('%H:%M:%S'):11} {'':11} {'':>5}") continue 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=" refrigerio (-45 si >45)" else: m=mins_laborales(nom_up,t1,t2); nota="" resp+=1; suma+=m print(f"{i:3} {tel:13} {t1.strftime('%H:%M:%S'):11} {t2.strftime('%H:%M:%S'):11} {m:>5}{nota}") print("-"*60) print(f"Respondidos: {resp} | Sin responder: {sinr} | Promedio: {round(suma/resp) if resp else 0} min")