Дмитрий Кайдаш
05.12.2019
3734

Добавление возможности выгрузки cdr_reports в формате *.xlsx (MS Office 2007+)

Описание: в данной статье будет рассмотрена работа с базовой отчётностью FreePBX – модулем CDR-Reports и, в частности модификация позволяющая производить выгрузку отчёта в современном формате. Использованные ресурсы: Необходимое оборудование: CentOS 6.9 Asterisk 13 FreePBX 13 Рано или поздно любой владелец задумывается о статистике своих звонков. Давайте обратимся к интерфейсу администрирования FreePBX и рассмотрим, что он […]

Описание: в данной статье будет рассмотрена работа с базовой отчётностью FreePBX – модулем CDR-Reports и, в частности модификация позволяющая производить выгрузку отчёта в современном формате.

Использованные ресурсы:

Необходимое оборудование:

  • CentOS 6.9
  • Asterisk 13
  • FreePBX 13
Указаны версии на которых проводилось тестирование, на других эффективность не гарантируется.

Рано или поздно любой владелец задумывается о статистике своих звонков. Давайте обратимся к интерфейсу администрирования FreePBX и рассмотрим, что он может нам предложить. Для озвученной задачи используется отдельный модуль CDR Reports, имеющий следующий интерфейс:

Первая функция – отображение в web
Первая функция – отображение в web

Первый из возможных вариантов предоставляет возможность просмотреть информацию по каналам, прослушать\скачать запись, получить сведения о продолжительности разговора и статусе звонка.

Информация предоставляется по каналам, а не звонкам. Поэтому на один звонок может приходиться множество записей со статусом «неотвечен» для нескольких операторов и «отвечен» для одного из них: это специфика работы модуля «queues».

При необходимости, можно использовать, обычно пустое, поле «userfield», записав в него свою информацию. Это весьма полезно, поскольку изменение штатных полей запрещено, а добавлять собственное в таблицу CDR – рискованно, и требует некоторого опыта. Для примера туда можно записать код канала первым завершившим вызов. Данная информация полезна для большинства систем статистики.

Если кликнуть на идентификатор звонка – третья колонка – можно просмотреть список событий в звонке, если у вас подключена таблица CEL.

Вторая форма отчётности – экспорт в файл. Вот тут и начинаются проблемы. Файл выгружается корректно, но по-умолчанию представляет собой *.csv формат. При открытии через Open Office вы сразу увидите предупреждение о настройке разметки и разделителей.

Открытие отчёта в OpenOffice
Открытие отчёта в OpenOffice

И так будет каждый раз при открытии, что доставляет неудобства и тратит время. Попробуем открыть через самый распространённый офисный пакет приложений, и конкретно через MS Excel. Получим следующее:

Открытие отчёта в MS Office
Открытие отчёта в MS Office

Стало только хуже. Да, как продукт с обширным функционалом этот редактор может привести данные в порядок. На случай если этот вариант приемлем опишем.

  1. Выполняем переход «данные» -> «текст по столбцам»
Вкладка форматирования
Вкладка форматирования

В появившемся окне указываем форматирование с разделителями.

Режим форматирования
Режим форматирования

Второй шаг: указываем какие именно разделители у нас используются в данных. Для нашего случая нужно выбрать «запятую» и «табуляцию».

Выбор разделителей
Выбор разделителей

После того, как в предпросмотре на последнем шаге мы получаем удовлетворительное отображение данных, можем нажать «готово» и пронаблюдать за результатом.

Применение форматирования
Применение форматирования

Всё отобразится, как и требовалось, но вновь было потрачено много времени, а неопытный пользователь и вовсе бы не справился с подобной задачей.

Результат форматирования
Результат форматирования

В связи со всем вышесказанным была разработана и внедрена выгрузка в формате *.xlsx. Опишем как произвести эту модификацию.

Получаем доступ в консоль сервера (SSH). Подключаемся и переходим в каталог модуля cdr_reports

# cd /var/www/html/admin/modules/cdr/

И выполняем бэкапы файлов, которые собираемся редактировать. Это необходимо для быстрого отката в случае необходимости.

Бэкап файлов модуля cdr
Бэкап файлов модуля cdr

Немного отвлечёмся. Сам по себе файл формата *.xlsx довольно сложен и отличается от своего предшественника уже тем, что является архивом с файлами и инструкциями. Сформировать такой файл php самостоятельно не способен, поэтому нам потребуется применение сторонней библиотеки, а именно «PhpSpreadsheet».

Установим её с помощью файлового менеджера php – «composer». Если ранее вы таким не пользовались сперва установим его, выполнив ряд несложных команд:

# cd /usr/src
# curl -sS https://getcomposer.org/installer | php
# mv composer.phar /usr/local/bin/composer
# chmod a+x /usr/local/bin/composer
Установка менеджера библиотек php
Установка менеджера библиотек php

С его помощью скачаем и установим библиотеку «PhpSpreadsheet». Для этого в целевой директории создадим файл инструкций для компоновщика.

# cd /var/www/html/admin/modules/cdr/
# nano composer.json

И добавим в него следующее содержимое:

{
        "require": {
                "phpoffice/phpspreadsheet": "*.*"
        }
}

После чего выполним скрипт с передачей единственного аргумента

# composer install
Установка библиотеки
Установка библиотеки

Отметим изменения в директории: добавился файл composer.lock и папка vendor.

Теперь начнём последовательное внедрение в модуль. Поскольку нужные фрагменты кода уже найдены, позиции будут указаны примерными номерами строк кода в базовом файле.

Для начала добавим новый пункт в интерфейс, для возможности выбора альтернативного отчёта.

Открываем файл

