Commit ef41533dc156d173d72742c5623e7565e7bcacc1

Authored by Mihail
1 parent 2d22aad2

temp commit - work with console Details validation

backend/.gitignore
1 1 /temp
2   -/uploads
3 2 \ No newline at end of file
  3 +/uploads
  4 +/runtime
4 5 \ No newline at end of file
... ...
backend/components/parsers/CustomConverter.php
1 1 <?php
2 2 namespace backend\components\parsers;
  3 +use common\components\CustomVarDamp;
3 4 use yii\multiparser\Converter;
  5 +use backend\models\Details;
4 6  
5 7 class CustomConverter extends Converter {
6 8  
... ... @@ -60,4 +62,26 @@ class CustomConverter extends Converter {
60 62 }
61 63 return $value_arr;
62 64 }
  65 +
  66 + public static function convertToDetails ( array $row )
  67 + {
  68 + // присвоим полный артикул
  69 + $row['FULL_ARTICLE'] = $row['ARTICLE'];
  70 +
  71 + $details_model = new Details();
  72 + // проверим все ли обязательные колонки были указаны пользователем
  73 + $details_model->load(['Details' => $row]);
  74 +
  75 + if (!$details_model->validate()){
  76 + $errors = '';
  77 + foreach ( $details_model->errors as $key => $arr_errors ) {
  78 + $errors .= "Аттрибут $key - " . implode( ' , ', $arr_errors );
  79 + }
  80 + throw new \ErrorException( $errors );
  81 + }
  82 + return $row;
  83 + }
  84 +
  85 +
  86 +
63 87 }
64 88 \ No newline at end of file
... ...
backend/components/parsers/CustomCsvParser.php
... ... @@ -10,6 +10,7 @@ namespace backend\components\parsers;
10 10  
11 11  
12 12 use common\components\CustomVarDamp;
  13 +use yii\base\ErrorException;
