Создание отчета по операторам, по различным показателям с использованием userfield
В данной статье рассмотрим возможность формирования отчетностей по операторам, с использованием дополнительного поля для записей в cdr – userfield. В отчетность можно добавлять различные показатели, такие как: Время до ответа Время разговора Кто положил трубку И многие другие. Добавлять показатели можно с помощью диалплана, в custom файлах (если используется FreePBX). Добавлять будем после завершения звонка. […]
В данной статье рассмотрим возможность формирования отчетностей по операторам, с использованием дополнительного поля для записей в cdr – userfield. В отчетность можно добавлять различные показатели, такие как:
- Время до ответа
- Время разговора
- Кто положил трубку
И многие другие.
Добавлять показатели можно с помощью диалплана, в custom файлах (если используется FreePBX). Добавлять будем после завершения звонка.
Для вывода информации, создадим небольшой web-интерфейс, с возможностью сохранить показатели в csv.
Время до ответа будем считать по разнице между общим временем и временем разговора с клиентом.
Источник можно получить несколькими способами, например из контекста откуда пришел вызов, либо из таблицы cel.
Информацию о том, кто положил трубку можно получить из переменных диалплана.
В диалплане внесем правки, для начала определить контекст, в котором будет происходить сбор переменных. Это можно делать в момент завершения вызова на локальный номер (контекст ext-local), в момент завершения вызова в очереди (ext-queues), в момент выполнения macro-hangupcall. Остановимся на последнем, поскольку для примера хватит и переменных оттуда.
В контексте для начала выводим необходимую информацию:
exten => s,n,NoOp(==${CALLERID(num)}==${EXTTOCALL}==${CDR(billsec)}==${CDR(duration)}==${CHANNEL(hangupsource)}==)
Для получения времени ожидания, используем функцию диалплана – MATH:
exten => s,n,Set(wait=${MATH(${CDR(duration)}-${CDR(billsec)},int)})
и добавим ее в вывод, пометив переменные для наглядности:
exten => s,n,NoOp(Caller=${CALLERID(num)}&Callee=${EXTTOCALL}&Billsec=${CDR(billsec)}&Duration=${CDR(duration)}&Res_Hangup=${CHANNEL(hangupsource)}&Wait=${wait})
Как видно из gif, переменная, обозначающая завершившего канал, пишется в его канале, в cdr это будет отображено в его поле. На данном этапе добавим запись в userfield этих значений как есть.
Пример:
ALTER TABLE cdr MODIFY userfield varchar(512);
Добавляем переменные в поле userfield:
exten => s,n,Set(CDR(userfield)=Caller=${CALLERID(num)}&Callee=${EXTTOCALL}&Billsec=${CDR(billsec)}&Duration=${CDR(duration)}&Res_Hangup=${CHANNEL(hangupsource)}&Wait=${wait})
Чтобы не заполнять лишние переменные в поле, можно создать обработчик, например, использовать ExecIf. Также можно изменить переменную отвечающую за целевой номер, на ${CONNECTEDLINE(num)}.
Например, будем записывать поле userfield, только для того, кто положил трубку:
exten => s,n,ExecIf($["${CHANNEL(hangupsource)}"!=""]?Set(CDR(userfield)=Caller=${CALLERID(num)}&Callee=${CONNECTEDLINE(num)}&Billsec=${CDR(billsec)}&Duration=${CDR(duration)}&Res_Hangup=${CHANNEL(hangupsource)}&Wait=${wait}))
Для отображения в отдельном окне выборки статистики, желательно записывать в оба поля, поскольку некоторые записи иначе будут потеряны.
Создадим небольшой веб-интерфейс отображения данных.
Для начала создадим скрипт в директории apache и дадим к нему доступ через нестандартный порт.
[root@localhost ~]# mkdir /var/www/html/userfield
[root@localhost ~]# touch /var/www/html/userfield/index.php
[root@localhost ~]# chown asterisk. /var/www/html/userfield/ -R
Параметры виртуального хоста в apache:
Listen 5446
NameVirtualHost *:5446
<VirtualHost *:5446>
DocumentRoot /var/www/html/userfield/
<Directory /var/www/html/userfield>
Options +Indexes
AllowOverride All
Order deny,allow
Deny from all
Allow from all
Satisfy all
RewriteEngine off
</Directory>
</VirtualHost>
На первой странице необходимо реализовать выборку по операторам АТС. Выбирать будем, основываясь на номерах из таблицы asterisk.devices.
Добавляем функцию bd_bridge, для запросов в базу и получаем список операторов.
function bd_bridge($db,$q){
$link = @mysqli_connect('localhost','freepbxuser','d45c7ea6a5460b03300977b1cd61f148',$db) or die("Error: ".@mysqli_connect_error($link));
$rs = @mysqli_query($link, $q) or die("Error: ".@mysqli_error($link));
if($rs){
//echo "Qwerty complete: $q <br />";
return $rs;
@mysqli_free_result($rs);
}
else{
//echo "Qwerty failure: $q <br />";
}
mysqli_close($link);
}
$result = bd_bridge('asterisk','SELECT id, description FROM devices ORDER BY id;');
echo "<form action='' method='post'><table>";
while ($row = mysqli_fetch_array($result))
{
$CellName = $row['description'];
$CellPhone = $row['id'];
echo "<tr><td><input type='checkbox' name='my_array[]' value='".$row[0].":".$row[1]."' />";
echo $row[0].":".$row[1];
echo "</td></tr>";
}
echo "<tr><td> <button name='inb' type='submit'>Отобразить входящие</button>
<button name='out' type='submit'>Отобразить исходящие</button> </td></tr>
</table>
</form>";
Список выведен, реализуем обработчик нажатия:
if (isset($_POST['inb']) && !empty($_POST['my_array'])) {
foreach ( $_POST['my_array'] as $value) {
$num=stristr($value,':',true);//получаем номер
$name=stristr($value,':');
$name=str_replace(":","",$name); //получаем имя
//запрос в базу за полем userfield
$result = bd_bridge('asteriskcdrdb',"SELECT calldate, userfield FROM cdr where calldate like '2018-12-25%' and (dst='".$num."');");
while ($row = mysqli_fetch_array($result)) {
if ($row['userfield'] != "") {
$arru=str_to_arr($row['userfield']);
echo $arru['Caller']." - ".$arru['Callee']." - ".$arru['Billsec']." - ".$arru['Duration']." - ".$arru['Res_Hangup']." - ".$arru['Wait']."</br>";
}
}
}
}
И организуем пока простой вывод информации на страницу.
Функция:
function str_to_arr($str){
$piece=array();
$string=array();
$arr=array();
$j=0;
$string = explode ("&",$str);
for($i=0;$i<count($string);$i++){
$piece=explode("=",$string[$i],2);
if (isset($piece[1])){
$arr[trim($piece[0])]=trim($piece[1]);
}
}
return $arr;
}
Далее формируем таблицу:
if ($arru['Res_Hangup']=="") $arru['Res_Hangup']=$arru['Caller'];
echo "<tr>
<td>".$row['calldate']."</td>
<td>".$arru['Caller']."</td>
<td>".$arru['Callee']."</td>
<td>".$arru['Billsec']."</td>
<td>".$arru['Duration']."</td>
<td>".$arru['Wait']."</td>
<td>".$arru['Res_Hangup']."</td>
</tr>";
Шапку таблицы укажем при входе в обработчик:
echo "
<table border=1>
<tr>
<td>Время</td>
<td>Номер источник</td>
<td>Номер направление</td>
<td>Время разговора</td>
<td>Общее время</td>
<td>Время ожидания</td>
<td>Источник завершения вызова</td>
</tr>";
Аналогично напишем обработчик исходящих вызовов:
if (isset($_POST['out']) && !empty($_POST['my_array'])) {
//echo "<pre>".print_r($_POST,true)."</pre>";
echo "
<table border=1>
<tr>
<td>Время</td>
<td>Номер источник</td>
<td>Номер направление</td>
<td>Время разговора</td>
<td>Общее время</td>
<td>Время ожидания</td>
<td>Источник завершения вызова</td></tr>";
foreach ( $_POST['my_array'] as $value) {
$num=stristr($value,':',true);
$name=stristr($value,':');
$name=str_replace(":","",$name);
$result = bd_bridge('asteriskcdrdb',"SELECT calldate, userfield FROM cdr where calldate like '2018-12-25%' and (src='".$num."');");
while ($row = mysqli_fetch_array($result)) {
if ($row['userfield'] != "") {
$arru=str_to_arr($row['userfield']);
//echo "<pre>".print_r($arru,true)."</pre>";
if ($arru['Res_Hangup']=="") $arru['Res_Hangup']=$arru['Callee'];
echo "
<tr>
<td>".$row['calldate']."</td>
<td>".$arru['Caller']."</td>
<td>".$arru['Callee']."</td>
<td>".$arru['Billsec']."</td>
<td>".$arru['Duration']."</td>
<td>".$arru['Wait']."</td>
<td>".$arru['Res_Hangup']."</td>
</tr>";
}
}
}
}
Если необходимо собирать информацию только за определенное время, необходима доработка, рассмотрим ее.
Для начала необходимо вывести форму выбора интервала времени:
Даты:<input name=d_first type='date' value=$date_start required> - <input name=d_second type='date' value=$date_start required> <br />
В соответствии с датой, меняем запрос в БД за информацией:
$result = bd_bridge('asteriskcdrdb',"SELECT calldate, userfield FROM cdr where calldate >= '".$_POST[d_first]." 00:00:00' and calldate <= '".$_POST[d_second]." 23:59:59' and (dst='".$num."');");
Изменения внесены, можно проверять.
Следующим шагом, реализуем возможность выгрузки статистики в csv.
Форма отправки та же самая, указываем две кнопки: для входящей и исходщей.
echo "<tr>
<td><button name='inb' type='submit'>Отобразить входящие</button>
<button name='out' type='submit'>Отобразить исходящие</button></td>
</tr>
<tr>
<td><button name='get_csv_inb' type='submit'>Выгрузить входящие</button>
<button name='get_csv_out' type='submit'>Выгрузить исходящие</button></td>
</tr>
</table>
</form>";
Обработчик нажатия кнопки выгрузки выполняет почти те же действия что и вывод таблицы, однако выводит не на страницу, а в файл и впоследствии предлагает его выгрузить.
if (isset($_POST['get_csv_inb'])&& !empty($_POST['my_array'])) {
$fp = fopen('statistic_inb.csv', 'w');
fputcsv($fp, array('Время','Номер источник','Номер направление','Время разговора','Общее время','Время ожидания','Источник завершения вызова'));
foreach ( $_POST['my_array'] as $value) {
$num=stristr($value,':',true);
$name=stristr($value,':');
$name=str_replace(":","",$name);
$result = bd_bridge('asteriskcdrdb',"SELECT calldate, userfield FROM cdr where calldate >= '".$_POST['d_first']." 00:00:00' and calldate <= '".$_POST['d_second']." 23:59:59' and (dst='".$num."');");
while ($row = mysqli_fetch_array($result)) {
if ($row['userfield'] != "") {
$arru=str_to_arr($row['userfield']);
//echo "<pre>".print_r($arru,true)."</pre>";
if ($arru['Res_Hangup']=="") $arru['Res_Hangup']=$arru['Caller'];
fputcsv($fp, array($row['calldate'],$arru['Caller'],$arru['Callee'],$arru['Billsec'],$arru['Duration'],$arru['Wait'],$arru['Res_Hangup']));
}
}
}fclose($fp);
file_force_download('statistic_inb.cs
Для выгрузки исходящей, обработчик аналогичен:
if (isset($_POST['get_csv_out'])&& !empty($_POST['my_array'])) {
$fp = fopen('statistic_out.csv', 'w');
fputcsv($fp, array('Время','Номер источник','Номер направление','Время разговора','Общее время','Время ожидания','Источник завершения вызова'));
foreach ( $_POST['my_array'] as $value) {
$num=stristr($value,':',true);
$name=stristr($value,':');
$name=str_replace(":","",$name);
$result = bd_bridge('asteriskcdrdb',"SELECT calldate, userfield FROM cdr where calldate >= '".$_POST['d_first']." 00:00:00' and calldate <= '".$_POST['d_second']." 23:59:59' and (dst='".$num."');");
while ($row = mysqli_fetch_array($result)) {
if ($row['userfield'] != "") {
$arru=str_to_arr($row['userfield']);
//echo "<pre>".print_r($arru,true)."</pre>";
if ($arru['Res_Hangup']=="") $arru['Res_Hangup']=$arru['Callee'];
fputcsv($fp, array($row['calldate'],$arru['Caller'],$arru['Callee'],$arru['Billsec'],$arru['Duration'],$arru['Wait'],$arru['Res_Hangup']));
}
}
}fclose($fp);
file_force_download('statistic_out.csv');
}
Функционал вывода реализован. Если текущих параметров недостаточно, можно добавить в заполнение поля необходимые данные, учитывая текущий формат записи.
Остались вопросы?
Я - Виталий Шелест, менеджер компании Voxlink. Хотите уточнить детали или готовы оставить заявку? Укажите номер телефона, я перезвоню в течение 3-х секунд.
категории
- DECT
- Linux
- Вспомогательный софт при работе с Asterisk
- Интеграция с CRM и другими системами
- Интеграция с другими АТС
- Использование Elastix
- Использование FreePBX
- Книга
- Мониторинг и траблшутинг
- Настройка Asterisk
- Настройка IP-телефонов
- Настройка VoIP-оборудования
- Новости и Статьи
- Подключение операторов связи
- Разработка под Asterisk
- Установка Asterisk
VoIP оборудование
ближайшие курсы
Новые статьи
10 доводов в пользу Asterisk
Распространяется бесплатно.
Asterisk – программное обеспечение с открытым исходным кодом, распространяется по лицензии GPL. Следовательно, установив один раз Asterisk вам не придется дополнительно платить за новых абонентов, подключение новых транков, расширение функционала и прочие лицензии. Это приближает стоимость владения станцией к нулю.
Безопасен в использовании.
Любое программное обеспечение может стать объектом интереса злоумышленников, в том числе телефонная станция. Однако, сам Asterisk, а также операционная система, на которой он работает, дают множество инструментов защиты от любых атак. При грамотной настройке безопасности у злоумышленников нет никаких шансов попасть на станцию.
Надежен в эксплуатации.
Время работы серверов некоторых наших клиентов исчисляется годами. Это значит, что Asterisk работает несколько лет, ему не требуются никакие перезагрузки или принудительные отключения. А еще это говорит о том, что в районе отличная ситуация с электроэнергией, но это уже не заслуга Asterisk.
Гибкий в настройке.
Зачастую возможности Asterisk ограничивает только фантазия пользователя. Ни один конструктор шаблонов не сравнится с Asterisk по гибкости настройки. Это позволяет решать с помощью Asterisk любые бизнес задачи, даже те, в которых выбор в его пользу не кажется изначально очевидным.
Имеет огромный функционал.
Во многом именно Asterisk показал какой должна быть современная телефонная станция. За многие годы развития функциональность Asterisk расширилась, а все основные возможности по-прежнему доступны бесплатно сразу после установки.
Интегрируется с любыми системами.
То, что Asterisk не умеет сам, он позволяет реализовать за счет интеграции. Это могут быть интеграции с коммерческими телефонными станциями, CRM, ERP системами, биллингом, сервисами колл-трекинга, колл-бэка и модулями статистики и аналитики.
Позволяет телефонизировать офис за считанные часы.
В нашей практике были проекты, реализованные за один рабочий день. Это значит, что утром к нам обращался клиент, а уже через несколько часов он пользовался новой IP-АТС. Безусловно, такая скорость редкость, ведь АТС – инструмент зарабатывания денег для многих компаний и спешка во внедрении не уместна. Но в случае острой необходимости Asterisk готов к быстрому старту.
Отличная масштабируемость.
Очень утомительно постоянно возвращаться к одному и тому же вопросу. Такое часто бывает в случае некачественного исполнения работ или выбора заведомо неподходящего бизнес-решения. С Asterisk точно не будет такой проблемы! Телефонная станция, построенная на Asterisk может быть масштабируема до немыслимых размеров. Главное – правильно подобрать оборудование.
Повышает управляемость бизнеса.
Asterisk дает не просто набор полезных функций, он повышает управляемость организации, качества и комфортности управления, а также увеличивает прозрачность бизнеса для руководства. Достичь этого можно, например, за счет автоматизации отчетов, подключения бота в Telegram, санкционированного доступа к станции из любой точки мира.
Снижает расходы на связь.
Связь между внутренними абонентами IP-АТС бесплатна всегда, независимо от их географического расположения. Также к Asterisk можно подключить любых операторов телефонии, в том числе GSM сим-карты и настроить маршрутизацию вызовов по наиболее выгодному тарифу. Всё это позволяет экономить с первых минут пользования станцией.