def calcular_tiempo_hold_tipo_fecha(self, agente, fecha_inferior, fecha_superior, agente_fecha): evento_hold = ['HOLD'] evento_unhold = ['UNHOLD'] tiempo_hold = timedelta(0) hold_fecha = [hold for hold in LlamadaLog.objects.obtener_evento_hold_fecha( evento_hold, fecha_inferior, fecha_superior, agente.id)] primer_unhold = LlamadaLog.objects.obtener_evento_hold_fecha(evento_unhold, fecha_inferior, fecha_superior, agente.id ).first() if hold_fecha: primer_hold = hold_fecha[0] if primer_unhold and primer_unhold.time < primer_hold.time: tiempo_hold += primer_unhold.time - fecha_inferior for log in hold_fecha: fecha_actual = fecha_local(log.time) agente_en_lista = list(filter(lambda x: x.agente == fecha_actual, agente_fecha)) inicio_hold = log.time callid = log.callid fecha_desde = datetime_hora_minima_dia(fecha_actual) fecha_hasta = datetime_hora_maxima_dia(fecha_actual) unhold_fecha = LlamadaLog.objects.filter(agente_id=agente.id, callid=callid, event='UNHOLD', time__range=(log.time, fecha_hasta) ).order_by('time').first() if unhold_fecha: # Si existen varios unhold dentro de una llamada se elige el primero fin_hold = unhold_fecha.time else: # Si se corta la llamada sin haber podido hacer unhold o por otro motivo log_llamada = LlamadaLog.objects.filter(agente_id=agente.id, callid=callid, time__range=(fecha_desde, fecha_hasta) ).last() if log_llamada and log_llamada.event != 'HOLD': fin_hold = log_llamada.time else: fin_hold = now() \ if datetime_hora_maxima_dia(fecha_superior) >= now() else fecha_superior tiempo_hold += fin_hold - inicio_hold if agente_en_lista: agente_nuevo = agente_en_lista[0] agente_nuevo._tiempo_hold = tiempo_hold else: agente_nuevo = AgenteTiemposReporte(fecha_local(fecha_inferior), timedelta(0), timedelta(0), timedelta(0), 0, 0, 0, 0, tiempo_hold, 0) agente_fecha.append(agente_nuevo) return agente_fecha
def url_archivo_grabacion(self): hoy = fecha_local(now()) dia_grabacion = fecha_local(self.time) filename = "/".join([crear_segmento_grabaciones_url(), dia_grabacion.strftime("%Y-%m-%d"), self.archivo_grabacion]) if dia_grabacion < hoy: return filename + '.' + settings.MONITORFORMAT else: return filename + '.wav'
def url_archivo_grabacion_url_encoded(self): # TODO: Refactorizar junto con url_archivo_grabacion para eliminar duplicidad de código hoy = fecha_local(now()) dia_grabacion = fecha_local(self.time) filename = "/".join([crear_segmento_grabaciones_url(), dia_grabacion.strftime("%Y-%m-%d"), urllib.parse.quote(self.archivo_grabacion)]) if dia_grabacion < hoy: return filename + '.' + settings.MONITORFORMAT else: return filename + '.wav'
def test_datos_reporte_grafico_detalle_llamadas_manuales_coinciden_estadisticas_sistema( self): campana_manual = CampanaFactory(type=Campana.TYPE_MANUAL, estado=Campana.ESTADO_ACTIVA) self.generador_log_llamadas.generar_log(campana_manual, True, 'COMPLETEAGENT', self.telefono1, agente=self.agente_profile) self.generador_log_llamadas.generar_log(campana_manual, True, 'COMPLETEOUTNUM', self.telefono2, agente=self.agente_profile) self.generador_log_llamadas.generar_log(campana_manual, True, 'FAIL', self.telefono3, agente=self.agente_profile) estadisticas_service = EstadisticasService() hoy = fecha_local(timezone.now()) reporte = estadisticas_service.calcular_cantidad_llamadas( campana_manual, hoy, hoy) self.assertEqual(reporte['Discadas'], 3) self.assertEqual(reporte['Discadas atendidas'], 2) self.assertEqual(reporte['Discadas no atendidas'], 1)
def calcular_tiempo_llamada_agente_fecha(self, agente, fecha_inferior, fecha_superior, agente_fecha): """ Calcula el tiempo de llamada teniendo en cuenta los eventos COMPLETECALLER y COMPLETEOUTNUM, por fecha dia a dia para el agente""" eventos_llamadas = list(LlamadaLog.EVENTOS_FIN_CONEXION) logs_time = LlamadaLog.objects.obtener_tiempo_llamada_agente( eventos_llamadas, fecha_inferior, fecha_superior, agente.id) for log in logs_time: date_time_actual = fecha_local(log.time) agente_en_lista = list( filter(lambda x: x.agente == date_time_actual, agente_fecha)) duracion_llamada = timedelta(seconds=log.duracion_llamada) if agente_en_lista: agente_nuevo = agente_en_lista[0] agente_nuevo._tiempo_llamada += duracion_llamada agente_nuevo._cantidad_llamadas_procesadas += 1 else: agente_nuevo = AgenteTiemposReporte(date_time_actual, timedelta(0), timedelta(0), duracion_llamada, 1, 0, 0, 0) agente_fecha.append(agente_nuevo) return agente_fecha
def get_context_data(self, **kwargs): context = super(ConsolaAgenteView, self).get_context_data(**kwargs) campanas_preview_activas = [] usuario_agente = self.request.user agente_profile = usuario_agente.get_agente_profile() kamailio_service = KamailioService() sip_usuario = kamailio_service.generar_sip_user( agente_profile.sip_extension) sip_password = kamailio_service.generar_sip_password(sip_usuario) hoy = fecha_local(now()) registros = LlamadaLog.objects.obtener_llamadas_finalizadas_del_dia( agente_profile.id, hoy) campanas_preview_activas = \ agente_profile.has_campanas_preview_activas_miembro() context['pausas'] = Pausa.objects.activas context['registros'] = registros context['tipos_salientes'] = LlamadaLog.TIPOS_LLAMADAS_SALIENTES context['campanas_preview_activas'] = campanas_preview_activas context['agente_profile'] = agente_profile context['sip_usuario'] = sip_usuario context['sip_password'] = sip_password context['agentes'] = AgenteProfile.objects.obtener_activos().exclude( id=agente_profile.id) context['max_session_age'] = settings.SESSION_COOKIE_AGE return context
def test_datos_reporte_grafico_detalle_llamadas_dialer_coinciden_estadisticas_sistema(self): campana_dialer = CampanaFactory(type=Campana.TYPE_DIALER, estado=Campana.ESTADO_ACTIVA) self.generador_log_llamadas.generar_log( campana_dialer, False, 'COMPLETEAGENT', self.telefono1, agente=self.agente_profile) self.generador_log_llamadas.generar_log( campana_dialer, False, 'COMPLETEOUTNUM', self.telefono2, agente=self.agente_profile) self.generador_log_llamadas.generar_log( campana_dialer, False, 'ABANDON', self.telefono3, agente=self.agente_profile) self.generador_log_llamadas.generar_log( campana_dialer, False, 'EXITWITHTIMEOUT', self.telefono4, agente=self.agente_profile) self.generador_log_llamadas.generar_log( campana_dialer, False, 'CANCEL', self.telefono4, agente=self.agente_profile) self.generador_log_llamadas.generar_log( campana_dialer, True, 'COMPLETEAGENT', self.telefono1, agente=self.agente_profile) self.generador_log_llamadas.generar_log( campana_dialer, True, 'COMPLETEOUTNUM', self.telefono2, agente=self.agente_profile) self.generador_log_llamadas.generar_log( campana_dialer, True, 'NOANSWER', self.telefono2, agente=self.agente_profile) estadisticas_service = EstadisticasService() hoy = fecha_local(timezone.now()) reporte = estadisticas_service.calcular_cantidad_llamadas(campana_dialer, hoy, hoy) self.assertEqual(reporte['Discadas'], 5) self.assertEqual(reporte['Conectadas al agente'], 2) self.assertEqual(reporte['Atendidas'], 4) self.assertEqual(reporte['Perdidas'], 2) self.assertEqual(reporte['Manuales'], 3) self.assertEqual(reporte['Manuales atendidas'], 2) self.assertEqual(reporte['Manuales no atendidas'], 1)
def calcular_tiempo_pausa_fecha_agente(self, agente, fecha_inferior, fecha_superior, agente_fecha): """ Calcula el tiempo de pausa teniendo en cuenta los eventos PAUSEALL, UNPAUSEALL y REMOVEMEMBER por fecha dia a dia para el agente""" eventos_pausa = ['PAUSEALL', 'UNPAUSEALL', 'REMOVEMEMBER'] logs_time = ActividadAgenteLog.objects.obtener_tiempos_event_agentes( eventos_pausa, fecha_inferior, fecha_superior, [agente.id]) # Establezco un limite hasta al cual calcular la ultima pausa no finalizada hora_limite = now() hora_maxima = datetime_hora_maxima_dia(fecha_superior) if hora_maxima < hora_limite: hora_limite = hora_maxima TIME = 1 EVENT = 2 time_actual = hora_limite for log in logs_time: agente_nuevo = None # Descarto Pausas sin log de finalización if log[EVENT] == 'PAUSEALL': resta = time_actual - log[TIME] date_time_actual = fecha_local(time_actual) agente_en_lista = list(filter(lambda x: x.agente == date_time_actual, agente_fecha)) if agente_en_lista: agente_nuevo = agente_en_lista[0] agente_nuevo._tiempo_pausa += resta else: agente_nuevo = AgenteTiemposReporte( fecha_local(time_actual), timedelta(0), resta, timedelta(0), 0, 0, 0, 0, timedelta(0), 0) agente_fecha.append(agente_nuevo) time_actual = log[TIME] if log[EVENT] == 'UNPAUSEALL' or log[EVENT] == 'REMOVEMEMBER': time_actual = log[TIME] return agente_fecha
def get_context_data(self, *args, **kwargs): context = super(HistoricoDeLlamadasView, self).get_context_data(*args, **kwargs) agente_profile = self.request.user.get_agente_profile() hoy = fecha_local(now()) logs = LlamadaLog.objects.obtener_llamadas_finalizadas_del_dia( agente_profile.id, hoy) context['registros'] = logs context['tipos_salientes'] = LlamadaLog.TIPOS_LLAMADAS_SALIENTES return context
def test_datos_reporte_grafico_detalle_llamadas_preview_coinciden_estadisticas_sistema(self): estadisticas_service = EstadisticasService() hoy = fecha_local(timezone.now()) reporte = estadisticas_service.calcular_cantidad_llamadas(self.campana_activa, hoy, hoy) # se usan los logs de llamadas del setUp pues la campaña usada es preview self.assertEqual(reporte['Discadas'], 2) self.assertEqual(reporte['Conectadas'], 2) self.assertEqual(reporte['No conectadas'], 0) self.assertEqual(reporte['Manuales'], 2) self.assertEqual(reporte['Manuales atendidas'], 1) self.assertEqual(reporte['Manuales no atendidas'], 1)
def calcular_tiempo_pausa_tipo_fecha(self, agente, fecha_inferior, fecha_superior, pausa_id): """ Calcula el tiempo de pausa de los agentes en el periodo evaluado :return: un listado de agentes con el tiempo de pausa """ agentes_tiempo = [] # iterar por agente evaluando los eventos de pausa logs_time = ActividadAgenteLog.objects.obtener_pausas_por_agente_fechas_pausa( fecha_inferior, fecha_superior, agente.id) # Establezco un limite hasta al cual calcular la ultima pausa no finalizada hora_limite = now() hora_maxima = datetime_hora_maxima_dia(fecha_superior) if hora_maxima < hora_limite: hora_limite = hora_maxima time_actual = hora_limite tiempos_pausa = {} # iterar los log teniendo en cuenta que si encuentra un evento # UNPAUSEALL/REMOVEMEMBER y luego un PAUSEALL calcula el tiempo de session for log in logs_time: # Descarto otras Pausas, pero las tengo en cuenta para contabilizar finalizaciones if log.event == 'PAUSEALL' and log.pausa_id != pausa_id: time_actual = log.time # Descarto Pausas sin log de finalización elif log.event == 'PAUSEALL': resta = time_actual - log.time fecha_pausa = fecha_local(time_actual) if fecha_pausa in tiempos_pausa.keys(): tiempos_pausa[fecha_pausa] += resta else: tiempos_pausa.update({fecha_pausa: resta}) time_actual = log.time if log.event == 'UNPAUSEALL' or log.event == 'REMOVEMEMBER': time_actual = log.time datos_de_pausa = self._obtener_datos_de_pausa(str(pausa_id)) for item in tiempos_pausa: tiempo = str(timedelta(seconds=tiempos_pausa[item].seconds)) tiempo_agente = { 'fecha': item, 'pausa': datos_de_pausa['nombre'], 'tipo_de_pausa': datos_de_pausa['tipo'], 'tiempo': tiempo, } agentes_tiempo.append(tiempo_agente) return agentes_tiempo
def _computar_tiempo_session_fecha(self, tiempos_fechas, inicio, fin): """ Computa la duracion de la sesion en la lista de tiempos por fecha """ fecha_inicio = fecha_local(inicio) fecha_fin = fecha_local(fin) if tiempos_fechas and tiempos_fechas[-1].agente == fecha_inicio: tiempos = tiempos_fechas[-1] else: tiempos = AgenteTiemposReporte( fecha_inicio, timedelta(0), timedelta(0), timedelta(0), 0, 0, 0, 0) tiempos_fechas.append(tiempos) if fecha_fin == tiempos.agente: tiempos._tiempo_sesion += fin - inicio else: fin_dia = datetime_hora_maxima_dia(fecha_inicio) tiempos._tiempo_sesion += fin_dia - inicio inicio_dia = datetime_hora_minima_dia(fecha_fin) duracion = fin - inicio_dia tiempos = AgenteTiemposReporte( fecha_fin, duracion, timedelta(0), timedelta(0), 0, 0, 0, 0) tiempos_fechas.append(tiempos)
def calcular_tiempo_pausa_fecha_agente(self, agente, fecha_inferior, fecha_superior, agente_fecha): """ Calcula el tiempo de pausa teniendo en cuenta los eventos PAUSEALL, UNPAUSEALL y REMOVEMEMBER por fecha dia a dia para el agente""" eventos_pausa = ['PAUSEALL', 'UNPAUSEALL', 'REMOVEMEMBER'] logs_time = ActividadAgenteLog.objects.obtener_tiempos_event_agentes( eventos_pausa, fecha_inferior, fecha_superior, [agente.id]) TIME = 1 EVENT = 2 time_actual = None is_unpause = False for log in logs_time: agente_nuevo = None if is_unpause and log[EVENT] == 'PAUSEALL': resta = time_actual - log[TIME] date_time_actual = fecha_local(time_actual) agente_en_lista = list( filter(lambda x: x.agente == date_time_actual, agente_fecha)) if agente_en_lista: agente_nuevo = agente_en_lista[0] agente_nuevo._tiempo_pausa += resta else: agente_nuevo = AgenteTiemposReporte( fecha_local(time_actual), timedelta(0), resta, timedelta(0), 0, 0, 0, 0) agente_fecha.append(agente_nuevo) is_unpause = False time_actual = None if log[EVENT] == 'UNPAUSEALL' or log[EVENT] == 'REMOVEMEMBER': time_actual = log[TIME] is_unpause = True return agente_fecha
def test_datos_reporte_grafico_llamadas_entrantes_realizadas_muestran_solo_dia_actual( self): campana_entrante = CampanaFactory(type=Campana.TYPE_ENTRANTE, estado=Campana.ESTADO_ACTIVA) hoy = fecha_hora_local(timezone.now()) ayer = hoy - timedelta(days=1) self.generador_log_llamadas.generar_log( campana_entrante, True, 'COMPLETEAGENT', self.telefono1, agente=self.agente_profile, time=ayer) self.generador_log_llamadas.generar_log( campana_entrante, True, 'COMPLETEOUTNUM', self.telefono2, agente=self.agente_profile, time=hoy) estadisticas_service = EstadisticasService() hoy = fecha_local(timezone.now()) _, llamadas_realizadas, _, _, _ = estadisticas_service.obtener_total_llamadas( campana_entrante) self.assertEqual(llamadas_realizadas, 1)
def test_datos_reporte_grafico_total_llamadas_entrantes_coinciden_estadisticas_sistema( self): campana_entrante = CampanaFactory(type=Campana.TYPE_ENTRANTE, estado=Campana.ESTADO_ACTIVA) self.generador_log_llamadas.generar_log(campana_entrante, False, 'COMPLETEAGENT', self.telefono1, agente=self.agente_profile) self.generador_log_llamadas.generar_log(campana_entrante, False, 'COMPLETEOUTNUM', self.telefono2, agente=self.agente_profile) self.generador_log_llamadas.generar_log(campana_entrante, False, 'EXITWITHTIMEOUT', self.telefono3, agente=self.agente_profile) self.generador_log_llamadas.generar_log(campana_entrante, False, 'ABANDON', self.telefono4, agente=self.agente_profile) self.generador_log_llamadas.generar_log(campana_entrante, True, 'COMPLETEAGENT', self.telefono1, agente=self.agente_profile) self.generador_log_llamadas.generar_log(campana_entrante, True, 'COMPLETEOUTNUM', self.telefono2, agente=self.agente_profile) estadisticas_service = EstadisticasService() hoy = fecha_local(timezone.now()) reporte = estadisticas_service.calcular_cantidad_llamadas( campana_entrante, hoy, hoy) self.assertEqual(reporte['Recibidas'], 4) self.assertEqual(reporte['Atendidas'], 2) self.assertEqual(reporte['Expiradas'], 1) self.assertEqual(reporte['Abandonadas'], 1) self.assertEqual(reporte['Manuales'], 2) self.assertEqual(reporte['Manuales atendidas'], 2) self.assertEqual(reporte['Manuales no atendidas'], 0)
def calcular_tiempo_llamada_agente_fecha(self, agente, fecha_inferior, fecha_superior, agente_fecha): """ Calcula el tiempo de llamada teniendo en cuenta los eventos COMPLETECALLER y COMPLETEOUTNUM, por fecha dia a dia para el agente""" eventos_llamadas = list(LlamadaLog.EVENTOS_FIN_CONEXION) logs_time = LlamadaLog.objects.obtener_tiempo_llamada_agente( eventos_llamadas, fecha_inferior, fecha_superior, agente.id).exclude(campana_id=0) campanas_ids = set() for log in logs_time: campanas_ids.add(log.campana_id) date_time_actual = fecha_local(log.time) agente_en_lista = list(filter(lambda x: x.agente == date_time_actual, agente_fecha)) duracion_llamada = timedelta(seconds=log.duracion_llamada) if agente_en_lista: agente_nuevo = agente_en_lista[0] agente_nuevo._tiempo_llamada += duracion_llamada agente_nuevo._cantidad_llamadas_procesadas += 1 else: agente_nuevo = AgenteTiemposReporte( date_time_actual, timedelta(0), timedelta(0), duracion_llamada, 1, 0, 0, 0, timedelta(0), 0) agente_fecha.append(agente_nuevo) for datos_fecha in agente_fecha: fecha = datos_fecha.agente fecha_inicial = datetime_hora_minima_dia(fecha) fecha_final = datetime_hora_maxima_dia(fecha) transferencias = LlamadaLog.objects.obtener_cantidades_de_transferencias_recibidas( fecha_inicial, fecha_final, [agente.id], campanas_ids) cant_transfers = 0 transferencias_por_camp = transferencias.get(agente.id, {}) for cant in transferencias_por_camp.values(): cant_transfers += cant datos_fecha._cantidad_llamadas_procesadas -= cant_transfers datos_fecha._transferidas_a_agente = cant_transfers return agente_fecha
def calcular_tiempo_pausa_tipo_fecha(self, agente, fecha_inferior, fecha_superior, pausa_id): """ Calcula el tiempo de pausa de los agentes en el periodo evaluado :return: un listado de agentes con el tiempo de pausa """ agentes_tiempo = [] # iterar por agente evaluando los eventos de pausa logs_time = ActividadAgenteLog.objects.obtener_pausas_por_agente_fechas_pausa( fecha_inferior, fecha_superior, agente.id, pausa_id) is_unpause = False time_actual = None tiempos_pausa = {} # iterar los log teniendo en cuenta que si encuentra un evento # UNPAUSEALL/REMOVEMEMBER y luego un PAUSEALL calcula el tiempo de session for log in logs_time: if is_unpause and log.event == 'PAUSEALL': resta = time_actual - log.time time_actual = fecha_local(time_actual) if time_actual in tiempos_pausa.keys(): tiempos_pausa[time_actual] += resta else: tiempos_pausa.update({time_actual: resta}) is_unpause = False time_actual = None if log.event == 'UNPAUSEALL' or log.event == 'REMOVEMEMBER': time_actual = log.time is_unpause = True for item in tiempos_pausa: datos_de_pausa = self._obtener_datos_de_pausa(str(pausa_id)) tiempo = str(timedelta(seconds=tiempos_pausa[item].seconds)) tiempo_agente = { 'fecha': item, 'pausa': datos_de_pausa['nombre'], 'tipo_de_pausa': datos_de_pausa['tipo'], 'tiempo': tiempo, } agentes_tiempo.append(tiempo_agente) return agentes_tiempo
def get_context_data(self, **kwargs): context = super(ConsolaAgenteView, self).get_context_data(**kwargs) campanas_preview_activas = [] usuario_agente = self.request.user agente_profile = usuario_agente.get_agente_profile() kamailio_service = KamailioService() sip_usuario = kamailio_service.generar_sip_user( agente_profile.sip_extension) sip_password = kamailio_service.generar_sip_password(sip_usuario) video_domain = '' if 'WEBPHONE_VIDEO_DOMAIN' in settings.CONSTANCE_CONFIG: video_domain = config_constance.WEBPHONE_VIDEO_DOMAIN fechas_agendas = AgendaContacto.objects.proximas( agente_profile).values_list('fecha', 'hora') fechas_agendas = [ make_aware(datetime.combine(x[0], x[1])).isoformat() for x in fechas_agendas ] hoy = fecha_local(now()) registros = LlamadaLog.objects.obtener_llamadas_finalizadas_del_dia( agente_profile.id, hoy) campanas_preview_activas = \ agente_profile.has_campanas_preview_activas_miembro() context['pausas'] = Pausa.objects.activas context['registros'] = registros context['tipos_salientes'] = LlamadaLog.TIPOS_LLAMADAS_SALIENTES context['campanas_preview_activas'] = campanas_preview_activas context['agente_profile'] = agente_profile context['sip_usuario'] = sip_usuario context['sip_password'] = sip_password context['agentes'] = AgenteProfile.objects.obtener_activos().exclude( id=agente_profile.id) context['max_session_age'] = settings.SESSION_COOKIE_AGE context['video_domain'] = video_domain context['fechas_agendas_json'] = json.dumps(fechas_agendas) context['listas_rapidas'] = ContactoListaRapida.objects.all() return context
def get_initial(self): initial = super(ReporteLlamadasFormView, self).get_initial() hoy = fecha_local(now()).strftime('%d/%m/%Y') initial['fecha'] = ' - '.join([hoy] * 2) return initial