# nano …/cdr/page.cdr.php

И после 168 строки вставляем следующий фрагмент:

<!-- CHANGE BEGIN -->
	<input <?php if ( ! empty($_POST['xlsxrepo']) && $_POST['xlsxrepo'] == 'true' ) { echo 'checked="checked"'; } ?> type="checkbox" name="xlsxrepo" value="true" /> : <?php echo _("XLSX-Report")?><br/>
<!-- CHANGE END -->

Ориентироваться можно на уже существующие элементы. Например быстро найти место можно поиском по фразе «Call Graph».

Добавление элемента интерфейса
Добавление элемента интерфейса

Обратите внимание: парой строк выше выделен маленький фрагмент. Его присутствие необязательно, но желательно, чтобы система не формировала два отчёта (веб и файл) одновременно.

Далее в этом же файле нам нужно добавить обработчик нового элемента формы. Следующий фрагмент размещаем после 704 строки.

// CHANGE BEGIN
/* ---------------------- Обработчик события ---------------------- */	
if(isset($_POST['xlsxrepo']) && $_POST['xlsxrepo'] == 'true'){
	// Формируем запрос
	$where = "WHERE $date_range $cnum $outbound_cnum $cnam $dst_cnam $did $dst $userfield $accountcode $disposition $duration";
	$query = "SELECT calldate, recordingfile, uniqueid, clid, did, lastapp, dst, disposition, duration, userfield FROM $db_name.$db_table_name $where $order $sort LIMIT $result_limit";
	// Получаем данные
	$answer = $dbcdr->getAll($query, DB_FETCHMODE_ASSOC);
	// Записываем заголовки в массив
	$head_ind = count($answer)+1;
	$answer[$head_ind][1] = _("Call Date");
	$answer[$head_ind][2] = _("Recording");
	$answer[$head_ind][3] = _("System");
	$answer[$head_ind][4] = _("CallerID");
	$answer[$head_ind][6] = _("DID");
	$answer[$head_ind][7] = _("App");
	$answer[$head_ind][8] = _("Destination");
	$answer[$head_ind][9] = _("Disposition");
	$answer[$head_ind][10] = _("Duration");
	$answer[$head_ind][11] = _("Userfield");
	
	// Сортируем в порядке индексирования, а не добавления
	$answer = array_reverse($answer);
	// Передаём данные в функцию экспорта
	cdr_export_xlsx($answer);
}
// CHANGE END
Здесь формируется структура будущего отчёта и можно редактировать заголовки.

На этом с файлом страницы мы закончили, перейдём к описанию функций которыми пользовались. Их принято размещать в отдельном файле:

# nano function.inc.php

Здесь просто добавляем код в конце файла. Первая функция служит для проверки существования файла и передачи его с сервера на клиент, т.е. пользователю в браузер.

function file_force_download($file) {
	if (file_exists($file)) {
		ob_end_clean();
		
		header('Pragma: public'); // required
		header('Expires: 0');
		header('Last-Modified: ' . gmdate('D,d M YH:i:s') . ' GMT');
		header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
		header('Cache-Control: private',false); // required for certain browsers
		header('Content-Transfer-Encoding: Binary');
		header('Content-Type: application/zip');
		header('Content-Disposition: attachment; filename="export-' . date('Y-d-m-H_i_s') . '.xlsx"');
		header('Content-Length:' . filesize($file));
		
		flush();
		readfile($file);
		die();
	}
}

Задача второй функции получить массив и сформировать файл *.xlsx по всем правилам и требованиям технологии.

function cdr_export_xlsx($xlsxdata){

	// Подготовка к созданию файла
	$spreadsheet = new Spreadsheet();
	$sheet = $spreadsheet->getActiveSheet();
	$sheet->setTitle('report');
	
	// оформляем границы
	$borderStyleArray = [
		'borders' => [
			'outline' => [
				'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
				'color' => ['rgb' => '000000'],
			],
			'horizontal' => [
				'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
				'color' => ['rgb' => '000000'],
			],
			'vertical' => [
				'borderStyle' => \PhpOffice\PhpSpreadsheet\Style\Border::BORDER_THIN,
				'color' => ['rgb' => '000000'],
			], 
		],
	];
	$sheet->getStyle('A1:J1')->applyFromArray($borderStyleArray);

	// Запись и передача файла клиенту
	$sheet->FromArray($xlsxdata,NULL,'A1', true);
	$writer = new Xlsx($spreadsheet);
	$writer->save('/var/tmp/report.xlsx');
	file_force_download('/var/tmp/report.xlsx');
}

Сохраняем и возвращаемся на страницу модуля во FreePBX. Отметим добавившийся пункт и сформируем интересующий нас отчёт.

Применение выгрузки в xlsx
Применение выгрузки в xlsx

И если всё было выполнено корректно, получим файл следующего содержания:

14. функцию
Результат выгрузки через новую функцию

При этом не требуется какая-либо постобработка или форматирование, можно сразу переходить к оперированию данными в привычном ПО.

Вывод: с помощью показанного здесь примера можно выполнять выгрузку в современный и удобный формат любых данных. Как в интерфейсе FreePBX, так и в собственных разработках.

Подписаться
Уведомление о
guest
0 Комментарий
Inline Feedbacks
View all comments

Остались вопросы?

Я - Першин Артём, менеджер компании Voxlink. Хотите уточнить детали или готовы оставить заявку? Укажите номер телефона, я перезвоню в течение 3-х секунд.

VoIP оборудование

ближайшие курсы

ближайшие Вебинары

ONLINE

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 сим-карты и настроить маршрутизацию вызовов по наиболее выгодному тарифу. Всё это позволяет экономить с первых минут пользования станцией.