====== Этап разработки системы планирования и учета ремонтов оборудования ======
[[start:|lss]]
===== Введение =====
На этом этапе мы разработаем экранные формы для планирования и учета ремонтов оборудования, допишем необходимый функционал в источники данных **DataSource**, скорректируем главное меню системы.
===== Развертывание этапа на площадке =====
* Скачаем архив **LSS проекта** для текущего этапа.
* Обновим проект из архива. Надо быть осторожным с конфигурационным файлом площадки **php/config/config-place.php**, он содержит текущие параметры соединения с базой данных, его обновлять не надо.
* Выполним с помощью утилиты **pgAdmin** скрипт заполнения содержимого таблиц первоначальными значениями, файл **export-import/backup/backup.sql**.
===== Описание =====
==== Контроллеры источников данных DataSource ====
=== Контроллер для таблицы machine ===
Вот содержимое файла контроллера источника данных для таблицы оборудования **machine**, файл **php/datasources/machine.php**:
class DataSource_Machine_Ext extends DataSource_Machine {
protected function onRowAfter(&$row, $params=Array()) {
$row['sectorid.readonly']=$row['departmentid']?0:1;
}
public function execChange($params=Array()) {
$result=parent::execChange($params);
$fieldName=$params['#request.mode'];
if ($fieldName=='departmentid') {
$row=Array();
$row['row.change']=1;
$row['sectorid.readonly']=$params['departmentid']?0:1;
$row['sectorid']='';
$row['sector_name']='';
$result[]=$row;
}
return $result;
}
}
return new DataSource_Machine_Ext();
* обработчик событий **onRowAfter** при чтении данных на сервере задает признак readonly полю **Участок** если не задано значение поля **Цех**
* метод **execChange** вызывается при правке пользователем значения поля **Цех**. Обратите внимание, в экранной форме **Разработка/Структура базы** у поля **departmentid** таблицы **machine** задан параметр **change** со значением **departmentid**. Это означает, что правка пользователем этого поля будет отправлять на сервер запрос **change** с параметром **departmentid** содержащим исправленное значение этого поля. В ответе можно скорректировать значения других полей, в нашем случае мы при правке **Цеха** очищаем **Участок** и корректируем для него признак **readonly**.
=== Контроллер для таблицы machinerepair ===
Вот содержимое файла контроллера источника данных для таблицы запланированных и фактически выполненных ремонтов **machinerepair**, файл **php/datasources/machinerepair.php**:
class DataSource_Machinerepair_Ext extends DataSource_Machinerepair {
protected function initRequests() {
$result=parent::initRequests();
$result[]=Array(
'name'=>'rebuild',
'permoper'=>'write'
);
return $result;
}
public function exec($params=Array()) {
$requestName=$params['#request.name'];
$requestMode=$params['#request.mode'];
if ($requestName=='rebuild') {
return $this->execRebuild($params);
}
return parent::exec($params);
}
public function execRebuild($params=Array()) {
$this->rebuild(24);
$result=Array();
return $result;
}
protected function rebuild($maxperiod) {
$sql_dmax=(new DateTime())->modify("+{$maxperiod} month")->format('Y-m-01');
{ // удаляем строки плана ремонтов
$sql=<<pdo($sql);
}
{ // упорядочиваем справочник видов ремонтов
$sql=<<a.npp
SQL;
$this->pdo($sql);
}
{ // добавляем строки планов ремонтов
for($i=0; $i<500; $i++) {
$sql=<<pdo($sql);
if (!$q->rowCount()) break;
}
}
return;
}
protected function onRowAfter(&$row, $params=Array()) {
$row['dplan.readonly']=1;
if ($row['dplan']) {
$row['repairid.readonly']=1;
$row['machineid.readonly']=1;
}
}
protected function onRowAfterDelete(&$row, $params=Array()) {
if ($row['dplan']) throw new Exception('Задана плановая дата ремонта, нельзя удалять');
}
}
return new DataSource_Machinerepair_Ext();
* добавляем в источник данных поддержку запроса **repair** - полный пересчет плана ремонтов оборудования на 24 месяца вперед.
* переопределяем метод **initRequests** для регистрации запроса **rebuild**, это нужно для передачи **LSS визуализатору** описания поддерживаемых источником данных запросов
* переопределяем метод **exec** для обработки запроса **rebuild** посредством вызова метода **execRebuild**
* реализуем методы **execRebuild** и **rebuild** для выполнения пересчета. Подробное описание алгоритма мы тут приводить не будем, скажем только, что реализован он посредством специфических SQL запросов для диалекта PostgreSql . Сначала мы очищаем все строки плана, а затем, в цикле, для каждого оборудования формируем очередной ближайший ремонт. Цикл заканчивается либо когда все строки плана сформированы (новых нет), либо когда превышено максимально допустимое число шагов итерации - в нашем случае 500.
* обработчик событий **onRowAfter** выставляет признак **readonly** полям **Оборудование** и **Вид ремонта** для автоматически сформированных строк плана ремонта
* обработчик событий **onRowAfterDelete** блокирует возможность ручного удаления автоматически сформированных строк плана ремонта. Этот обработчик вызывается после удаления строк, но перед подтверждением транзакции. Вызов исключения приводит к откату транзакции.
=== Контроллер для таблицы repairnorm ===
Вот содержимое файла контроллера источника данных для таблицы норм ремонтов **repairnorm**, файл **php/datasources/repairnorm.php**:
class DataSource_Repairnorm_Ext extends DataSource_Repairnorm {
/// переопределяем проверку после правки строки
protected function onRowValid(&$row) {
{ // проверка значений repairid и machinetypeid на уникальность - для более понятного пользователю сообщения об ошибке
$sql_repairid=$this->str2Sql($row['repairid']);
$sql_machinetypeid=$this->str2Sql($row['machinetypeid']);
$sql_id=$this->str2Sql($row['id']);
$sql=<<'{$sql_id}'
SQL;
$rec=$this->pdoFetch($sql);
if ($rec['n']) throw new Exception("Для типа оборудования '{$row['machinetype_name']}' периодичность ремонта '{$row['repair_name']}' уже задана");
}
{ // проверка значения периодичности ремонта
if ($row['period']<=0) throw new Exception('Периодичность ремонтов должна быть положительна');
}
}
}
return new DataSource_Repairnorm_Ext();
* обработчик события **onRowValid** проверяет уникальность сочетания полей **Оборудование** и **Вид ремонта**, и проверяет неотрицательность значения поля **Периодичность ремонта**.
==== Экранные формы FormController ====
=== Экранная форма нормативов ремонта ===
Экранная форма справочника **Типы оборудования** переделана в экранную форму **Типы оборудования и нормативы ремонта**:
* к источнику данных **machinetype** добавлен дочерний источник данных **repairnorm**, автоматически перечитывающийся при смене текущей строки родительского источника данных.
* добавлена дополнительная панель **grid**, позволяющая в табличном виде редактировать содержимое источника данных **repairnorm**.
=== Экранная форма паспортов оборудования и ремонтов ===
Разработана экранная форма formMachine, XML описание ее расположено в файле **php/forms/formMachine/formMachine.xml**:
* задействованы родительский источник данных списка оборудования **machine** и два дочерних: список ремонтов **machinerepair** и нормы ремонтов **repairnorm**. Нормы ремонтов в этой экранной форме приведены для ознакомления, поэтому источник данных **repairnorm** подключен в режиме только для чтения.
* в разделе запросов формы **requests** объявлен запрос перестроения планов ремонтов оборудования **machinerepair-rebuild**. Он вызывает запрос **rebuild** источника данных **machinerepair** а затем для отображения пересчитанного плана ремонтов вызывает перечитку источника данных **machinerepair**.
* Структура панелей организована следующим образом: слева панель **grid** паспортов оборудования, справа панель закладок **tab**, составленная из 3-х панелей:
* анкета паспорта оборудования
* **grid** списка ремонтов
* **grid** норматива ремонтов
* Вызов запроса **machinerepair-rebuild** пересчитывающего план ремонтов сделан кнопкой
==== Главное меню проекта ====
Главное меню проекта описывается в XML файле **php/config/appmenu.xml**:
* Добавлен пункт вызова экранной формы **Паспорта оборудования и ремонты**
* Вызов экранной формы **Типы оборудования и нормативы ремонтов** перенесен из раздела **Справочники** в корень меню
===== Демонстрационные примеры и ссылки =====
Демонстрационные примеры доступны в режиме "**только чтение**". Для входа используйте логин **root**, пароль **1**.
* демонстрация работы **тестового примера** "Материальные активы" у нас на сайте: [[https://lss.m-cti.ru/storage/example/lss-exampl]]