Marcadores v4 ES
IN PROGRESS
Voz
Variables a Configurar
- Tipo de Marcador: PowerDialer, VoiceBroadCast, Progressive (Con asignación por Agente), Predictive (mínimo 50 agentes)
- Nombre: Es el nombre del Marcador para VoiceBroadCast se puede poner cualquier nombre, para PowerDialer y Predictive se selecciona una Campaña Entrante, para Progressive una Campaña Saliente.
- Habilitado: Si esta activado
- Cadena de Marcado: Es lo que se utiliza para hacer la llamada Ejemplo: DAHDI/G1/ o SIP/CARRIER/
- Contexto: Al que va a entrar el marcador. Para VoiceBroadCast, PowerDialer, Predictive es el Contexto que entra una llamada conectada con un cliente y matchea un workflow, en Progressive es el Contexto por donde se realiza la llamada al cliente una vez conectado con el Agente. (Ya existen Contexto prearmados cada uno con el nombre del Marcador)
- Máximo: Cantidad maxima de llamadas simultáneas.
- Tiempo Entre Llamadas: Es el tiempo que se espera entre llamada y llamada, la idea es que cuando por ejemplo tomo 100 canales para marcar y el servidor no puede manejar tantas solicitudes al mismo tiempo le ponemos un tiempo entre llamada y llamada Ejemplo: 300 ms Habitualmente esta en 0, si se pone -1 en PowerDialer, ejecuta sobremarcado para tener mas agentes ocupados via formula estadística.
- Tiempo Máximo: tiempo máximo de espera al llamar a una destino o en Progressive para contactar un agente.
- Reintento: Cantidad maxima de llamadas para un numero en la base en Progressive para intentar conectar con el Agente.
- Audios: Audio o concatenación de audios (con &) que se le pasan al Workflow, util para VoiceBroadCast.
Callerid: Número con que salen las llamadas.
CallerPres: Para ISDN si muestra o no el CallerID donde el proveedor lo admita
AMD: si esta activado la detección de Answering Machine, esta variable llega ${am} en 1 o 0 y es posible en el flujo utilizarlo para usar la actividad amd para cortar las llamadas de Correos de Voz.
DNCR: Do Not Call Registry, permite verificar si se bloquea el registro por BlackLists
- Variables: Todo lo que se quiera pasar al worklfow a nivel global de marcador
Proceso
El sistema inicia según el scheduler creado.
Al comenzar el sistema Crea una Tarea para Cada Marcador definida en el sistema, las mismas arrancan y terminan de acuerdo al schedule que tengan. En el Dashboard de Monitoreo se ven todos los valores en Tiempo Real para el día del marcador.
Se pueden observar dos dashboards circulares que indican la cantidad de llamadas procesadas y no procesadas al igual que la cantidad de agentes en sus diferentes estados, así como también una gráfica que indica en tiempo real el total de llamadas activas, los agentes ocupados y las llamadas que se están marcando.
Nota: Es posible observar en esta última gráfica que la cantidad de ocupados sea mayor que el total asi como también ver a los marcandos negativos. Esto sucede cuando la campaña realiza llamadas manuales o cuando tenga llamadas entrantes que no sean del marcador, de todas formas la gráficas muestran la evolución del marcador.
Es posible en cualquier momento parar o volver a prender la campaña manualmente y subir nuevas listas o registros de lista negra, también es posible descargar las listas subidas para ese marcador accediendo desde el botón de listas ubicado en la parte superior derecha.
Se ejecuta la tarea, esta tarea es la encargada de hacer las llamadas enviando llamadas obtenidas del spool (tabla calls_spool) para la misma, estas son obtenidas de acuerdo al tipo de marcador que sea y son marcadas de acuerdo al string de marcado de la misma (puede ser por TDM o VOIP) cabe destacar que solo va a funcionar en lineas Digitales, VOIP o Analógicas con Disconnect Supervision (o sea inversion de polaridad). Al ejecutar la llamada esta se cambia de estado. Siempre se obtienen Llamadas únicamente de la lista activa.
SPOOL
CAMPAIGN: Nombre del marcador para el contacto
DESTINATION: telefono a llamar del contacto
STATUS: Estado del contacto
- STATUS: 0 - PROCESSING (se esta marcando)
- STATUS: 1 - TO PROCESS (esta en spool lista a ser procesada, son las que toma el marcador)
- STATUS: 3 - BLOCKED (bloqueado por DNCR se borran del spool en el job de mantenimiento diario)
DATA: valores pasados al workflow para poder utilizar
ALTERNATIVES: números alternativos para el contacto separados por :
RETRIES: 0 inicialmente, > 0 cantidad de intentos a ese número
CONTACT: Autogenerado para diferenciar el contacto
DIALERBASE: nombre de la base subida del marcador, tiene nombre mas la fecha de subida.
PRIORITY: 9999. a 1, inicialmente todas son insertadas con un numero alto, pero por razones del Agendamiento de Llamadas de marcador, son insertadas con 1 para que se ejecuten de inmediato mientas el marcador este activo, si se requiere dar prioridades a otras es posible insertarlas con valores intermedios.
AGENTPHONE: Para Progressive a que agente va cada contacto
Las llamadas son borradas del spool si son atendidas o superan la cantidad máxima de reintentos definido en el marcador.
Cuando llega algún evento de que el sistema pudo procesar la llamada esta se borra de la tabla, si fue ocupado o no answer o algún problema de que no había canales esta llamada se realiza un nuevo intento, incrementando el retry, esto para que no sea tomada inmediatamente y se procesen otras antes de volver a intentar con ella. Cabe destacar que entre llamada y llamada espera el tiempo TBC en milisegundos el cual habitualmente es 0 (sin delay) si el servidor no soporta y/o son muchos canales simultaneos es mejor poner el delay en por ejemplo 300 ms para lograr que cuando genera un lote de llamadas de golpe no sean demasiado rápido y el sistema no las pueda procesar correctamente.
Es importante no solapar cantidad de canales, si disponemos de 30 canales y tenemos 2 campañas al mismo tiempo con un máximo de 20 va a resultar en posibles errores del marcador pudiendo repetir algunas llamadas. Tambien al tener mas de 1 campaña para mejor performance es buena idea dejar 1 canal de pivote ya que al ser un sistema asincrónico basado en eventos es posible que en algún milisegundo se esten marcando en otras campañas y todavía no se tiene dato de que la misma esta realmente activa ocupando un canal, por lo tanto en el caso de borde es posible que pueda pasarse una de las campañas, de todas formas si se llegara a pasar y al sistema no le fuera posible crear un canal porque no hay, este se va a procesar mas tarde cuando se terminen de procesar las existentes en el spool ya que la misma va a quedar con un intento mas.
Dentro del Callerid(name) se encuentra VoiceBroadCast:Campaña:Numero:Lista a Marcar Esto permite el seguimiento de eventos del sistema para saber cuantas llamadas activas por campañas y permite volver a poner en el spool llamadas que no pudieron contactar al destino.
Carga de Contactos
Archivo CSV donde se encuentra: campaña, numero de telefono, status, datos El formato correcto es MSDOS CSV (esperado por ; y los saltos de linea \n)
El orden que se marcan es el orden del excel, lo unico que va variando de acuerdo a que los que suben los intentos van al final y si se insertan otros de Agendado o prioritarios van a salir primero.
Base.csv
campaña | teléfono | datos | telefonos alternativos | priority | agentphonev(Progresivo) |
---|---|---|---|---|---|
prueba1 | 098344484 | variable1=valor1:variable2=valor2 | 099111111:099121212 | 9999 | 1001 |
prueba1;098344484;var1=val1:var2=val2;099124484:099111111;99;1001
VoiceBroadCast
Introducción
El sistema de VoiceBroadCast es para realizar campañas de marcado automático, se sube una base de datos de teléfonos y estos son dirigidos hacia un flujo IVR el cual puede ser para reproducir avisos, audios, de forma dinámica o estática, también puede lograr realizar encuestas automáticas estáticas o dinámicas, así también como permitir que de acuerdo a una opción el cliente sea redirigido a una Campaña.
En este caso lo importante es setear la cantidad de canales ya que el VoiceBroadCast utiliza todos los posibles la mayor parte del tiempo.
Pasos
- El marcador obtiene la cantidad de llamadas a realizar, si es 0 espera y vuelve a preguntar, sino obtiene de acuerdo a:
- Cantidad de canales disponibles (Maximo - Usados)
- El marcador obtiene los contactos en base a la cantidad y las siguientes reglas:
- Pide para esa campaña contactos que esten activos para la base que este marcada como activa
- O cualquier contacto que sea Agendado para esa campaña con maxima prioridad
- Ordenando los contactos por Prioridad y Cantidad de reintentos (Prioridad --> 1 va a llamar antes)
- Si DNCR (do not call registry) se encuentra activo solo deja hacer la llamada si no se encuentra en lista negra.
- Se pasan todas las variables a los Workflows ya sean de campaña o de contacto
- Se pasa el registro del contacto de marcador con el reintento +1 a la lógica de negocio, esto va a permitir crear Logica de Respooling (volver a ingresar el contacto por no ser realmente efectivo con su alternativo)
- Si Supera la cantidad de intentos para ese numero entonces si existen alternativos obtiene el primero lo deja como principal y deja el resto como alternativos y comienza el proceso nuevamente.
- Se realiza la llamada
- Si no es atendida o da algun error al llamar entonces se incrementa los reintentos y pasa al fondo ese contacto para marcar luego
- Si es atendida y se ejecuta el workflow asociado y los pasos del mismo.
prueba1;098344484;NOMBRE=Sebastian Gutierrez:Monto=200;099124484:099111111;9999;
Flujo Standard
exten=> _X.,1,Set(CHANNEL(Language)=es) exten=> _X.,2,Answer(5) exten=> _X.,3,Set(CALLERID(num)=${EXTEN}) exten=> _X.,4,Set(CALLERID(name)=${CDR(campaign)}) exten=> _X.,5,Set(__dialed=${EXTEN}) exten=> _X.,6,Set(__REALDIALED=${EXTEN}) exten=> _X.,7,Playback(${sound},) exten=> _X.,8,Read(__confirma,IVRDemoDesicion,1,,1,5) exten=> _X.,9,GotoIf($["${confirma}" = "1"]?12:10) exten=> _X.,10,GotoIf($["${confirma}" = "2"]?7:11) exten=> _X.,11,Hangup() exten=> _X.,12,GUID(__guid) exten=> _X.,13,Set(CDR(guid)=${guid}) exten=> _X.,14,Set(CDR(campaign)=${CDR(campaign)}) exten=> _X.,15,Set(MONITOR_FILENAME=${guid}) exten=> _X.,16,Set(__Ani=${EXTEN}) exten=> _X.,17,Set(CDR(type)=record) exten=> _X.,18,Set(AUDIOHOOK_INHERIT(MixMonitor)=yes) exten=> _X.,19,SipAddHeader(CTI: {"Guid": "${guid}" , "Screen": "FALSE" , "Form": "${FORM}" , "Campaign" : "${CDR(campaign)}" , "Callerid" : "${CALLERID(num)}" , "ParAndValues" : "${PARAVAL}" , "Beep" : "TRUE" , "Answer" : "TRUE" , "Dialer" : "${DIALERRECORD}"}) exten=> _X.,20,Queue(${VBQUEUE},TtKk,,,600,,,,,) exten=> _X.,21,Goto(VoiceBroadCast,${EXTEN},11) exten=> h,1,Set(HASH(rates)=${ODBC_Data(select rates.gateway\, rates.rate\, rates.cost\, rates.note FROM rates LEFT JOIN provider ON provider.name=rates.gateway WHERE provider.status = 'true' AND substring( '${EXTEN}'\, 1\, length( prefix_regexp ) ) REGEXP prefix_regexp ORDER BY length(prefix_regexp) DESC\,rates.rate ASC)}) exten=> h,2,Set(talkedminutes=${MATH(${CDR(billsec)} / 60,f)}) exten=> h,3,Set(talkedminutes=$[CEIL(${talkedminutes})]) exten=> h,4,Set(chargedbalance=${MATH(${talkedminutes} * ${HASH(rates,rate)},f)}) exten=> h,5,Set(realbalance=${MATH(${talkedminutes} * ${HASH(rates,cost)},f)}) exten=> h,6,Set(CDR(charged_balance)=${chargedbalance}) exten=> h,7,Set(CDR(real_balance)=${realbalance}) exten=> h,8,Set(CDR(note)=${HASH(rates,note)}) exten=> h,9,Set(CDR(carrier)=${HASH(rates,gateway)}) exten=> h,10,Set(CDR(userfield)=${userfield}) exten=> h,11,Set(CDR(direction)=outgoing) exten=> h,12,Set(CDR(causecode)=${HANGUPCAUSE}) exten=> h,13,Hangup()
Variables que llegan al flujo: ${sound}, ${am},${FORM}, ${VBQUEUE} todas las variables configuradas para esa campaña. Luego con eso es posible en vez de hacer un simple Flujo de BroadCast, es posible diseñar IVRs donde se generen dinamicamente encuestas automáticas.
Marcadores Progresivos
Introducción
En este caso es un escalón mas abajo respecto a PowerDialer o Predictivo a la máxima automatización, pero nos mantenemos en sistemas de llamadas puramente automatizados. Los Marcadores progresivos se basan en la disponibilidad de los Agentes.
Los marcadores progresivos, suelen ser muy apropiados para los Centros con un volumen bajo o moderado de llamadas, donde no serían capaces de recabar suficiente información para alcanzar estadísticas fiables.
Basicamente llama al agente y cuando este atiende ejecuta la llamada, esto hace que muchos intentos puedan ser ocupado, numero equivocado, etc usando tiempo de agente. El workflow que se utiliza es el de salida por esto usamos en Progresivos Campañas salientes y no entrantes (no existe manejo de colas pero si concepto de wrapup).
Los contactos tienen propiedad de Agentes, o sea cada contacto se asocia a un telefono de un agente que es el que va a disponer de ese contacto.
Pasos
- El marcador obtiene la cantidad de llamadas a realizar, si es 0 espera y vuelve a preguntar, sino obtiene de acuerdo a:
- Cantidad de Agentes disponibles que no esten en wrapup
- El marcador obtiene los contactos en base a la cantidad y las siguientes reglas:
- Pide para esa campaña, contactos que esten activos, para la base que este marcada como activa pero para los agentes que estan disponibles, uno para cada uno
- O cualquier contacto que sea Agendado para esa campaña con maxima prioridad, mientras que el agente este activo
- Ordenando los contactos por Prioridad y Cantidad de reintentos (Prioridad --> 1 va a llamar antes)
- Si DNCR (do not call registry) se encuentra activo solo deja hacer la llamada si no se encuentra en lista negra.
- Se pasan todas las variables a los Workflows ya sean de campaña o de contacto
- Se pasa el registro del contacto de marcador con el reintento +1 a la lógica de negocio, esto va a permitir crear Logica de Respooling (volver a ingresar el contacto por no ser realmente efectivo)
- Si Supera la cantidad de intentos para ese numero entonces si existen alternativos obtiene el primero lo deja como principal y deja el resto como alternativos y comienza el proceso nuevamente.
- Se realiza la llamada al agente, si por alguna razon no puede atender, se va a reintentar sin afectar la cantidad de reintentos una vez el agente vuelva a estar disponible.
- Si no es atendida o da algun error al llamar entonces se incrementa los reintentos y pasa al fondo ese contacto para marcar luego
- Al Agente se le pasa el registro de contacto para que se pueda tomar acciones basados en logica de negocio y asi poder realizar el Respooling del contacto segun se requiera (teniendo todos los datos del mismo). Tambien le llegan datos para el CTI (poder abrir el form con los datos del cliente a llamar)
prueba1;098344484;NOMBRE=Sebastian Gutierrez:Monto=200;099124484:099111111;9999;1001
Flujo Standard
exten=> _X.,1,Set(VOLUME(TX)=2) exten=> _X.,2,Set(VOLUME(RX)=2) exten=> _X.,3,Set(__OUTQUEUE=${CDR(campaign)}) exten=> _X.,4,Set(__DIALED=${EXTEN}) exten=> _X.,5,Set(__AGENT=${OUTAGENT}) exten=> _X.,6,Set(__guid=${OUTGUID}) exten=> _X.,7,Set(CALLERID(num)=${OUTDID}) exten=> _X.,8,Set(CALLERID(name-pres)=${CALLERPRESS}) exten=> _X.,9,Set(dummy=${ODBC_Data(UPDATE calls_spool set status =0\, retries = retries + 1 WHERE contact = ${CDR(contact)} AND destination = '${EXTEN}')}) exten=> _X.,10,Set(CDR(guid)=${guid}) exten=> _X.,11,Set(CDR(type)=record) exten=> _X.,12,MixMonitor(${guid}.gsm,b,) exten=> _X.,13,Set(CDR(accountcode)=${AGENT}) exten=> _X.,14,Set(__idLlamada=${guid}) exten=> _X.,15,Set(__REALDIALED=${EXTEN}) exten=> _X.,16,Dial(${DIALSTRING:0:-1}/${EXTEN},30,TtKkc,) exten=> _X.,17,Set(CDR(causecode)=${HANGUPCAUSE}) exten=> _X.,18,NoOp(${DIALSTATUS} - ${HASH(SIP_CAUSE,${CDR(dstchannel)})} - ${HANGUPCAUSE}) exten=> _X.,19,Hangup() exten=> h,1,Set(HASH(rates)=${ODBC_Data(select rates.gateway\, rates.rate\, rates.cost\, rates.note FROM rates LEFT JOIN provider ON provider.name=rates.gateway WHERE provider.status = 'true' AND substring( '${EXTEN}'\, 1\, length( prefix_regexp ) ) REGEXP prefix_regexp ORDER BY length(prefix_regexp) DESC\,rates.rate ASC)}) exten=> h,2,Set(talkedminutes=${MATH(${CDR(billsec)} / 60,f)}) exten=> h,3,Set(talkedminutes=$[CEIL(${talkedminutes})]) exten=> h,4,Set(chargedbalance=${MATH(${talkedminutes} * ${HASH(rates,rate)},f)}) exten=> h,5,Set(realbalance=${MATH(${talkedminutes} * ${HASH(rates,cost)},f)}) exten=> h,6,Set(CDR(charged_balance)=${chargedbalance}) exten=> h,7,Set(CDR(real_balance)=${realbalance}) exten=> h,8,Set(CDR(note)=${HASH(rates,note)}) exten=> h,9,Set(CDR(carrier)=${HASH(rates,gateway)}) exten=> h,10,Set(CDR(userfield)=${userfield}) exten=> h,11,Set(CDR(direction)=outgoing) exten=> h,12,Set(CDR(causecode)=${HANGUPCAUSE}) exten=> h,13,QueueUpdate(${OUTQUEUE},${UNIQUEID},${AGENT},${DIALSTATUS},${ANSWEREDTIME},${DIALEDTIME}|${DIALED}|${IdLlamada}|) exten=> h,14,Hangup()
Marcadores Powerdialer
Introducción
A diferencia del marcador Progresivo el Power Dialer no llama primero al agente y luego realiza la llamada sino que es muy similar a un Predictivo pero con un calculo de sobre marcado mas básico.
Lo primero que realiza el sistema es marcar mientras existan agentes disponibles para atender llamadas en la campaña, ejemplo si hay 2 agentes disponibles va a realizar 2 llamadas simultáneamente y así hasta que contacte a alguno, una vez contactado un cliente se envía a la campaña, en el 99% de los casos debería tener agente libre para atender al instante. Esto nos evita tener que entregarle al agente llamadas de números ocupados o inexistentes y entregarle llamadas solamente que fueron atendidas. La forma de trabajar es exactamente la misma en los marcadores VoiceBroadCast, PowerDialer,Predictive lo único que cambia es la cantidad de llamadas que se ejecutan.
El PowerDialer intenta tener a todos los agentes con llamada con su sobremarcado.
Pasos
- El marcador obtiene la cantidad de llamadas a realizar, si es 0 espera y vuelve a preguntar, sino obtiene de acuerdo a:
- Modo Normal (TBC >= 0): Cantidad de Agentes disponibles que no esten en wrapup sin pasar la maxima cantidad de canales para la campaña
- Modo Sobremarcado (TBC -1): igual a Modo Normal pero con un porcentaje de sobremarcado basado en un modelo estadístico (Predictivo)
- El marcador obtiene los contactos en base a la cantidad y las siguientes reglas:
- Pide para esa campaña, contactos que esten activos, para la base que este marcada como activa
- O cualquier contacto que sea Agendado para esa campaña con maxima prioridad
- Ordenando los contactos por Prioridad y Cantidad de reintentos (Prioridad --> 1 va a llamar antes)
- Si DNCR (do not call registry) se encuentra activo solo deja hacer la llamada si no se encuentra en lista negra.
- Se pasan todas las variables a los Workflows ya sean de campaña o de contacto
- Se pasa el registro del contacto de marcador con el reintento +1 a la lógica de negocio, esto va a permitir crear Logica de Respooling (volver a ingresar el contacto por no ser realmente efectivo)
- Si Supera la cantidad de intentos para ese numero entonces si existen alternativos obtiene el primero lo deja como principal y deja el resto como alternativos y comienza el proceso nuevamente.
- Se realiza la llamada
- Si no es atendida o da algun error al llamar entonces se incrementa los reintentos y pasa al fondo ese contacto para marcar luego
- Si es atendida y esta habilitada AMD entonces si es MACHINE se reinserta el registro con el proximo alternativo a no ser que sea el ultimo reintento del contacto HUMAN entonces va al ACD a repartir entre los agentes disponibles
- Si es atendida y no esta habilitada AMD pasa directamente al ACD a los agentes.
- Al Agente se le pasa el registro de contacto para que se pueda tomar acciones basados en logica de negocio y asi poder realizar el Respooling del contacto segun se requiera (teniendo todos los datos del mismo).
prueba1;098344484;var1=val1:var2=val2;099124484:099111111;9999;
Flujo Standard
exten=> _X.,1,Set(CHANNEL(Language)=es) exten=> _X.,2,Answer(0) exten=> _X.,3,Set(CALLERID(num)=${EXTEN}) exten=> _X.,4,Set(CALLERID(name)=${CDR(campaign)}) exten=> _X.,5,Set(__dialed=${EXTEN}) exten=> _X.,6,Set(__REALDIALED=${EXTEN}) exten=> _X.,7,Set(__Ani=${EXTEN}) exten=> _X.,8,GUID(__guid) exten=> _X.,9,Set(CDR(guid)=${guid}) exten=> _X.,10,Set(CDR(campaign)=${CDR(campaign)}) exten=> _X.,11,Set(MONITOR_FILENAME=${guid}) exten=> _X.,12,Set(CDR(type)=record) exten=> _X.,13,Set(AUDIOHOOK_INHERIT(MixMonitor)=yes) exten=> _X.,14,SipAddHeader(CTI: {"Guid": "${guid}" , "Screen": "FALSE" , "Form": "${FORM}" , "Campaign" : "${CDR(campaign)}" , "Callerid" : "${CALLERID(num)}" , "ParAndValues" : "${PARAVAL}" , "Beep" : "TRUE" , "Answer" : "TRUE" , "Dialer" : "${DIALERRECORD}"}) exten=> _X.,15,GotoIf($["${am}" = "1"]?18:16) exten=> _X.,16,Queue(${CDR(campaign)},TtKk,,,600,,,,,) exten=> _X.,17,Hangup() exten=> _X.,18,WaitForSilence(1000,,) exten=> _X.,19,AMD(6000,1500,800,2500,100,50,3,256) exten=> _X.,20,GotoIf($["${AMDSTATUS}" = "MACHINE"]?21:16) exten=> _X.,21,Set(__userfield=${AMDSTATUS} - ${AMDCAUSE}) exten=> _X.,22,GotoIf($["${RESPOOL}" = "true"]?24:23) exten=> _X.,23,Hangup() exten=> _X.,24,Set(dummy=${ODBC_Data(INSERT INTO calls_spool VALUES(${DIALERRECORD}))}) exten=> _X.,25,Goto(PowerDialer,${EXTEN},23) exten=> h,1,Set(HASH(rates)=${ODBC_Data(select rates.gateway\, rates.rate\, rates.cost\, rates.note FROM rates LEFT JOIN provider ON provider.name=rates.gateway WHERE provider.status = 'true' AND substring( '${EXTEN}'\, 1\, length( prefix_regexp ) ) REGEXP prefix_regexp ORDER BY length(prefix_regexp) DESC\,rates.rate ASC)}) exten=> h,2,Set(talkedminutes=${MATH(${CDR(billsec)} / 60,f)}) exten=> h,3,Set(talkedminutes=$[CEIL(${talkedminutes})]) exten=> h,4,Set(chargedbalance=${MATH(${talkedminutes} * ${HASH(rates,rate)},f)}) exten=> h,5,Set(realbalance=${MATH(${talkedminutes} * ${HASH(rates,cost)},f)}) exten=> h,6,Set(CDR(charged_balance)=${chargedbalance}) exten=> h,7,Set(CDR(real_balance)=${realbalance}) exten=> h,8,Set(CDR(note)=${HASH(rates,note)}) exten=> h,9,Set(CDR(carrier)=${HASH(rates,gateway)}) exten=> h,10,Set(CDR(userfield)=${userfield}) exten=> h,11,Set(CDR(direction)=outgoing) exten=> h,12,Set(CDR(causecode)=${HANGUPCAUSE}) exten=> h,13,Hangup()
Marcadores Predictivos
Introducción
Los marcadores predictivos basan su funcionamiento, en bases de datos de teléfonos a llamar, y lo hacen como su nombre indica de una forma "predictiva".
Esto quiere decir que entra en juego un algoritmo basado subyacéntemente en estrategias estadísticas, las cuales toman múltiples variables del Centro de Llamadas y calculan diversos factores para poder poner en contacto a los Agentes con los contactos de la manera más eficiente posible.
Por regla general, la principal utilidad y ventaja para los Marcadores Predictivos radica en el volumen de llamadas de los Centros en los que se basan, dado que al estar fundamentos en técnicas estadísticas, su máxima fiabilidad redunda en la Ley de los Grandes Números. Es por ello, que en Call-Centers de carácter reducido son bastante poco recomendados por su funcionamiento base.
En esencia, la idea conceptual detrás de los marcadores predictivos es la siguiente:
- Primero ha de calcularse el tiempo ideal para lanzar llamadas a clientes utilizando estrategias estadísticas de diversa índole, entre las que se incluyen:
- Calculan el tiempo medio por cada llamada que resulta en éxito, y cada llamada que resulta en fracaso.
- Calculan la proporción media de llamadas resultantes en éxito y en fracaso y con ello se pondera un tiempo medio estimado para todas las llamadas en general
- Utilizan otros factores que influyan en los tiempos, como el tiempo medio de preparación para aceptar otra llamada de cada agente y Wrapup
Cuanto más sofisticado sea este algoritmo, mejor en términos generales será el Marcador Predictivo. De hecho este es uno de los factores clave que determinara su éxito en un futuro. Muchos Algoritmos predictivos se basan en la distribución de Erlang
- En segundo lugar, se lanzan llamadas a los números almacenados en la base de datos, respetando este tiempo calculado:
- Con las llamadas en curso, el Marcador Predictivo debe ser capaz de identificar si existe algún tipo de inconveniente para no poder contactar con el cliente, principalmente por el tipo de tono que se recibe, según la convención de tonos a nivel nacional del país en concreto.
- También ser capaz de detectar Tonos de Fax y otras posibilidades que también sigan algún tipo de estándar
- En caso que ocurra un evento de este tipo, dependiendo del evento, la aplicación ha de ser capaz de marcar el teléfono apropiadamente en función de lo ocurrido:
- Además la capacidad de detectar VoiceMail dado que por regla general son símbolos de "No Disponible", para volver a intentar la llamada más tarde. La detección es relativamente fácil, en función del tiempo total de respuesta de voz, dado que la mayoría de las respuestas de personas físicas suelen ser, un simple "Hola?", mientras que los contestadores suelen ser una frase bastante larga.
- En el momento que recibe una llamada atendida, se la pasa a la cola de los Agentes para que sea atendida con brevedad.
Con este sistema, los agentes solo quedan a la espera de que la máquina haga su trabajo, y por regla general, no tienen la posibilidad de elegir si desean responder la llamada, sino que esta se pone directamente en comunicación con el Agente.
A priori, este método puede ser ideal, y realmente si estamos ante un Marcador Predictivo de calidad, es cierto esta premisa. Pero en contrapartida nos encontramos con algunos inconvenientes, que debemos sopesar, a la hora de elegir este tipo de Marcadores:
- Si en el intervalo en el que el cliente atiende una llamada, y el operador la recibe, no hay respuesta, es muy probable que el cliente abandone la llamada. En este caso la mayoría de los marcadores predictivos, ponen el número para ser llamado en un futuro, pero podemos generar insatisfacción en el cliente por causas de molestia
- Si lo queremos utilizar con fines comerciales de Empresa a Empresa, es posible que sea bastante ineficiente, dado que la mayoría de las empresas dispongan de un IVR el cual posiblemente impida que nuestro marcador predictivo cumpla su propósito en condiciones.
- Como comentábamos, si tenemos pocas llamadas en el Centro, es posible que los algoritmos estadísticos no saquen cifras de calidad y por tanto ocurra mucho el primer problema, siendo un sistema muy ineficiente.
prueba1;098344484;var1=val1:var2=val2;099124484:099111111;9999;
Flujo Standard
exten=> _X.,1,Set(CHANNEL(Language)=es) exten=> _X.,2,Answer(0) exten=> _X.,3,Set(CALLERID(num)=${EXTEN}) exten=> _X.,4,Set(CALLERID(name)=${CDR(campaign)}) exten=> _X.,5,Set(__dialed=${EXTEN}) exten=> _X.,6,Set(__REALDIALED=${EXTEN}) exten=> _X.,7,Set(__Ani=${EXTEN}) exten=> _X.,8,GUID(__guid) exten=> _X.,9,Set(CDR(guid)=${guid}) exten=> _X.,10,Set(CDR(campaign)=${CDR(campaign)}) exten=> _X.,11,Set(MONITOR_FILENAME=${guid}) exten=> _X.,12,Set(CDR(type)=record) exten=> _X.,13,Set(AUDIOHOOK_INHERIT(MixMonitor)=yes) exten=> _X.,14,SipAddHeader(CTI: {"Guid": "${guid}" , "Screen": "FALSE" , "Form": "${FORM}" , "Campaign" : "${CDR(campaign)}" , "Callerid" : "${CALLERID(num)}" , "ParAndValues" : "${PARAVAL}" , "Beep" : "TRUE" , "Answer" : "TRUE" , "Dialer" : "${DIALERRECORD}"}) exten=> _X.,15,GotoIf($["${am}" = "1"]?18:16) exten=> _X.,16,Queue(${CDR(campaign)},TtKk,,,600,,,,,) exten=> _X.,17,Hangup() exten=> _X.,18,WaitForSilence(1000,,) exten=> _X.,19,AMD(6000,1500,800,2500,100,50,3,256) exten=> _X.,20,GotoIf($["${AMDSTATUS}" = "MACHINE"]?21:16) exten=> _X.,21,Set(__userfield=${AMDSTATUS} - ${AMDCAUSE}) exten=> _X.,22,GotoIf($["${RESPOOL}" = "true"]?24:23) exten=> _X.,23,Hangup() exten=> _X.,24,Set(dummy=${ODBC_Data(INSERT INTO calls_spool VALUES(${DIALERRECORD}))}) exten=> _X.,25,Goto(PowerDialer,${EXTEN},23) exten=> h,1,Set(HASH(rates)=${ODBC_Data(select rates.gateway\, rates.rate\, rates.cost\, rates.note FROM rates LEFT JOIN provider ON provider.name=rates.gateway WHERE provider.status = 'true' AND substring( '${EXTEN}'\, 1\, length( prefix_regexp ) ) REGEXP prefix_regexp ORDER BY length(prefix_regexp) DESC\,rates.rate ASC)}) exten=> h,2,Set(talkedminutes=${MATH(${CDR(billsec)} / 60,f)}) exten=> h,3,Set(talkedminutes=$[CEIL(${talkedminutes})]) exten=> h,4,Set(chargedbalance=${MATH(${talkedminutes} * ${HASH(rates,rate)},f)}) exten=> h,5,Set(realbalance=${MATH(${talkedminutes} * ${HASH(rates,cost)},f)}) exten=> h,6,Set(CDR(charged_balance)=${chargedbalance}) exten=> h,7,Set(CDR(real_balance)=${realbalance}) exten=> h,8,Set(CDR(note)=${HASH(rates,note)}) exten=> h,9,Set(CDR(carrier)=${HASH(rates,gateway)}) exten=> h,10,Set(CDR(userfield)=${userfield}) exten=> h,11,Set(CDR(direction)=outgoing) exten=> h,12,Set(CDR(causecode)=${HANGUPCAUSE}) exten=> h,13,Hangup()
Scheduler
El scheduler de marcadores es para poder Agendar llamadas y que el marcador las realice en el momento adecuado, para esto existe un WebService de Tipo REST que permite agendar las mismas. y es posible hacerlo desde Forms, o Workflows o desde sistemas externos.
Basicamente el proceso es que existe una tabla donde estan las llamadas que estan agendadas con toda su informacion pertinente
calls_scheduler
calldate | campaign | destination | alternatives | agentphone | data |
---|---|---|---|---|---|
fecha y hora de cuando tiene que ejectuar | prueba1 | 098344484 | 099111111:099121212 | 1001 | variable1=valor1:variable2=valor2 |
El scheduler estar ubicando en el calls_spool con prioridad 1 a las llamadas que tienen que ejecutar en ese minuto, lo cual va a hacer que los marcadores la tomen lo antes posible para realizarla, queda con nombre de base Schedule y Fecha para poder ver cuales son las llamadas que se agendaron y cuando debían realizarse para poder comparar con el calldate del CDR.
WebService
POST http://<IP-INTEGRASERVER>/Integra/resources/Dialers/ScheduleDialerCall param: @FormParam("call") (json con formato call_scheduler) { "calldate" : "2015-10-11 15:00:00", "campaign" : "Ventas->", "destination" : "098344484", "alternatives" : "099124484:099121212", "agentphone" : "1001", "data" : "Par1=Val1:Par2=Val2" }
RESPOOL
El respool esta dado por un webservice que permite volver a procesar un contacto que fue atendido debido a la logica de negocio, permite insertar un contacto como se requiera con alternativos, prioridad, etc.
En el CTI llega un registro
Dialer: Ventas->, 098344484, 1, Par1=val1:Par2=val2, 091121212:099888888, 1, 12, basetesting, 99, 1001
(campaña, destino, status, parametros y valores, alternativos, reintentos, contactid, nombrebase, prioridad, telefono agente)
Con Este dato y el siguiente webservice, es posible agregar cualquier tipo de logica de negocio al marcador desde Forms o Aplicaciones de 3ros (Llega como numero primario el primer alternativo ya que se considera que el principal ya fue contactado, de todas formas se puede hacer Reschedule de ese numero principal en si mismo)
POST http://<IP-INTEGRASERVER>/Integra/resources/Dialers/Respool param: @FormParam("callspool") (json con formato call_spool) { "callsSpoolPK": { "campaign": "Ventas->", "destination": "098344484", "dialerbase": "basetest" }, "status": 1, "data": "Par1=Val1:Par2=Val2", "alternatives": "098124484", "contact": 222, "retries": 0, "priority": 99, "agentphone": "1001" }
CTI
Ejemplo Evento CTI que llega al Browser
LIST MANAGMENT
El sistema permite tener multiples listas para una campaña, al subir las listas estas van accediendo al sistema en orden de subida, la primera para una campaña se marca como activa, luego el resto como inactivas.
El supervisor luego puede decidir desde el dashboard de marcadores cual lista quiere tener activa, el dashboard muestra las listas que hay en el sistema, la cantidad de registros que le queda a cada una, pudiendo activar o desactivar las mismas y la cantidad de registros por agente. Para visualizar la cantidad de registros por agente se debe presionar el ícono de agentes de la lista deseada.
Es importante saber que las llamadas del scheduler son siempre prioritarias no importa que lista se este ejecutando.
Una vez una lista es finalizada y le queda 0 registros esta es eliminada del sistema, se envía un mail (Configuración AlertMail) avisando que base se finalizo y se activa automaticamente la siguiente que fue cargada.
El proceso puede llegar a demorar un máximo de 10 seg en activar la nueva lista si una se queda sin registros.
Los marcadores solo seleccionaran contactos de la lista activa.
SMS
Basicamente trabaja de forma similar al resto de los marcadores que tenemos, se ponen en memoria 50 mensajes de state 1 de la tabla sms_spool ordenado por la posición de ingreso de los mismos, se fija si esta en la black_list, si esta no lo envía y lo pone en estado 3,
Estados
STATE: 0 NONE
STATE: 1 TO PROCESS
STATE: 3 BLOCKED
campaign | destination | message | device | idm | data |
---|---|---|---|---|---|
prueba1 | 098344484 | este es mi sms | Dinstar | autonumerico | datos extra |
Base.csv
campaign | destination | message | priority |
---|---|---|---|
prueba1 | 098344484 | este es mi sms | 9999 |
prueba1;098344484;Hola Mundo!;9999
WebService
POST http://INTEGRASERVER/Integra/resources/SMS/SendSMS params: @FormParam("destination"), @FormParam("message"), @FormParam("campaign"), @FormParam("agent")
Scheduler
El scheduler de marcadores de SMS es para poder Agendar SMS y que el marcador las realice en el momento adecuado, para esto existe un WebService de Tipo REST que permite agendar las mismas. y es posible hacerlo desde Forms, Workflows o desde sistemas externos.
Basicamente el proceso es que existe una tabla donde estan las llamadas que estan agendadas con toda su informacion pertinente
sms_scheduler
calldate | campaign | destination | data |
---|---|---|---|
fecha y hora de cuando tiene que ejectuar | prueba1 | 098344484 | El mensaje |
El scheduler estar ubicando en el sms_spool con prioridad 1 a los mensajes que tienen que ejecutar en ese minuto, lo cual va a hacer que los marcadores lo tomen lo antes posible para enviar el mensaje, queda con nombre de base Schedule y Fecha para poder ver cuales son los sms que se agendaron y cuando debían realizarse para poder comparar con el dateprocessed del sms_repo.
POST http://<IP-INTEGRASERVER>/Integra/resources/SMS/ScheduleDialerSMS param: @FormParam("sms") (json con formato sms_scheduler) { "calldate" : "2015-10-11 15:00:00", "campaign" : "Ventas->", "destination" : "098344484", "data" : "MEnsaje" }
Formatear de excel a CSV
Se tiene que cambiar primeramente la opcion delimitar dentro del panel de control> opciones de lenguaje region y tiempo> cambiar fecha hora y formato numerico.
1) Change date,time or number formats
2)Additional settings...
3)Cambiamos el cambo de list separator del que figure a un punto y coma.
Apply y cerramos.
4)CREACIÓN DE BASE
Necesariamente tendremos que insertar una fila al comienzo de todas nuestras bases independientemente del tipo de marcador que utilicemos,
ya que al momento de exportar a CSV el mismo se guía por los cabezales que tengamos ya sean 5 o 6 en total.
4)Nos dirigimos a archivo>guardar como..
Seleccionamos que el campo tipo, sea CSV (MS-DOS)
5)Damos click derecho al archivo que se genero, le damos edit para visualizarlo en modo CSV y corroboramos que se exporto correctamente.
6) Este es el archivo que se va a generar, borramos la primera linea por completo y guardamos nuevamente.
7)Finalmente queda el archivo listo para subir a uContact
*Podemos observar en la linea 3 y 5 que si uno de los campos se encuentra vació el delimitador va a generar igual las comas pertinentes para que la base se suba de todas formas
*Así mismo también podemos observar que al finalizar 9999 inserto otra coma al final, tomándolo como un campo adicional y sea acorde a los requerimientos de dichas bases para subir a uContact
ACLARACIÓN
Supongamos que poseemos una base sin números alternativos ni prioridad
sin dichos campos este seria el resultado primario del CSV después de realizar la importación:
Procedemos a borrar la primera linea, y el resultado optimo seria: