CDR

Довольно часто наши клиенты сталкиваются с необходимостью выгрузить информацию о звонках из раздела Call Detail Record к себе. Как вы уже знаете (даже если взять во внимание предыдущую запись в этом блоге, а именно Липкость звонка), вся историческая статистика хранится в базе elasticsearch. В документации вы так же могли увидеть пример получения данных с помощью нашего REST API. Но, что если звонков несколько сотен? Или несколько тысяч? Как правильно получить такой объем данных? Сегодня я расскажу как работать с большими объемами данных.

Scroll

Для получения большого количества данных, в elasticsearch предусмотрен функционал scroll, который мы повторили и в нашем REST API. Рассмотрим на примере:

Использование IVR меню, в большинстве случаем, позволяет эффективно распределять входящие звонки и снижать нагрузку с секретаря. Клиент звонит, выбирает нужный отдел либо до набирает внутренний номер сотрудника и достигает цели. Но, как быть в ситуации, когда клиент не знает кому он звонит? Что если это наш менеджер не смог дозвонится клиенту, который перезвонил и попал на IVR? В данном случае будет полезным функционал «Липкости звонка». Мы уже рассматривали реализацию: Входящий звонок с маршрутизацией на ответственного в bpm’online. Сегодня мы рассмотрим пример маршрутизации в первую очередь на того, кто сегодня уже общался с данным номером либо звонил ему. Приступим!

Kibana нам в помощь

Для решения поставленной задачи нам понадобится приложение cdr, которое предназначено для поиска по журналу звонков в elasticsearch. В начале, нам нужно написать правильный запрос. Делаем тестовый звонок и открываем интерфейс Kibana, раздел Discover. Выбираем для отображения колонки extension (номер сотрудника), caller_id_number (номер абонента), destination (номер назначения).

Теперь сделаем запрос с фильтрацией по номеру абонента, он может быть либо в номере назначения (для исходящих) либо в номере абонента (для входящих):

destination_number:/0969716158/ OR caller_id_number:/0969716158/

Как результат, мы получаем номер сотрудника, extension, который общался либо звонил абоненту. И обязательно открываем Response (ответ со стороны elasticsearh), он нам пригодится ниже:

И так, как искать мы уже поняли, а теперь, добавим это все в маршрутизацию на стороне Webitel.

Лет 7 тому назад, я уже писал на тему обработки входящего звонка от клиента, с поиском внутреннего номера сотрудника, который последним звонил на номер клиента. Теперь пришло время написать похожую статью, как такое реализовать в webitel, тем более, что начиная с версии 3.8.2 (UPD: как оказалось, нужна версия старше 3.8.2) у нас в маршрутизации появилось отдельное приложение для запросов в базу elasticsearch, где и хранится вся информация о звонках. Давайте рассмотрим пример, как научить webitel соединять клиентов с последним звонившим.

Предположим, что у нас уже имеется любая существующая схема с IVR и другими полезностями. Мы хотим добавить в начале проверку по номеру телефона, звонящего к нам в офис, кто из сотрудников последним звонил на данный номер. Дополнительно мы еще добавим ограничение в «за последние 30 минут». Все это мы можем сделать с помощью запроса в cdr:

Очень сильно раздражает, если для поиск нужного звонка в статистике любой АТС нужно ждать десятки секунд, а то и минуты. А теперь представьте, что Вы постоянно работаете со статистикой… Каждый поиск, каждый новый фильтр — потерянные минуты, которые собираются в часы 🙁 Вы можете увеличить вычислительные ресурсы сервера, можно удалить старые записи… А можно перейти на полнотекстовый поиск. Вот это последние мы и решили испытать в ожидающем нас новом релизе webitel.

Те, кто пользовался админкой в webitel 3.0 или 3.1, очень хорошо помнят ее ограничения при работе со статистикой — только фильтры по дате. Я сам неоднократно не мог найти нужный мне звонок:

Старая статистика звонков

В релизе 3.2 мы презентовали новый Webitel WebClient, который обзавелся не только новым видом, но и новым конструктором фильтров:

Конструктор фильтров

Недавно я рассказывал о нашем опыте подружить webitel с elasticsearch. И вот мы запустили в тестовом режиме сервис аналитики по звонкам для всех пользователей webitel on-demand. В основе все та же связка elasticsearch и kibana. Сегодня я хочу более подробней рассказать, что это такое.

Пройдя авторизацию (все данные можете запросить у поддержки), для Вас открывается простой Dashboard:

Dashboard