13 14  
14 15 class CustomCsvParser extends \yii\multiparser\CsvParser {
15 16  
... ... @@ -35,7 +36,8 @@ class CustomCsvParser extends \yii\multiparser\CsvParser {
35 36 */
36 37 protected function convert($arr)
37 38 {
38   - $arr = \Yii::$app->multiparser->convertByConfiguration($arr, $this->converter_conf);
  39 + $arr = \Yii::$app->multiparser->convertByConfiguration($arr, $this->converter_conf);
  40 +
39 41 return $arr;
40 42  
41 43 }
... ...
backend/components/parsers/config.php
... ... @@ -26,7 +26,8 @@
26 26 'hasKey' => 1,
27 27 'configuration' => ["string" => 'DESCR',
28 28 "float" => 'PRICE',
29   - "integer" => ['BOX','ADD_BOX']
  29 + "integer" => ['BOX','ADD_BOX'],
  30 + "details" => [], // @todo сделать отдельно конфигурирование валидации
30 31 ]
31 32 ],],
32 33  
... ...
backend/controllers/ParserController.php
... ... @@ -95,7 +95,7 @@ class ParserController extends BaseController
95 95 $file_name = $model->record_id . '.' . $model->file->extension;
96 96  
97 97 if ($model->mode) {
98   - $model->file_path = Yii::getAlias('@auto_upload') . '/' . $file_name;
  98 + $model->file_path = Yii::getAlias('@temp_upload') . '/' . $file_name;
99 99 } else {
100 100 $model->file_path = Yii::getAlias('@manual_upload') . '/' . $file_name;
101 101 }
... ... @@ -105,6 +105,7 @@ class ParserController extends BaseController
105 105 // для авто загрузки, обработка завершена
106 106 if ($model->mode) {
107 107 $model->success = true;
  108 +
108 109 return $this->render('index', ['model' => $model]);
109 110 }
110 111  
... ... @@ -218,13 +219,15 @@ class ParserController extends BaseController
218 219  
219 220 public function actionServerFiles ()
220 221 {
221   - $arr_id_files = [];
  222 +
  223 + $arr_id_files = [];
  224 +
222 225 // получим список файлов которые ожидают к загрузке
223   - foreach (glob(Yii::getAlias('@auto_upload') . '/*') as $server_file) {
  226 + foreach ( glob(Yii::getAlias('@temp_upload') . '/*.csv') as $server_file ) {
224 227 $file_id = basename($server_file,".csv");
225 228 $arr_id_files[] = (int) $file_id;
226 229 }
227   - Yii::$app->cache->set( 'files_to_parse',json_encode( $arr_id_files ) );
  230 + // Yii::$app->cache->set( 'files_to_parse',json_encode( $arr_id_files ) );
228 231 $query = ImportersFiles::find()->where(['in', 'id', $arr_id_files])->orderBy(['upload_time' => SORT_DESC]);
229 232  
230 233 $provider = new ActiveDataProvider([
... ... @@ -247,17 +250,17 @@ class ParserController extends BaseController
247 250 $id = Yii::$app->request->post()['id'];
248 251 try {
249 252 $files_model->delete($id);
250   - unlink(Yii::getAlias('@auto_upload') . '/' . $id . '.csv' );
  253 + unlink(Yii::getAlias('@temp_upload') . '/' . $id . '.csv' );
251 254  
252 255 // удалим этот id и из кэша
253   - if( $arr_id_files = Yii::$app->cache->get( 'files_to_parse' ) ){
254   - $arr_id_files = json_decode($arr_id_files);
255   - if (isset( $arr_id_files[$id] ) ) {
256   - unset( $arr_id_files[$id] );
257   - // положем уже обновленный массив
258   - Yii::$app->cache->set( 'files_to_parse',json_encode( $arr_id_files ) );
259   - }
260   - }
  256 +// if( $arr_id_files = Yii::$app->cache->get( 'files_to_parse' ) ){
  257 +// $arr_id_files = json_decode($arr_id_files);
  258 +// if (isset( $arr_id_files[$id] ) ) {
  259 +// unset( $arr_id_files[$id] );
  260 +// // положем уже обновленный массив
  261 +// Yii::$app->cache->set( 'files_to_parse',json_encode( $arr_id_files ) );
  262 +// }
  263 +// }
261 264 // сообщим скрипту что все ОК
262 265 echo 1;
263 266 } catch (ErrorException $e) {
... ... @@ -271,63 +274,76 @@ class ParserController extends BaseController
271 274  
272 275 }
273 276  
  277 + public function actionLaunchCroneUploads ()
  278 + {
  279 +
274 280  
  281 + foreach (glob(Yii::getAlias('@temp_upload') . '/*.csv') as $server_file) {
275 282  
  283 + $file_name = basename($server_file,".csv");
  284 + rename( $server_file, Yii::getAlias('@auto_upload') . '/' . $file_name . '.csv');
  285 +
  286 + }
  287 +
  288 + //$this->redirect('server-files');
  289 + $this->actionParseCsv();
  290 + }
276 291  
277   - public function actionParse ()
  292 + public function actionParseCsv ()
278 293 {
279   -// $comand = "/usr/bin/php -f ".Yii::getAlias('@console') ."/Controllers/ParserController.php";
280   -// exec($comand);
281   -
282   - if( $arr_id_files = Yii::$app->cache->get( 'files_to_parse' ) ) {
283   - $arr_id_files = json_decode( $arr_id_files );
284   - foreach ( $arr_id_files as $file_name ) {
285   -
286   - $importer_id = ImportersFiles::findOne(['id' => $file_name])->importer_id;
287   - $keys = Importers::findOne( ['id' => $importer_id] )->keys;
288   -
289   - $file_path = Yii::getAlias('@auto_upload') . '/' . $file_name . '.csv';
290   - $config = ['record_id' => $file_name,
291   - 'importer_id' => $importer_id,
292   - 'parser_config' => ['keys' => $keys,
293   - 'mode' => 'console']
294   - ];
295   - if( $this->parseFileConsole( $file_path, $config ) ){
296   - unlink( $file_path );
297   - if (isset( $arr_id_files[$file_path] ) ) {
298   - unset($arr_id_files[$file_path]);
299   - }
300   - } else {
301   - // Yii::$app->log->
302   - // не дошли до конца по этому остатки вернем в кеш
303   - Yii::$app->cache->set( 'files_to_parse',json_encode( $arr_id_files ) );
  294 + // Console::output('1');
  295 + foreach (glob( \Yii::getAlias('@auto_upload') . '/*.csv' ) as $file_path) {
  296 + $file_name = basename( $file_path,".csv" );
  297 + // Console::output('2');
  298 + $importer_id = ImportersFiles::findOne(['id' => $file_name])->importer_id;
  299 + $keys = Importers::findOne( ['id' => $importer_id] )->keys;
  300 +
  301 + $config = ['record_id' => $file_name,
  302 + 'importer_id' => $importer_id,
  303 + 'parser_config' => ['keys' => $keys,
  304 + 'mode' => 'console']
  305 + ];
  306 + // Console::output('3');
  307 + if( $this->parseFileConsole( $file_path, $config ) ){
  308 + // Console::output('4');
  309 + unlink( $file_path );
  310 + if (isset( $arr_id_files[$file_path] ) ) {
  311 + unset( $arr_id_files[$file_path] );
304 312 }
305 313 }
306   - if ( !count( $arr_id_files ) ) {
307   - Yii::$app->cache->delete( 'files_to_parse' );
308   - }
309 314 }
310 315  
311   - return $this->redirect('serverFiles');
  316 +
  317 + //return $this->redirect('serverFiles');
312 318 }
313 319  
  320 +
314 321 protected function parseFileConsole( $file_path, $configuration ){
  322 +
  323 + if( !file_exists( $file_path ) )
  324 + throw new ErrorException("$file_path - файл не найден!");
  325 +
315 326 $parser_config = [];
316 327 if ( isset( $configuration['parser_config'] ) ) {
317 328 $parser_config = $configuration['parser_config'];
318 329 }
  330 + try {
  331 + $data = \Yii::$app->multiparser->parse( $file_path, $parser_config );
  332 + } catch (ErrorException $e) {
  333 + throw $e;
  334 + }
319 335  
320   - $data = Yii::$app->multiparser->parse( $file_path, $parser_config );
321   - CustomVarDamp::dumpAndDie($data);
  336 + // CustomVarDamp::dumpAndDie($data);
322 337 $writer = new PriceWriter();
323 338 $writer->configuration = $configuration;
324 339 $writer->data = $data;
325 340 $writer->mode = 1; //console-режим
326 341 if ( $writer->writeDataToDB() ){
327   - //Console::output('It is working');
  342 + // Console::output('It is working');
328 343 return true;
329 344 }
330 345  
331 346 return false;
332 347 }
  348 +
333 349 }
... ...
backend/models/Details.php
... ... @@ -41,6 +41,7 @@ class Details extends BaseActiveRecord
41 41 [[ 'BRAND', 'ARTICLE', 'PRICE', 'DESCR', 'BOX'], 'required'],
42 42 // [['IMPORT_ID', 'BOX', 'ADD_BOX'], 'integer'],
43 43 [['PRICE'], 'number'],
  44 + [['BOX'], 'integer'],
44 45 [['timestamp'], 'safe'],
45 46 [['BRAND', 'ARTICLE'], 'string', 'max' => 100],
46 47 [['FULL_ARTICLE'], 'string', 'max' => 150],
... ... @@ -97,6 +98,7 @@ class Details extends BaseActiveRecord
97 98 $res = Yii::$app->db->createCommand($query)->execute();
98 99  
99 100 }
100   -
101 101 }
  102 +
  103 +
102 104 }
... ...
backend/views/parser/server-files.php
... ... @@ -45,7 +45,7 @@ Pjax::begin([&#39;id&#39; =&gt; &#39;server_files_grid&#39;]);
45 45  
46 46 ]] );?>
47 47  
48   - <?= Html::a('Загрузить файлы', ['parse'],['class' => 'btn btn-success']) ?>
  48 + <?= Html::a('Запустить загрузку файлов', ['launch-crone-uploads'],['class' => 'btn btn-success']) ?>
49 49  
50 50 </div>
51 51 <?php
... ...
common/components/PriceWriter.php
... ... @@ -18,7 +18,6 @@ class PriceWriter {
18 18 public $mode;
19 19 public $configuration;
20 20 public $data;
21   - // public $errors = [];
22 21  
23 22 public function writeDataToDB ()
24 23 {
... ... @@ -26,40 +25,37 @@ class PriceWriter {
26 25 // id загруженного файла получим из конфигурации
27 26 $files_model = ImportersFiles::findOne( $this->configuration['record_id'] );
28 27  
29   - //$files_model->load(['ImportersFiles' => $this->configuration->toArray()]);
30 28 $update_date = date('Y-m-d H:i:s');
31 29 $files_model->time_start = $update_date;
32 30 // запишем дату начала загрузки
33 31 if (!$files_model->save()) {
34   - $this->errors[] = implode( ', ', $files_model->getErrors());
35   - return false;
36   - //CustomVarDamp::dumpAndDie($files_model->implode ( ', ', getErrors())());
  32 + throw new \ErrorException(implode( ', ', $files_model->getErrors()));
37 33 }
38 34  
39   -
40 35 // 2. запишем полученные данные в таблицу товаров (Details)
41 36 $details_model = new Details();
42   - // преобразуем числовые значения
43   - foreach ($this->data as &$row) {
44   - $row['PRICE'] = \Yii::$app->multiparser->convertToFloat($row['PRICE']);
45   - $row['BOX'] = \Yii::$app->multiparser->convertToInteger($row['BOX']);
46   - // присвоим полный артикул
47   - $row['FULL_ARTICLE'] = $row['ARTICLE'];
48   - if(isset($row['ADD_BOX']))
49   - $row['ADD_BOX'] = \Yii::$app->multiparser->convertToInteger($row['ADD_BOX']);
50   -
51   - // проверим все ли обязательные колонки были указаны пользователем
52   - $details_model->load(['Details' => $row]);
53   -
54   - if (!$details_model->validate())
55   - break;
56   - }
57 37  
58   - if ($details_model->hasErrors()) {
59   - //@todo предоставить более детальную информацию об ошибке
60   - throw new \ErrorException('Ошибка записи товаров');
  38 + // только для ручной загрузки, в авто режиме все делает конвертер при первом же проходе (в процессе парсинга)
  39 + if ($this->mode = 0) {
  40 + // преобразуем числовые значения
  41 + foreach ($this->data as &$row) {
  42 + $row['PRICE'] = \Yii::$app->multiparser->convertToFloat($row['PRICE']);
  43 + $row['BOX'] = \Yii::$app->multiparser->convertToInteger($row['BOX']);
  44 + // присвоим полный артикул
  45 + $row['FULL_ARTICLE'] = $row['ARTICLE'];
  46 + if(isset($row['ADD_BOX']))
  47 + $row['ADD_BOX'] = \Yii::$app->multiparser->convertToInteger($row['ADD_BOX']);
  48 +
  49 + // проверим все ли обязательные колонки были указаны пользователем
  50 + $details_model->load(['Details' => $row]);
  51 +
  52 + if (!$details_model->validate())
  53 + //@todo предоставить более детальную информацию об ошибке
  54 + throw new \ErrorException('Ошибка записи товаров');
  55 +
  56 + }
61 57 }
62   - else{
  58 +
63 59 // дополним данные значением импортера и даты обновления цены
64 60 $this->data = \Yii::$app->multiparser->addColumns($this->data, ['IMPORT_ID' => $this->configuration['importer_id'], 'timestamp' => $update_date]);
65 61  
... ... @@ -70,13 +66,8 @@ class PriceWriter {
70 66  
71 67 // 3. зафиксируем дату конца загрузки в файлах поставщика
72 68  
73   - $files_model->time_end = date('Y-m-d H:i:s');
74   - // CustomVarDamp::dumpAndDie($files_model);
75 69 if (!$files_model->save()) {
76 70 throw new \ErrorException(implode( ', ', $files_model->getErrors()));
77   -// $this->errors[] = $files_model->implode ( ', ', getErrors());
78   -// return false;
79   - // CustomVarDamp::dumpAndDie($files_model->implode ( ', ', getErrors())());
80 71 }
81 72  
82 73 // 4. зафиксируем дату загрузки в таблице поставщиков
... ... @@ -84,18 +75,12 @@ class PriceWriter {
84 75 $imp_model->price_date_update = $update_date;
85 76  
86 77 if (!$imp_model->save()) {
87   -// $this->errors[] = $imp_model->implode ( ', ', getErrors())();
88   -// return false;
89 78 throw new \ErrorException(implode( ', ', $imp_model->getErrors()));
90   - // CustomVarDamp::dumpAndDie($imp_model->implode ( ', ', getErrors())());
91 79 }
92   -
93   -
94 80 } catch (ErrorException $e) {
95   - //CustomVarDamp::dump($e->getMessage());
96 81 throw new \ErrorException( $e->getMessage() );
97 82 }
98   - }
  83 +
99 84  
100 85  
101 86 return true;
... ...
common/config/bootstrap.php
... ... @@ -5,3 +5,4 @@ Yii::setAlias(&#39;backend&#39;, dirname(dirname(__DIR__)) . &#39;/backend&#39;);
5 5 Yii::setAlias('console', dirname(dirname(__DIR__)) . '/console');
6 6 Yii::setAlias('auto_upload', dirname(dirname(__DIR__)) . '/backend/uploads/auto');
7 7 Yii::setAlias('manual_upload', dirname(dirname(__DIR__)) . '/backend/uploads/manual');
  8 +Yii::setAlias('temp_upload', dirname(dirname(__DIR__)) . '/backend/uploads/temp');
... ...
console/config/main.php
... ... @@ -20,12 +20,14 @@ return [
20 20 ],
21 21 [
22 22 'class' => 'yii\log\FileTarget',
23   - 'logFile' => 'C:\xampp\htdocs\ital\console\runtime\logs\parser.log',
  23 + 'logFile' => __DIR__ . '/../runtime/logs/parser.log',
24 24 'levels' => ['info', 'error'],
25   - // 'categories' => ['parser'],
  25 + 'categories' => ['yii\base\ErrorException:*', 'parser'],
  26 + 'logVars' => [],
26 27 ],
27 28 ],
28 29 ],
  30 + ],
29 31 'params' => $params,
30   -]
31 32 ];
  33 +
... ...
console/controllers/ParserController.php
... ... @@ -5,46 +5,54 @@ use yii\console\Controller;
5 5 use yii\helpers\Console;
6 6 use common\components\PriceWriter;
7 7 use backend\models\ImportersFiles;
  8 +use backend\models\Importers;
  9 +use yii\base\ErrorException;
8 10  
9 11 class ParserController extends Controller{
10   - public function actionParseCSV ()
  12 +
  13 + public function actionParseCsv ()
11 14 {
12   - \common\components\CustomVarDamp::dumpAndDie(45);
13   - if( $arr_id_files = Yii::$app->cache->get( 'files_to_parse' ) ) {
14   - $arr_id_files = json_decode( $arr_id_files );
15   - foreach ( $arr_id_files as $file_name ) {
16   - $file_path = Yii::getAlias('@auto_upload') . '/' . $file_name . '.csv';
  15 + Console::output('1');
  16 + foreach (glob( \Yii::getAlias('@auto_upload') . '/*.csv' ) as $file_path) {
  17 + $file_name = basename($file_path,".csv");
  18 + Console::output('2');
  19 + $importer_id = ImportersFiles::findOne(['id' => $file_name])->importer_id;
  20 + $keys = Importers::findOne( ['id' => $importer_id] )->keys;
  21 +
17 22 $config = ['record_id' => $file_name,
18   - 'importer_id' => ImportersFiles::findOne(['id' => $file_name])->id,
19   - 'parser_config' => ['keys' => ['DESCR', 'ARTICLE', 'BRAND', 'PRICE', 'BOX']]
  23 + 'importer_id' => $importer_id,
  24 + 'parser_config' => ['keys' => $keys,
  25 + 'mode' => 'console']
20 26 ];
  27 + Console::output('3');
21 28 if( $this->parseFileConsole( $file_path, $config ) ){
  29 + Console::output('4');
22 30 unlink( $file_path );
23 31 if (isset( $arr_id_files[$file_path] ) ) {
24   - unset($arr_id_files[$file_path]);
  32 + unset( $arr_id_files[$file_path] );
25 33 }
26   - } else {
27   - // Yii::$app->log->
28   - // не дошли до конца по этому остаки вернем в кеш
29   - Yii::$app->cache->set( 'files_to_parse',json_encode( $arr_id_files ) );
30 34 }
31 35 }
32   - if ( !count( $arr_id_files ) ) {
33   - Yii::$app->cache->delete( 'files_to_parse' );
34   - }
35   - }
  36 +
  37 +
  38 + //return $this->redirect('serverFiles');
36 39 }
37   - public function actionParseXML ()
  40 +
  41 + public function actionParseXml ()
38 42 {
39 43  
40 44 }
41 45 protected function parseFileConsole( $file_path, $configuration ){
  46 +
  47 + if( !file_exists( $file_path ) )
  48 + throw new ErrorException("$file_path does not exist!");
  49 +
42 50 $parser_config = [];
43 51 if ( isset( $configuration['parser_config'] ) ) {
44 52 $parser_config = $configuration['parser_config'];
45 53 }
46 54  
47   - $data = Yii::$app->multiparser->parse( $file_path, $parser_config );
  55 + $data = \Yii::$app->multiparser->parse( $file_path, $parser_config );
48 56  
49 57 $writer = new PriceWriter();
50 58 $writer->configuration = $configuration;
... ... @@ -60,11 +68,8 @@ class ParserController extends Controller{
60 68  
61 69 public function actionTest ()
62 70 {
63   - // Console::output('It is working ');
64   - \Yii::warning('1');
65   - \Yii::info('2');
66   -// \Yii::info('3');
67   -// \Yii::warning('4');
  71 + Console::output('It is working ');
  72 + \Yii::info('2','parser');
68 73  
69 74 }
70 75 }
71 76 \ No newline at end of file
... ...