OSDN Git Service

Изменён тип хранения информации о проинвентаризированных, учтённых, и непроверенных...
[invent/invent.git] / controllers / ItemsController.php
1 <?php
2
3 namespace app\controllers;
4
5 use Yii;
6 use app\models\Items;
7 use app\models\Import;
8 use app\models\Check;
9 use app\models\Moving;
10 use app\models\Locations;
11 use app\models\ItemsSearch;
12 use app\models\MovingSearch;
13 use app\models\Status;
14 use app\models\User;
15 use yii\web\Controller;
16 use yii\web\NotFoundHttpException;
17 use yii\web\UploadedFile;
18 use yii\filters\VerbFilter;
19
20 use kartik\mpdf\Pdf;
21 use \phpexcel;
22
23 #require "/vendor/phpoffice/phpexcel/Classes/PHPExcel.php";
24
25 /**
26  * ItemsController implements the CRUD actions for Items model.
27  */
28 class ItemsController extends Controller
29 {
30     /**
31      * {@inheritdoc}
32      */
33     public function behaviors()
34     {
35         return [
36             'verbs' => [
37                 'class'   => VerbFilter::className(),
38                 'actions' => [
39                     'delete' => [ 'POST' ],
40                 ],
41             ],
42         ];
43     }
44
45     /**
46      * Добавление предмета/оборудование если его нет
47      * @param array $options
48      *        string 'invent'
49      *        string 'model'
50      *        string 'comment'
51      *        string|NULL 'type'
52      *        string|NULL 'netname'
53      *        string|NULL 'os'
54      *        string|NULL 'mac'
55      *        string|NULL 'serial'
56      *        string|NULL 'product'
57      *        string|NULL 'modelnumber'
58      * @return integer|FALSE
59      */
60     public static function addIfNeed($options)
61     {
62         $result = [
63             'id' => FALSE,
64             'error' => Yii::t('items', 'Items: Key field missing "invent" :') . print_r($options, TRUE),
65         ];
66         // Если указан инвентарный номер
67         if (is_array($options) && isset($options[ 'invent' ]))
68         {
69             $item = Items::find()
70                 ->where([ 'invent' => $options[ 'invent' ]]); // Ищем оборудование с инвентарным номером.
71             // Если указан серийный номер
72             if (isset($options[ 'serial' ])) {
73                 $item = $item->andWhere([ 'like', 'serial', $options[ 'serial' ]]); // Ищем дополнительно с серийным номером
74             }
75             $item = $item->all(); // Получаем все записи
76
77             if (count($item) > 0) // Записи найдены, выводим первую совпавшую
78             {
79                 $result[ 'id' ] = $item[ 0 ]->id;
80                 $result[ 'error' ] = '';
81             }
82             else
83             {
84                 // Внесённого оборудования не найдено. Добавим новую запись
85                 if (isset($options[ 'model' ]))
86                 {
87                     $model = ModelsController::addIfNeed($options);
88                     if ($model[ 'id' ] === FALSE)
89                     {
90                         $result[ 'error' ] .= '<br />' . $model[ 'error' ];
91                     }
92                     else
93                     {
94                         // Создаём новую запись предмета/оборудования
95                         $item = new Items();
96                         $item->name        = isset($options[ 'netName' ]) ? $options[ 'netName' ] : NULL; // Сетевое имя
97
98                         $item->model_id    = $model[ 'id' ];                                              // идентификатор модели (Подготовлено для преобразования)
99                         $item->invent      = isset($options[ 'invent' ]) ? $options[ 'invent' ] : NULL;   // Инвентарный номер
100                         $item->comment     = isset($options[ 'comment' ]) ? $options[ 'comment' ] : NULL; // Коментарий
101                         $item->os          = isset($options[ 'os' ]) ? $options[ 'os' ] : NULL;           // Операционная система
102                         $item->mac         = isset($options[ 'mac' ]) ? $options[ 'mac' ] : NULL;         // MAC-адрес
103                         $item->serial      = isset($options[ 'serial' ]) ? $options[ 'serial' ] : NULL;   // Серийный номер
104                         $item->checked     = 2;                                                           // Не инвентризирован (требует внимания после импорта)
105                         // Сохраняем запись
106                         if ($item->validate() && $item->save())
107                         {
108                             $result[ 'id' ] = $item->id; // Возвращаем идентификатор записанного оборудования
109                             $result[ 'error' ] = '';
110                         }
111                         else
112                         {
113                             $result[ 'error' ] .= Yii::t('items', 'Items: Failed to add entry: ') . print_r($item->errors, TRUE) . '<br />';
114                         }
115                     }
116                 }
117             }
118         }
119         return $result;
120     }
121
122     /**
123      * Формирование PDF файла для печати QR-кодов для наклеек
124      * @param integer|array|null id
125      * @return mixed
126      */
127     public function actionPrint()
128     {
129         if (! User::canPermission('takingInventory') ) {
130             return Yii::$app->response->redirect(['site/index']);
131         }
132 //        Yii::$app->response->format = \yii\web\Response::FORMAT_RAW;
133 //        Yii::$app->response->headers->add('Content-Type', 'application/pdf');
134         // Список предметов/оборудования, если есть
135         $id = Yii::$app->request->get('id');
136
137         $models = Items::find();
138         if (isset($id))
139             if (is_array($id))
140             {
141                 $models = $models->where([ 'in', 'id', $id ]); // Несколько предметов/оборудования
142             } else
143             {
144                 $models = $models->where([ 'id' => $id ]); // Один предмет/оборудование
145             }
146         $models = $models->all(); // Формирование списка
147
148         $pdf = Yii::$app->pdf; // Pабота с PDF
149
150         $pdf->methods[ 'SetHeader' ] = ''; // Yii::t('items', 'Items');
151         $pdf->methods[ 'SetFooter' ] = ''; // ['{PAGENO}'];
152         // Границы листа
153         $pdf->marginLeft   = 5;
154         $pdf->marginRight  = 5;
155         $pdf->marginTop    = 9;
156         $pdf->marginBottom = 15;
157         // Имя файла для выгрузки, по умолчанию document.pdf
158         $pdf->filename     = Yii::t('app', Yii::$app->name) . ' (' . Yii::t('items', 'Items') . ').pdf';
159
160         // Заполнение страницы данными
161         $pdf->content = $this->renderPartial('print', [ 'models' => $models ]);
162
163
164         // Выгрузка PDF
165         return $pdf->render();
166     }
167
168     /**
169      * Процедура начала инвентаризации.
170      * @return mixed
171      */
172     public function actionStart_checking()
173     {
174         // Проверка доступа для проведения инвентаризации
175         if (! User::canPermission('takingInventory') ) {
176             // Переход к списку предметов/оборудования, если доступ не разрешён.
177             return $this->redirect(['index']);
178         }
179         // Запрос на получение списка идентификаторов предметов/оборудования, которые списаны
180         $modelS = Moving::find()
181             ->select('item_id')
182             ->joinWith('status')
183             ->Where([ 'ilike', Status::tableName() . '.name', 'Списано' ])
184             ->orWhere( [ 'checked' => 2 ] );
185
186         // Получаем список всех предметов/оборудования, кроме списанного
187         $model = Items::find()
188             ->select('id')
189             ->innerJoin([ 'm' => $modelS ], 'not m.item_id = id')
190             ->all();
191
192         // Устанавливаем флаг непроинвентаризированных для всех предметов/оборудования из полученного списка.
193         Items::updateAll([ 'checked' => 0 ], [ 'in', 'id', $model ]);
194
195         // Переход к списку предметов/оборудования.
196         return $this->redirect([ 'index' ]);
197     }
198
199     /**
200      * Инвентаризация
201      * @param string|null $qrcheck считанный QR-код
202      * @return mixed
203      */
204      public function actionCheck()
205      {
206         // Проверка доступа для проведения инвентаризации
207         if (! User::canPermission('takingInventory') ) {
208             // Показ стартовой страницы, если доступ не разрешён.
209             return $this->redirect(['site/index']);
210         }
211
212         $model = new Check();
213         $message = '';
214         if ($model->load(Yii::$app->request->post()))
215         {
216             if ((! empty($model->qrcheck)) && strpos($model->qrcheck, ',') !== false)
217             {
218                 $keys = explode(',', $model->qrcheck);
219                 $color=''; // Цветовая метка по умолчанию
220                 // Получаем все предметы/оборудование с совпадением инвентарного и серийного номеров
221                 $items = Items::find()->where([ 'invent' => trim($keys[ 0 ]), 'serial' => trim($keys[ 1 ]) ])->all();
222                 if (count($items) > 0 )
223                 {
224                     foreach ($items as $row)
225                     {
226                         if ( $row->checked == 1 )
227                         {
228                             // Этот инвентарный номер был учтён
229                             $color = ' color="#FF0000"';
230                         }
231                         // Ищем местоположение
232                         $moving_id = Moving::find()->select('MAX(id) as id')->groupBy([ 'item_id' ])->where([ 'item_id' => $row->id ])->one()->id;
233                         $moving = Moving::find()->where([ 'id' => $moving_id ])->one();
234                         // Показываем название и местоположение
235                         $message .= $row->models->name . ' (' . $moving->locations->name  . ' [' . $moving->regions->name . '])';
236                     }
237                 }
238                 else
239                 {
240                     // Неизвестный инвентарный номер
241                     $color = ' color = "#FF8830"';
242                     $message .= Yii::t('items', 'Not found!') . ' ' . Yii::t('items', 'Inventory number') . ': ' . trim($keys[ 0 ]);
243                 }
244                 // Отмечаем проинвентаризированными все найденные предметы/оборудование
245                 Items::updateAll([ 'checked' => 1 ], [ 'invent' => trim($keys[ 0 ]), 'serial' => trim($keys[ 1 ]) ]);
246
247                 if ($message != '')
248                     if ( $color == ' color = "#FF8830"')
249                     {
250                         $message = '<font' . $color . '>' . $message . '</font>';
251                     }
252                     else
253                     {
254                         $message = '<font' . $color . '>' . Yii::t('items', 'Checked item(s): ') . $message . '</font>';
255                     }
256                 $model->qrcheck = '';
257             }
258         }
259         $searchModel = new ItemsSearch();
260         //$dataProvider = $searchModel->noinvent($model);
261         $dataProvider = $searchModel->noinvent(Yii::$app->request->queryParams);
262
263         return $this->render('check', [
264             'message'      => $message,
265             'model'        => $model,
266             'searchModel'  => $searchModel,
267             'dataProvider' => $dataProvider,
268         ]);
269      }
270
271     /**
272      * Список всех предметов/оборудования.
273      * @return mixed
274      */
275     public function actionIndex()
276     {
277         if (! User::canPermission('createRecord') )
278         {
279             return $this->redirect(['site/index']);
280         }
281         if (isset($_GET[ 'pageSize' ]))
282         {
283             Yii::$app->session['pageSize'] = (int) $_GET[ 'pageSize' ];
284             unset($_GET[ 'pageSize' ]);
285         }
286         $searchModel = new ItemsSearch();
287         if (isset(Yii::$app->request->queryParams['id']))
288         {
289             $id = Yii::$app->request->queryParams['id'];
290             $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
291             $pageSize = $dataProvider->pagination->pageSize;
292             $dataProvider->pagination = FALSE;
293             $rows = $dataProvider->getModels();
294             $page = 0;
295             foreach ($rows as $key => $val)
296             {
297                 if ($id == $val->id)
298                 {
299                     $page = ceil(($key + 1) / $pageSize);
300                     break;
301                 }
302             }
303             return $this->redirect(['index', 'page' => $page]);
304         }
305         $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
306
307         return $this->render('index', [
308             'searchModel' => $searchModel,
309             'dataProvider' => $dataProvider,
310         ]);
311     }
312
313     /**
314      * Импортирование строк товаров из массива
315      */
316     public function doImport($arrayRows)
317     {
318         // Инициализация счётчиков
319         $arrayReturn = [
320             'countRows'     => count($arrayRows),
321             'countImported' => 0,
322             'countExists'   => 0,
323             'countErrors'   => 0,
324             'errors'        => '',
325         ];
326
327         // Проверка наличия ключевых полей
328         if ((!isset($arrayRows[ 0 ][ 'model' ]))
329             || (!isset($arrayRows[ 0 ][ 'type' ]))
330             || (!isset($arrayRows[ 0 ][ 'invent' ]))
331             || (!isset($arrayRows[ 0 ][ 'location' ]))
332             || (!isset($arrayRows[ 0 ][ 'region' ]))
333             || (!isset($arrayRows[ 0 ][ 'date' ]))
334         )
335         {
336             // Сообщение об ошибке
337             $arrayReturn[ 'countErrors' ] = count($arrayRows);
338             $arrayReturn[ 'errors' ] .= '<br />' . Yii::t('import', 'Skip all. Key column(s) "model", "type", "invent", "location", "region", "date" not found: ') . print_r($arrayRows[0], TRUE);
339         }
340         else
341         {
342             // Просмотрим весь массив
343             foreach($arrayRows as $row)
344             {
345                 // ПОлучим местоположения
346                 $location = LocationsController::addIfNeed($row); // Получение идентификатора расположения
347                 if ( $location[ 'id' ] === FALSE)
348                 {
349                     // Сообщим об ошибке
350                     $arrayReturn[ 'countErrors' ]++;
351                     $arrayReturn[ 'errors' ] .= '<br />' . $location[ 'error' ];
352                 }
353                 else
354                 {
355                     // Попробуем найти или добавить предмет/оборудование
356                     $item = $this->addIfNeed($row);
357                     if ($item[ 'id' ] === FALSE)
358                     {
359                         $arrayReturn[ 'countErrors' ]++;
360                         $arrayReturn[ 'errors' ] .= '<br />' . $item[ 'error' ];
361                     }
362                     else
363                     {
364                         // Проверка, что предмет/оборудование уже были в базе
365                         $item = Items::find()->where([ 'id' => $item[ 'id' ]])->one();
366                         if ($item->checked < 2)
367                         {
368                             $arrayReturn[ 'countExists' ]++;
369                         }
370                         else
371                         {
372                             $state = isset($row[ 'status' ]) ? StatusController::addIfNeed($row) : StatusController::addIfNeed([ 'status' => 'Склад' ]);
373                             if ( $state[ 'id' ] === FALSE )
374                             {
375                                 // Сообщим об ошибке
376                                 $arrayReturn[ 'countErrors' ]++;
377                                 $arrayReturn[ 'errors' ] .= '<br />' . $state[ 'error' ];
378                             }
379                             else
380                             {
381                                 // Новый предмет/оборудование. Пробуем добавить первое перемещение
382                                 // Проверка что последнее перемещение такое же, как и импортируемое
383                                 $moving = Moving::find()->where([ 'item_id' => $item[ 'id' ]])->all();
384                                 $flag = false;
385                                 if (count($moving) > 0)
386                                 {
387                                     // Признак, что последнее перемещение совпало с импортируемым
388                                     $flag = $moving[ count($moving) - 1 ]->location_id == $location[ 'id' ];
389                                 }
390                                 // Проверим, что существующая запись перемещения больше добавляемой
391                                 $moving = Moving::find()->where([ 'item_id' => $item[ 'id' ]])->andWhere([ '>', 'date', $row[ 'date' ]])->all();
392                                 if ($flag || count($moving) > 0)
393                                 {
394                                     // Добавлять запись до существующих нельзя.
395                                     $arrayReturn[ 'countExists' ]++;
396                                 }
397                                 else
398                                 {
399                                     // Проверим, есть ли уже такое перемещение
400                                     $moving = Moving::find()->where([ 'item_id' => $item[ 'id' ], 'date' => $row[ 'date' ]])->orderBy([ 'id' => SORT_ASC ])->all();
401                                     if (count($moving) == 0)
402                                     {
403                                         // Такой транзакции нет ещё.
404                                         $moving = new Moving();
405                                         $moving->date        = $row[ 'date' ];
406                                         $moving->state_id    = $state[ 'id' ];
407                                         $moving->item_id     = $item[ 'id' ];
408                                         $moving->location_id = $location[ 'id' ];
409                                         $moving->comment     = Yii::t('import', 'Import: {comment}', $row);
410
411                                         if ($moving->validate() && $moving->save())
412                                         {
413                                             // Записаали первое движение
414                                             $arrayReturn[ 'countImported' ]++;
415                                         }
416                                         else
417                                         {
418                                             // Запись не удалась, пробуем удалить предмет/оборудование
419                                             Items::find()->where([ 'id' => $item[ 'id' ], 'checked' => 2 ])->one()->delete();
420                                             // Сообщим об ошибке
421                                             $arrayReturn[ 'countErrors' ]++;
422                                             $arrayReturn[ 'errors' ] .= '<br />' . Yii::t('import', 'Moving: {date} (') . $moving->errors['date'][0]. Yii::t('import', '), Inventory number:{invent}, model: {model}, location: {location} ( {region} )' , $row);
423                                         }
424                                     }
425                                     else
426                                     {
427                                         // Такое перемещение уже было
428                                         $arrayReturn[ 'countExists' ]++;
429                                         // Удаление дубликатов, если вдруг они образовались
430                                         if (count($moving) > 1)
431                                         {
432                                             // переберём все записи со второй  и удалим их.
433                                             for ($i = 1; $i < count($moving); $i++)
434                                             {
435                                                 $moving[$i]->delete();
436                                             }
437                                         }
438                                     }
439                                 }
440                                 unset($moving);
441                             }
442                         }
443                     }
444                 }
445             }
446         }
447
448         // Возврат результата импорта
449         return $arrayReturn;
450     }
451
452     /**
453      * Импорт данных из файла csv
454      * Структура файла данных при выгрузке из 1С: (Колонки могут меняться.
455      * | № п/п |  | Предмет/оборудование |  |  |  |  |  |  | Инвентарный номер | Материально отвественное лицо |  |  | Место размещения | Регион/подразделение | Количество |
456      * Так как 1С из коробки не умеет выгружать форму в .csv, то приходится сначала выгрузить в .xls(x), и уже из MS Excel/Lible office Calc сохранять в .csv
457      */
458     public function actionImport()
459     {
460         if (! User::canPermission('updateRecord') ) {
461             return $this->redirect(['site/index']);
462         }
463         $model   = new Import();
464         $message = '';
465         $searchModel = new ItemsSearch();
466         $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
467         if (Yii::$app->request->isPost)
468         {
469             $rows = [];
470             $columns = [];
471             $columnsNames = [
472                 'npp'         => Yii::t('import', 'No. in order'),
473                 'model'       => Yii::t('import', 'Primary means'),
474                 'netname'     => Yii::t('import', 'Network name'),
475                 'invent'      => Yii::t('import', 'Inventory number'),
476                 'comment'     => Yii::t('import', 'Financially responsible person'),
477                 'os'          => Yii::t('import', 'Operation system'),
478                 'mac'         => Yii::t('import', 'MAC address'),
479                 'serial'      => Yii::t('import', 'Serial number'),
480                 'product'     => Yii::t('import', 'Product number'),
481                 'modelnumber' => Yii::t('import', 'Model number'),
482                 'date'        => Yii::t('import', 'Date of acceptance for registration'),
483                 'location'    => Yii::t('import', 'Location'),
484                 'region'      => Yii::t('import', 'Region'),
485                 'type'        => Yii::t('import', 'Type'),
486                 'status'      => Yii::t('import', 'State'),
487             ];
488             $model->filecsv = UploadedFile::getInstance($model, 'filecsv');
489             if ($model->upload())
490             {
491                 $fileName = 'upload/' . $model->filecsv->baseName . '.' . $model->filecsv->extension;
492                 $handle = fopen($fileName, 'r');
493                 if ($handle !== FALSE)
494                 {
495                     if (strcasecmp($model->filecsv->extension, 'csv') === 0 )
496                     {
497                         // Построчное чтение CSV файла
498                         while (($row = fgetcsv($handle, 2048, ';')) !== false )
499                         {
500                             // Пока не собраны индексы столбцов из шапки
501                             if (count($columns) == 0)
502                             {
503                                 // Ищем строку с заголовком таблицы
504                                 if ( stripos($row[0], $columnsNames[ 'npp' ]) !== FALSE )
505                                 {
506                                     // Перебираем все колонки
507                                     foreach ($row as $key => $item)
508                                     {
509                                         // Перебираем все названия заголовков колонок
510                                         foreach($columnsNames as $name => $text)
511                                         {
512                                             // Если название совпало,
513                                             if (stripos($item, $text) !== FALSE)
514                                             {
515                                                 // Сохраняем индек колонки
516                                                 $columns[ $name ] = $key;
517                                             }
518                                         }
519                                     }
520                                 }
521                             }
522                             else
523                             {
524                                 // Перебираем предметы/оборудование (Номер по порядку должен быть целым числом)
525                                 if (ctype_digit(str_replace(' ', '', $row[ $columns[ 'npp' ]])))
526                                 {
527                                     // Заполняем очередную строку для таблицы
528                                     $line = [];
529                                     foreach ($columns as $key => $index)
530                                     {
531                                         $line[ $key ] = trim(str_replace("\t", ' ', $row[ $index ])); // Заменяем табуляторы на пробелы и удаляем ведущие и ведомые пробелы.
532                                     }
533                                     // Обработка даты
534                                     if (isset($line[ 'date' ]))
535                                     {
536                                         if ($line[ 'date' ] == '#NULL!') $line[ 'date' ] = date('d.m.Y');
537                                     }
538                                     else
539                                     {
540                                         $line[ 'date' ] = date('d.m.Y');
541                                     }
542                                     array_push($rows, $line);
543                                 }
544                             }
545                         } // Перебор строк файла
546                     }
547                     else // xls(x) файлы
548                     {
549                         $inputFileType = \PHPExcel_IOFactory::identify($fileName); // Получение типа данных в файле
550                         $excelReader = \PHPExcel_IOFactory::createReader($inputFileType); // Создание потока чтения из файла
551                         $excelObj = $excelReader->load($fileName); // Открытие файла
552                         $worksheet = $excelObj->getSheet(0);       // Работаем только с первым листом (обычно туда выгружает 1С)
553                         // Индексы ячеек
554
555                         // Цикл по всем строкам
556                         foreach ($worksheet->getRowIterator() as $row)
557                         {
558                             $cellIterator = $row->getCellIterator(); // Получаем итератор ячеек в строке
559                             $cellIterator->setIterateOnlyExistingCells(FALSE); // Указываем проверять даже не установленные ячейки
560
561                             if (count($columns) == 0) // Пока не найдена шапка, проверяем строку
562                             {
563                                 $flag = FALSE;
564                                 foreach ($cellIterator as $key => $item)
565                                 {
566                                     if (($key == 'A') && (stripos($item->getCalculatedValue(), $columnsNames[ 'npp' ]) !== FALSE)) $flag = TRUE;
567                                     if ($flag)
568                                     {
569                                         foreach ($columnsNames as $name => $text)
570                                         {
571                                             if (stripos($item->getCalculatedValue(), $text) !== FALSE)
572                                             {
573                                                 $columns[ $name ] = $key;
574                                             }
575                                         }
576                                     }
577                                 }
578                             }
579                             else
580                             {
581                                 $flag = FALSE;
582                                 $line = [];
583                                 foreach ($cellIterator as $key => $item)
584                                 {
585                                     if ($key == $columns[ 'npp' ])
586                                     {
587                                         $npp = str_replace(' ', '', $item->getCalculatedValue());
588                                         if (ctype_digit($npp)) $flag = TRUE;
589                                     }
590                                     if ($flag)
591                                     {
592                                         foreach($columns as $keym => $index)
593                                         {
594                                             if ($index == $key) $line[ $keym ] = trim(str_replace("\t", ' ', $item->getCalculatedValue()));
595                                         }
596                                     }
597                                 }
598                                 if ($flag)
599                                 {
600                                     if (isset($line[ 'date' ]))
601                                     {
602                                         if ($line[ 'date' ] == '#NULL!') $line[ 'date' ] = date('d.m.Y');
603                                     }
604                                     else
605                                     {
606                                         $line[ 'date' ] = date('d.m.Y');
607                                     }
608                                     array_push($rows, $line);
609                                 }
610                             }
611                         }
612                     }
613                     fclose($handle);
614                     $res = $this->doImport($rows);
615                 }
616                 $message .= Yii::t('items', 'Read {countRows} records.<br />Imported {countImported} Items.<br />Exists {countExists} Items.<br />Error read {countErrors} records.<br />{errors}', $res);
617             }
618         }
619         return $this->render('import',[
620             'message' => $message,
621             'model' => $model,
622             'searchModel' => $searchModel,
623             'dataProvider' => $dataProvider,
624         ]);
625     }
626
627     /**
628      * Показ одного предмета/оборудования. (не используется)
629      * @param integer $id
630      * @return mixed
631      * @throws NotFoundHttpException если предмет/оборудование отсутствует
632      */
633     public function actionView($id)
634     {
635         if (! User::canPermission('updateRecord') ) {
636             return $this->redirect([ 'index', 'id' => $id ]);
637         }
638         return $this->render('view', [
639             'model' => $this->findModel($id),
640         ]);
641     }
642
643     /**
644      * Создание нового предмета/оборудования.
645      * @return mixed
646      */
647     public function actionCreate()
648     {
649         if (! User::canPermission('createRecord') ) {
650             return $this->redirect([ 'site/index' ]);
651         }
652         $model = new Items(); // Новый предмет/оборудование
653         $model->checked = 1;
654         $modelm = new Moving();
655         if ($model->load(Yii::$app->request->post()) && $model->save())
656         {
657             // Удалось сохранить, создаём первую запись движения
658             if ($modelm->load(Yii::$app->request->post()))
659             {
660                 $modelm->item_id = $model->id;
661                 $modelm->comment = 'Поступление';
662
663                 if ( $modelm->save() ) // Пробуем сохранить движение
664                 {
665                     return $this->redirect([ 'index', 'id' => $model->id ]); // Если удалось, показываем список оборудования
666                 } else
667                 {
668                     $this->findModel($model->id)->delete();  // Иначе удаляем созданную запись предмета/оборудования
669                     unset($model->id);                       // Очищаем идентификатор предмета/оборудования
670                     $model->isNewRecord = TRUE;
671                     return $this->render('create', [         // Показываем форму создания нового предмета/оборудования
672                         'model'  => $model,
673                         'modelm' => $modelm,
674                     ]);
675                 }
676             } else
677             {
678                 $this->findModel($model->id)->delete();  // Иначе удаляем созданную запись предмета/оборудования
679                 unset($model->id);                      // Очищаем идентификатор предмета/оборудования
680                 $model->isNewRecord = TRUE;
681                 return $this->render('create', [        // Показываем форму создания нового предмета/оборудования
682                     'model'  => $model,
683                     'modelm' => $modelm,
684                 ]);
685             }
686         } else // не удалось сохранить - отображаем форму создания нового предмета/оборудования
687         {
688             return $this->render('create', [
689                 'model'  => $model,
690                 'modelm' => $modelm,
691             ]);
692         }
693
694     }
695
696     /**
697      * Добавление новой записи как копии существующей
698      * @param integer $id - идентификатор существующей записи предмета/оборудования
699      * @return mixed
700      */
701     public function actionAddcopy($is)
702     {
703         if (! User::canPermission('createRecord') )
704         {
705             return $this->redirect([ 'site/index' ]);
706         }
707         $origin = Items::find()->where([ 'id' => $is ])->one();
708         $model = new Items();
709         $model->checked = 1;
710         $modelm = new Moving();
711         if ($model->load(Yii::$app->request->post()) && $model->save())
712         {
713             // Удалось сохранить, создаём первую запись движения
714             if ($modelm->load(Yii::$app->request->post()))
715             {
716                 $modelm->item_id = $model->id;
717                 $modelm->comment = 'Поступление';
718
719                 if ( $modelm->save() ) // Пробуем сохранить движение
720                 {
721                     return $this->redirect([ 'index', 'id' => $model->id ]); // Если удалось, показываем список оборудования
722                 } else
723                 {
724                     $this->findModel($model->id)->delete();  // Иначе удаляем созданную запись предмета/оборудования
725                     unset($model->id);                       // Очищаем идентификатор предмета/оборудования
726                     $model->isNewRecord = TRUE;
727                     return $this->render('create', [         // Показываем форму создания нового предмета/оборудования
728                         'model'  => $model,
729                         'modelm' => $modelm,
730                     ]);
731                 }
732             } else
733             {
734                 $this->findModel($model->id)->delete();  // Иначе удаляем созданную запись предмета/оборудования
735                 unset($model->id);                      // Очищаем идентификатор предмета/оборудования
736                 $model->isNewRecord = TRUE;
737                 return $this->render('create', [        // Показываем форму создания нового предмета/оборудования
738                     'model'  => $model,
739                     'modelm' => $modelm,
740                 ]);
741             }
742
743         } else
744         {
745             $model->isNewRecord = TRUE;
746             $model->model_id = $origin->model_id;
747             $model->invent = $origin->invent;
748             return $this->render('create', [
749                 'model' => $model,
750                 'modelm' => $modelm,
751             ]);
752         }
753     }
754
755     /**
756      * Изменение существующего предмета/оборудвания.
757      * Если премет/обрудование сохранён, то возвращаемся на страницу списка всех предметов/оборудования.
758      * @param integer $id
759      * @return mixed
760      * @throws NotFoundHttpException если предмет/оборудование отсутствует
761      */
762     public function actionUpdate($id)
763     {
764         if (! User::canPermission('updateRecord') ) {
765             return $this->redirect(['index']);
766         }
767         $model = $this->findModel($id);
768
769         if ($model->load(Yii::$app->request->post()) && $model->save())
770         {
771             return $this->redirect([ 'index', 'id' => $model->id ]);
772         }
773
774         $searchModelM = new MovingSearch([ 'item_id' => $model->id ]);
775         $dataProviderM = $searchModelM->search(Yii::$app->request->queryParams);
776
777          return $this->render('update', [
778             'searchModelM'  => $searchModelM,
779             'dataProviderM' => $dataProviderM,
780             'model'         => $model,
781         ]);
782     }
783
784     /**
785      * Удаляет сушествующий предмет/оборудование.
786      * Если премет/обрудование удалён, то возвращаемся на страницу списка всех предметов/оборудования.
787      * @param integer $id
788      * @return mixed
789      * @throws NotFoundHttpException if the model cannot be found
790      */
791     public function actionDelete($id)
792     {
793         if (! User::canPermission('updateRecord') ) {
794             return $this->redirect(['site/index']);
795         }
796         $this->findModel($id)->delete();
797
798         return $this->redirect([ 'index' ]);
799     }
800
801     /**
802      * Finds the Items model based on its primary key value.
803      * If the model is not found, a 404 HTTP exception will be thrown.
804      * @param integer $id
805      * @return Items the loaded model
806      * @throws NotFoundHttpException если предмет/оборудование отсутствует
807      */
808     protected function findModel($id)
809     {
810         if (($model = Items::findOne($id)) !== null)
811         {
812             return $model;
813         }
814
815         throw new NotFoundHttpException(Yii::t('app', 'The requested page does not exist.'));
816     }
817 }