-
Ручная настройка субпанелей в SugarCRM
В статье Настройка субпанелей в SugarCRM я описал, как можно редактировать список полей, отображаемых в сабпанелях. Делалось это через студию в админке SugarCRM, и потому раздел был для администраторов SugarCRM. Но при всей своей крутизне и навороченности студии SugarCRM, все же не все действия можно там делать. Иногда встают задачи, когда необходимо ручками лезть в код и менять его по своему усмотрению.
Но вернемся к нашему предмету разговора: сабпанелям. На в встал вопрос: А как же "запихать" в сабпанель "История" еще одно поле, а в частности - описание заметок? Т.е. пользователь хотел, чтобы в его CRM-системе в сабпанели "История", при отображении в ней заметок, помимо стандартных полей выводилось описание заметок.
Сабпанель "История", как "Мероприятия", является несколько обособленным объектом в SugarCRM, и представляет собой "коллекцию" из нескольких модулей сразу. В частности, в сабпанели "История" отображаются записи модулей: "Звонки", "Встречи", "Задачи", "Заметки", "Е-майлы". Если посмотреть на описание этой сабпанели, например, для Контрагентов, то мы увидим следующий блок кода: Файл /modules/Accounts/metadata/subpaneldefs.php
'history' => array( 'order' => 20, 'sort_order' => 'desc', 'sort_by' => 'date_entered', 'title_key' => 'LBL_HISTORY_SUBPANEL_TITLE', 'type' => 'collection', 'subpanel_name' => 'history', //this values is not associated with a physical file. 'header_definition_from_subpanel'=> 'meetings', 'module'=>'History', 'top_buttons' => array( array('widget_class' => 'SubPanelTopCreateNoteButton'), array('widget_class' => 'SubPanelTopArchiveEmailButton'), array('widget_class' => 'SubPanelTopSummaryButton'), ), 'collection_list' => array( 'tasks' => array( 'module' => 'Tasks', 'subpanel_name' => 'ForHistory', 'get_subpanel_data' => 'tasks', ), 'meetings' => array( 'module' => 'Meetings', 'subpanel_name' => 'ForHistory', 'get_subpanel_data' => 'meetings', ), 'calls' => array( 'module' => 'Calls', 'subpanel_name' => 'ForHistory', 'get_subpanel_data' => 'calls', ), 'notes' => array( 'module' => 'Notes', 'subpanel_name' => 'ForHistory', 'get_subpanel_data' => 'notes', ), 'emails' => array( 'module' => 'Emails', 'subpanel_name' => 'ForHistory', 'get_subpanel_data' => 'emails', ), ) ),
Блок collection_list содержит список модулей, записи которых будут отображаться в сабпанели "История". Для каждого из модулей, как вы видите, присутствует параметр subpanel_name. Этот параметр указывает название сабпанели, чья конфигурация будет применена для вывода общей, итоговой сабпанели. Фактически, этот параметр указывает на название файла в модуле, который будет обработан при выводе итоговых данных. Файлы с названием, указанным в subpanel_name, находятся в /modules/модуль/metadata/subpanels/значение_subpanel_name.php.
Как вы видите, все сабпанели называются ForHistory. Связано это с тем, что коллекционная субпанель будет работать только в том случае, если сабпанели каждого из модулей будут НАСТРОЕНЫ НА ОТОБРАЖЕНИЕ ОДИНАКОВЫХ ПОЛЕЙ В ОДИНАКОВОЙ ПОСЛЕДОВАТЕЛЬНОСТИ! Это ключевое условие. Если "докопаться" до функционала получения записей для коллекционной сабпанели, то можно увидеть, что SQL-запрос на получение связанных записей разных модулей формируется SugarCRM через UNION, т.е.:
( SELECT поля FROM звонки JOIN связи WHERE условия попадания) UNION ( SELECT поля FROM встречи JOIN связи WHERE условия попадания) UNION ( SELECT поля FROM задачи JOIN связи WHERE условия попадания) UNION ( SELECT поля FROM заметки JOIN связи WHERE условия попадания) UNION ( SELECT поля FROM емайлы JOIN связи WHERE условия попадания)
а одно из условий корректного использования конструкции UNION в MySQL - это одинаковое кол-во и названия возвращаемого результата у каждого из SELECT-ов. Вот и получается по нашей задаче, что если мы хотим добавить какое-либо поле в отображение коллекционной сабпанели "История", то вывод этого поля необходимо прописать в файле ForHistory.php каждого из модулей, находящихся в коллекции.
Для этого добавляем в каждый файл ForHistory.php в переменную list_fields, в нужное нам место (но это место должно быть для всех файлов одно и тоже) следующий код:
'description'=>array( 'vname' => 'LBL_DESCRIPTION', 'width' => '30%', ),
Эта конструкция укажет, что необходимо в результирующий список добавить поле "Описание".
Получилось примерно следующее:
-