После публикации «Звонок с сайта«, ко мне обращались несколько человек с одним вопросом: «Можно вместо CallerID подставить IP-адрес звонящего?» Отвечаю: Можно! 🙂 Просто добавьте в Ваш диалплан:

<action application=“set” data=“effective_caller_id_number=${network_addr}”/>
<action application=“set” data=“effective_caller_id_name=Site Call”/>

Получите:

Если Вы используете Oktell IP PBX без модуля КЦ и Вы не умеете разрабатывать плагины, а необходимо быстро решить вопрос: При входящем звонке отобразить историю всех звонков по номеру с комментариями. Как это сделать? Пойдем через веб-страничку 🙂

Для начало разработаем SQL запрос, что бы увидеть все входящие, исходящие и пропущенные звонки по номеру:

SELECT [s].[TimeAnswer] as [TimeAnswer]
   ,CONVERT(varchar(max), Cast (Cast ( [s].TimeStop - [s].TimeAnswer as float ) * 1440 as decimal(15,2))) as [TimeLong]
   ,'входящий' AS [D]
   ,CONVERT(varchar(max), [s].[Astr]) as [Abonent] 
   ,CONVERT(varchar(max), [s].[Bstr]) as [Oper] 
   ,l.LineCode as [LineCode]
   ,CONVERT(varchar(max), [c].[Comment])  AS [Comment]
   FROM [oktell].[dbo].[A_Stat_Comments] [c]
   right outer join [oktell].[dbo].[A_Stat_Connections_1x1] [s] on [s].[Id] = c.[id]
   join [oktell].[dbo].A_ServerExtLines [l] on [s].ALineId = [l].id
WHERE ([s].[AOutNumber] like '$c' AND [s].[Bstr] not like 'IVR') 

UNION

SELECT [s].[TimeAnswer] as [TimeAnswer]
   ,CONVERT(varchar(max), Cast (Cast ( [s].TimeStop - [s].TimeAnswer as float ) * 1440 as decimal(15,2))) as [TimeLong]
   ,'исходящий' AS [D]
   ,CONVERT(varchar(max), [s].[Bstr]) as [Abonent] 
   ,CONVERT(varchar(max), [s].[Astr]) as [Oper] 
   ,l.LineCode as [LineCode]
   ,CONVERT(varchar(max), [c].[Comment])  AS [Comment]
   FROM [oktell].[dbo].[A_Stat_Comments] [c]
   right outer join [oktell].[dbo].[A_Stat_Connections_1x1] [s] on [s].[Id] = c.[id]
   join [oktell].[dbo].A_ServerExtLines [l] on [s].BLineId = [l].id
WHERE [s].[BOutNumber] like '$c' AND [s].[Astr] not like 'IVR'

UNION

SELECT [s].[TimeAnswer] as [TimeAnswer]
   ,CONVERT(varchar(max), Cast (Cast ( [s].TimeStop - [s].TimeAnswer as float ) * 1440 as decimal(15,2))) as [TimeLong]
   ,'пропущенный' AS [D]
   ,CONVERT(varchar(max), [s].[Astr]) as [Abonent] 
   ,CONVERT(varchar(max), [s].[Bstr]) as [Oper] 
   ,l.LineCode as [LineCode]
   ,CONVERT(varchar(max), [c].[Comment])  AS [Comment]
   FROM [oktell].[dbo].[A_Stat_Comments] [c]
   right outer join [oktell].[dbo].[A_Stat_Connections_1x1] [s] on [s].[Id] = c.[id]
   join [oktell].[dbo].A_ServerExtLines [l] on [s].ALineId = [l].id
WHERE [s].[AOutNumber] like '$c' AND [s].[Bstr] like 'IVR' AND [s].[ReasonStop] = '3'

ORDER BY [TimeAnswer] DESC

Стоит задача на Oktell IP PBX ограничить длительность внешних разговоров для всех сотрудников до 10 мин. Решил задачу так:

1. Создаем служебный сценарий который проверяет активность на каждой из внешних SIP-линий и если превышено 10 мин. — разрывает соединение:

2. Прописываем служебный сценарий на периодический запуск каждых 20 сек.

Задача решена 🙂

Запускаем новую услугу для пользователей Oktell“Подписка ua-region.info”. Есть одна из лучших баз с актуальной информацией по украинским предприятиям http://www.ua-region.info/. Вы можете оформить подписку на год и при входящем звонке, Oktell отправит запрос на сайт ua-region.info, где по callerid найдет компанию и ее описание. Эти данные с сайта Вы увидите у себя на мониторе (и на дисплее ip-телефона) вот так:

Всегда приятно знать кто тебе сейчас звонит 🙂