Содержание
Этап разработки отчетов
Введение
На этом этапе мы разрабатываем 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
