SalesPlatform Vtiger CRM Developers Руководство Создание программного отчета

Материал из SalesPlatform Wiki
Перейти к: навигация, поиск

Главная страница руководства



Содержание

Программный отчет

В системе 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');

где:

Vt important.png Важно
Для версии 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');

где:


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

Таблица содержит следующий набор столбцов отчета:

в таблице помимо произвольных полей есть два обязательных:

Программный отчет формируется в функции, которая может содержать произвольный программный PHP-код, включающий операции выборки необходимых данных из БД, производить различные расчеты и т.д. В результате мы должны получить заполненную таблицу (в нашем случае “sp_Test_report”) программного отчета актуальными данными, а именно подсчитать общее количество Контрагентов и Контактов.

Формирование отчета

Функция подготовки отчета создается в отдельном файле в директории: modules/Reports/sp_custom_reports. Наименование файла должно подчиняться следующему правилу: xxxx.inc.php, где вместо “xxxx” подставляется строковый идентификатор типа отчета (н-р: test.inc.php).
Функция генерации отчета:

 function prepareTestReport($startdate, $enddate, $filterhash, $params) {
 
 }

где:


Vt note.png Примечание
Наименование функции может быть произвольным, но рекомендуется придерживаться следующего стиля: 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” передаются выбранные вами значения, а именно:

При условии, что Вы выбрали фильтрацию по дате и указали диапазон дат, далее из значения параметра “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";
}


Vt note.png Примечание
Для локализации названий полей необходимо добавить локализацию для модуля languages/ru_ru/Reports.php:
 ...
 'recordsAccounts'       => 'Количество Контрагентов',
 'recordsContacts'       => 'Количество Контактов',    
 ...

В результате у Вас должен создаться отчет “Тестовый отчет” в директории “Тестовые отчеты” (см. рис. 1).

Рис. 1: Программный отчет


Пример фильтрации по дате:

Рис. 2: Фильтрация по дате


Пример фильтрации по ответственному:

Рис. 3: Фильтрация по ответственному (пользователь)
Рис. 4: Фильтрация по ответственному (пользователь и группа)


Механизм создания программного отчета, поддерживаемый начиная с версии Salesplatform Vtiger CRM 6.5.0-201707

Обновленный механизм создания программного отчета больше не использует принцип создания отдельной таблицы для каждого отчета. Идеология заключается в том, что разработчик готовит только код получения данных для отчета и передает их в механизм-обертку для отображения.
Новый механизм позволяет гибко настраивать представления программных отчетов. Присутствует возможность выводить данные отчета не только в табличном представлении, но и в графическом. Базовые графические представления, предоставляемые программными отчетами:

Имеется возможность добавления собственных типов отображения данных и переопределения существующих представлений. Подробнее см. в разделе «Описание методов класса AbstractCustomReportModel».
В отличии от старого механизма, в обновленном механизме присутствует возможность добавлять произвольные фильтры. Фильтры могут базироваться как на реальных полях, доступных в стандартных отчетах, так и на “виртуальных” фильтрах, созданных разработчиком. Подробнее см. в разделе «Фильтрация в отчете».

Vt important.png Важно
в связи с изменением структуры данных для хранения информации о программных отчетах, совместимость с механизмами создания программных отчетов до версии Salesplatform Vtiger CRM 6.5.0-201707 не поддерживается. Необходимо мигрировать код старых отчетов на новый механизм.

Создание функции подготовки отчета

Программный отчет формируется в функции, которая может содержать произвольный программный PHP-код, включающий операции выборки необходимых данных из БД, производить различные расчеты и т.д. В результате мы должны получить актуальные данные для программного отчета, а именно подсчитать общее количество Контрагентов и Контактов.

Формирование отчета

Функция подготовки отчета создается в отдельном файле в директории: modules/Reports/sp_custom_reports. Наименование файла должно подчиняться следующему правилу: xxxx.inc.php, где вместо “xxxx” подставляется строковый идентификатор типа отчета (н-р: TestReport.inc.php).
Для того, чтобы создать программный отчет, необходимо создать класс и унаследовать его от класса AbstractCustomReportModel. После этого следует реализовать два абстрактных метода:

В функции 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-выражения.
Например, пусть заданы следующие фильтры:

Рис. 5: Фильтры для отчета


Тогда следующий код:

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, должна совпадать с размерностью 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']
       ];

Результат:

Рис. 6: “График”


2. Для типа построения "Столбиковая диаграмма"
(Reports_CustomReportTypes_Model::BARCHART)


Формат данных должен быть задан аналогично формату данных для Графика. Для данных из примера пункта 1 результат будет выглядеть следующим образом:

Рис. 7: “Столбиковая диаграмма”


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']
       ];

Результат:

Рис. 8: “Круговая диаграмма”


4. Для типа построения "Таблица"
(Reports_CustomReportTypes_Model::TABLE)

Формат данных:

 return [][] 

Пример:

return [
            [1,2],
            [3,4]
       ];

Возвращаемое значение функции getLabels (для названий столбцов таблицы)

 return ["Поле 1", "Поле 2"];

Результат:

Рис. 9: “Таблица”


Описание методов класса 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' => 'Количество задач'
	             )
        	 )
    );
}
Для типов отчетов PIE, BARCHART, LINEAR - управляющие параметры задаются как в примере выше. Их назначение:
- 'group' - список полей, по которым группируется расчет для диаграммы. В данном случае sp_delay_level - имя поля, которое будет передано при выборе соответствующей опции в UI - отчета, Уровень просрочки - отображаемое имя.
- 'agregate' - список полей, по которым нужно произвести вычисления. В данном случае 'treatments_count' - название поля которое будет передано при выборе соответствующей опции в UI отчета, Количество задач - отображаемое имя.

Пример:

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("Количество Контрагентов", "Количество Контактов");
        }
    }

В результате будет создан отчет “Тестовый отчет” в директории “Тестовые отчеты”.
На рисунках ниже представлены примеры программного отчета с типом построения “Таблица”, “График”, “Круговая диаграмма” и “Столбиковая диаграмма”.

Рис. 10: Программный отчет с типом построения “Таблица”


Рис. 11: Программный отчет с типом построения “График”


Рис. 12: Программный отчет с типом построения “Круговая диаграмма”


Рис. 13: Программный отчет с типом построения “Столбиковая диаграмма”


Пример фильтрации по полю “Телефон”:

Рис. 14: Фильтрация по телефону



Главная страница руководства

Личные инструменты
Пространства имён
Варианты
Действия
Навигация
Документация
Разработчикам
Присоединяйтесь!
Инструменты