Commit 40cac1b611a0d7f946e42d308f4591e518045cfb
1 parent
7ee738d0
add delete func in deteils model
Showing
5 changed files
with
111 additions
and
42 deletions
Show diff stats
backend/controllers/ParserController.php
| ... | ... | @@ -101,7 +101,6 @@ class ParserController extends BaseController |
| 101 | 101 | } |
| 102 | 102 | |
| 103 | 103 | $model->file->saveAs($model->file_path); |
| 104 | - | |
| 105 | 104 | // для авто загрузки, обработка завершена |
| 106 | 105 | if ($model->mode) { |
| 107 | 106 | $model->success = true; |
| ... | ... | @@ -124,12 +123,11 @@ class ParserController extends BaseController |
| 124 | 123 | |
| 125 | 124 | } else { |
| 126 | 125 | // не прошла валидация форма загрузки файлов |
| 127 | - //@todo - отправка на страницу ошибок | |
| 128 | - $errors_arr = $model->getErrors(); | |
| 129 | - foreach ($errors_arr as $error) { | |
| 130 | - CustomVarDamp::dump(array_values($error)); | |
| 126 | + $errors_str = ''; | |
| 127 | + foreach ($model->getErrors() as $error) { | |
| 128 | + $errors_str .= implode( array_values($error) ); | |
| 131 | 129 | } |
| 132 | - die; | |
| 130 | + throw new ErrorException( $errors_str ); | |
| 133 | 131 | } |
| 134 | 132 | // листаем пагинатором, или повторно вызываем - считываем из кеша отпрасенные данные |
| 135 | 133 | } else if (Yii::$app->getCache()->get('parser_data')) { |
| ... | ... | @@ -145,8 +143,11 @@ class ParserController extends BaseController |
| 145 | 143 | ], |
| 146 | 144 | ]); |
| 147 | 145 | |
| 146 | + | |
| 147 | + $last_index = end( array_flip( $data[0] ) ); | |
| 148 | + $header_counts = $last_index + 1; | |
| 148 | 149 | //формируем заголовок для пользователя, где он сможет выбрать соответсвие полей (выпадающий список) |
| 149 | - $header_model = DynamicFormHelper::CreateDynamicModel(count($data[0])); | |
| 150 | + $header_model = DynamicFormHelper::CreateDynamicModel( $header_counts ); | |
| 150 | 151 | |
| 151 | 152 | return $this->render('results', |
| 152 | 153 | ['model' => $data, | ... | ... |
backend/models/Details.php
| ... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | namespace backend\models; |
| 4 | 4 | |
| 5 | +use common\components\CustomVarDamp; | |
| 5 | 6 | use Yii; |
| 6 | 7 | use backend\components\base\BaseActiveRecord; |
| 7 | 8 | |
| ... | ... | @@ -22,8 +23,22 @@ use backend\components\base\BaseActiveRecord; |
| 22 | 23 | */ |
| 23 | 24 | class Details extends BaseActiveRecord |
| 24 | 25 | { |
| 25 | - const KEY_COLUMN = ['IMPORT_ID','BRAND','ARTICLE']; | |
| 26 | + /** | |
| 27 | + *обязательные колонки | |
| 28 | + */ | |
| 29 | + const KEY_COLUMN = ['IMPORT_ID', 'BRAND', 'ARTICLE']; | |
| 30 | + | |
| 31 | + /** | |
| 32 | + * int - размер пакета запроса | |
| 33 | + */ | |
| 26 | 34 | const BATCH = 500; |
| 35 | + | |
| 36 | + /** | |
| 37 | + * @var bool - признак необходимости удалить префикс Артикула перед вставкой | |
| 38 | + */ | |
| 39 | + public $delete_prefix = false; | |
| 40 | + public $delete_price = false; | |
| 41 | + | |
| 27 | 42 | /** |
| 28 | 43 | * @inheritdoc |
| 29 | 44 | */ |
| ... | ... | @@ -38,8 +53,8 @@ class Details extends BaseActiveRecord |
| 38 | 53 | public function rules() |
| 39 | 54 | { |
| 40 | 55 | return [ |
| 41 | - [[ 'BRAND', 'ARTICLE', 'PRICE', 'DESCR', 'BOX'], 'required'], | |
| 42 | - // [['IMPORT_ID', 'BOX', 'ADD_BOX'], 'integer'], | |
| 56 | + [['BRAND', 'ARTICLE', 'PRICE', 'DESCR', 'BOX'], 'required'], | |
| 57 | + // [['IMPORT_ID', 'BOX', 'ADD_BOX'], 'integer'], | |
| 43 | 58 | [['PRICE'], 'number'], |
| 44 | 59 | [['BOX'], 'integer'], |
| 45 | 60 | [['timestamp'], 'safe'], |
| ... | ... | @@ -69,13 +84,38 @@ class Details extends BaseActiveRecord |
| 69 | 84 | ]; |
| 70 | 85 | } |
| 71 | 86 | |
| 72 | - public function ManualInsert ($data) | |
| 87 | + /** | |
| 88 | + *удаление (если $delete_price установлен)б а затем вставка данных с апдейтом прямымыми запросоми SQL | |
| 89 | + * @param $data - массив вставляемых данных, вставка будет прозводится пакетами размером указанным в константе BATCH | |
| 90 | + * @param $importer_id - (int) - идентификатор поставщика у которого будет сперва удалены прайсы а потом вставлены из массива $data | |
| 91 | + * @throws \yii\db\Exception | |
| 92 | + */ | |
| 93 | + public function ManualInsert($data, $importer_id) | |
| 94 | + { | |
| 95 | + if ($this->delete_price) { | |
| 96 | + // запустим пакетное удаление всех прайсов поставщика | |
| 97 | + do { | |
| 98 | + $query = Yii::$app->db->createCommand()->delete(self::tableName(), "IMPORT_ID = {$importer_id}")->sql . ' Limit ' . $this::BATCH; | |
| 99 | + $res = Yii::$app->db->createCommand($query)->execute(); | |
| 100 | + } while ($res); | |
| 101 | + | |
| 102 | + } | |
| 103 | + | |
| 104 | + $this->ManualInsertWithUpdate($data); | |
| 105 | + } | |
| 106 | + | |
| 107 | + /** | |
| 108 | + * вставка данных с апдейтом прямым запросом SQL | |
| 109 | + * @param $data - массив вставляемых данный, вставка будет прозводится пакетами размером указанным в константе BATCH | |
| 110 | + * @throws \yii\db\Exception | |
| 111 | + */ | |
| 112 | + private function ManualInsertWithUpdate($data) | |
| 73 | 113 | { |
| 74 | 114 | // \common\components\CustomVarDamp::dumpAndDie($data); |
| 75 | 115 | $table_name = self::tableName(); |
| 76 | - $keys_arr = array_keys( $data[0] ); | |
| 116 | + $keys_arr = array_keys($data[0]); | |
| 77 | 117 | // найдем те поля которые не являются ключами. Их нужно будет при дубляже апдейтить |
| 78 | - $fields_arr_to_update = array_diff( $keys_arr, $this::KEY_COLUMN ); | |
| 118 | + $fields_arr_to_update = array_diff($keys_arr, $this::KEY_COLUMN); | |
| 79 | 119 | |
| 80 | 120 | $query_update = ' on duplicate key update '; |
| 81 | 121 | foreach ($fields_arr_to_update as $field) { |
| ... | ... | @@ -87,8 +127,8 @@ class Details extends BaseActiveRecord |
| 87 | 127 | // запросы будем выполнять пакетами |
| 88 | 128 | // размер пакета установлен в константе |
| 89 | 129 | // разобъем массив на пакеты и будем их проходить |
| 90 | - $data = array_chunk($data, $this::BATCH ); | |
| 91 | - foreach( $data as $current_batch_array ){ | |
| 130 | + $data = array_chunk($data, $this::BATCH); | |
| 131 | + foreach ($data as $current_batch_array) { | |
| 92 | 132 | |
| 93 | 133 | //воспользуемся пакетной вставкой от фреймворка, плюс сразу с экранированием и защитой от инъекций |
| 94 | 134 | $query_insert = Yii::$app->db->createCommand()->batchInsert($table_name, $keys_arr, $current_batch_array)->sql; |
| ... | ... | @@ -100,5 +140,4 @@ class Details extends BaseActiveRecord |
| 100 | 140 | } |
| 101 | 141 | } |
| 102 | 142 | |
| 103 | - | |
| 104 | 143 | } | ... | ... |
backend/models/UploadFileParsingForm.php
| ... | ... | @@ -77,7 +77,9 @@ class UploadFileParsingForm extends Model |
| 77 | 77 | throw new ErrorException("Ошибка чтения из файла прайса {$this->file_path}"); |
| 78 | 78 | } |
| 79 | 79 | // файл больше не нужен - данные прочитаны и сохранены в кеш |
| 80 | - unlink($this->file_path); | |
| 80 | + if( file_exists($this->file_path) ) | |
| 81 | + unlink($this->file_path); | |
| 82 | + | |
| 81 | 83 | return $data; |
| 82 | 84 | } |
| 83 | 85 | ... | ... |
common/components/PriceWriter.php
| ... | ... | @@ -14,22 +14,45 @@ use backend\models\ImportersFiles; |
| 14 | 14 | use backend\models\Importers; |
| 15 | 15 | use backend\models\Details; |
| 16 | 16 | |
| 17 | -class PriceWriter { | |
| 17 | +/** | |
| 18 | + * Class PriceWriter | |
| 19 | + * @package common\components | |
| 20 | + * записывает в БД отпарсенные данные | |
| 21 | + * запись происходит в несколько таблиц | |
| 22 | + */ | |
| 23 | +class PriceWriter | |
| 24 | +{ | |
| 25 | + /** | |
| 26 | + * @var - int - 0 - интерактивный режим, 1 - консольный | |
| 27 | + */ | |
| 18 | 28 | public $mode; |
| 29 | + | |
| 30 | + /** | |
| 31 | + * @var - массив с настройками записи | |
| 32 | + */ | |
| 19 | 33 | public $configuration; |
| 34 | + | |
| 35 | + /** | |
| 36 | + * @var - массив с данными которые нужно записать | |
| 37 | + */ | |
| 20 | 38 | public $data; |
| 21 | 39 | |
| 22 | - public function writeDataToDB () | |
| 40 | + function __construct() | |
| 41 | + { | |
| 42 | + set_time_limit(300); | |
| 43 | + } | |
| 44 | + | |
| 45 | + public function writeDataToDB() | |
| 23 | 46 | { |
| 24 | 47 | // 1. запишем дату старта в таблицу файлов поставщика (ImportersFiles) |
| 25 | 48 | // id загруженного файла получим из конфигурации |
| 26 | - $files_model = ImportersFiles::findOne( $this->configuration['record_id'] ); | |
| 49 | + $files_model = ImportersFiles::findOne($this->configuration['record_id']); | |
| 27 | 50 | |
| 28 | 51 | $update_date = date('Y-m-d H:i:s'); |
| 29 | 52 | $files_model->time_start = $update_date; |
| 30 | 53 | // запишем дату начала загрузки |
| 31 | 54 | if (!$files_model->save()) { |
| 32 | - throw new \ErrorException(implode( ', ', $files_model->getErrors())); | |
| 55 | + throw new \ErrorException(implode(', ', $files_model->getErrors())); | |
| 33 | 56 | } |
| 34 | 57 | |
| 35 | 58 | // 2. запишем полученные данные в таблицу товаров (Details) |
| ... | ... | @@ -43,7 +66,7 @@ class PriceWriter { |
| 43 | 66 | $row['BOX'] = \Yii::$app->multiparser->convertToInteger($row['BOX']); |
| 44 | 67 | // присвоим полный артикул |
| 45 | 68 | $row['FULL_ARTICLE'] = $row['ARTICLE']; |
| 46 | - if(isset($row['ADD_BOX'])) | |
| 69 | + if (isset($row['ADD_BOX'])) | |
| 47 | 70 | $row['ADD_BOX'] = \Yii::$app->multiparser->convertToInteger($row['ADD_BOX']); |
| 48 | 71 | |
| 49 | 72 | // проверим все ли обязательные колонки были указаны пользователем |
| ... | ... | @@ -55,31 +78,35 @@ class PriceWriter { |
| 55 | 78 | } |
| 56 | 79 | } |
| 57 | 80 | |
| 58 | - // дополним данные значением импортера и даты обновления цены | |
| 59 | - $this->data = \Yii::$app->multiparser->addColumns($this->data, ['IMPORT_ID' => $this->configuration['importer_id'], 'timestamp' => $update_date]); | |
| 81 | + // дополним данные значением импортера и даты обновления цены | |
| 82 | + $this->data = \Yii::$app->multiparser->addColumns($this->data, ['IMPORT_ID' => $this->configuration['importer_id'], 'timestamp' => $update_date]); | |
| 83 | + try { | |
| 84 | + //@todo add transaction | |
| 60 | 85 | |
| 61 | - try { | |
| 62 | - //@todo add transaction | |
| 63 | - // попытаемся вставить данные в БД с апдейтом по ключам | |
| 64 | - $details_model->ManualInsert($this->data); | |
| 65 | - | |
| 66 | - // 3. зафиксируем дату конца загрузки в файлах поставщика | |
| 86 | + if ((int)$this->configuration['delete_prefix']) { | |
| 87 | + $details_model->delete_prefix = true; | |
| 88 | + } | |
| 89 | + if ((int)$this->configuration['delete_price']) { | |
| 90 | + $details_model->delete_price = true; | |
| 91 | + } | |
| 92 | + //2. попытаемся вставить данные в БД с апдейтом по ключам | |
| 93 | + $details_model->ManualInsert($this->data, $this->configuration['importer_id']); | |
| 67 | 94 | |
| 68 | - if (!$files_model->save()) { | |
| 69 | - throw new \ErrorException(implode( ', ', $files_model->getErrors())); | |
| 70 | - } | |
| 95 | + // 3. зафиксируем дату конца загрузки в файлах поставщика | |
| 96 | + if (!$files_model->save()) { | |
| 97 | + throw new \ErrorException(implode(', ', $files_model->getErrors())); | |
| 98 | + } | |
| 71 | 99 | |
| 72 | - // 4. зафиксируем дату загрузки в таблице поставщиков | |
| 73 | - $imp_model = Importers::findOne($this->configuration['importer_id']); | |
| 74 | - $imp_model->price_date_update = $update_date; | |
| 100 | + // 4. зафиксируем дату загрузки в таблице поставщиков | |
| 101 | + $imp_model = Importers::findOne($this->configuration['importer_id']); | |
| 102 | + $imp_model->price_date_update = $update_date; | |
| 75 | 103 | |
| 76 | - if (!$imp_model->save()) { | |
| 77 | - throw new \ErrorException(implode( ', ', $imp_model->getErrors())); | |
| 78 | - } | |
| 79 | - } catch (ErrorException $e) { | |
| 80 | - throw new \ErrorException( $e->getMessage() ); | |
| 104 | + if (!$imp_model->save()) { | |
| 105 | + throw new \ErrorException(implode(', ', $imp_model->getErrors())); | |
| 81 | 106 | } |
| 82 | - | |
| 107 | + } catch (ErrorException $e) { | |
| 108 | + throw new \ErrorException($e->getMessage()); | |
| 109 | + } | |
| 83 | 110 | |
| 84 | 111 | |
| 85 | 112 | return true; | ... | ... |
test1.zip deleted
No preview for this file type