====== Этап разработки системы планирования и учета ремонтов оборудования ====== [[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]]