Commit 66adbd632678bf78088510b48e73b30ddad816b9
1 parent
d4d85fc1
sinhronize with server
Showing
9 changed files
with
265 additions
and
76 deletions
Show diff stats
backend/controllers/ParserController.php
@@ -101,7 +101,6 @@ class ParserController extends BaseController | @@ -101,7 +101,6 @@ class ParserController extends BaseController | ||
101 | } | 101 | } |
102 | 102 | ||
103 | $model->file->saveAs($model->file_path); | 103 | $model->file->saveAs($model->file_path); |
104 | - | ||
105 | // для авто загрузки, обработка завершена | 104 | // для авто загрузки, обработка завершена |
106 | if ($model->mode) { | 105 | if ($model->mode) { |
107 | $model->success = true; | 106 | $model->success = true; |
@@ -112,7 +111,10 @@ class ParserController extends BaseController | @@ -112,7 +111,10 @@ class ParserController extends BaseController | ||
112 | // === ручная загрузка =========== | 111 | // === ручная загрузка =========== |
113 | //запускаем парсинг | 112 | //запускаем парсинг |
114 | // доп. опции для парсера | 113 | // доп. опции для парсера |
115 | - $options = []; | 114 | + $options = ['converter_conf' => |
115 | + ['importer_id' => $files_model->importer_id] | ||
116 | + ]; | ||
117 | + | ||
116 | if( ! $model->action ) // обработка с кастомным разделителем | 118 | if( ! $model->action ) // обработка с кастомным разделителем |
117 | $options['$delimiter'] = $model->delimiter; | 119 | $options['$delimiter'] = $model->delimiter; |
118 | 120 | ||
@@ -124,12 +126,11 @@ class ParserController extends BaseController | @@ -124,12 +126,11 @@ class ParserController extends BaseController | ||
124 | 126 | ||
125 | } else { | 127 | } else { |
126 | // не прошла валидация форма загрузки файлов | 128 | // не прошла валидация форма загрузки файлов |
127 | - //@todo - отправка на страницу ошибок | ||
128 | - $errors_arr = $model->getErrors(); | ||
129 | - foreach ($errors_arr as $error) { | ||
130 | - CustomVarDamp::dump(array_values($error)); | 129 | + $errors_str = ''; |
130 | + foreach ($model->getErrors() as $error) { | ||
131 | + $errors_str .= implode( array_values($error) ); | ||
131 | } | 132 | } |
132 | - die; | 133 | + throw new ErrorException( $errors_str ); |
133 | } | 134 | } |
134 | // листаем пагинатором, или повторно вызываем - считываем из кеша отпрасенные данные | 135 | // листаем пагинатором, или повторно вызываем - считываем из кеша отпрасенные данные |
135 | } else if (Yii::$app->getCache()->get('parser_data')) { | 136 | } else if (Yii::$app->getCache()->get('parser_data')) { |
@@ -145,8 +146,11 @@ class ParserController extends BaseController | @@ -145,8 +146,11 @@ class ParserController extends BaseController | ||
145 | ], | 146 | ], |
146 | ]); | 147 | ]); |
147 | 148 | ||
149 | + | ||
150 | + $last_index = end( array_flip( $data[0] ) ); | ||
151 | + $header_counts = $last_index + 1; | ||
148 | //формируем заголовок для пользователя, где он сможет выбрать соответсвие полей (выпадающий список) | 152 | //формируем заголовок для пользователя, где он сможет выбрать соответсвие полей (выпадающий список) |
149 | - $header_model = DynamicFormHelper::CreateDynamicModel(count($data[0])); | 153 | + $header_model = DynamicFormHelper::CreateDynamicModel( $header_counts ); |
150 | 154 | ||
151 | return $this->render('results', | 155 | return $this->render('results', |
152 | ['model' => $data, | 156 | ['model' => $data, |
backend/models/Details.php
@@ -2,6 +2,7 @@ | @@ -2,6 +2,7 @@ | ||
2 | 2 | ||
3 | namespace backend\models; | 3 | namespace backend\models; |
4 | 4 | ||
5 | +use common\components\CustomVarDamp; | ||
5 | use Yii; | 6 | use Yii; |
6 | use backend\components\base\BaseActiveRecord; | 7 | use backend\components\base\BaseActiveRecord; |
7 | 8 | ||
@@ -22,8 +23,22 @@ use backend\components\base\BaseActiveRecord; | @@ -22,8 +23,22 @@ use backend\components\base\BaseActiveRecord; | ||
22 | */ | 23 | */ |
23 | class Details extends BaseActiveRecord | 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 | const BATCH = 500; | 34 | const BATCH = 500; |
35 | + | ||
36 | + /** | ||
37 | + * @var bool - признак необходимости удалить префикс Артикула перед вставкой | ||
38 | + */ | ||
39 | + public $delete_prefix = false; | ||
40 | + public $delete_price = false; | ||
41 | + | ||
27 | /** | 42 | /** |
28 | * @inheritdoc | 43 | * @inheritdoc |
29 | */ | 44 | */ |
@@ -38,8 +53,8 @@ class Details extends BaseActiveRecord | @@ -38,8 +53,8 @@ class Details extends BaseActiveRecord | ||
38 | public function rules() | 53 | public function rules() |
39 | { | 54 | { |
40 | return [ | 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 | [['PRICE'], 'number'], | 58 | [['PRICE'], 'number'], |
44 | [['BOX'], 'integer'], | 59 | [['BOX'], 'integer'], |
45 | [['timestamp'], 'safe'], | 60 | [['timestamp'], 'safe'], |
@@ -69,13 +84,38 @@ class Details extends BaseActiveRecord | @@ -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 | // \common\components\CustomVarDamp::dumpAndDie($data); | 114 | // \common\components\CustomVarDamp::dumpAndDie($data); |
75 | $table_name = self::tableName(); | 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 | $query_update = ' on duplicate key update '; | 120 | $query_update = ' on duplicate key update '; |
81 | foreach ($fields_arr_to_update as $field) { | 121 | foreach ($fields_arr_to_update as $field) { |
@@ -87,18 +127,24 @@ class Details extends BaseActiveRecord | @@ -87,18 +127,24 @@ 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 | $query_insert = Yii::$app->db->createCommand()->batchInsert($table_name, $keys_arr, $current_batch_array)->sql; | 134 | $query_insert = Yii::$app->db->createCommand()->batchInsert($table_name, $keys_arr, $current_batch_array)->sql; |
135 | + if ($this->delete_prefix) { | ||
136 | + $query_insert = $this->prepareArticul( $query_insert ); | ||
137 | + } | ||
95 | // добавим фрагмент с апдейтом при дубляже | 138 | // добавим фрагмент с апдейтом при дубляже |
96 | $query = "{$query_insert} {$query_update}"; | 139 | $query = "{$query_insert} {$query_update}"; |
97 | // \common\components\CustomVarDamp::dumpAndDie($query); | 140 | // \common\components\CustomVarDamp::dumpAndDie($query); |
98 | - $res = Yii::$app->db->createCommand($query)->execute(); | 141 | + Yii::$app->db->createCommand($query)->execute(); |
99 | 142 | ||
100 | } | 143 | } |
101 | } | 144 | } |
102 | 145 | ||
103 | - | 146 | + private function prepareArticul( $query_insert ){ |
147 | + //CustomVarDamp::dumpAndDie($query_insert); | ||
148 | + return $query_insert; | ||
149 | + } | ||
104 | } | 150 | } |
backend/models/UploadFileParsingForm.php
1 | <?php | 1 | <?php |
2 | namespace backend\models; | 2 | namespace backend\models; |
3 | 3 | ||
4 | +use yii\base\ErrorException; | ||
4 | use yii\base\Model; | 5 | use yii\base\Model; |
5 | use yii\web\UploadedFile; | 6 | use yii\web\UploadedFile; |
6 | use Yii; | 7 | use Yii; |
@@ -73,8 +74,11 @@ class UploadFileParsingForm extends Model | @@ -73,8 +74,11 @@ class UploadFileParsingForm extends Model | ||
73 | 74 | ||
74 | $data = Yii::$app->multiparser->parse( $this->file_path, $options ); | 75 | $data = Yii::$app->multiparser->parse( $this->file_path, $options ); |
75 | if( !is_array( $data ) ){ | 76 | if( !is_array( $data ) ){ |
76 | - $data = ['No results']; | 77 | + throw new ErrorException("Ошибка чтения из файла прайса {$this->file_path}"); |
77 | } | 78 | } |
79 | + // файл больше не нужен - данные прочитаны и сохранены в кеш | ||
80 | + if( file_exists($this->file_path) ) | ||
81 | + unlink($this->file_path); | ||
78 | 82 | ||
79 | return $data; | 83 | return $data; |
80 | } | 84 | } |
common/components/PriceWriter.php
@@ -14,22 +14,45 @@ use backend\models\ImportersFiles; | @@ -14,22 +14,45 @@ use backend\models\ImportersFiles; | ||
14 | use backend\models\Importers; | 14 | use backend\models\Importers; |
15 | use backend\models\Details; | 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 | public $mode; | 28 | public $mode; |
29 | + | ||
30 | + /** | ||
31 | + * @var - массив с настройками записи | ||
32 | + */ | ||
19 | public $configuration; | 33 | public $configuration; |
34 | + | ||
35 | + /** | ||
36 | + * @var - массив с данными которые нужно записать | ||
37 | + */ | ||
20 | public $data; | 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 | // 1. запишем дату старта в таблицу файлов поставщика (ImportersFiles) | 47 | // 1. запишем дату старта в таблицу файлов поставщика (ImportersFiles) |
25 | // id загруженного файла получим из конфигурации | 48 | // id загруженного файла получим из конфигурации |
26 | - $files_model = ImportersFiles::findOne( $this->configuration['record_id'] ); | 49 | + $files_model = ImportersFiles::findOne($this->configuration['record_id']); |
27 | 50 | ||
28 | $update_date = date('Y-m-d H:i:s'); | 51 | $update_date = date('Y-m-d H:i:s'); |
29 | $files_model->time_start = $update_date; | 52 | $files_model->time_start = $update_date; |
30 | // запишем дату начала загрузки | 53 | // запишем дату начала загрузки |
31 | if (!$files_model->save()) { | 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 | // 2. запишем полученные данные в таблицу товаров (Details) | 58 | // 2. запишем полученные данные в таблицу товаров (Details) |
@@ -43,7 +66,7 @@ class PriceWriter { | @@ -43,7 +66,7 @@ class PriceWriter { | ||
43 | $row['BOX'] = \Yii::$app->multiparser->convertToInteger($row['BOX']); | 66 | $row['BOX'] = \Yii::$app->multiparser->convertToInteger($row['BOX']); |
44 | // присвоим полный артикул | 67 | // присвоим полный артикул |
45 | $row['FULL_ARTICLE'] = $row['ARTICLE']; | 68 | $row['FULL_ARTICLE'] = $row['ARTICLE']; |
46 | - if(isset($row['ADD_BOX'])) | 69 | + if (isset($row['ADD_BOX'])) |
47 | $row['ADD_BOX'] = \Yii::$app->multiparser->convertToInteger($row['ADD_BOX']); | 70 | $row['ADD_BOX'] = \Yii::$app->multiparser->convertToInteger($row['ADD_BOX']); |
48 | 71 | ||
49 | // проверим все ли обязательные колонки были указаны пользователем | 72 | // проверим все ли обязательные колонки были указаны пользователем |
@@ -55,31 +78,35 @@ class PriceWriter { | @@ -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 | return true; | 112 | return true; |
common/components/parsers/CustomConverter.php
1 | <?php | 1 | <?php |
2 | namespace common\components\parsers; | 2 | namespace common\components\parsers; |
3 | + | ||
3 | use common\components\CustomVarDamp; | 4 | use common\components\CustomVarDamp; |
4 | use yii\multiparser\Converter; | 5 | use yii\multiparser\Converter; |
5 | use backend\models\Details; | 6 | use backend\models\Details; |
7 | +use backend\models\ImportersPrefix; | ||
6 | 8 | ||
7 | -class CustomConverter extends Converter { | 9 | +class CustomConverter extends Converter |
10 | +{ | ||
8 | 11 | ||
9 | /** | 12 | /** |
10 | * @param $value_arr - двумерный массив значений, которому нужно присвоить ключи | 13 | * @param $value_arr - двумерный массив значений, которому нужно присвоить ключи |
@@ -13,38 +16,43 @@ class CustomConverter extends Converter { | @@ -13,38 +16,43 @@ class CustomConverter extends Converter { | ||
13 | */ | 16 | */ |
14 | public static $sign; | 17 | public static $sign; |
15 | public static $multiplier; | 18 | public static $multiplier; |
19 | + public static $importer_id; | ||
16 | 20 | ||
17 | - public static function convertToAssocArray ( array $value_arr, array $key_array, $key_prefix = '' ) | 21 | + public static function convertToAssocArray(array $value_arr, array $key_array, $key_prefix = '') |
18 | { | 22 | { |
19 | // очистка служебного префикса в массиве заголовков | 23 | // очистка служебного префикса в массиве заголовков |
20 | if ($key_prefix) { | 24 | if ($key_prefix) { |
21 | // @todo оптимизировать - два переворота массива - избыточно | 25 | // @todo оптимизировать - два переворота массива - избыточно |
22 | - $key_array = array_flip( $key_array ); | 26 | + $key_array = array_flip($key_array); |
23 | 27 | ||
24 | - array_walk( $key_array, function ( &$value, $key, $key_prefix ){ $value = str_replace( $key_prefix, '',$value ); }, $key_prefix ); | 28 | + array_walk($key_array, function (&$value, $key, $key_prefix) { |
29 | + $value = str_replace($key_prefix, '', $value); | ||
30 | + }, $key_prefix); | ||
25 | 31 | ||
26 | - $key_array = array_flip( $key_array ); | 32 | + $key_array = array_flip($key_array); |
27 | //уберем пустые элементы | 33 | //уберем пустые элементы |
28 | - $key_array = array_filter($key_array, function ($value){ return $value !==''; }); | 34 | + $key_array = array_filter($key_array, function ($value) { |
35 | + return $value !== ''; | ||
36 | + }); | ||
29 | } | 37 | } |
30 | 38 | ||
31 | - array_walk( $value_arr, | ||
32 | - function ( &$value, $key, $key_array ) { | 39 | + array_walk($value_arr, |
40 | + function (&$value, $key, $key_array) { | ||
33 | $res = $value; | 41 | $res = $value; |
34 | foreach ($res as $sub_key => $sub_value) { | 42 | foreach ($res as $sub_key => $sub_value) { |
35 | if (isset($key_array[$sub_key])) { | 43 | if (isset($key_array[$sub_key])) { |
36 | // если такой ключ в базовом массиве (массиве ключей) есть, то заменим новым, иначе просто удалим | 44 | // если такой ключ в базовом массиве (массиве ключей) есть, то заменим новым, иначе просто удалим |
37 | $new_key = $key_array[$sub_key]; | 45 | $new_key = $key_array[$sub_key]; |
38 | - if( !array_key_exists( $new_key , $res ) ){ | ||
39 | - $res[ $new_key ] = $value[$sub_key]; | 46 | + if (!array_key_exists($new_key, $res)) { |
47 | + $res[$new_key] = $value[$sub_key]; | ||
40 | } | 48 | } |
41 | } | 49 | } |
42 | - unset( $res[$sub_key] ); | 50 | + unset($res[$sub_key]); |
43 | $value = $res; | 51 | $value = $res; |
44 | } | 52 | } |
45 | 53 | ||
46 | }, | 54 | }, |
47 | - $key_array); | 55 | + $key_array); |
48 | 56 | ||
49 | return $value_arr; | 57 | return $value_arr; |
50 | } | 58 | } |
@@ -54,7 +62,7 @@ class CustomConverter extends Converter { | @@ -54,7 +62,7 @@ class CustomConverter extends Converter { | ||
54 | * @param $add_array - массив с колонками (ключи) и значениями колонок | 62 | * @param $add_array - массив с колонками (ключи) и значениями колонок |
55 | * @return mixed | 63 | * @return mixed |
56 | */ | 64 | */ |
57 | - public function addColumns ( array $value_arr , array $add_array ) | 65 | + public function addColumns(array $value_arr, array $add_array) |
58 | { | 66 | { |
59 | $i = 0; | 67 | $i = 0; |
60 | while ($i < count($value_arr)) { | 68 | while ($i < count($value_arr)) { |
@@ -66,7 +74,7 @@ class CustomConverter extends Converter { | @@ -66,7 +74,7 @@ class CustomConverter extends Converter { | ||
66 | return $value_arr; | 74 | return $value_arr; |
67 | } | 75 | } |
68 | 76 | ||
69 | - public static function convertToDetails ( array $row ) | 77 | + public static function convertToDetails(array $row) |
70 | { | 78 | { |
71 | // присвоим полный артикул | 79 | // присвоим полный артикул |
72 | $row['FULL_ARTICLE'] = $row['ARTICLE']; | 80 | $row['FULL_ARTICLE'] = $row['ARTICLE']; |
@@ -75,19 +83,19 @@ class CustomConverter extends Converter { | @@ -75,19 +83,19 @@ class CustomConverter extends Converter { | ||
75 | // проверим все ли обязательные колонки были указаны пользователем | 83 | // проверим все ли обязательные колонки были указаны пользователем |
76 | $details_model->load(['Details' => $row]); | 84 | $details_model->load(['Details' => $row]); |
77 | 85 | ||
78 | - if (!$details_model->validate()){ | 86 | + if (!$details_model->validate()) { |
79 | $errors = ''; | 87 | $errors = ''; |
80 | - foreach ( $details_model->errors as $key => $arr_errors ) { | ||
81 | - $errors .= "Аттрибут $key - " . implode( ' , ', $arr_errors ); | 88 | + foreach ($details_model->errors as $key => $arr_errors) { |
89 | + $errors .= "Аттрибут $key - " . implode(' , ', $arr_errors); | ||
82 | } | 90 | } |
83 | - throw new \ErrorException( $errors ); | 91 | + throw new \ErrorException($errors); |
84 | } | 92 | } |
85 | return $row; | 93 | return $row; |
86 | } | 94 | } |
87 | 95 | ||
88 | - public function ConvertToMultiply ( array $row ) | 96 | + public function ConvertToMultiply(array $row) |
89 | { | 97 | { |
90 | - $PRICE = $row[ 'PRICE' ]; | 98 | + $PRICE = $row['PRICE']; |
91 | $sign = self::$sign; | 99 | $sign = self::$sign; |
92 | $multiplier = self::$multiplier; | 100 | $multiplier = self::$multiplier; |
93 | //CustomVarDamp::dumpAndDie(self); | 101 | //CustomVarDamp::dumpAndDie(self); |
@@ -96,28 +104,68 @@ class CustomConverter extends Converter { | @@ -96,28 +104,68 @@ class CustomConverter extends Converter { | ||
96 | if ($multiplier > 0) { | 104 | if ($multiplier > 0) { |
97 | $PRICE += $multiplier; | 105 | $PRICE += $multiplier; |
98 | } | 106 | } |
99 | - } | ||
100 | - else if ($sign == '-') { | 107 | + } else if ($sign == '-') { |
101 | if ($multiplier > 0) { | 108 | if ($multiplier > 0) { |
102 | $PRICE -= $multiplier; | 109 | $PRICE -= $multiplier; |
103 | } | 110 | } |
104 | - } | ||
105 | - else if ($sign == '*') { | 111 | + } else if ($sign == '*') { |
106 | if ($multiplier > 0) { | 112 | if ($multiplier > 0) { |
107 | $PRICE *= $multiplier; | 113 | $PRICE *= $multiplier; |
108 | } | 114 | } |
109 | - } | ||
110 | - else if ($sign == '/') { | 115 | + } else if ($sign == '/') { |
111 | if ($multiplier > 0) { | 116 | if ($multiplier > 0) { |
112 | $PRICE /= $multiplier; | 117 | $PRICE /= $multiplier; |
113 | } | 118 | } |
114 | } | 119 | } |
115 | } | 120 | } |
116 | 121 | ||
117 | - $row[ 'PRICE' ] = $PRICE; | 122 | + $row['PRICE'] = $PRICE; |
123 | + | ||
124 | + return $row; | ||
125 | + | ||
126 | + } | ||
127 | + | ||
128 | + public static function convertToArticul(array $row) | ||
129 | + { | ||
130 | + if (isset($row['ARTICLE']) && isset($row['BRAND']) && isset(self::$importer_id)) { | ||
131 | + | ||
132 | + // 1. Уберем префикс который разделен пробелом (если он есть) | ||
133 | + $words = explode(" ", $row['ARTICLE']); | ||
134 | + if (count($words) > 1) { | ||
135 | + array_shift($words); | ||
136 | + $row['ARTICLE'] = implode(" ", $words); | ||
137 | + } | ||
138 | + | ||
139 | + // 2. Уберем брендовый префикс (если он есть) | ||
140 | + $prefix = ''; | ||
141 | + // запрос закешируем | ||
142 | + $prefix = ImportersPrefix::getDb()->cache( function ($db, $configuration, $row ) { | ||
143 | + return ImportersPrefix::find()->where([ 'importer_id' => self::$importer_id, | ||
144 | + 'brand' => $row['BRAND'] ])->one(); | ||
145 | + }); | ||
118 | 146 | ||
147 | + if ($prefix) { | ||
148 | + $row['BRAND'] = str_replace($prefix, "", $row['BRAND']); | ||
149 | + } | ||
150 | + } | ||
119 | return $row; | 151 | return $row; |
152 | + } | ||
153 | + | ||
154 | + public static function convertToBrand($value) | ||
155 | + { | ||
156 | + $res = $value; | ||
157 | + $res = trim(strtoupper($res)); | ||
158 | + $res = str_replace("Ä", "A", str_replace("Ö", "O", str_replace("Ü", "U", str_replace("Ë", "E", str_replace("Ò", "O", $res))))); | ||
159 | + $res = str_replace(array('@', '#', '~', '"', "'", "?", "!"), '', $res); | ||
160 | + | ||
161 | + return $res; | ||
162 | + } | ||
163 | + | ||
164 | + public static function convertToString($value) | ||
165 | + { | ||
166 | + $value = parent::convertToString($value); | ||
120 | 167 | ||
168 | + return str_replace(array('!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', '=', '-', '~', '`', '"', "'", ' ', '№', '%', ';', ':', '[', ']', '{', '}', '*', '?', '/', '\'', '|', '.', ',', '<', '>', '\\'), '', $value); | ||
121 | } | 169 | } |
122 | 170 | ||
123 | 171 |
common/components/parsers/CustomCsvParser.php
@@ -16,7 +16,7 @@ use yii\base\ErrorException; | @@ -16,7 +16,7 @@ use yii\base\ErrorException; | ||
16 | 16 | ||
17 | class CustomCsvParser extends \yii\multiparser\CsvParser { | 17 | class CustomCsvParser extends \yii\multiparser\CsvParser { |
18 | 18 | ||
19 | - public $last_line = 10; | 19 | + public $last_line = 100; |
20 | //public $hasHeaderRow = true; | 20 | //public $hasHeaderRow = true; |
21 | // public $keys = ['first','second', 'third', 'forth', 'fifth']; | 21 | // public $keys = ['first','second', 'third', 'forth', 'fifth']; |
22 | public function setupConverter() | 22 | public function setupConverter() |
common/components/parsers/config.php
@@ -17,9 +17,11 @@ | @@ -17,9 +17,11 @@ | ||
17 | 'hasKey' => 1, | 17 | 'hasKey' => 1, |
18 | 'configuration' => ["string" => 'DESCR', | 18 | 'configuration' => ["string" => 'DESCR', |
19 | "float" => 'PRICE', | 19 | "float" => 'PRICE', |
20 | + "brand" => 'BRAND', | ||
20 | "integer" => ['BOX','ADD_BOX'], | 21 | "integer" => ['BOX','ADD_BOX'], |
21 | "multiply" => [], | 22 | "multiply" => [], |
22 | - "details" => [] // @todo сделать отдельно конфигурирование валидации | 23 | + "details" => [], |
24 | + "articul" => [] | ||
23 | 25 | ||
24 | ] | 26 | ] |
25 | ],], | 27 | ],], |
console/controllers/ParserController.php
@@ -32,8 +32,7 @@ class ParserController extends Controller | @@ -32,8 +32,7 @@ class ParserController extends Controller | ||
32 | 'importer_id' => $importer_id, | 32 | 'importer_id' => $importer_id, |
33 | 'parser_config' => ['keys' => $keys, | 33 | 'parser_config' => ['keys' => $keys, |
34 | 'converter_conf' => | 34 | 'converter_conf' => |
35 | - ['sign' => $sign, | ||
36 | - 'multiplier' => $multiplier], | 35 | + [ 'sign' => $sign, 'multiplier' => $multiplier, 'importer_id' => $importer_id ], |
37 | 'mode' => 'console'] | 36 | 'mode' => 'console'] |
38 | ]; | 37 | ]; |
39 | if ($this->parseFileConsole($file_path, $config)) { | 38 | if ($this->parseFileConsole($file_path, $config)) { |
console/migrations/m151013_062829_deletePrefixFunction.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +use yii\db\Schema; | ||
4 | +use yii\db\Migration; | ||
5 | + | ||
6 | +/** | ||
7 | + * Class m151013_062829_deletePrefixFunction | ||
8 | + * добавляем две функции - одна ищет префикс по поставщику и бренду, | ||
9 | + * другая удаляет найденный префикс из переданного артикула | ||
10 | + */ | ||
11 | +class m151013_062829_deletePrefixFunction extends Migration | ||
12 | +{ | ||
13 | + public function safeUp() | ||
14 | + { | ||
15 | + $find_prefix = <<< SQL | ||
16 | + CREATE FUNCTION FindPrefix(p_importer_id int, p_brand VARCHAR(100)) RETURNS VARCHAR(50) | ||
17 | + BEGIN | ||
18 | + DECLARE _prefix varchar(10); | ||
19 | + | ||
20 | + select prefix into _prefix From w_importers_prefix where importer_id = p_importer_id and brand = p_brand COLLATE utf8_general_ci; | ||
21 | + | ||
22 | + RETURN (_prefix); | ||
23 | + END | ||
24 | +SQL; | ||
25 | + | ||
26 | + $delete_prefix = <<< SQL | ||
27 | + CREATE FUNCTION DeletePrefix(p_articul VARCHAR(150), p_importer_id int, p_brand VARCHAR(100)) RETURNS VARCHAR(150) | ||
28 | + BEGIN | ||
29 | + DECLARE _articul varchar(10); | ||
30 | + | ||
31 | + select substring(p_articul, LENGTH( FindPrefix( p_importer_id, p_brand ) ) + 1 ) into _articul; | ||
32 | + RETURN (_articul); | ||
33 | + END | ||
34 | +SQL; | ||
35 | + | ||
36 | + $this->execute($find_prefix); | ||
37 | + $this->execute($delete_prefix); | ||
38 | + | ||
39 | + } | ||
40 | + | ||
41 | + public function safedown() | ||
42 | + { | ||
43 | + | ||
44 | + $find_prefix = <<< SQL | ||
45 | + drop FUNCTION FindPrefix; | ||
46 | +SQL; | ||
47 | + | ||
48 | + $delete_prefix = <<< SQL | ||
49 | + drop FUNCTION DeletePrefix; | ||
50 | +SQL; | ||
51 | + | ||
52 | + $this->execute($find_prefix); | ||
53 | + $this->execute($delete_prefix); | ||
54 | + | ||
55 | + | ||
56 | + } | ||
57 | + | ||
58 | + | ||
59 | +} |