Содержание
Этап разработки отчетов
Введение
На этом этапе мы разрабатываем 2 отчета - по планам и фактическому исполнению ремонтов. Мы создаем экранные формы для возможности задать параметры этим отчетам, контроллеры отчетов и прописываем вызовы в главном меню системы.
Развертывание этапа на площадке
- Скачаем архив LSS проекта для текущего этапа.
- Обновим проект из архива. Надо быть осторожным с конфигурационным файлом площадки php/config/config-place.php, он содержит текущие параметры соединения с базой данных, его обновлять не надо.
- база данных не поменялась, скрипты можно не прогонять.
Описание
Экранные формы для вызова отчетов
Для вызова и задания параметров отчета разработаны 2 экранные формы: formReportPlan и formReportFact. Они похожи, разберем подробно экранную форму formReportPlan. Она размещена в папке php/forms/reports. XML описание в файле formReportPlan.xml:
<form name="%form%" caption="Отчет по плану ремонтов"> <rowsets> <rowset name="filter" filter="1" > <fields> <field name="dplanmin" type="date" caption="с"/> <field name="dplanmax" type="date" caption="по"/> <field name="departmentid" type="ref" caption="Цех"> <change> <param name="departmentid"/> </change> <ref datasource="department"/> </field> <field name="sectorid" type="ref" caption="Участок" js_readonly="!get('filter.departmentid')"> <ref datasource="sector"> <param name="filter.departmentid" js_value="get('filter.departmentid',-1)"/> </ref> </field> <field name="machinetypeid" type="multilist" caption="Тип оборудования" refname="name" stretch="1"> <ref datasource="machinetype"/> </field> <field name="machinestatusid" type="multilist" caption="Состояние" refname="name" stretch="1"> <ref datasource="machinestatus"/> </field> <field name="department_name" type="string" refid="departmentid" refname="name" stretch="1" caption="Цех"/> <field name="sector_name" type="string" refid="sectorid" refname="name" stretch="1" caption="Участок"/> </fields> </rowset> </rowsets> <request name="go" icon="ok" caption="Перечитать"> <request rowset="filter" name="refresh"/> </request> <panels> <panel rowset="filter"> <panel align="right" type="scroll" width="420px" color="scheme3" margin="1"> <panel align="top" height="10px"/> <panel align="top" type="fields" caption="Период"> <field name="dplanmin" line="1"/> <field name="dplanmax" line="1"/> </panel> <panel align="top" height="6px"/> <panel align="top" height="1px" color="white"/> <panel align="top" height="6px"/> <panel type="fields" align="top" padding="5px" captionup="1" caption="Место размещения"> <field name="department_name"/> <field name="sector_name"/> </panel> <panel align="top" height="6px"/> <panel align="top" height="1px" color="white"/> <panel align="top" height="6px"/> <panel type="fields" align="top" padding="5px" captionup="1" caption="Дополнительно"> <field name="machinetypeid"/> <field name="machinestatusid"/> </panel> <panel align="top" height="6px"/> <panel align="top" height="1px" color="white"/> <panel align="top" height="6px"/> <panel align="top"> <buttons> <request name="go" align="right"/> </buttons> </panel> </panel> <panel border="1"> <panel rowset="filter" type="webbrowser" url="/reports.php?name=plan" repaint="manual"> <param name="dplanmin" js_value="get('filter.dplanmin')" skipempty="1"/> <param name="dplanmax" js_value="get('filter.dplanmax')" skipempty="1"/> <param name="departmentid" js_value="get('filter.departmentid')" skipempty="1"/> <param name="sectorid" js_value="get('filter.sectorid')" skipempty="1"/> <param name="machinetypeid" js_value="get('filter.machinetypeid')" skipempty="1"/> <param name="machinestatusid" js_value="get('filter.machinestatusid')" skipempty="1"/> </panel> </panel> </panel> </panels> </form>
- В форме присутствует единственный источник данных filter с признаком filter=«1». Имя filter служебное, оно означает, что на стороне сервера у источника данных нет контроллера, все должно быть описано прямо в экранной форме. Признак filter=«1» означает особое поведение источника данных - он всегда состоит из 1-й строки, не пытается отписывать значения полей на сервер, автоматически перечитывает подчиненные источники данных при изменении значений своих полей (в нашем случае это не актуально). В нем явно объявлены поля:
- dplanmin, dplanmax - даты
- deparmentid, sectorid - справочники цехов и участков соответственно. Участки привязаны к цехам, если цех не задан то участок readonly. При смене значения поля цеха deparmentid формируется запрос change, его обрабатывает контроллер экранной формы и очищает участок.
- department_name, sector_name - поля отображения значений цехов и участков, соответствуют полям name соответствующих справочников.
- machinetypeid, machinestatusid - поля справочников множественного выбора. Значением поля является список, через запятую, ключей выбранных значений.
- форма состоит из 2-х панелей. Справа поля справочника и кнопка перечитки. Слева панель webbrowser вызывающая формирование и отображение отчета. Режим repaint=«manual» означает, что содержимое панели надо обновлять при перечитке связанного с панелью источника данных, в нашем случае это filter. Соответственно, запрос go формирования отчета, это запрос на перечитку источника данных filter. В атрибуте url=«/reports.php?name=plan» указано имя контроллера отчета - plan. Параметры param передают контроллеру отчетов значения полей источника данных filter.
Для этой экранной формы написан контроллер - formReportPlan.php:
class FormReportPlan extends FormController { protected function getDefinitionMacro($params=Array()) { $result=parent::getDefinitionMacro($params); return $result; } public function getResponse($params=Array(), $events=Array()) { $result=''; $dataSourceName=$params['#request.datasource']; $requestName=$params['#request.name']; $requestMode=$params['#request.mode']; if ($dataSourceName=='filter') { if ($requestName=='change' && $requestMode=='departmentid') { $result.="\n".<<<XML <response name="ok"> <change sectorid="" sector_name=""/> </response> XML; } } return $result; } } return new FormReportPlan();
- метод getResponse позволяет обрабатывать запросы контроллером формы. В нашем случае он обрабатывает запрос change поля departmentid, посылая ответ, требующий очистить поля участка при смене цеха.
Контроллеры отчетов
Разработаны 2 контроллера отчетов - plan и fact. Они размещены в папке php/reports. Разберем подробно контроллер plan.php:
includeLib('lib-report.php'); class ReportPlan extends ReportController { public function getParams() { $params=parent::getParams(); if (testDate($_REQUEST['dplanmin'])) $params['dplanmin']=$_REQUEST['dplanmin']; if (testDate($_REQUEST['dplanmax'])) $params['dplanmax']=$_REQUEST['dplanmax']; if ($_REQUEST['departmentid']) { $dataStorageDepartment=getDataStorage('department'); $itemDepartment=$dataStorageDepartment->getItem($_REQUEST['departmentid']); if ($itemDepartment->getId()) $params['departmentid']=$itemDepartment->getId(); } if ($_REQUEST['sectorid']) { $dataStorageSector=getDataStorage('sector'); $itemSector=$dataStorageSector->getItem($_REQUEST['sectorid']); if ($itemSector->getId()) $params['sectorid']=$itemSector->getId(); } if ($_REQUEST['machinetypeid']) { $dataStorageMachineType=getDataStorage('machinetype'); $lst=Array(); foreach($dataStorageMachineType->getItems(Array('filter.id'=>$_REQUEST['machinetypeid'])) as $itemMachineType) { $machinetypeid=$itemMachineType->getId(); $lst[$machinetypeid]=$machinetypeid; } if (count($lst)>0) $params['machinetypeid']=$lst; } if ($_REQUEST['machinestatusid']) { $dataStorageMachineStatus=getDataStorage('machinestatus'); $lst=Array(); foreach($dataStorageMachineStatus->getItems(Array('filter.id'=>$_REQUEST['machinestatusid'])) as $itemMachineStatus) { $machinestatusid=$itemMachineStatus->getId(); $lst[$machinestatusid]=$machinestatusid; } if (count($lst)>0) $params['machinestatusid']=$lst; } return $params; } public function getBody(&$params=Array()) { $format=$params['format']; $result=<<<HTML <h1>План ремонтов</h1> HTML; $sql_where='1=1'; $html_params=''; { // период $html=''; if ($params['dplanmin']) { if ($html) $html.=' '; $html.='с <b>'.date2Html($params['dplanmin']).'</b>'; $sql_date=$this->str2Sql($params['dplanmin']); $sql_where.="\n".<<<HTML and "machinerepair".dplan>='{$sql_date}' HTML; } if ($params['dplanmax']) { if ($html) $html.=' '; $html.='по <b>'.date2Html($params['dplanmax']).'</b>'; $sql_date=$this->str2Sql($params['dplanmax']); $sql_where.="\n".<<<HTML and "machinerepair".dplan<='{$sql_date}' HTML; } if ($html) { if ($html_params) $html_params.="\n"; $html_params.="<div>{$html}</div>"; } } { // цех, участок $html=''; if ($params['departmentid']) { if ($html) $html.=', '; $dataStorageDepartment=getDataStorage('department'); $itemDepartment=$dataStorageDepartment->getItem($params['departmentid']); $html.='цех <b>'.$itemDepartment->getHtml('name').'</b>'; $sql_value=$this->php2SqlIn($params['departmentid']); $sql_where.="\n".<<<HTML and "machine".departmentid in ({$sql_value}) HTML; } if ($params['sectorid']) { if ($html) $html.=', '; $dataStorageSector=getDataStorage('sector'); $itemSector=$dataStorageSector->getItem($params['sectorid']); $html.='участок <b>'.$itemSector->getHtml('name').'</b>'; $sql_value=$this->php2SqlIn($params['sectorid']); $sql_where.="\n".<<<HTML and "machine".sectorid in ({$sql_value}) HTML; } if ($html) { if ($html_params) $html_params.="\n"; $html_params.="<div>{$html}</div>"; } } { // тип оборудования $html=''; if ($params['machinetypeid']) { $dataStorageMachineType=getDataStorage('machinetype'); foreach($dataStorageMachineType->getItems(Array('filter.id'=>$params['machinetypeid'])) as $itemMachineType) { if ($html) $html.=', '; $html.='<b>'.$itemMachineType->getHtml('name').'</b>'; } $sql_value=$this->php2SqlIn($params['machinetypeid']); $sql_where.="\n".<<<HTML and "machine".machinetypeid in ({$sql_value}) HTML; } if ($html) { if ($html_params) $html_params.="\n"; $html_params.="<div>тип оборудования {$html}</div>"; } } { // состояние оборудования $html=''; if ($params['machinestatusid']) { $dataStorageMachineStatus=getDataStorage('machinestatus'); foreach($dataStorageMachineStatus->getItems(Array('filter.id'=>$params['machinestatusid'])) as $itemMachineStatus) { if ($html) $html.=', '; $html.='<b>'.$itemMachineStatus->getHtml('name').'</b>'; } $sql_value=$this->php2SqlIn($params['machinestatusid']); $sql_where.="\n".<<<HTML and "machine".machinestatusid in ({$sql_value}) HTML; } if ($html) { if ($html_params) $html_params.="\n"; $html_params.="<div>состояние оборудования {$html}</div>"; } } if ($html_params) { $result.="\n".<<<HTML <div class="params-report"> {$html_params} </div> HTML; } $p=Array(); $p['sql']=<<<SQL select "machine".*, "machinerepair".dplan, "repair".name as repair_name, "department".name as department_name, "sector".name as sector_name, "machinetype".name as machinetype_name, "machinestatus".name as machinestatus_name from "machine" join "machinerepair" on "machinerepair".machineid="machine".id and "machinerepair".dplan is not null left join "repair" on "repair".id="machinerepair".repairid left join "department" on "department".id="machine".departmentid left join "sector" on "sector".id="machine".sectorid left join "machinetype" on "machinetype".id="machine".machinetypeid left join "machinestatus" on "machinestatus".id="machine".machinestatusid where {$sql_where} order by "machinerepair".dplan desc, "machine".invnum, "machine".id SQL; $fields=Array(); $fields[]=Array( 'fieldname'=>'dplan', 'caption'=>'Плановая дата', 'type'=>'date' ); $fields[]=Array( 'fieldname'=>'repair_name', 'caption'=>'Вид ремонта' ); $fields[]=Array( 'fieldname'=>'invnum', 'caption'=>'Инвентарный номер' ); $fields[]=Array( 'fieldname'=>'model', 'caption'=>'Модель' ); $fields[]=Array( 'fieldname'=>'department_name', 'caption'=>'Цех' ); $fields[]=Array( 'fieldname'=>'sector_name', 'caption'=>'Участок' ); $fields[]=Array( 'fieldname'=>'machinetype_name', 'caption'=>'Тип оборудования' ); $fields[]=Array( 'fieldname'=>'machinestatus_name', 'caption'=>'Состояние оборудования' ); $p['fields']=$fields; $p['format']=$format; $objReport=new ReportBuilder($p); $result.=$objReport->Get(); unset($objReport); if ($format=='html') { $toolBarPrint=$this->getToolBarPrint($params); $result=<<<HTML <div class="container"> {$toolBarPrint} {$result} </div> HTML; } return $result; } } return new ReportPlan();
- метод getParams разбирает входные параметры отчета, проверяет их корректность и возвращает в виде ассоциативного массива.
- метод getBody возвращает HTML текст отчета. Для формирования отчета используется генератор табличных отчетов из php/lss-server/lib/lib-report.php. Формируется SQL запрос, описание полей и по ним строится таблица. Режим format может принимать значения 'html', 'xls', 'word'. В зависимости от него формируется HTML, адаптированный под корректное отображение в web-браузере, MS-Excel или MS-Word.
Главное меню проекта
Главное меню проекта описывается в XML файле php/config/appmenu.xml:
<node name="Паспорта оборудования и ремонты" icon="box" form="formMachine"/> <node name="Типы оборудования и нормативы ремонтов" icon="ref" form="ref.formMachineType"/> <node name="Отчеты" icon="print"> <node name="Отчет по плану ремонтов" icon="print" form="reports.formReportPlan"/> <node name="Отчет по выполненным ремонтам" icon="print" form="reports.formReportFact"/> </node> <node name="Справочники" icon="reffolder"> <node name="Структура предприятия" icon="ref" form="ref.formDepartment"/> <node name="Виды ремонта" icon="ref" form="ref.formRepair"/> <node name="Состояния оборудования" icon="ref" form="ref.formMachineStatus"/> </node>
- Добавлен раздел Отчеты
Демонстрационные примеры и ссылки
Демонстрационные примеры доступны в режиме «только чтение». Для входа используйте логин root, пароль 1.
- демонстрация работы тестового примера «Материальные активы» у нас на сайте: https://lss.m-cti.ru/storage/example/lss-exampl