SalesPlatform Vtiger CRM Developers Руководство Создание программного отчета
Содержание |
Программный отчет
В системе SalesPlatform Vtiger CRM присутствует возможность создавать программные отчеты. Программные отчеты создаются в том случае, когда достижение требований невозможно стандартными средствами мастера отчетов vtiger (например, необходимость создать вычисляемые поля, промежуточные итоги и т.д.).
Необходимо создать программный отчет “Тестовый отчет” в директории “Тестовые отчеты” следующего вида:
Количество Контрагентов | Количество Контактов |
---|---|
5 | 6 |
Реализовать фильтрацию по (до версии Salesplatform Vtiger CRM 6.5.0):
- дате (указывается диапазон дат);
- ответственному;
Реализовать фильтрацию по всем полям модуля (начиная с версии Salesplatform Vtiger CRM 6.5.0-201704).
Создание записей о программном отчете в БД
Перед тем, как создавать программный отчет необходимо создать соответствующие структуры данных в базе, а именно:
1. Программные отчеты регистрируются в таблице “sp_custom_reports”. Зарегистрируйте наш отчет в данной таблице:
mysql>INSERT INTO sp_custom_reports(reporttype,datefilter,ownerfilter,accountfilter,functionname) values('test', 1, 1, 1, 'prepareTestReport');
где:
- reporttype - строковый идентификатор отчета (должен быть уникальным);
- datefilter - "1" если отчет имеет фильтр по дате, иначе "0";
- ownerfilter - "1" если отчет имеет фильтр по ответственному, иначе "0";
- accountfilter - "1" если отчет имеет фильтр по контрагенту, иначе "0";
- functionname - наименование функции генерации отчета.
Важно
- Для версии SalesPlatform Vtiger CRM 6.5.0-201707 и выше таблица "sp_custom_reports" состоит из одного поля "reporttype". В результате запрос для регистрации отчета будет выглядеть следующим образом:
INSERT INTO sp_custom_reports(reporttype) values('test');
2. Создайте директорию для отчета с указанием ее названия и описания:
mysql>set @folderid = (select max(folderid)+1 from vtiger_reportfolder); mysql>INSERT INTO vtiger_reportfolder values(@folderid, 'Тестовые отчеты', 'Размещаем здесь тестовые отчеты', 'SAVED');
где:
- folderid - индекс новой директории, который вычисляется по формуле: max(folderid)+1
3. Регистрация запроса для отчета:
mysql>update vtiger_selectquery_seq set id=LAST_INSERT_ID(id+1); mysql>set @reportid = (select id from vtiger_selectquery_seq); mysql>INSERT INTO vtiger_selectquery (QUERYID,STARTINDEX,NUMOFOBJECTS) values (@reportid,0,0);
4. Добавьте отчет в таблицу отчетов:
mysql>INSERT INTO vtiger_report (REPORTID,FOLDERID,REPORTNAME,DESCRIPTION,REPORTTYPE,QUERYID,STATE,OWNER,SHARINGTYPE,customizable,category) values (@reportid,@folderid,'Тестовый отчет','','test',@reportid,'SAVED','1','Public',0,1);
5. Задайте основной модуль отчета:
mysql>INSERT INTO vtiger_reportmodules(REPORTMODULESID,PRIMARYMODULE,SECONDARYMODULES) values (@reportid,'Accounts','');
6. Создайте фильтр по датам:
mysql>INSERT INTO vtiger_reportdatefilter values(@reportid,'date:date:date:date','thismonth','0000-00-00','0000-00-00');
Механизм создания программного отчета, поддерживаемый до версии Salesplatform Vtiger CRM 6.5.0
Механизм создания программного отчета, поддерживаемый до версии Salesplatform Vtiger CRM 6.5.0, использует принцип создания отдельной таблицы для каждого отчета. Таблица программного отчета должна быть заполнена актуальными данными для отчета.
Создание функции подготовки отчета
Обычно для каждого программного отчета в БД создается отдельная таблица. В данном случае в качестве примера создайте таблицу “sp_Test_report” для данных нашего отчета:
mysql> CREATE TABLE IF NOT EXISTS `sp_Test_report` ( `row_id` int(19) NOT NULL auto_increment, `accounts_count` int(11) default NULL, `contacts_count` int(11) default NULL, `filterhash` varchar(200) collate utf8_unicode_ci default NULL, `sequence` int(11) NOT NULL, PRIMARY KEY (`row_id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8
Таблица содержит следующий набор столбцов отчета:
- row_id - поле-счетчик;
- accounts_count - подсчитанное общее количество Контрагентов;
- contacts_count - подсчитанное общее количество Контактов;
в таблице помимо произвольных полей есть два обязательных:
- filterhash - для разделения данных отдельных отчетов в одной таблице БД;
- sequence - для управления порядком отображения строк отчета пользователю.
Программный отчет формируется в функции, которая может содержать произвольный программный PHP-код, включающий операции выборки необходимых данных из БД, производить различные расчеты и т.д. В результате мы должны получить заполненную таблицу (в нашем случае “sp_Test_report”) программного отчета актуальными данными, а именно подсчитать общее количество Контрагентов и Контактов.
Формирование отчета
Функция подготовки отчета создается в отдельном файле в директории: modules/Reports/sp_custom_reports. Наименование файла должно подчиняться следующему правилу: xxxx.inc.php, где вместо “xxxx” подставляется строковый идентификатор типа отчета (н-р: test.inc.php).
Функция генерации отчета:
function prepareTestReport($startdate, $enddate, $filterhash, $params) { }
где:
- startdate - дата начала выбранного периода отчета (может быть пустой);
- enddate - дата окончания выбранного периода отчета (может быть пустой);
- filterhash - хэш-код данных конкретного построенного отчета;
- params - значения фильтров отчета.
Примечание
- Наименование функции может быть произвольным, но рекомендуется придерживаться следующего стиля: prepareXxxxReport, где вместо “Xxxx” подставляется строковый идентификатор типа отчета с заглавной буквы.
Для начала необходимо очистить данные отчета по хэш-коду:
$adb->pquery("delete from sp_Test_report where filterhash=?", array($filterhash));
Произведем подсчет общего количества Контрагентов, используя оператор “Count(*)”:
$Quantity_Accounts = $adb->query("SELECT COUNT(*) AS Count_Accounts FROM vtiger_account INNER JOIN vtiger_crmentity ON vtiger_account.accountid=vtiger_crmentity.crmid WHERE vtiger_crmentity.deleted=0");
Далее из результирующей таблицы считываем полученное значение (количество Контрагентов):
$quantity_Accounts = $adb->query_result($Quantity_Accounts,0,0);
Подсчет и получение данных о Контактах происходит аналогичным образом.
Заполните таблицу “sp_Test_report” полученными данными:
$insertSql = 'insert into sp_Test_report(accounts_count,contacts_count,filterhash,sequence) values(?,?,?,?)'; $result = $adb->pquery($insertSql, array($quantity_Accounts, $quantity_Contacts, $filterhash, 1));
Возвращаемым значением функции подготовки отчета является SQL-выражение для выборки отчета стандартным модулем отчетов “vtiger”. Обычно это выражение SELECT над подготовленной таблицей программного отчета следующего вида:
return "select accounts_count as recordsAccounts, contacts_count as recordsContacts from sp_Test_report where filterhash='$filterhash' order by sequence";
Все поля выбираются с использованием конструкции “AS”, которая задает человеко-читаемые метки столбцов отчета.
Фильтрация в отчете
Как уже говорилось выше фильтрация будет осуществляться по:
- дате (указывается диапазон дат);
- ответственному;
Фильтрация по Дате.
После того, как Вы задали диапазон дат, по которым надо отфильтровать записи, в параметр “$params” функции “prepareTestReport” передаются выбранные вами значения, а именно:
- columnname - поле по которому будет фильтроваться записи;
- comparator - условие отбора (в нашем случае: пользовательское);
- value - значение, заданное пользователем.
При условии, что Вы выбрали фильтрацию по дате и указали диапазон дат, далее из значения параметра “value” получаем две даты, которые будут храниться в переменных: “ $startdate” и “$enddate”. После того, как получили даты, выбранные пользователем, можно выполнить запрос на выборку данных из БД:
$Quantity_Accounts = $adb->query("SELECT COUNT(*) AS Count_Accounts FROM vtiger_account INNER JOIN vtiger_crmentity ON vtiger_account.accountid=vtiger_crmentity.crmid WHERE vtiger_crmentity.deleted=0 and vtiger_crmentity.createdtime BETWEEN ' ".$startdate." ' AND ' ".$enddate."'");
Аналогично выполняется запрос для Модуля “Контакты”.
Фильтрация по Ответственному
Ответственными за создаваемые Сущности могут быть как пользователи, так и группы. Для того, чтобы правильно осуществить выборку необходимых данных для программного отчета, необходимо сформировать строку из выбранных пользователем ответственных. В дальнейшем сформированная строка будет использоваться в запросе.
foreach($params as $paramsValues) { if(isset($paramsValues['columnname']) && $paramsValues['columnname'] == 'owner' && isset($paramsValues['comparator']) && $paramsValues['comparator'] == 'e' && isset($paramsValues['value']) && !empty($paramsValues['value'])) { $paramsVal = $paramsValues['value']; $string_responsible = "'".implode("','", explode(',', $paramsVal))."'";
После этого в запросе необходимо осуществить проверку на то, входит ли заданный ответственный определенной Сущности в сформированную строку.
$Quantity_Accounts = $adb->query("SELECT COUNT(*) AS Count_Accounts FROM vtiger_account INNER JOIN vtiger_crmentity ON vtiger_account.accountid=vtiger_crmentity.crmid LEFT JOIN vtiger_users ON vtiger_crmentity.smownerid=vtiger_users.id LEFT JOIN vtiger_groups ON vtiger_groups.groupid=vtiger_crmentity.smownerid WHERE vtiger_crmentity.deleted=0 and (vtiger_groups.groupname in (".$string_responsible.")) OR (CONCAT(vtiger_users.first_name,' ',vtiger_users.last_name) in (".$comma_separated."))");
Готовый скрипт генерации отчета
<?php function prepareTestReport($startdate, $enddate, $filterhash, $params) { global $adb; // Создание таблицы генерации отчета $adb->query("CREATE TABLE IF NOT EXISTS `sp_Test_report` ( `row_id` int(19) NOT NULL auto_increment, `accounts_count` int(11) default NULL, `contacts_count` int(11) default NULL, `filterhash` varchar(200) collate utf8_unicode_ci default NULL, `sequence` int(11) NOT NULL, PRIMARY KEY (`row_id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8"); // Очистка старых данных отчета $adb->pquery("delete from sp_Test_report where filterhash=?", array($filterhash));//очистка старых данных //получение дат $startdate = date('Y-m-d',(int)time() - 315360000); $enddate = date('Y-m-d',(int)time() + 315360000); //фильтрация по дате if(count($params) > 0) { foreach($params as $paramsValues) { if(isset($paramsValues['columnname']) && $paramsValues['columnname'] =='date' && isset($paramsValues['comparator']) && $paramsValues['comparator'] == 'custom' && isset($paramsValues['value']) && !empty($paramsValues['value']) && strpos($paramsValues['value'], ',')){ $paramsDates = explode(',', $paramsValues['value']); if(!strtotime($paramsDates[0]) || !strtotime($paramsDates[1])) { break; } $startdate = $paramsDates[0]; $enddate = $paramsDates[1]; $startdate = date('Y-m-d H:i:s',strtotime($startdate)); $enddate = date('Y-m-d H:i:s',strtotime($enddate)); $Quantity_Accounts = $adb->query("SELECT COUNT(*) AS Count_Accounts FROM vtiger_account INNER JOIN vtiger_crmentity ON vtiger_account.accountid=vtiger_crmentity.crmid WHERE vtiger_crmentity.deleted=0 and vtiger_crmentity.createdtime BETWEEN ' ".$startdate." ' AND ' ".$enddate."'"); $Quantity_Contacts = $adb->query("SELECT COUNT(*) AS Count_Contacts FROM vtiger_contactdetails INNER JOIN vtiger_crmentity ON vtiger_contactdetails.contactid=vtiger_crmentity.crmid WHERE vtiger_crmentity.deleted=0 and vtiger_crmentity.createdtime BETWEEN ' ".$startdate." ' AND ' ".$enddate."'"); break; } } } //фильтрация по ответственному if(count($params) > 0) { foreach($params as $paramsValues) { if(isset($paramsValues['columnname']) && $paramsValues['columnname'] == 'owner' && isset($paramsValues['comparator']) && $paramsValues['comparator'] == 'e' && isset($paramsValues['value']) && !empty($paramsValues['value'])) { $paramsVal = $paramsValues['value']; $string_responsible = "'".implode("','", explode(',', $paramsVal))."'"; $Quantity_Accounts = $adb->query("SELECT COUNT(*) AS Count_Accounts FROM vtiger_account INNER JOIN vtiger_crmentity ON vtiger_account.accountid=vtiger_crmentity.crmid LEFT JOIN vtiger_users ON vtiger_crmentity.smownerid=vtiger_users.id LEFT JOIN vtiger_groups ON vtiger_groups.groupid=vtiger_crmentity.smownerid WHERE vtiger_crmentity.deleted=0 and (vtiger_groups.groupname in (".$string_responsible.")) OR (CONCAT(vtiger_users.first_name,' ',vtiger_users.last_name) in (".$comma_separated."))"); $Quantity_Contacts = $adb->query("SELECT COUNT(*) AS Count_Contacts FROM vtiger_contactdetails INNER JOIN vtiger_crmentity ON vtiger_contactdetails.contactid=vtiger_crmentity.crmid LEFT JOIN vtiger_users ON vtiger_crmentity.smownerid=vtiger_users.id LEFT JOIN vtiger_groups ON vtiger_groups.groupid=vtiger_crmentity.smownerid WHERE vtiger_crmentity.deleted=0 and (vtiger_groups.groupname in (".$string_responsible.")) OR (CONCAT(vtiger_users.first_name,' ',vtiger_users.last_name) in (".$comma_separated."))"); } } } if (empty($params)) { // Подготовка данных для заполнения таблицы отчета $Quantity_Accounts = $adb->query("SELECT COUNT(*) AS Count_Accounts FROM vtiger_account INNER JOIN vtiger_crmentity ON vtiger_account.accountid=vtiger_crmentity.crmid WHERE vtiger_crmentity.deleted=0"); $Quantity_Contacts = $adb->query("SELECT COUNT(*) AS Count_Contacts FROM vtiger_contactdetails INNER JOIN vtiger_crmentity ON vtiger_contactdetails.contactid=vtiger_crmentity.crmid WHERE vtiger_crmentity.deleted=0"); } $quantity_Accounts = $adb->query_result($Quantity_Accounts,0,0); $quantity_Contacts = $adb->query_result($Quantity_Contacts,0,0); $insertSql = 'insert into sp_Test_report(accounts_count,contacts_count,filterhash,sequence) values(?,?,?,?)'; $result = $adb->pquery($insertSql, array($quantity_Accounts, $quantity_Contacts, $filterhash, 1)); return "select accounts_count as recordsAccounts, contacts_count as recordsContacts from sp_Test_report where filterhash='$filterhash' order by sequence"; }
Примечание
- Для локализации названий полей необходимо добавить локализацию для модуля languages/ru_ru/Reports.php:
... 'recordsAccounts' => 'Количество Контрагентов', 'recordsContacts' => 'Количество Контактов', ...
В результате у Вас должен создаться отчет “Тестовый отчет” в директории “Тестовые отчеты” (см. рис. 1).
Пример фильтрации по дате:
Пример фильтрации по ответственному:
Механизм создания программного отчета, поддерживаемый начиная с версии Salesplatform Vtiger CRM 6.5.0-201707
Обновленный механизм создания программного отчета больше не использует принцип создания отдельной таблицы для каждого отчета. Идеология заключается в том, что разработчик готовит только код получения данных для отчета и передает их в механизм-обертку для отображения.
Новый механизм позволяет гибко настраивать представления программных отчетов. Присутствует возможность выводить данные отчета не только в табличном представлении, но и в графическом. Базовые графические представления, предоставляемые программными отчетами:
- Круговая диаграмма
- Столбиковая диаграмма
- Линейный график
Имеется возможность добавления собственных типов отображения данных и переопределения существующих представлений. Подробнее см. в разделе «Описание методов класса AbstractCustomReportModel».
В отличии от старого механизма, в обновленном механизме присутствует возможность добавлять произвольные фильтры. Фильтры могут базироваться как на реальных полях, доступных в стандартных отчетах, так и на “виртуальных” фильтрах, созданных разработчиком. Подробнее см. в разделе «Фильтрация в отчете».
Важно
- в связи с изменением структуры данных для хранения информации о программных отчетах, совместимость с механизмами создания программных отчетов до версии Salesplatform Vtiger CRM 6.5.0-201707 не поддерживается. Необходимо мигрировать код старых отчетов на новый механизм.
Создание функции подготовки отчета
Программный отчет формируется в функции, которая может содержать произвольный программный PHP-код, включающий операции выборки необходимых данных из БД, производить различные расчеты и т.д. В результате мы должны получить актуальные данные для программного отчета, а именно подсчитать общее количество Контрагентов и Контактов.
Формирование отчета
Функция подготовки отчета создается в отдельном файле в директории: modules/Reports/sp_custom_reports. Наименование файла должно подчиняться следующему правилу: xxxx.inc.php, где вместо “xxxx” подставляется строковый идентификатор типа отчета (н-р: TestReport.inc.php).
Для того, чтобы создать программный отчет, необходимо создать класс и унаследовать его от класса AbstractCustomReportModel. После этого следует реализовать два абстрактных метода:
- protected function getCalculationData($outputFormat = 'PDF');
- protected function getLabels($outputFormat = 'PDF').
В функции getCalculationData осуществляется выборка актуальных данных для программного отчета, а именно подсчет общего количества Контрагентов и Контактов. После того, как данные будут получены, они могут быть возвращены функцией getCalculationData. Формат данных (см. раздел «Форматы возвращаемых данных, для различных типов построения отчета»), возвращаемый функцией getCalculationData может отличаться, в зависимости от типа отображения отчета. Тип отображения отчета задается функцией getChartsViewControlData() (см. раздел «Описание методов класса AbstractCustomReportModel»). «Описание методов класса AbstractCustomReportModel»
Перед тем как отдать данные для построения программного отчета, необходимо осуществить проверку типа построения отчета, для этого надо определить для какого представления они будут использованы. Для этого следует воспользоваться функцией getViewTypeName().
Метод getLabels возвращает массив названий колонок для табличного представления отчета.
Реализация функции getCalculationData и getLabels для нашего примера:
class TestReport extends AbstractCustomReportModel { protected function getCalculationData($outputFormat = 'PDF') { global $adb; // Подготовка данных для заполнения таблицы отчета $Quantity_Accounts = $adb->query("SELECT COUNT(*) AS Count_Accounts FROM vtiger_account INNER JOIN vtiger_crmentity ON vtiger_account.accountid=vtiger_crmentity.crmid WHERE vtiger_crmentity.deleted=0"); $Quantity_Contacts = $adb->query("SELECT COUNT(*) AS Count_Contacts FROM vtiger_contactdetails INNER JOIN vtiger_crmentity ON vtiger_contactdetails.contactid=vtiger_crmentity.crmid WHERE vtiger_crmentity.deleted=0"); $quantity_Accounts = $adb->query_result($Quantity_Accounts, 0, 0); $quantity_Contacts = $adb->query_result($Quantity_Contacts, 0, 0); if ($this->getViewTypeName() === Reports_CustomReportTypes_Model::TABLE) { return [ [$quantity_Accounts, $quantity_Contacts], ]; } else if ($this->getViewTypeName() === Reports_CustomReportTypes_Model::PIE) { return [ 'values' => [$quantity_Accounts, $quantity_Contacts], 'labels' => ['A', 'B'], 'data_labels' => ['Q', 'W'] ]; } else { return [ 'values' => [[$quantity_Accounts, $quantity_Contacts]], 'labels' => ['A'], 'data_labels' => ['Q'] ]; } } protected function getLabels($outputFormat = 'PDF') { return array("Количество Контрагентов", "Количество Контактов"); } }
Фильтрация в отчете
Для получения значений фильтров используются методы getFiltersConditions() и getFilterSql().
Метод getFiltersConditions() возвращает необработанный список фильтров. Каждый элемент списка содержит название поля, таблицу, колонку таблицы, компаратор и сравниваемое значение.
Метод getFilterSql() возвращает трансформированные движком отчетов vtiger значения фильтров в виде sql-выражения.
Например, пусть заданы следующие фильтры:
Тогда следующий код:
protected function getCalculationData($outputFormat = 'PDF') { $sql = $this->getFilterSql(); ... }
запишет в переменную $sql следующее значение:
- (( vtiger_leaddetails.salutation = 'Mr.' and (vtiger_leaddetails.leadstatus = 'Cold' or vtiger_leaddetails.leadstatus = 'Contact in Future') and trim(case when (vtiger_usersLeads.last_name NOT LIKE ) then CONCAT(vtiger_usersLeads.first_name,' ',vtiger_usersLeads.last_name) else vtiger_groupsLeads.groupname end) = 'Администратор' ) )
Полученное значение можно использовать для фильтрации в sql-выборке. Предварительно необходимо подключить таблицы, перечисленные в фильтрующем выражении.
Например:
- $selectSql = “select firstname FROM vtiger_leaddetails INNER JOIN vtiger_crmentity ON vtiger_crmentity.crmid=vtiger_leaddetails.leadid LEFT JOIN vtiger_users AS vtiger_usersLeads ON vtiger_usersLeads.id=vtiger_crmentity.smownerid LEFT JOIN vtiger_groups AS vtiger_groupsLeads ON vtiger_groupsLeads.groupid=vtiger_crmentity.smownerid WHERE vtiger_crmentity.deleted=0 AND {$sql}”
Также следует не забывать о проверке, когда не указан ни один из фильтров. Кроме того, всегда стоит присоединять таблицу vtiger_crmentity для фильтрации удаленных записей.
При наличии полей-ссылок в фильтрах (например как Ответственный), стоит учитывать, что движок vtiger генерирует sql с применением синонимов. Поэтому таблицы необходимо соединять под именем синонимом.
Форматы возвращаемых данных, для различных типов построения отчета
1. Для типа построения “График” (Reports_CustomReportTypes_Model::LINEAR) необходимо вернуть ассоциативный массив следующего вида:
return array( 'values' => [][], 'labels' => [], 'data_labels' => [] );
где:
- values - двумерный массив значений линий графиков
- labels - имена отсечек по оси X
- data_labels - имена линий графиков
При этом размерность каждого элемента в values, должна совпадать с размерностью data_labels.
Пример:
return [ 'values' => [[5,6,7,8],[1,2,3,8],[1,2,3,8], [1,2,3,8]], 'labels' => ['A','B','C','D'], 'data_labels' => ['Q','W', 'E', 'R'] ];
Результат:
2. Для типа построения "Столбиковая диаграмма"
(Reports_CustomReportTypes_Model::BARCHART)
Формат данных должен быть задан аналогично формату данных для Графика. Для данных из примера пункта 1 результат будет выглядеть следующим образом:
3. Для типа построения "Круговая диаграмма"
(Reports_CustomReportTypes_Model::PIE)
Формат данных:
return [ 'values' => [], 'labels' => [] 'data_labels' =>[]; ]
Пример:
return [ 'values' => [5,6,7,8], 'labels' => ['A','B','C','D'], 'data_labels' => ['Q','W', 'E', 'R'] ];
Результат:
4. Для типа построения "Таблица"
(Reports_CustomReportTypes_Model::TABLE)
Формат данных:
return [][]
Пример:
return [ [1,2], [3,4] ];
Возвращаемое значение функции getLabels (для названий столбцов таблицы)
return ["Поле 1", "Поле 2"];
Результат:
Описание методов класса AbstractCustomReportModel
- public static function generateAdvSql($advanceFilter) - генерирует sql-выражение из набора переданных фильтров. Используется только когда необходимо сгенерировать фильтрующий sql-запрос из списка фильтров.
- public final function getData($outputFormat = 'PDF') - возвращается данные для построения отчета. Форматирует их вывод в требуемую структуру данных в зависимости от типа построения отчета (таблица, круговая диаграмма и т.п.)
- protected abstract function getCalculationData($outputFormat = 'PDF') - реализуемая пользователем функция, возвращающая выбранные данные по отчету. Параметр $outputFormat может принимать значения HTML, PDF. При значении PDF вывод содержимого отчета осуществляется в csv, файл на печать и т.п. При значении HTML - в браузер. Параметр автоматически устанавливается механизмом отчетов. Необходим только когда требуется разделять форматирующие символы для HTML и PDF (например перенос строки - <br> и \r\n)
- protected abstract function getCalculationData($outputFormat = 'PDF') - список названий полей для табличного представления отчета.
- public function getCount() - количество строк в табличном представлении отчета
- public function getReportCalulationData() - опциональные данные - выводятся в раздел summary-вычислений отчета.
- public function getReportCalulationData() - название JS-функции, которая выполняет управление пользовательским интерфейсом отчета. По умолчанию “Custom_Reports_Conroller”. Если требуется дополнительная функциональность в UI для конкретного отчета, то необходимо переопределить данный метод, указав название функции JS. Пример в разделе Front-End
- public function getContentsTpl() - возвращает название шаблона содержимого программного отчета.
- public function getContentsTpl() - возвращает название шаблона заголовка программного отчета.
- public function getPrintData() - возвращает данные для печати отчета.
- public function getTotalPrintData() - возвращает summary данные при выводе отчета на печать.
- public function hasLastLinkColumn() - возвращает true если последний столбец в табличном представлении отчета содержит ссылки на сущности. Если значение true, то при выводе на печать, экспорте в csv последняя колонка не будет выведена. По умолчанию false.
- public function hasLastLinkColumn() - если true, то пользователь может добавлять фильтры при построении отчета. По умолчанию - true.
- public function setViewTypeDetails($viewTypeDetails) - устанавливает параметры построения отчета - какой тип (таблица, столбиковая диаграмма и т.п.). Для не табличных типов построения дополнительно содержит поле, по которому производится группировка и поля, по которым производится расчет.
- public function getViewTypeName() - возвращает тип построения (таблица, столбиковая диаграмма и т.п.).
- public function getViewTypeDetails() - возвращает всю информацию по типу построения отчета.
- public function getPrimaryModuleRecordStructure() - возвращает структуру полей модуля, к которому принадлежит отчет. В данной структуре находятся поля, которые доступны для фильтрации.
- public function getFiltersComparatorsRules() - возвращает список поддерживаемых операторов сравнения для каждого типа поля (больше меньше и т.п.).
- public function getCustomReportControlData() - дополнительные данные отчета, которые будут сериализованы в JSON переданы в UI.
- public function getChartsViewControlData() - доступные для построения типы отчета. Возвращает карту, в которой в качестве ключей перечислены типы построений отчета, а в качестве значений их управляющие параметры.
Пример:
public function getChartsViewControlData() { return array( Reports_CustomReportTypes_Model::TABLE => array(), Reports_CustomReportTypes_Model::PIE => array( 'group' => array( 'sp_delay_level' => 'Уровень просрочки', ), 'agregate' => array( 'treatments_count' => 'Количество задач' ) ) ); }
- Для типов отчетов PIE, BARCHART, LINEAR - управляющие параметры задаются как в примере выше. Их назначение:
- - 'group' - список полей, по которым группируется расчет для диаграммы. В данном случае sp_delay_level - имя поля, которое будет передано при выборе соответствующей опции в UI - отчета, Уровень просрочки - отображаемое имя.
- - 'agregate' - список полей, по которым нужно произвести вычисления. В данном случае 'treatments_count' - название поля которое будет передано при выборе соответствующей опции в UI отчета, Количество задач - отображаемое имя.
- public function getCustomControlFields() - список дополнительный произвольных полей, которые будут выведены в отчет. Используется если требуется задавать произвольную информацию, подлежащую обработке.
- public function getJsScripts() - Javascript ресурсы, которые подключаются к отчету.
- public function getJsScripts() - css ресурсы, которые подключаются к отчету.
- public function setRunTimeSqlFilter($filterSql) - устанавливает sql фильтр, который можно использовать при формировании sql выборки.
- public static function getInstance($reportModel) - возвращает программный отчет, по связанному с ним обычному отчету-обертке.
- public static function getInstance($reportModel) - удаляет программный отчет по связанному с ним обычному отчету-обертке.
- public function getBlockedFiltersNames() - список фильтров, который всегда присутствует в отчете, и не может быть удален.
- protected function getDefaultViewType() - вид построения по умолчанию (при первом заходе в отчет). Базовое значение - табличное представление.
- protected function beforeStartInitializate() - вызывается до фактического начала вычисления данных по отчету. Функция используется, если требуется выполнить специфические действия или проверки.
- protected function getFiltersConditions() - возвращает данные фильтров, которые пользователь выбрал в отчете. Полученные значения от этой функции можно передать в функцию generateAdvSql для получения реального фильтрующего sql.
- protected function setFilterCondition($conditionIndex, $conditionBody) - устанавливает значение фильтра. Можно использовать для неявного задания дополнительных фильтров в коде отчета.
- protected final function getFilterSql() - возвращает подготовленное sql-выражение, соответствующее выбранным фильтрам в отчете.
- protected function checkFilter() - проверяет, и если требуется, устанавливает фильтры значениями, выбранными пользователем в отчете.
- protected function initilizatePrimaryModuleRecordStructure() - инициализирует доступные для фильтрации поля по базовому модуля отчета.
- protected function initializateVirtualRecordStructure() -инициализирует дополнительные виртуальные фильтры, заданные в функции getVirtualFiltersFields().
- protected function getVirtualFiltersFields() - возвращает список полей, которые доступны для фильтрации.
Пример:
protected function getVirtualFiltersFields() { return array($this->getVirtualField()); } protected function getVirtualField() { $fieldModel = new Vtiger_Field_Model(); $fieldModel->id = -1; $fieldModel->name = 'sp_current_labor'; $fieldModel->label = 'Текущая трудоемкость(час)'; $fieldModel->table = 'vtiger_some_module'; $fieldModel->column = 'sp_current_labor'; $fieldModel->columntype = 0; $fieldModel->uitype = 7; $fieldModel->typeofdata = 'N~O'; $fieldModel->block = Vtiger_Block::getInstance('LBL_CUSTOMER', Vtiger_Module_Model::getInstance('SPSomeModule')); return $fieldModel; }
Управление Front-end
Для управления интерфейсом из программного отчета с помощью метода getCustomUIControllerName() передается имя функции javaScript, которая управляет UI событиями. По умолчанию это Custom_Reports_Conroller. Если требуется внести свою собственную функциональность, то можно указать свою собственную JS-функцию, и добавить в нее требуемое поведение.
Последовательность шагов:
1. Необходимо переопределить метод getCustomUIControllerName()
public function getCustomUIControllerName() { return 'My_Reports_Conroller'; }
2. Подключите JS-ресурс, в котором будет описана функция.
public function getJsScripts() { return array_merge(parent::getJsScripts(), [ 'modules.Reports.resources.MyReportsController' ]); }
3. По указанному пути (в данном случае layouts/vlayout/modules/Reports/resources) следует создать файл MyReportsController.js
4. Создайте jquery “класс” с именем My_Reports_Conroller и “наследуем” его от Custom_Reports_Conroller. Регистрируем/переопределяем требуемую функциональность:
Custom_Reports_Conroller("My_Reports_Conroller", {}, { registerMyFunctionality : function(){ alert("Works!"); }, registerEvents : function() { this._super(); this.registerMyFunctionality(); } });
Готовый скрипт генерации отчета
<?php class TestReport extends AbstractCustomReportModel { public function getChartsViewControlData() { return array( Reports_CustomReportTypes_Model::TABLE => array(), Reports_CustomReportTypes_Model::PIE => array( 'group' => array( 'sp_delay_level' => 'Уровень просрочки', ), 'agregate' => array( 'treatments_count' => 'Количество задач' ) ), Reports_CustomReportTypes_Model::LINEAR=> array( 'group' => array( 'sp_delay_level' => 'Уровень просрочки', ), 'agregate' => array( 'treatments_count' => 'Количество задач' ) ), Reports_CustomReportTypes_Model::BARCHART => array( 'group' => array( 'sp_delay_level' => 'Уровень просрочки', ), 'agregate' => array( 'treatments_count' => 'Количество задач' ) ) ); } protected function getCalculationData($outputFormat = 'PDF') { global $adb; $sql = $this->getFilterSql(); error_log("Filter - " . $sql); if ($sql == '') { // Подготовка данных для заполнения таблицы отчета $Quantity_Accounts = $adb->query("SELECT COUNT(*) AS Count_Accounts FROM vtiger_account INNER JOIN vtiger_crmentity ON vtiger_account.accountid=vtiger_crmentity.crmid WHERE vtiger_crmentity.deleted=0"); $Quantity_Contacts = $adb->query("SELECT COUNT(*) AS Count_Contacts FROM vtiger_contactdetails INNER JOIN vtiger_crmentity ON vtiger_contactdetails.contactid=vtiger_crmentity.crmid WHERE vtiger_crmentity.deleted=0"); } else { $Quantity_Accounts = $adb->query("SELECT COUNT(*) AS Count_Accounts FROM vtiger_account INNER JOIN vtiger_crmentity ON vtiger_account.accountid=vtiger_crmentity.crmid WHERE vtiger_crmentity.deleted=0 AND {$sql}"); $Quantity_Contacts = $adb->query("SELECT COUNT(*) AS Count_Contacts FROM vtiger_contactdetails INNER JOIN vtiger_crmentity ON vtiger_contactdetails.contactid=vtiger_crmentity.crmid INNER JOIN vtiger_account ON vtiger_contactdetails.accountid=vtiger_account.accountid WHERE vtiger_crmentity.deleted=0 AND {$sql}"); } $quantity_Accounts = $adb->query_result($Quantity_Accounts, 0, 0); $quantity_Contacts = $adb->query_result($Quantity_Contacts, 0, 0); if ($this->getViewTypeName() === Reports_CustomReportTypes_Model::TABLE) { return [ [$quantity_Accounts, $quantity_Contacts], ]; } else if ($this->getViewTypeName() === Reports_CustomReportTypes_Model::PIE) { return [ 'values' => [$quantity_Accounts, $quantity_Contacts], 'labels' => ['A', 'B'], 'data_labels' => ['Q', 'W'] ]; } else { return [ 'values' => [[$quantity_Accounts, $quantity_Contacts]], 'labels' => ['A'], 'data_labels' => ['Q','W'] ]; } } protected function getLabels($outputFormat = 'PDF') { return array("Количество Контрагентов", "Количество Контактов"); } }
В результате будет создан отчет “Тестовый отчет” в директории “Тестовые отчеты”.
На рисунках ниже представлены примеры программного отчета с типом построения “Таблица”, “График”, “Круговая диаграмма” и “Столбиковая диаграмма”.
Пример фильтрации по полю “Телефон”: