def post(self, request, *args, **kwargs): campana = Campana.objects.get(pk=request.POST['campana_pk']) try: campana_service = CampanaService() campana_service.start_campana_wombat(campana) campana.play() message = _(u'<strong>Operación Exitosa!</strong>\ Se llevó a cabo con éxito la activación de\ la Campaña.') messages.add_message( self.request, messages.SUCCESS, message, ) except WombatDialerError as e: message = _("<strong>¡Cuidado!</strong> " "con el siguiente error: ") + "{0} .".format(e) messages.add_message( self.request, messages.WARNING, message, ) except RequestException as e: message = _("<strong>¡Cuidado!</strong> " "con el siguiente error: ") + "{0} .".format(e) messages.add_message( self.request, messages.WARNING, message, ) return HttpResponseRedirect(reverse('campana_dialer_list'))
def _obtener_total_llamadas( self, evento, es_campana_entrante, calificacion_final, callid, callids_analizados, bridge_wait_time): if calificacion_final and calificacion_final.opcion_calificacion.es_agenda() and \ callid not in callids_analizados: self.reporte_totales_llamadas._llamadas_pendientes += 1 if evento == 'DIAL': self.reporte_totales_llamadas.llamadas_realizadas += 1 if es_campana_entrante: if evento in ['ENTERQUEUE', 'ABANDONWEL', 'ENTERQUEUE-TRANSFER']: self.reporte_totales_llamadas._llamadas_recibidas += 1 if evento == 'ABANDONWEL': self.reporte_totales_llamadas._llamadas_abandonadas += 1 self.reporte_totales_llamadas._tiempo_acumulado_abandono += bridge_wait_time elif evento == 'ABANDON': self.reporte_totales_llamadas._llamadas_abandonadas += 1 self.reporte_totales_llamadas._tiempo_acumulado_abandono += bridge_wait_time elif evento == 'CONNECT': self.reporte_totales_llamadas._llamadas_conectadas += 1 self.reporte_totales_llamadas._tiempo_acumulado_espera += bridge_wait_time if self.campana.es_dialer: campana_service = CampanaService() dato_campana = campana_service.obtener_dato_campana_run(self.campana) self.reporte_totales_llamadas._llamadas_pendientes = 0 if dato_campana: self.reporte_totales_llamadas._llamadas_pendientes = dato_campana.get( 'n_est_remaining_calls', 0)
def _reciclar_misma_campana(self, campana): campana_service = CampanaService() campana_service.cambiar_base(campana, [], False, False, "") update_campana = "campana_dialer_update" campana.estado = Campana.ESTADO_INACTIVA campana.save() return update_campana
def get_context_data(self, **kwargs): context = super( CampanaDialerDetailView, self).get_context_data(**kwargs) campana = self.get_object() campana_service = CampanaService() estados_running_wombat = [Campana.ESTADO_ACTIVA, Campana.ESTADO_PAUSADA, Campana.ESTADO_FINALIZADA] opciones_calificacion = campana.opciones_calificacion.all() context['opciones_calificacion'] = opciones_calificacion.values('nombre') context['opciones_calificacion_gestion'] = opciones_calificacion.filter( tipo=OpcionCalificacion.GESTION).values('nombre') if campana.estado in estados_running_wombat: dato_campana = campana_service.obtener_dato_campana_run(campana) if dato_campana: status = campana_service.obtener_status_campana_running( dato_campana['hoppercampId']) context['efectuadas'] = dato_campana['n_calls_attempted'] context['terminadas'] = dato_campana['n_calls_completed'] context['estimadas'] = dato_campana['n_est_remaining_calls'] context['reintentos_abiertos'] = dato_campana['n_open_retries'] context['cant_contactos_llamados'] = \ LlamadaLog.objects.cantidad_contactos_llamados(campana) context['status'] = status context['resultado'] = True else: context['resultado'] = False return context
def detalle_campana_dialer_view(request): """Vista que muestrar el detalle de campana en wombat""" pk_campana = int(request.GET['pk_campana']) campana = Campana.objects.get(pk=pk_campana) campana_service = CampanaService() dato_campana = campana_service.obtener_dato_campana_run(campana) if dato_campana: status = campana_service.obtener_status_campana_running( dato_campana['hoppercampId']) data = { 'error_consulta': False, 'campana': campana, 'efectuadas': dato_campana['n_calls_attempted'], 'terminadas': dato_campana['n_calls_completed'], 'estimadas': dato_campana['n_est_remaining_calls'], 'reintentos_abiertos': dato_campana['n_open_retries'], 'cant_contactos_llamados': LlamadaLog.objects.cantidad_contactos_llamados(campana), 'status': status } else: data = { 'campana': campana, 'error_consulta': _(u"No se pudo consultar el estado actual de la campaña. " "Consulte con su administrador.") } return render(request, 'campanas/campana_dialer/detalle_campana.html', data)
def post(self, request, *args, **kwargs): campana = Campana.objects.get(pk=request.POST['campana_id']) try: campana_service = CampanaService() campana_service.despausar_campana_wombat(campana) campana.activar() message = _('<strong>Operación Exitosa!</strong>\ Se llevó a cabo con éxito la activación dela Campaña.') messages.add_message( self.request, messages.SUCCESS, message, ) except WombatDialerError as e: message = _("<strong>¡Cuidado!</strong> " "con el siguiente error: ") + "{0} .".format(e) messages.add_message( self.request, messages.WARNING, message, ) except RequestException as e: e = _(u'Imposible conectarse con el servicio Wombat') message = _("<strong>¡Cuidado!</strong> " "con el siguiente error: ") + "{0} .".format(e) messages.add_message( self.request, messages.WARNING, message, ) return super(ActivarCampanaDialerView, self).post(request, *args, **kwargs)
def post(self, request, *args, **kwargs): campanas = Campana.objects.obtener_campanas_dialer() campana_service = CampanaService() error_finalizadas = campana_service.chequear_campanas_finalizada_eliminarlas( campanas.filter(estado=Campana.ESTADO_ACTIVA)) if error_finalizadas: messages.add_message(self.request, messages.WARNING, error_finalizadas) return HttpResponseRedirect(reverse('campana_dialer_list'))
def form_valid(self, form): reciclado_calificacion = form.cleaned_data.get( 'reciclado_calificacion') reciclado_no_contactacion = form.cleaned_data.get( 'reciclado_no_contactacion') reciclado_radio = form.cleaned_data.get('reciclado_radio') if not (reciclado_calificacion or reciclado_no_contactacion): message = '<strong>Operación Errónea!</strong> \ Debe seleccionar al menos una opcion para reciclar ' messages.add_message( self.request, messages.ERROR, message, ) return self.form_invalid(form) campana = Campana.objects.get(pk=self.kwargs['pk_campana']) reciclador = RecicladorContactosCampanaDIALER() bd_contacto_reciclada = reciclador.reciclar(campana, reciclado_calificacion, reciclado_no_contactacion) if reciclado_radio == 'nueva_campaña': try: # Intenta reciclar la campana con el tipo de reciclado # seleccionado. campana_reciclada = Campana.objects.reciclar_campana( campana, bd_contacto_reciclada) except OmlRecicladoCampanaError: message = '<strong>Operación Errónea!</strong>\ No se pudo reciclar la Campana.' messages.add_message( self.request, messages.ERROR, message, ) return self.form_invalid(form) return HttpResponseRedirect( reverse("crea_campana_dialer_template", kwargs={ "pk_campana_template": campana_reciclada.pk, "borrar_template": 1 })) elif reciclado_radio == 'misma_campana': campana.update_basedatoscontactos(bd_contacto_reciclada) campana_service = CampanaService() campana_service.cambiar_base(campana, [], False, False, "") campana.estado = Campana.ESTADO_INACTIVA campana.save() return HttpResponseRedirect( reverse("campana_dialer_update", kwargs={"pk_campana": campana.pk}))
def obtener_total_llamadas(self, campana): """Obtiene los totales de llamadas realizadas y pendiente por la campaña :param campana: campana la cual se obtiene los totales :return: los totales de llamadas realizadas y pendientes de la campaña """ logs_llamadas_campana_raw = LlamadaLog.objects.filter( campana_id=campana.pk) logs_llamadas_campana = logs_llamadas_campana_raw.values( 'event').annotate(cantidad=Count('event')) if campana.type == Campana.TYPE_ENTRANTE: # en las campañas entrantes solo queremos mostrar las llamadas ocurridas en el día # actual hoy_ahora = fecha_hora_local(timezone.now()) hoy = hoy_ahora.date() fecha_desde = datetime.datetime.combine(hoy, datetime.time.min) fecha_hasta = datetime.datetime.combine(hoy_ahora, datetime.time.max) logs_llamadas_campana_raw = logs_llamadas_campana_raw.filter( time__range=(fecha_desde, fecha_hasta)) logs_llamadas_campana = logs_llamadas_campana.filter( time__range=(fecha_desde, fecha_hasta)) logs_llamadas_campana_raw = logs_llamadas_campana_raw.filter( time__range=(fecha_desde, fecha_hasta)) # obtenemos los eventos en formato más sencillo para indexar dict_eventos_campana = self._convertir_eventos_values_dict( logs_llamadas_campana) # calculamos los contadores de cada tipo de llamada (llamadas_pendientes, llamadas_realizadas, llamadas_recibidas, tiempo_promedio_espera, tiempo_promedio_abandono) = (None, ) * 5 llamadas_realizadas = dict_eventos_campana.get('DIAL', 0) if campana.type == Campana.TYPE_DIALER: campana_service = CampanaService() dato_campana = campana_service.obtener_dato_campana_run(campana) llamadas_pendientes = 0 if dato_campana: llamadas_pendientes = dato_campana.get('n_est_remaining_calls', 0) elif campana.type == Campana.TYPE_ENTRANTE: llamadas_recibidas = dict_eventos_campana.get('ENTERQUEUE', 0) +\ dict_eventos_campana.get('ABANDONWEL', 0) llamadas_recibidas_transferidas = dict_eventos_campana.get( 'ENTERQUEUE-TRANSFER', 0) llamadas_recibidas += llamadas_recibidas_transferidas tiempo_promedio_espera = self._calcular_tiempo_promedio_espera( logs_llamadas_campana_raw) tiempo_promedio_abandono = self._calcular_tiempo_promedio_abandono( logs_llamadas_campana_raw) elif campana.type == Campana.TYPE_PREVIEW: llamadas_pendientes = AgenteEnContacto.objects.filter( estado=AgenteEnContacto.ESTADO_INICIAL, campana_id=campana.pk, es_originario=True).count() llamadas_pendientes = self._adicionar_agendas_pendientes( campana, llamadas_pendientes) return (llamadas_pendientes, llamadas_realizadas, llamadas_recibidas, tiempo_promedio_espera, tiempo_promedio_abandono)
def _reciclar_crear_nueva_campana(self, campana_reciclada, campana): if campana.estado != Campana.ESTADO_FINALIZADA: campana_service = CampanaService() campana_service.remove_campana_wombat(campana) campana.estado = Campana.ESTADO_FINALIZADA campana.save() crea_campana_template = reverse("crea_campana_dialer_template", kwargs={ "pk_campana_template": campana_reciclada.pk, "borrar_template": 1 }) return crea_campana_template
def llamadas_pendientes(self): if not self.campana.es_preview: llamadas_pendientes_extra = 0 else: llamadas_pendientes_extra = AgenteEnContacto.objects.filter( estado=AgenteEnContacto.ESTADO_INICIAL, campana_id=self.campana.pk, es_originario=True).count() if self.campana.es_dialer: campana_service = CampanaService() dato_campana = campana_service.obtener_dato_campana_run( self.campana) llamadas_pendientes_extra = 0 if dato_campana: llamadas_pendientes_extra = dato_campana.get( 'n_est_remaining_calls', 0) return self._llamadas_pendientes + llamadas_pendientes_extra
def _contabilizar_llamadas_pendientes(self): estados_running_wombat = [ Campana.ESTADO_ACTIVA, Campana.ESTADO_PAUSADA, Campana.ESTADO_FINALIZADA ] campanas_por_id_wombat = {} for campana_id, campana in self.campanas.items(): if campana.estado in estados_running_wombat: campanas_por_id_wombat[campana.campaign_id_wombat] = campana campana_service = CampanaService() dato_campanas = campana_service.obtener_datos_campanas_run( campanas_por_id_wombat) for campana_id, datos_campana in dato_campanas.items(): if campana_id not in self.estadisticas: self._inicializar_conteo_de_campana(campana_id) self.estadisticas[campana_id]['pendientes'] = datos_campana[ 'n_est_remaining_calls']
def done(self, form_list, **kwargs): success = False try: with transaction.atomic(): campana_form = list(form_list)[int(self.INICIAL)] queue_form = list(form_list)[int(self.COLA)] opciones_calificacion_formset = list(form_list)[int( self.OPCIONES_CALIFICACION)] campana = campana_form.save() queue = self._save_queue(queue_form) opciones_calificacion_formset.save() if campana.tipo_interaccion == Campana.SITIO_EXTERNO: parametros_crm_formset = list(form_list)[int( self.PARAMETROS_CRM)] parametros_crm_formset.save() self._insert_queue_asterisk(queue) campana_service = CampanaService() service_ok = campana_service.crear_campana_wombat(campana) if service_ok: service_ok = campana_service.update_endpoint(campana) if not service_ok: raise Exception( 'No se ha podico crear la campaña en Wombat.') success = True except Exception as e: logger.error(e) success = False if success: messages.add_message(self.request, messages.SUCCESS, _('Se ha modificado la campaña.')) else: messages.add_message( self.request, messages.ERROR, _('<strong>¡ATENCIÓN!</strong> El servicio Discador no se encuentra disponible. ' 'No se pudo modificar la campaña. Por favor contacte un administrador.' )) return HttpResponseRedirect(reverse('campana_dialer_list'))
def delete(self, request, *args, **kwargs): self.object = self.get_object() success_url = self.get_success_url() service = CampanaService() # remueve campana de wombat remover = service.remove_campana_wombat(self.object) if not remover: message = _("<strong>Operación Errónea!</strong> " "No se pudo eliminar la campana {0} del discador").format( self.object.nombre) messages.add_message( self.request, messages.ERROR, message, ) else: super(CampanaDialerDeleteView, self).delete(request, *args, **kwargs) self.object.remover() return HttpResponseRedirect(success_url)
def form_valid(self, form): evitar_duplicados = form.cleaned_data.get('evitar_duplicados') evitar_sin_telefono = form.cleaned_data.get('evitar_sin_telefono') prefijo_discador = form.cleaned_data.get('prefijo_discador') columnas = form.cleaned_data.get('telefonos') bd_contacto = form.cleaned_data.get('bd_contacto') self.object = self.get_object() campana_service = CampanaService() # valida de que se pueda cambiar la base de datos que tenga las misma columnas # que la actualmente poseee error = campana_service.validar_modificacion_bd_contacto( self.get_object(), bd_contacto) if error: return self.form_invalid(form, error=error) if self.object.bd_contacto == bd_contacto: message = _('Atención!\ Ud ha escogido la misma base de datos, corre riesgo de calificar los' ' mismos contactos pisando la calificación previa.') messages.add_message( self.request, messages.SUCCESS, message, ) self.object.bd_contacto = bd_contacto self.object.save() # realiza el cambio de la base de datos en wombat campana_service.cambiar_base(self.get_object(), columnas, evitar_duplicados, evitar_sin_telefono, prefijo_discador) message = _('Operación Exitosa!\ Se llevó a cabo con éxito el cambio de base de datos.') messages.add_message( self.request, messages.SUCCESS, message, ) self.object.estado = Campana.ESTADO_INACTIVA self.object.save() return redirect(self.get_success_url())
def form_valid(self, form): regla = form.save(commit=False) try: campana_service = CampanaService() editado = campana_service.editar_reschedule_por_calificacion_wombat( regla, self.wombat_id) if not editado: messages.error(_('No se pudo guardar la regla de incidencia.')) return self.form_invalid(form) if self.campana.estado == Campana.ESTADO_ACTIVA: campana_service.reload_campana_wombat(self.campana) except WombatDialerError as e: error_message = _("Error al editar regla de incidencia: ") + "{0} .".format(e) logger.error(error_message) messages.error(_('No se pudo guardar la regla de incidencia.')) return self.form_invalid(form) regla.save() return super(ReglasDeIncidenciaDeCalificacionesUpdateView, self).form_valid(form)
def delete(self, request, *args, **kwargs): self.object = self.get_object() success_url = self.get_success_url() service = CampanaService() # remueve campana de wombat remover = service.eliminar_reschedule_por_calificacion_wombat(self.object) if not remover: message = _("<strong>Operación Errónea!</strong> " "No se pudo eliminar la Regla de Incidencia por calificación: {0}").format( self.object.opcion_calificacion.nombre) messages.add_message( self.request, messages.ERROR, message, ) else: if self.campana.estado == Campana.ESTADO_ACTIVA: service.reload_campana_wombat(self.campana) super(ReglasDeIncidenciaDeCalificacionesDeleteView, self).delete( request, *args, **kwargs) messages.success(request, _('Regla de incidencia eliminada.')) return HttpResponseRedirect(success_url)
def _sincronizar_campana(self, sincronizar_form, campana): evitar_duplicados = sincronizar_form.cleaned_data.get( 'evitar_duplicados') evitar_sin_telefono = sincronizar_form.cleaned_data.get( 'evitar_sin_telefono') prefijo_discador = sincronizar_form.cleaned_data.get( 'prefijo_discador') service_base = SincronizarBaseDatosContactosService() # Crea un achivo con la lista de contactos para importar a wombat service_base.crear_lista(campana, evitar_duplicados, evitar_sin_telefono, prefijo_discador) campana_service = CampanaService() # crear campana en wombat campana_service.crear_campana_wombat(campana) # crea trunk en wombat campana_service.crear_trunk_campana_wombat(campana) # crea reglas de incidencia en wombat for regla in campana.reglas_incidencia.all(): parametros = [ regla.get_estado_wombat(), regla.estado_personalizado, regla.intento_max, regla.reintentar_tarde, regla.get_en_modo_wombat() ] campana_service.crear_reschedule_campana_wombat( campana, parametros) # crea endpoint en wombat campana_service.crear_endpoint_campana_wombat(campana) # asocia endpoint en wombat a campana campana_service.crear_endpoint_asociacion_campana_wombat(campana) # crea lista en wombat campana_service.crear_lista_contactos_wombat(campana) # asocia lista a campana en wombat campana_service.crear_lista_asociacion_campana_wombat(campana)
def _calificar_form(self, calificacion_form): calificacion_nueva = False if calificacion_form.instance.pk is None: calificacion_nueva = True self.object_calificacion = calificacion_form.save(commit=False) self.object_calificacion.callid = self._obtener_call_id() self.object_calificacion.agente = self.agente self.object_calificacion.contacto = self.contacto # TODO: Ver si hace falta guardar que es una llamada manual # El parametro manual no viene mas if self.object is None: es_calificacion_manual = 'manual' in self.kwargs and self.kwargs[ 'manual'] self.object_calificacion.es_calificacion_manual = es_calificacion_manual self.object_calificacion.save() # modificamos la entrada de la modificación en la instancia para así diferenciar # cambios realizados directamente desde una llamada de las otras modificaciones update_change_reason(self.object_calificacion, self.kwargs.get('from')) # check metadata en calificaciones de no accion y eliminar self._check_metadata_no_accion_delete(self.object_calificacion) # Verificar si es dialer y hay regla de incidencia por calificacion if self.call_data and 'dialer_id' in self.call_data: regla = ReglaIncidenciaPorCalificacion.objects.filter( opcion_calificacion=self.object_calificacion. opcion_calificacion) if regla: regla = regla[0] campana_service = CampanaService() campana_service.notificar_incidencia_por_calificacion( self.call_data['dialer_id'], regla) if self.object_calificacion.es_gestion() and \ not self.campana.tiene_interaccion_con_sitio_externo: if self.agente.grupo.obligar_calificacion: calificacion_llamada = CalificacionLLamada() calificacion_llamada.create_family( self.agente, self.call_data, self.kwargs['call_data_json'], calificado=False, gestion=True, id_calificacion=calificacion_form.instance.pk) return redirect(self.get_success_url_venta()) else: message = _( 'Operación Exitosa! ' 'Se llevó a cabo con éxito la calificación del cliente') messages.success(self.request, message) if self.object_calificacion.es_agenda() and calificacion_nueva: return redirect(self.get_success_url_agenda()) elif self.object_calificacion.es_agenda(): # se esta modificando una calificacion de agenda existente # con una agenda creada agenda_calificacion = AgendaContacto.objects.filter( contacto=self.contacto, campana=self.campana, agente=self.agente).first() if agenda_calificacion is not None: return redirect( self.get_success_url_agenda_update(agenda_calificacion.pk)) else: return redirect(self.get_success_url_agenda()) elif self.kwargs['from'] == 'reporte': return redirect(self.get_success_url_reporte()) else: return redirect(self.get_success_url())
def get_context_data(self, **kwargs): context = super(LlamadasActivasView, self).get_context_data(**kwargs) service = CampanaService() context['llamadas'] = service.obtener_calls_live() return context