Commit c3d64258a6230ff4e8a12a1d9a7a4a34890e8e6c

Authored by Mihail
1 parent 45c41a76

merge with server

backend/.gitignore 0 → 100644
  1 +/temp
  2 +/uploads
0 3 \ No newline at end of file
... ...
backend/components/base/CustomDbConnection.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: Cibermag
  5 + * Date: 21.09.2015
  6 + * Time: 17:36
  7 + */
  8 +
  9 +namespace backend\components\base;
  10 +
  11 +use yii\db\Connection;
  12 +
  13 +class CustomDbConnection extends Connection {
  14 + //@todo - переписать с использованием событий - почемуто не сработало это событие
  15 + public function afterOpen()
  16 + {
  17 + $now = new \DateTime();
  18 + $mins = $now->getOffset() / 60;
  19 + $sgn = ($mins < 0 ? -1 : 1);
  20 + $mins = abs($mins);
  21 + $hrs = floor($mins / 60);
  22 + $mins -= $hrs * 60;
  23 + $offset = sprintf('%+d:%02d', $hrs*$sgn, $mins);
  24 +
  25 + $this->pdo->exec("SET time_zone='$offset';");
  26 +
  27 + }
  28 +
  29 + protected function initConnection()
  30 + {
  31 + parent::initConnection();
  32 + $this->afterOpen();
  33 +
  34 + }
  35 +
  36 +
  37 +}
0 38 \ No newline at end of file
... ...
backend/components/parsers/CustomConverter.php 0 → 100644
  1 +<?php
  2 +namespace backend\components\parsers;
  3 +use yii\multiparser\Converter;
  4 +
  5 +class CustomConverter extends Converter {
  6 +
  7 + /**
  8 + * @param $value_arr - двумерный массив значений, которому нужно присвоить ключи
  9 + * @param $key_array - ключи для вложенного массива
  10 + * @return array - таблица с проименованными колонками
  11 + */
  12 + public static function convertToAssocArray ( array $value_arr, array $key_array, $key_prefix = '')
  13 + {
  14 + // очистка служебного префикса в массиве заголовков
  15 + if ($key_prefix) {
  16 + $params_array = array_fill( 0, count($key_array), $key_prefix );
  17 + //@todo переписать с использованием array_walk
  18 + $key_array = array_map( function ($value, $key_prefix){ return str_replace( $key_prefix, '',$value ); }, $key_array, $params_array );
  19 + //уберем пустые элементы
  20 + $key_array = array_filter($key_array, function ($value){ return $value !==''; });
  21 + }
  22 +
  23 + // преобразуем массив ключей (обернем в массив), для передачи его в качестве параметра в анонимную функцию для array_map
  24 + // для этого увеличим размерность массива, что бы при каждом обходе массива $value_arr , функции был доступен исходный массив ключей
  25 + $key_array = array_fill( 0, count($value_arr), $key_array );
  26 + // \common\components\CustomVarDamp::dumpAndDie($key_array);
  27 + $result = array_map(
  28 + function ($value, $key_array) {
  29 + $res = $value;
  30 + foreach ($value as $key => $sub_value) {
  31 + if (isset($key_array[$key])) {
  32 + // если такой ключ в базовом массиве (массиве ключей) есть, то заменим новым, иначе просто удалим
  33 + $new_key = $key_array[$key];
  34 + if( !array_key_exists( $new_key , $res ) ){
  35 + $res[ $new_key ] = $res[$key];
  36 + }
  37 + }
  38 + unset( $res[$key] );
  39 + }
  40 +
  41 + return $res;
  42 + },
  43 + $value_arr, $key_array);
  44 + return $result;
  45 + }
  46 +
  47 + /**
  48 + * @param $value_arr - двумерный массив к которому нужно добавить колонки
  49 + * @param $add_array - массив с колонками (ключи) и занчениями колонок
  50 + * @return mixed
  51 + */
  52 + public function addColumns ( array $value_arr , array $add_array )
  53 + {
  54 + $i = 0;
  55 + while ($i < count($value_arr)) {
  56 + foreach ($add_array as $add_key => $add_value) {
  57 + $value_arr[$i][$add_key] = $add_value;
  58 + }
  59 + $i++;
  60 + }
  61 + return $value_arr;
  62 + }
  63 +}
0 64 \ No newline at end of file
... ...
backend/components/parsers/CustomCsvParser.php
... ... @@ -16,15 +16,27 @@ class CustomCsvParser extends \yii\multiparser\CsvParser {
16 16 // public $keys = ['first','second', 'third', 'forth', 'fifth'];
17 17 public function setupConverter()
18 18 {
  19 + if (!count($this->converter_conf)) {
  20 + if ($this->hasHeaderRow) {
  21 + // если у файла есть заголовок, то в результате имеем ассоциативный массив
  22 + $this->converter_conf['hasKey'] = 1;
  23 + }
19 24  
20   - if ($this->hasHeaderRow) {
21   - // если у файла есть заголовок, то в результате имеем ассоциативный массив
22   - $this->converter_conf['hasKey'] = 1;
23 25 }
24 26  
25   - $this->converter = \Yii::createObject($this->converter_conf);
26   -
27 27 }
28 28  
  29 + /**
  30 + * @param $arr
  31 + * @return mixed
  32 + * преобразовует значения прочитанного массива в нужные типы, согласно конфигурации конвертера
  33 + */
  34 + protected function convert($arr)
  35 + {
  36 + $result = \Yii::$app->multiparser->convertByConfiguration( $arr, $this->converter_conf );
  37 +
  38 + return $result;
  39 +
  40 + }
29 41  
30 42 }
31 43 \ No newline at end of file
... ...
backend/components/parsers/config.php
1 1 <?php
2 2 return [
  3 + 'global' =>
  4 + ['ini' => ['upload_max_filesize' => '20M',
  5 + 'post_max_size integer' => '30M',
  6 + ]],
3 7 'csv' =>
4 8 ['web' =>
5 9 ['class' => 'backend\components\parsers\CustomCsvParser',
6 10 'auto_detect_first_line' => true,
7   - 'converter_conf' => ['class' => 'yii\multiparser\Converter',
8   - 'configuration' => [
9   - "string" => 'DESCR'
10   - ]
11   - ,]],
  11 + 'converter_conf' => ['class' => ' backend\components\parsers\CustomConverter',
  12 + 'configuration' => ["string" => 'DESCR'],]
  13 + ],
12 14  
13 15 'basic_column' => [
14 16 Null => 'Пусто',
... ...
backend/config/main.php
... ... @@ -43,6 +43,9 @@ return [
43 43  
44 44 'class' => 'yii\multiparser\YiiMultiparser',
45 45 'configuration' => $mp_configuration,
  46 + 'as behavior' => [
  47 + 'class' => 'backend\components\parsers\CustomConverter',
  48 + ],
46 49  
47 50 ],
48 51 ],
... ...
backend/controllers/CheckPriceController.php 0 → 100644
  1 +<?php
  2 +namespace backend\controllers;
  3 +
  4 +use Yii;
  5 +use yii\bootstrap\Modal;
  6 +use yii\data\ActiveDataProvider;
  7 +use yii\filters\AccessControl;
  8 +use backend\components\base\BaseController;
  9 +use yii\filters\VerbFilter;
  10 +use backend\models\Details;
  11 +use backend\models\ImporterFiles;
  12 +use backend\models\Importer;
  13 +use yii\base\ErrorException;
  14 +
  15 +use common\components\CustomVarDamp;
  16 +
  17 +/**
  18 + * Parser controller
  19 + */
  20 +class CheckPriceController extends BaseController
  21 +{
  22 + public $layout = "/column";
  23 +
  24 + /**
  25 + * @inheritdoc
  26 + */
  27 + public function behaviors()
  28 + {
  29 + return [
  30 + 'access' => [
  31 + 'class' => AccessControl::className(),
  32 + 'rules' => [
  33 + [
  34 + 'actions' => ['index', 'view'],
  35 + 'allow' => true,
  36 + 'roles' => ['@'],
  37 + ],
  38 + ],
  39 + ],
  40 +// 'verbs' => [
  41 +// 'class' => VerbFilter::className(),
  42 +// 'actions' => [
  43 +// 'logout' => ['post'],
  44 +// ],
  45 +// ],
  46 + ];
  47 + }
  48 +
  49 + /**
  50 + * @inheritdoc
  51 + */
  52 + public function actions()
  53 + {
  54 + return [
  55 + 'error' => [
  56 + 'class' => 'yii\web\ErrorAction',
  57 + ],
  58 + ];
  59 + }
  60 +
  61 +
  62 + public function actionIndex()
  63 + {
  64 + if(Yii::$app->request->isAjax){
  65 + CustomVarDamp::dumpAndDie(1);
  66 + }
  67 +
  68 + //$query = (new Query())->select('*')->from('{{%importer_files}}')->where(['not', ['time_end' => null]])->orderBy(['upload_time' => SORT_DESC]);
  69 + $query = Importer::find()->where(['active' => true])->orderBy(['price_date_update' => SORT_DESC]);
  70 +
  71 + $provider = new ActiveDataProvider([
  72 + 'query' => $query,
  73 + 'pagination' => [
  74 + 'pageSize' => 10,
  75 + ],
  76 + ]);
  77 + return $this->render('index',
  78 + [
  79 + 'dataProvider' => $provider,
  80 + ]);
  81 + }
  82 +
  83 +
  84 + public function actionView ($id)
  85 + {
  86 + // @todo переписать запрос - нужно условие на равенство даты, а также вьюшка должна быть модальным окном вызываемой по аджаксу
  87 + $query = Details::find()->where(['IMPORT_ID' => $id])->orderBy(['timestamp' => SORT_DESC]);
  88 +
  89 + $provider = new ActiveDataProvider([
  90 + 'query' => $query,
  91 + 'pagination' => [
  92 + 'pageSize' => 16,
  93 + ],
  94 + ]);
  95 + return $this->render('view',
  96 + ['dataProvider' => $provider]);
  97 + }
  98 +
  99 +}
... ...
backend/controllers/Check_priceController.php 0 → 100644
  1 +<?php
  2 +namespace backend\controllers;
  3 +
  4 +use Yii;
  5 +use yii\bootstrap\Modal;
  6 +use yii\data\ActiveDataProvider;
  7 +use yii\filters\AccessControl;
  8 +use backend\components\base\BaseController;
  9 +use yii\filters\VerbFilter;
  10 +use backend\models\UploadFileParsingForm;
  11 +use yii\web\UploadedFile;
  12 +use yii\data\ArrayDataProvider;
  13 +use yii\multiparser\DynamicFormHelper;
  14 +use backend\components\parsers\CustomParserConfigurator;
  15 +use backend\models\Details;
  16 +use backend\models\ImporterFiles;
  17 +use backend\models\Importer;
  18 +use yii\base\ErrorException;
  19 +use yii\db\Query;
  20 +
  21 +use common\components\CustomVarDamp;
  22 +
  23 +/**
  24 + * Parser controller
  25 + */
  26 +class Check_priceController extends BaseController
  27 +{
  28 + public $layout = "/column";
  29 +
  30 + /**
  31 + * @inheritdoc
  32 + */
  33 + public function behaviors()
  34 + {
  35 + return [
  36 + 'access' => [
  37 + 'class' => AccessControl::className(),
  38 + 'rules' => [
  39 + [
  40 + 'actions' => ['index', 'view'],
  41 + 'allow' => true,
  42 + 'roles' => ['@'],
  43 + ],
  44 + ],
  45 + ],
  46 +// 'verbs' => [
  47 +// 'class' => VerbFilter::className(),
  48 +// 'actions' => [
  49 +// 'logout' => ['post'],
  50 +// ],
  51 +// ],
  52 + ];
  53 + }
  54 +
  55 + /**
  56 + * @inheritdoc
  57 + */
  58 + public function actions()
  59 + {
  60 + return [
  61 + 'error' => [
  62 + 'class' => 'yii\web\ErrorAction',
  63 + ],
  64 + ];
  65 + }
  66 +
  67 +
  68 + public function actionIndex()
  69 + {
  70 +
  71 + if(Yii::$app->request->isAjax){
  72 + CustomVarDamp::dumpAndDie(1);
  73 + }
  74 +
  75 + //$query = (new Query())->select('*')->from('{{%importer_files}}')->where(['not', ['time_end' => null]])->orderBy(['upload_time' => SORT_DESC]);
  76 + $query = Importer::find()->where(['active' => true])->orderBy(['price_date_update' => SORT_DESC]);
  77 +
  78 + $provider = new ActiveDataProvider([
  79 + 'query' => $query,
  80 + 'pagination' => [
  81 + 'pageSize' => 10,
  82 + ],
  83 + ]);
  84 + return $this->render('index',
  85 + [
  86 + 'dataProvider' => $provider,
  87 + ]);
  88 + }
  89 +
  90 +
  91 + public function actionView ($id)
  92 + {
  93 +
  94 +
  95 +
  96 +
  97 + $query = Details::find()->where(['IMPORT_ID' => $id])->orderBy(['timestamp' => SORT_DESC]);
  98 +
  99 + $provider = new ActiveDataProvider([
  100 + 'query' => $query,
  101 + 'pagination' => [
  102 + 'pageSize' => 16,
  103 + ],
  104 + ]);
  105 + return $this->render('view',
  106 + ['dataProvider' => $provider]);
  107 + }
  108 +}
... ...
backend/controllers/ParserController.php
... ... @@ -2,6 +2,7 @@
2 2 namespace backend\controllers;
3 3  
4 4 use Yii;
  5 +use yii\data\ActiveDataProvider;
5 6 use yii\filters\AccessControl;
6 7 use backend\components\base\BaseController;
7 8 use yii\filters\VerbFilter;
... ... @@ -10,16 +11,21 @@ use yii\web\UploadedFile;
10 11 use yii\data\ArrayDataProvider;
11 12 use yii\multiparser\DynamicFormHelper;
12 13 use backend\components\parsers\CustomParserConfigurator;
  14 +use backend\models\Details;
  15 +use backend\models\ImporterFiles;
  16 +use backend\models\Importer;
  17 +use yii\base\ErrorException;
  18 +use yii\db\Query;
13 19  
14 20 use common\components\CustomVarDamp;
15 21  
16 22 /**
17 23 * Parser controller
18 24 */
19   -
20 25 class ParserController extends BaseController
21 26 {
22 27 public $layout = "/column";
  28 +
23 29 /**
24 30 * @inheritdoc
25 31 */
... ... @@ -30,7 +36,6 @@ class ParserController extends BaseController
30 36 'class' => AccessControl::className(),
31 37 'rules' => [
32 38 [
33   - 'actions' => ['index','results','write'],
34 39 'allow' => true,
35 40 'roles' => ['@'],
36 41 ],
... ... @@ -58,34 +63,84 @@ class ParserController extends BaseController
58 63 }
59 64  
60 65  
61   -
62   - public function actionIndex()
  66 + public function actionIndex($mode = 0)
63 67 {
64 68 $model = new UploadFileParsingForm();
65   -
  69 + // установим режим, 0 - ручная загрузка, 1 - автозагрузка
  70 + $model->mode = $mode;
  71 + //CustomVarDamp::dumpAndDie(phpinfo());
66 72 return $this->render('index', ['model' => $model]);
67 73 }
68 74  
69   - public function actionResults(){
  75 +// public function beforeAction($action)
  76 +// {
  77 +// if($action->actionMethod ='actionResults'){
  78 +// CustomVarDamp::dumpAndDie(phpinfo());
  79 +// }
  80 +// }
70 81  
71   - $model = new UploadFileParsingForm();
  82 + public function actionResults($mode = 0)
  83 + {
  84 + $model = new UploadFileParsingForm(['mode' => $mode]);
72 85 $data = [];
73 86 if ($model->load(Yii::$app->request->post())) {
74 87 $model->file = UploadedFile::getInstance($model, 'file');
75   -
  88 + // первый проход - валидируем, сохраняем файл, ложим в кеш (для ручной загрузки) отпарсенные данные и параметры модели (потом при записи в базу данных они пригодятся)
76 89 if ($model->validate()) {
77   - $filePath = Yii::getAlias('@webroot') . '/uploads/' . $model->file->baseName . '.' . $model->file->extension;
  90 + // запишем дату загрузки файла в таблицу файлов поставщика (ImportersFiles)
  91 + $files_model = new ImporterFiles();
  92 + // id поставщика получим из конфигурации
  93 + $files_model->load(['ImporterFiles' => $model->toArray()]);
  94 + try {
  95 + $files_model->save();
  96 + } catch (ErrorException $e) {
  97 + CustomVarDamp::dump($e->getMessage());
  98 + }
  99 + // получим id только что записанной записи - его запишем в название файла
  100 + $model->record_id = $files_model->find()
  101 + ->where(['importer_id' => $files_model->importer_id])
  102 + ->orderBy(['id' => SORT_DESC])
  103 + ->one()
  104 + ->id;
78 105  
79   - $model->file->saveAs( $filePath );
80   - $data = $model->readFile($filePath);
  106 + $file_name = $model->record_id . '.' . $model->file->extension;
81 107  
82   - Yii::$app->getCache()->set( 'parser_data', json_encode($data) );
  108 + if ($model->mode) {
  109 + $model->file_path = Yii::getAlias('@auto_upload') . '/' . $file_name;
  110 + } else {
  111 + $model->file_path = Yii::getAlias('@manual_upload') . '/' . $file_name;
  112 + }
83 113  
84   - }
  114 + $model->file->saveAs($model->file_path);
85 115  
86   - } else if( Yii::$app->getCache()->get( 'parser_data' )) {
  116 + // для авто загрузки, обработка завершена
  117 + if ($model->mode) {
  118 + $model->success = true;
  119 + return $this->render('index', ['model' => $model]);
  120 + }
87 121  
88   - $data = json_decode( Yii::$app->getCache()->get( 'parser_data' ),true );
  122 + // === ручная загрузка ===========
  123 + //запускаем парсинг
  124 + $data = $model->readFile();
  125 + // сохраняем в кеш отпарсенные даные
  126 + Yii::$app->getCache()->set('parser_data', json_encode($data));
  127 + // сохраняем в кеш модель - в ней настройки для дальнейшей обработки данных
  128 + Yii::$app->getCache()->set('parser_configuration', serialize($model));
  129 +
  130 +
  131 + } else {
  132 + // не прошла валидация форма загрузки файлов
  133 + //@todo - отправка на страницу ошибок
  134 + $errors_arr = $model->getErrors();
  135 + foreach ($errors_arr as $error) {
  136 + CustomVarDamp::dump(array_values($error));
  137 + }
  138 + die;
  139 + }
  140 + // листаем пагинатором, или повторно вызываем - считываем из кеша отпрасенные данные
  141 + } else if (Yii::$app->getCache()->get('parser_data')) {
  142 +
  143 + $data = json_decode(Yii::$app->getCache()->get('parser_data'), true);
89 144  
90 145 }
91 146  
... ... @@ -96,38 +151,168 @@ class ParserController extends BaseController
96 151 ],
97 152 ]);
98 153  
99   - // CustomVarDamp::dumpAndDie($data);
100   - $header_model = DynamicFormHelper::CreateDynamicModel( count( $data[0] ) );
  154 + //формируем заголовок для пользователя, где он сможет выбрать соответсвие полей (выпадающий список)
  155 + $header_model = DynamicFormHelper::CreateDynamicModel(count($data[0]));
101 156  
102   - // CustomVarDamp::dumpAndDie(Yii::$app->multiparser->getConfiguration('csv','basic_column'));
103 157 return $this->render('results',
104 158 ['model' => $data,
105 159 'header_model' => $header_model,
106   - 'basic_column' => Yii::$app->multiparser->getConfiguration('csv','basic_column'),
  160 + // список колонок для выбора
  161 + 'basic_column' => Yii::$app->multiparser->getConfiguration('csv', 'basic_column'),
107 162 'dataProvider' => $provider]);
108 163 }
109 164  
110   -public function actionWrite()
111   -{
112   - //CustomVarDamp::dumpAndDie(Yii::$app->request->post());
  165 + public function actionWrite()
  166 + {
  167 + //получим колонки которые выбрал пользователь
  168 + $arr_attributes = Yii::$app->request->post()['DynamicModel'];
  169 + //соберем модель по полученным данным
  170 + $model = DynamicFormHelper::CreateDynamicModel($arr_attributes);
  171 + //добавим правила валидации (колонки должны быть те что указаны в конфиге)
  172 + foreach ($arr_attributes as $key => $value) {
  173 + $model->addRule($key, 'in', ['range' => array_keys(Yii::$app->multiparser->getConfiguration('csv', 'basic_column'))]);
  174 + }
  175 +
  176 + // провалидируем выбранные колонки
  177 + if ($model->validate()) {
  178 +
  179 + // валидация успешна у нас есть соответсвие колонок, преобразуем в массив данное соответсвие для дальнейшей работы
  180 + $arr = $model->toArray();
  181 +
  182 + // получим данные из кеша
  183 + if (Yii::$app->getCache()->get('parser_data') && Yii::$app->getCache()->get('parser_configuration')) {
  184 + $data = json_decode(Yii::$app->getCache()->get('parser_data'), true);
  185 + $configuration = unserialize(Yii::$app->getCache()->get('parser_configuration'));
  186 + } else {
  187 + CustomVarDamp::dumpAndDie('Ошибка кеша');
  188 + }
  189 +
  190 + // соотнесем отпарсенные данные с соответсивем полученным от пользователя
  191 + // для этого преобразуем массив отпарсенных данных - назначим ключи согласно соответствию
  192 + $data = \Yii::$app->multiparser->convertToAssocArray($data, $arr, 'attr_');
  193 +
  194 +
  195 + // 1. запишем дату старта в таблицу файлов поставщика (ImportersFiles)
  196 + // id загруженного файла получим из конфигурации
  197 + $files_model = ImporterFiles::findOne( $configuration->record_id );
  198 +
  199 + //$files_model->load(['ImporterFiles' => $configuration->toArray()]);
  200 + $update_date = date('Y-m-d H:i:s');
  201 + $files_model->time_start = $update_date;
  202 + // запишем дату начала загрузки
  203 + if (!$files_model->save()) {
  204 + CustomVarDamp::dumpAndDie($files_model->getErrors());
  205 + }
  206 +
  207 +
  208 + // 2. запишем полученные данные в таблицу товаров (Details)
  209 + $details_model = new Details();
  210 + // проверим все ли обязательные колонки были указаны пользователем
  211 + $details_model->load(['Details' => $data[0]]);
  212 + if ($details_model->validate()) {
  213 + // дополним данные значением импортера и даты обновления цены
  214 + $data = \Yii::$app->multiparser->addColumns($data, ['IMPORT_ID' => $configuration->importer_id, 'timestamp' => $update_date]);
  215 +
  216 + try {
  217 + //@todo add transaction
  218 + // попытаемся вставить данные в БД с апдейтом по ключам
  219 + $details_model->ManualInsert($data);
  220 +
  221 + // 3. зафиксируем дату конца загрузки в файлах поставщика
  222 +
  223 + $files_model->time_end = date('Y-m-d H:i:s');
  224 + // CustomVarDamp::dumpAndDie($files_model);
  225 + if (!$files_model->save()) {
  226 + CustomVarDamp::dumpAndDie($files_model->getErrors());
  227 + }
  228 +
  229 + // 4. зафиксируем дату загрузки в таблице поставщиков
  230 + $imp_model = Importer::findOne($configuration['importer_id']);
  231 + $imp_model->price_date_update = $update_date;
  232 +
  233 + if (!$imp_model->save()) {
  234 + CustomVarDamp::dumpAndDie($imp_model->getErrors());
  235 + }
  236 + $configuration['success'] = true;
  237 + // все прошло успешно - очищаем кеш
  238 + Yii::$app->getCache()->delete('parser_data');
  239 + Yii::$app->getCache()->delete('parser_configuration');
  240 +
  241 + unlink($configuration['file_path']);
  242 + return $this->render('index', ['model' => $configuration]);
  243 +
  244 + } catch (ErrorException $e) {
  245 + CustomVarDamp::dump($e->getMessage());
  246 + }
  247 + }
  248 + if ($details_model->hasErrors()) {
  249 + $errors_arr = $details_model->getErrors();
  250 + foreach ($errors_arr as $error) {
  251 + CustomVarDamp::dump(array_values($error));
  252 + }
  253 +
  254 + }
  255 +
  256 +
  257 + }
113 258  
114   - $arr_attributes = Yii::$app->request->post()['DynamicModel'];
115   - $model = DynamicFormHelper::CreateDynamicModel( $arr_attributes );
116   - foreach ($arr_attributes as $key => $value) {
117   - $model->addRule($key, 'in', ['range' => array_keys( Yii::$app->multiparser->getConfiguration('csv','basic_column') )]);
118 259 }
119 260  
120   - //CustomVarDamp::dumpAndDie($model);
121   - if ($model->validate()) {
122   - $arr = $model->toArray();
123   - $data = json_decode( Yii::$app->getCache()->get( 'parser_data' ),true );
  261 + public function actionAutoUpload()
  262 + {
  263 + $query = Importer::find()->where(['active' => true])->orderBy(['price_date_update' => SORT_DESC]);
124 264  
125   - // CustomVarDamp::dumpAndDie(DynamicFormHelper::CreateAssocArray($data, $arr));
126   - CustomVarDamp::dumpAndDie($arr);
  265 + $provider = new ActiveDataProvider([
  266 + 'query' => $query,
  267 + 'pagination' => [
  268 + 'pageSize' => 10,
  269 + ],
  270 + ]);
  271 + return $this->render('check_price',
  272 + [
  273 + 'dataProvider' => $provider]);
127 274 }
128 275  
  276 + public function actionServerFiles ()
  277 + {
  278 + $arr_id = [];
  279 + // получим список файлов которые ожидают к загрузке
  280 + foreach (glob(Yii::getAlias('@auto_upload') . '/*') as $server_file) {
  281 + $file_id = basename($server_file,".csv");
  282 + $arr_id[] = (int) $file_id;
  283 + }
129 284  
  285 + $query = ImporterFiles::find()->where(['in', 'id', $arr_id])->orderBy(['upload_time' => SORT_DESC]);
130 286  
131   -}
  287 + $provider = new ActiveDataProvider([
  288 + 'query' => $query,
  289 + 'pagination' => [
  290 + 'pageSize' => 10,
  291 + ],
  292 + ]);
  293 + return $this->render('server-files',
  294 + [
  295 + 'dataProvider' => $provider]);
  296 + }
  297 +
  298 + public function actionDelete ($id)
  299 + {
  300 + if(Yii::$app->request->isAjax){
  301 + CustomVarDamp::dumpAndDie(1);
  302 + }
  303 +
  304 + $files_model = new ImporterFiles();
  305 + try {
  306 +
  307 + $files_model->delete($id);
  308 + unlink(Yii::getAlias('@auto_upload') . '/' . $id . '.csv' );
  309 +
  310 + } catch (ErrorException $e) {
132 311  
  312 + CustomVarDamp::dump($e->getMessage());
  313 +
  314 + }
  315 +
  316 + $this->redirect('server-files');
  317 + }
133 318 }
... ...
backend/models/Details.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace backend\models;
  4 +
  5 +use Yii;
  6 +use backend\components\base\BaseActiveRecord;
  7 +
  8 +/**
  9 + * This is the model class for table "{{%details}}".
  10 + *
  11 + * @property string $ID
  12 + * @property string $IMPORT_ID
  13 + * @property string $BRAND
  14 + * @property string $ARTICLE
  15 + * @property string $FULL_ARTICLE
  16 + * @property double $PRICE
  17 + * @property string $DESCR
  18 + * @property string $BOX
  19 + * @property string $ADD_BOX
  20 + * @property string $GROUP
  21 + * @property string $timestamp
  22 + */
  23 +class Details extends BaseActiveRecord
  24 +{
  25 + const KEY_COLUMN = ['IMPORT_ID','BRAND','ARTICLE'];
  26 + const BATCH = 500;
  27 + /**
  28 + * @inheritdoc
  29 + */
  30 + public static function tableName()
  31 + {
  32 + return '{{%details}}';
  33 + }
  34 +
  35 + /**
  36 + * @inheritdoc
  37 + */
  38 + public function rules()
  39 + {
  40 + return [
  41 + [[ 'BRAND', 'ARTICLE', 'PRICE', 'DESCR', 'BOX'], 'required'],
  42 + // [['IMPORT_ID', 'BOX', 'ADD_BOX'], 'integer'],
  43 + [['PRICE'], 'number'],
  44 + [['timestamp'], 'safe'],
  45 + [['BRAND', 'ARTICLE'], 'string', 'max' => 100],
  46 + [['FULL_ARTICLE'], 'string', 'max' => 150],
  47 + [['DESCR', 'GROUP'], 'string', 'max' => 200]
  48 + ];
  49 + }
  50 +
  51 + /**
  52 + * @inheritdoc
  53 + */
  54 + public function attributeLabels()
  55 + {
  56 + return [
  57 + 'ID' => Yii::t('app', 'ID'),
  58 + 'IMPORT_ID' => Yii::t('app', 'Import ID'),
  59 + 'BRAND' => Yii::t('app', 'Brand'),
  60 + 'ARTICLE' => Yii::t('app', 'Article'),
  61 + 'FULL_ARTICLE' => Yii::t('app', 'Full Article'),
  62 + 'PRICE' => Yii::t('app', 'Price'),
  63 + 'DESCR' => Yii::t('app', 'Descr'),
  64 + 'BOX' => Yii::t('app', 'Box'),
  65 + 'ADD_BOX' => Yii::t('app', 'Add Box'),
  66 + 'GROUP' => Yii::t('app', 'Group'),
  67 + 'timestamp' => Yii::t('app', 'Timestamp'),
  68 + ];
  69 + }
  70 +
  71 + public function ManualInsert ($data)
  72 + {
  73 + // \common\components\CustomVarDamp::dumpAndDie($data);
  74 + $table_name = self::tableName();
  75 + $keys_arr = array_keys( $data[0] );
  76 + // найдем те поля которые не являются ключами. Их нужно будет при дубляже апдейтить
  77 + $fields_arr_to_update = array_diff( $keys_arr, $this::KEY_COLUMN );
  78 +
  79 + $query_update = ' on duplicate key update ';
  80 + foreach ($fields_arr_to_update as $field) {
  81 + $query_update .= "{$field} = values({$field}),";
  82 + }
  83 + // удалим последнюю запятую
  84 + $query_update = substr($query_update, 0, strlen($query_update) - 1);
  85 +
  86 + // запросы будем выполнять пакетами
  87 + // размер пакета установлен в константе
  88 + // разобъем массив на пакеты и будем их проходить
  89 + $data = array_chunk($data, $this::BATCH );
  90 + foreach( $data as $current_batch_array ){
  91 +
  92 + //воспользуемся пакетной вставкой от фреймворка, плюс сразу с экранированием и защитой от инъекций
  93 + $query_insert = Yii::$app->db->createCommand()->batchInsert($table_name, $keys_arr, $current_batch_array)->sql;
  94 + // добавим фрагмент с апдейтом при дубляже
  95 + $query = "{$query_insert} {$query_update}";
  96 + // \common\components\CustomVarDamp::dumpAndDie($query);
  97 + $res = Yii::$app->db->createCommand($query)->execute();
  98 +
  99 + }
  100 +
  101 + }
  102 +}
... ...
backend/models/Details_old.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: Cibermag
  5 + * Date: 15.09.2015
  6 + * Time: 16:49
  7 + */
  8 +
  9 +namespace backend\models;
  10 +
  11 +use yii\base\Model;
  12 +use Yii;
  13 +
  14 +class Details_old extends Model{
  15 + const KEY_COLUMN = ['IMPORT_ID','BRAND','ARTICLE'];
  16 + const BATCH = 500;
  17 +
  18 + private $mode;
  19 +
  20 + // обязательные поля модели
  21 + public $BRAND;
  22 + public $ARTICLE;
  23 + public $PRICE;
  24 + public $BOX;
  25 +
  26 + function __construct($mode)
  27 + {
  28 + $this->mode = $mode;
  29 + }
  30 +
  31 + public function rules()
  32 + {
  33 + return [
  34 + [['BRAND','ARTICLE', 'PRICE', 'BOX'], 'required' ],
  35 + ];
  36 + }
  37 +
  38 + public function formName()
  39 + {
  40 + return 'Details';
  41 + }
  42 +
  43 +
  44 + public static function tableName()
  45 + {
  46 + return '{{%details}}';
  47 + }
  48 +
  49 +// //@todo вероятно этой функции не место здесь
  50 +// public function prepareData ( $data, $configuration )
  51 +// {
  52 +// if ( isset($configuration['importer_id']) && $configuration['importer_id']) {
  53 +// $data = \Yii::$app->multiparser->addColumn( $data, 'IMPORT_ID', $configuration['importer_id'] );
  54 +// }
  55 +// // \common\components\CustomVarDamp::dumpAndDie($data);
  56 +// return $data;
  57 +// }
  58 +
  59 + /**
  60 + * @param $data - двумерный массив данных для записи в таблицу details
  61 + * @throws \yii\db\Exception
  62 + * вставляет записи с апдейтом при дубляже ключей
  63 + */
  64 + public function save ($data)
  65 + {
  66 + $table_name = self::tableName();
  67 + $keys_arr = array_keys( $data[0] );
  68 + // найдем те поля которые не являются ключами. Их нужно будет при дубляже апдейтить
  69 + $fields_arr_to_update = array_diff( $keys_arr, $this::KEY_COLUMN );
  70 +
  71 + $query_update = ' on duplicate key update ';
  72 + foreach ($fields_arr_to_update as $field) {
  73 + $query_update .= "{$field} = values({$field}),";
  74 + }
  75 + // удалим последнюю запятую
  76 + $query_update = substr($query_update, 0, strlen($query_update) - 1);
  77 +
  78 + // запросы будем выполнять пакетами
  79 + // размер пакета установлен в константе
  80 + // разобъем массив на пакеты и будем их проходить
  81 + $data = array_chunk($data, $this::BATCH );
  82 + foreach( $data as $current_batch_array ){
  83 +
  84 + //воспользуемся пакетной вставкой от фреймворка, плюс сразу с экранированием и защитой от инъекций
  85 + $query_insert = Yii::$app->db->createCommand()->batchInsert($table_name, $keys_arr, $current_batch_array)->sql;
  86 + // добавим фрагмент с апдейтом при дубляже
  87 + $query = "{$query_insert} {$query_update}";
  88 + // \common\components\CustomVarDamp::dumpAndDie($query);
  89 + $res = Yii::$app->db->createCommand($query)->execute();
  90 +
  91 + }
  92 +
  93 + }
  94 +}
  95 +
  96 +//
  97 +
  98 +//$q = " INSERT INTO {$table_name} ({$keys_string}) VALUES (";
  99 +
  100 +//$q .= " on duplicate key update `FULL_ARTICLE` = values (`FULL_ARTICLE`),
  101 +// `PRICE` = values (`PRICE`),
  102 +// `DESCR` = values(`DESCR`),
  103 +// `BOX` = values(`BOX`),
  104 +// `ADD_BOX` = values(`ADD_BOX`),
  105 +// `GROUP` = values(`GROUP`);";
  106 +
  107 +// INSERT INTO table (a,b,c) VALUES (1,2,3),(4,5,6)
  108 +// ON DUPLICATE KEY UPDATE c=VALUES(a)+VALUES(b);
  109 +
  110 +
  111 +
  112 +//INSERT INTO `books` (`UserId`, `BookId`, `Count`) VALUES (13, 1001, 3)
  113 +//ON DUPLICATE KEY UPDATE `Count` = `Count` + VALUES(`Count`);
  114 +
  115 +//$values_string = '';
  116 +//$keys_arr = array_keys( $data[0] );
  117 +//$keys_string = implode( ',', $keys_arr);
  118 +//$table_name = self::tableName();
  119 +//$current_batch = 0;
  120 +//for ($i = $current_batch; $i < $this::BATCH AND $i < count($data); $i++) {
  121 +// $values_string .= '(' . implode( ',', $data[$i]) . '),';
  122 +//}
  123 +// for ($current_batch = $this::BATCH; $current_batch<count($data); $current_batch + $this::BATCH )
  124 +//// удалим последнюю запятую
  125 +//$values_string = substr($values_string, 0, strlen($values_string) - 1) . ' ';
  126 +////\common\components\CustomVarDamp::dumpAndDie($values_string);
  127 +//// $query = "INSERT INTO {$table_name}({$keys_string}) VALUES {$values_string}";
  128 +//// on duplicate key update `PRICE` = values (`PRICE`),`DESCR` = values(`DESCR`),`BOX` = values(`BOX`)";
  129 +//$query_insert = Yii::$app->db->createCommand()->batchInsert($table_name, $keys_arr, $data)->sql;
  130 +//$query = "{$query_insert} on duplicate key update `PRICE` = values (`PRICE`),`DESCR` = values(`DESCR`),`BOX` = values(`BOX`)";
  131 +//$res = Yii::$app->db->createCommand($query)->execute();
  132 +
  133 +
  134 +
  135 +// Yii::$app->db->createCommand()->batchInsert($table_name, $keys_arr, $data)->sql execute();
0 136 \ No newline at end of file
... ...
backend/models/Importer.php
... ... @@ -47,13 +47,14 @@ class Importer extends BaseActiveRecord
47 47 public function rules()
48 48 {
49 49 return [
50   - [['code', 'name', 'name_price', 'currency_id', 'delivery', 'email', 'info', 'PARSER_FIELD_SIGN', 'price_date_update'], 'required'],
  50 + [['code', 'name', 'currency_id', 'delivery', 'price_date_update'], 'required'],
  51 + [['name_price', 'email', 'PARSER_FIELD_SIGN', 'info'], 'safe'],
51 52 [['currency_id', 'active', 'PARSER_IS_ACTIVE', 'PARSER_COLUMN_COUNT', 'PARSER_FIELD_BRAND', 'PARSER_FIELD_ARTICLE', 'PARSER_FIELD_ARTICLE_PREFIX', 'PARSER_FIELD_PRICE', 'PARSER_FIELD_DESCR', 'PARSER_FIELD_BOX', 'PARSER_FIELD_ADD_BOX', 'PARSER_FIELD_GROUP_RG'], 'integer'],
52 53 [['info'], 'string'],
53 54 [['PARSER_FIELD_MULTIPLIER'], 'number'],
54 55 [['code', 'name', 'name_price', 'delivery', 'email'], 'string', 'max' => 254],
55 56 [['PARSER_FIELD_SIGN'], 'string', 'max' => 1],
56   - [['price_date_update'], 'string', 'max' => 15],
  57 + // [['price_date_update'], 'string', 'max' => 15],
57 58 [['code'], 'unique'],
58 59 [['name'], 'unique']
59 60 ];
... ...
backend/models/ImporterFiles.php 0 → 100644
  1 +<?php
  2 +
  3 +namespace backend\models;
  4 +
  5 +use common\components\CustomVarDamp;
  6 +use Yii;
  7 +
  8 +/**
  9 + * This is the model class for table "{{%importer_files}}".
  10 + *
  11 + * @property integer $id
  12 + * @property string $importer_id
  13 + * @property string $upload_time
  14 + * @property string $time_start
  15 + * @property string $time_end
  16 + */
  17 +class ImporterFiles extends \yii\db\ActiveRecord
  18 +{
  19 + /**
  20 + * @inheritdoc
  21 + */
  22 + public static function tableName()
  23 + {
  24 + return '{{%importer_files}}';
  25 + }
  26 +
  27 + /**
  28 + * @inheritdoc
  29 + */
  30 + public function rules()
  31 + {
  32 + return [
  33 + [['importer_id'], 'required'],
  34 + [['importer_id'], 'integer'],
  35 + [['upload_time', 'time_start', 'time_end'], 'safe']
  36 + ];
  37 + }
  38 +
  39 + public function getImporter ()
  40 + {
  41 + return $this->hasOne(Importer::className(), ['id' => 'importer_id'])->one()->name;
  42 + }
  43 +
  44 + /**
  45 + * @inheritdoc
  46 + */
  47 + public function attributeLabels()
  48 + {
  49 + return [
  50 + 'id' => Yii::t('app', 'ID'),
  51 + 'importer_id' => Yii::t('app', 'Importer ID'),
  52 + 'upload_time' => Yii::t('app', 'Upload Time'),
  53 + 'time_start' => Yii::t('app', 'Time Start'),
  54 + 'time_end' => Yii::t('app', 'Time End'),
  55 + ];
  56 + }
  57 +}
... ...
backend/models/UploadFileParsingForm.php
... ... @@ -14,28 +14,48 @@ class UploadFileParsingForm extends Model
14 14 /**
15 15 * @var UploadedFile file attribute
16 16 */
  17 + // атрибуты формы
17 18 public $file;
18   - public $importer;
  19 + public $importer_id;
19 20 public $action;
20 21 public $delimiter;
21 22 public $delete_price;
22 23 public $delete_prefix;
23 24  
  25 + // служебные атрибуты
  26 + public $file_path;
  27 + public $success;
  28 + public $mode; //0 - режим ручной загрузки, 1 - режим автозагрузки
  29 + public $record_id; // id таблицы в которую записывается информация о файле
  30 +
24 31 /**
25 32 * @return array the validation rules.
26 33 */
  34 + public function __construct($config = [])
  35 + {
  36 + parent::__construct($config);
  37 + if ( $this->mode ) {
  38 + // автозагрузка, проставим сценарий
  39 + $this->scenario = 'auto';
  40 + }
  41 +
  42 + }
  43 +
  44 +
27 45 public function rules()
28 46 {
29 47 return [
30   - ['importer', 'required', 'message' => 'Не указан поставщик!' ],
  48 + ['importer_id', 'required', 'message' => 'Не указан поставщик!' ],
31 49 ['file', 'required', 'message' => 'Не выбран файл!' ],
32 50 //@todo - not working this file validator!!! - fixed
33 51 [['file'], 'file'],// 'extensions' => ['csv', 'xml'] ],
34 52 // 'wrongMimeType' => 'Указан неподдерживаемый тип файла. Можно выбирать csv, xml файлы.' ],
35   - ['importer', 'integer','max' => 999999, 'min' => 0 ],
36   - [['action','delete_prefix', 'delete_price'], 'boolean'],
  53 + ['importer_id', 'integer','max' => 999999, 'min' => 0 ],
  54 + [['action','delete_prefix', 'delete_price', 'success'], 'boolean', 'except' => 'auto' ], // только для ручной загрузки
37 55 ['delimiter', 'string', 'max' => 1],
38   - ['delimiter', 'default', 'value' => ';']
  56 + [['mode','record_id'], 'safe'],
  57 + ['delimiter', 'default', 'value' => ';'],
  58 + [ 'success', 'default', 'value' => false]
39 59  
40 60 ];
41 61 }
... ... @@ -44,17 +64,34 @@ class UploadFileParsingForm extends Model
44 64 {
45 65 return [
46 66 'file' => Yii::t('app', 'Источник'),
47   - 'importer' => Yii::t('app', 'Поставщик'),
  67 + 'importer_id' => Yii::t('app', 'Поставщик'),
48 68 'delimiter' => Yii::t('app', 'Разделитель'),
49 69 ];
50 70 }
51 71  
52   - public function readFile($filePath){
  72 + public function readFile(){
53 73  
54   - $data = Yii::$app->multiparser->parse($filePath);
  74 + $data = Yii::$app->multiparser->parse( $this->file_path );
55 75 if( !is_array($data) ){
56 76 $data = ['No results'];
57 77 }
  78 +
58 79 return $data;
59 80 }
  81 +
  82 + public function fields()
  83 + {
  84 + return [
  85 +
  86 + 'importer_id',
  87 + 'delimiter',
  88 + 'delete_price',
  89 + 'delete_prefix',
  90 + 'file_path',
  91 + // id записи таблицы ImportersFiles,
  92 + // 'id' => 'record_id',
  93 + ];
  94 + }
  95 +
  96 +
60 97 }
61 98 \ No newline at end of file
... ...
backend/views/check-price/index.php 0 → 100644
  1 +<?php
  2 +use yii\helpers\Html;
  3 +use yii\grid\GridView;
  4 +use yii\grid\SerialColumn;
  5 +use yii\grid\ActionColumn;
  6 +use yii\widgets\Pjax;
  7 +
  8 +
  9 +/* @var $this yii\web\View */
  10 +/* @var $searchModel backend\models\CatalogSearch */
  11 +/* @var $dataProvider yii\data\ActiveDataProvider */
  12 +
  13 +$this->title = 'Проверка прайсов';
  14 +$this->params['breadcrumbs'][] = $this->title;
  15 +?>
  16 +<div class="catalog-index">
  17 +
  18 + <h1><?= Html::encode($this->title) ?></h1>
  19 +
  20 +
  21 + <?= GridView::widget( ['dataProvider' => $dataProvider,
  22 + 'columns' => [['class' => SerialColumn::className()],
  23 + [
  24 + 'class' => ActionColumn::className(),
  25 + 'template'=>'{view}',
  26 + 'contentOptions' => function ($model, $key, $index, $column){
  27 + return ['data' => ['id' => $model->id, 'date' => $model->price_date_update]];
  28 + }
  29 + ],
  30 + [
  31 + 'label' =>'Поставщик',
  32 + 'value' => function ($data) {
  33 + return '№ ' .$data->id . ' ' . $data->name;
  34 + },
  35 + ],
  36 + ['label' =>'Дата обновления',
  37 + 'attribute' => 'price_date_update' ],
  38 + ['label' => 'Кол-во дней',
  39 + 'value' => function ($data) {
  40 + $date1 = new DateTime("now");
  41 + $date2 = new DateTime( $data->price_date_update );
  42 + $quo_days = $date2->diff($date1)->format('%R%a');
  43 + // уберем первый символ - там знак "+"
  44 + $quo_days = substr( $quo_days, 1, strlen($quo_days) );
  45 + $quo_days = (int) $quo_days;
  46 +
  47 + if($quo_days > 15)
  48 + $quo_days = '>15';
  49 +
  50 + return $quo_days;
  51 + }
  52 + ],
  53 + ]] );?>
  54 +
  55 +
  56 +
  57 +
  58 +</div>
0 59 \ No newline at end of file
... ...
backend/views/check-price/view.php 0 → 100644
  1 +<?php
  2 +use yii\helpers\Html;
  3 +use yii\grid\GridView;
  4 +use yii\grid\SerialColumn;
  5 +use yii\bootstrap\Modal;
  6 +
  7 +
  8 +/* @var $this yii\web\View */
  9 +/* @var $searchModel backend\models\CatalogSearch */
  10 +/* @var $dataProvider yii\data\ActiveDataProvider */
  11 +
  12 +$this->title = 'Проверка прайсов';
  13 +$this->params['breadcrumbs'][] = $this->title;
  14 +
  15 +?>
  16 +<div class="catalog-index">
  17 +
  18 + <h1><?= Html::encode($this->title) ?></h1>
  19 +
  20 + <?= GridView::widget( ['dataProvider' => $dataProvider,
  21 +
  22 + ] );
  23 +
  24 +
  25 + ?>
  26 +
  27 +
  28 +
  29 +</div>
  30 +<?php
  31 +
  32 +?>
0 33 \ No newline at end of file
... ...
backend/views/check_price/index.php 0 → 100644
  1 +<?php
  2 +use yii\helpers\Html;
  3 +use yii\grid\GridView;
  4 +use yii\grid\SerialColumn;
  5 +use yii\grid\ActionColumn;
  6 +use yii\widgets\Pjax;
  7 +
  8 +
  9 +/* @var $this yii\web\View */
  10 +/* @var $searchModel backend\models\CatalogSearch */
  11 +/* @var $dataProvider yii\data\ActiveDataProvider */
  12 +
  13 +$this->title = 'Проверка прайсов';
  14 +$this->params['breadcrumbs'][] = $this->title;
  15 +?>
  16 +<div class="catalog-index">
  17 +
  18 + <h1><?= Html::encode($this->title) ?></h1>
  19 +
  20 +
  21 + <?= GridView::widget( ['dataProvider' => $dataProvider,
  22 + 'columns' => [['class' => SerialColumn::className()],
  23 + [
  24 + 'class' => ActionColumn::className(),
  25 + 'template'=>'{view}',
  26 + 'contentOptions' => function ($model, $key, $index, $column){
  27 + return ['data' => ['id' => $model->id, 'date' => $model->price_date_update]];
  28 + }
  29 + ],
  30 + [
  31 + 'label' =>'Поставщик',
  32 + 'value' => function ($data) {
  33 + return '№ ' .$data->id . ' ' . $data->name;
  34 + },
  35 + ],
  36 + ['label' =>'Дата обновления',
  37 + 'attribute' => 'price_date_update' ],
  38 + ['label' => 'Кол-во дней',
  39 + 'value' => function ($data) {
  40 + $date1 = new DateTime("now");
  41 + $date2 = new DateTime( $data->price_date_update );
  42 + $quo_days = $date2->diff($date1)->format('%R%a');
  43 + // уберем первый символ - там знак "+"
  44 + $quo_days = substr( $quo_days, 1, strlen($quo_days) );
  45 + $quo_days = (int) $quo_days;
  46 +
  47 + if($quo_days > 15)
  48 + $quo_days = '>15';
  49 +
  50 + return $quo_days;
  51 + }
  52 + ],
  53 + ]] );?>
  54 +
  55 +
  56 +
  57 +
  58 +</div>
0 59 \ No newline at end of file
... ...
backend/views/check_price/view.php 0 → 100644
  1 +<?php
  2 +use yii\helpers\Html;
  3 +use yii\grid\GridView;
  4 +use yii\grid\SerialColumn;
  5 +use yii\bootstrap\Modal;
  6 +
  7 +
  8 +/* @var $this yii\web\View */
  9 +/* @var $searchModel backend\models\CatalogSearch */
  10 +/* @var $dataProvider yii\data\ActiveDataProvider */
  11 +
  12 +$this->title = 'Проверка прайсов';
  13 +$this->params['breadcrumbs'][] = $this->title;
  14 +
  15 +?>
  16 +<div class="catalog-index">
  17 +
  18 + <h1><?= Html::encode($this->title) ?></h1>
  19 +
  20 + <?= GridView::widget( ['dataProvider' => $dataProvider,
  21 +
  22 + ] );
  23 +
  24 +
  25 + ?>
  26 +
  27 +
  28 +
  29 +</div>
  30 +<?php
  31 +
  32 +?>
0 33 \ No newline at end of file
... ...
backend/views/layouts/column.php
... ... @@ -282,7 +282,13 @@ $this-&gt;beginContent(&#39;@app/views/layouts/main.php&#39;);
282 282 echo Menu::widget([
283 283 'options' => ['class' => 'sidebar-menu'],
284 284 'items' => [
285   - ['label' => "Прайс парсер", 'url' => ['parser/index']],
  285 + ['label' => "Загрузка файлов", 'url' => ['#'], 'items' => [
  286 + ['label' => 'Файлы на сервере', 'url' => ['parser/server-files']],
  287 + ['label' => 'Загрузить файл на сервер', 'url' => ['parser/index', 'mode' => 1]],
  288 + ['label' => 'Ручная загрузка', 'url' => ['parser/index']],
  289 + ['label' => 'Проверка прайс файлов', 'url' => ['check-price/index']],
  290 + ],
  291 + ],
286 292 ['label' => 'Управление ролями', 'url' => ['#'], 'items' => [
287 293 ['label' => 'Покупатели', 'url' => '#'],
288 294 ['label' => 'Поставщики', 'url' => '#'],
... ...
backend/views/parser/index.php
... ... @@ -3,29 +3,50 @@ use yii\widgets\ActiveForm;
3 3 use yii\helpers\Html;
4 4 use backend\models\Importer;
5 5 use yii\helpers\ArrayHelper;
  6 +if ( $model->mode ) {
  7 + // авто загрузка
  8 + $mode = 1;
  9 + $button_label = 'Загрузить';
  10 +} else {
  11 + // ручная загрузка
  12 + $mode = 0;
  13 + $button_label = 'Прочитать';
  14 +}
6 15  
7 16 ?>
8 17 <div class="row">
9 18 <div class="col-lg-5">
10   - <?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data',],'action'=>['parser/results']]);
  19 + <?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data',],'action'=>['parser/results', 'mode' => $mode]]);
11 20 if (!$model->action) {
12 21 $model->action = 1;
13 22 }
  23 + if ($model->success) { // вернулись после успешной загрузки данного файла
  24 + echo Html::tag('h3', 'Файл успешно загружен',['class'=>'bg-success']);
  25 + }
14 26 ?>
15 27 <h3>Загрузка прайсов поставщиков</h3>
16 28  
17 29  
18   - <?= $form->field($model, 'importer')->dropDownList(ArrayHelper::map( Importer::find()->all(), 'id','name' )); ?>
19   - <?= $form->field($model, 'delete_price')->checkbox(['label' => 'Загрузить с удалением старого прайса']) ?>
  30 + <?= $form->field($model, 'importer_id')->dropDownList(ArrayHelper::map( Importer::find()->all(), 'id','name' )); ?>
  31 +
  32 + <?php if ( !$mode ) {
  33 + echo $form->field($model, 'delete_price')->checkbox(['label' => 'Загрузить с удалением старого прайса']);
  34 + }
  35 + ?>
  36 +
20 37 <?= $form->field($model, 'file')->fileInput()->label(false) ?>
21   - <?= $form->field($model, 'action')->radioList([1 => 'Стандартная обработка', 0 => 'С разделителем'])->label(false) ?>
22   - <?= $form->field($model, 'delimiter', ['inputOptions' => ['value' => ';']]) ?>
23 38  
24   - <?= $form->field($model, 'delete_prefix')->checkbox(['label' => 'Удалять префикс']) ?>
  39 + <?php if ( !$mode ) {
  40 + echo $form->field($model, 'action')->radioList([1 => 'Стандартная обработка', 0 => 'С разделителем'])->label(false);
  41 + echo $form->field($model, 'delimiter', ['inputOptions' => ['value' => ';']]);
  42 +
  43 + echo $form->field($model, 'delete_prefix')->checkbox(['label' => 'Удалять префикс']);
  44 + }
  45 + ?>
25 46  
26 47  
27 48 <div class="form-group">
28   - <?= Html::submitButton(Yii::t('app', 'Прочитать'), ['class' => 'btn btn-primary']) ?>
  49 + <?= Html::submitButton(Yii::t( 'app', $button_label ), ['class' => 'btn btn-primary']) ?>
29 50 </div>
30 51  
31 52 <?php ActiveForm::end() ?>
... ...
backend/views/parser/server-files.php 0 → 100644
  1 +<?php
  2 +use yii\helpers\Html;
  3 +use yii\grid\GridView;
  4 +use yii\grid\SerialColumn;
  5 +use yii\grid\ActionColumn;
  6 +use yii\widgets\Pjax;
  7 +
  8 +
  9 +/* @var $this yii\web\View */
  10 +/* @var $searchModel backend\models\CatalogSearch */
  11 +/* @var $dataProvider yii\data\ActiveDataProvider */
  12 +
  13 +$this->title = 'Проверка прайсов';
  14 +$this->params['breadcrumbs'][] = $this->title;
  15 +Pjax::begin();
  16 +
  17 +?>
  18 + <div class="catalog-index">
  19 +
  20 + <h1><?= Html::encode($this->title) ?></h1>
  21 +
  22 + <?= GridView::widget( ['dataProvider' => $dataProvider,
  23 + 'columns' => [['class' => SerialColumn::className()],
  24 + [
  25 + 'label' =>'Поставщик',
  26 + 'value' => function ($data) {
  27 + return $data->importer;
  28 + },
  29 + ],
  30 + ['label' =>'Дата загрузки',
  31 + 'attribute' => 'upload_time' ],
  32 +
  33 + ['class' => ActionColumn::className(),
  34 + 'template'=>'{delete}',
  35 + 'buttons' => [
  36 + 'delete' => function ($url, $model, $key) {
  37 + return Html::a('<span class="glyphicon glyphicon-remove"></span>', $url, [
  38 + 'title' => Yii::t('yii', 'Удалить файл'),
  39 + 'data-confirm' => 'Вы уверены что хотите удалить этот файл?',
  40 + 'data-method' => 'post',
  41 + 'data-pjax' => '1',
  42 + ]);
  43 + },
  44 + ],
  45 + ]
  46 +
  47 + ]] );?>
  48 +
  49 +
  50 +
  51 + </div>
  52 +<?php
  53 +Pjax::end();
  54 +?>
0 55 \ No newline at end of file
... ...
common/config/bootstrap.php
... ... @@ -3,3 +3,5 @@ Yii::setAlias(&#39;common&#39;, dirname(__DIR__));
3 3 Yii::setAlias('frontend', dirname(dirname(__DIR__)) . '/frontend');
4 4 Yii::setAlias('backend', dirname(dirname(__DIR__)) . '/backend');
5 5 Yii::setAlias('console', dirname(dirname(__DIR__)) . '/console');
  6 +Yii::setAlias('auto_upload', dirname(dirname(__DIR__)) . '/backend/uploads/auto');
  7 +Yii::setAlias('manual_upload', dirname(dirname(__DIR__)) . '/backend/uploads/manual');
... ...
console/migrations/m150915_125129_addDetails.php 0 → 100644
  1 +<?php
  2 +
  3 +use yii\db\Schema;
  4 +use yii\db\Migration;
  5 +
  6 +class m150915_125129_addDetails extends Migration
  7 +{
  8 + public function up()
  9 + {
  10 + $this->execute('CREATE TABLE `details` (
  11 + `ID` int(10) unsigned NOT NULL AUTO_INCREMENT,
  12 + `IMPORT_ID` int(6) unsigned NOT NULL,
  13 + `BRAND` varchar(100) NOT NULL,
  14 + `ARTICLE` varchar(100) NOT NULL,
  15 + `FULL_ARTICLE` varchar(150) NOT NULL,
  16 + `PRICE` float(15,2) unsigned NOT NULL,
  17 + `DESCR` varchar(200) NOT NULL,
  18 + `BOX` int(6) unsigned NOT NULL,
  19 + `ADD_BOX` int(6) unsigned NOT NULL DEFAULT 0,
  20 + `GROUP` varchar(200) NOT NULL DEFAULT \'\',
  21 + `timestamp` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  22 + PRIMARY KEY (`ARTICLE`,`BRAND`,`IMPORT_ID`),
  23 + UNIQUE KEY `ID_delete` (`ID`),
  24 + KEY `timestamp` (`timestamp`),
  25 + KEY `ARTICLE` (`ARTICLE`,`BRAND`,`BOX`),
  26 + KEY `BRAND` (`BRAND`,`ARTICLE`),
  27 + KEY `ARTICLE_2` (`ARTICLE`,`BRAND`,`ADD_BOX`),
  28 + KEY `IMPORT_ID` (`IMPORT_ID`,`ARTICLE`),
  29 + KEY `IMPORT_ID_2` (`IMPORT_ID`,`timestamp`)
  30 + ) ENGINE=InnoDB DEFAULT CHARSET=utf8');
  31 +
  32 + }
  33 +
  34 + public function down()
  35 + {
  36 + $this->dropTable('{{%details}}');
  37 +
  38 + }
  39 +
  40 +}
... ...
console/migrations/m150922_094313_change_key_ImportFiles.php 0 → 100644
  1 +<?php
  2 +
  3 +use yii\db\Schema;
  4 +use yii\db\Migration;
  5 +
  6 +class m150922_094313_change_key_ImportFiles extends Migration
  7 +{
  8 + //@todo вероятно что эта миграция ненужна - посмотреть ближе к концу проекта на ключи которые используются - остальные удалить.
  9 + public function up()
  10 + {
  11 + $this->dropIndex('importer_id', '{{%importer_files}}');
  12 + $this->createIndex('importer_id', '{{%importer_files}}', 'importer_id, upload_time', false);
  13 + }
  14 +
  15 + public function down()
  16 + {
  17 + $this->dropIndex('importer_id', '{{%importer_files}}');
  18 + $this->createIndex('importer_id', '{{%importer_files}}', 'importer_id, time_start', false);
  19 + }
  20 +
  21 +
  22 +}
... ...
console/migrations/m150922_144040_change_Importer_dataPrice.php 0 → 100644
  1 +<?php
  2 +
  3 +use yii\db\Schema;
  4 +use yii\db\Migration;
  5 +
  6 +class m150922_144040_change_Importer_dataPrice extends Migration
  7 +{
  8 + public function up()
  9 + {
  10 + $this->alterColumn('{{%importer}}','price_date_update','TIMESTAMP' );
  11 + $this->createIndex('price_date', '{{%importer}}', 'price_date_update', false);
  12 + }
  13 +
  14 + public function down()
  15 + {
  16 + $this->alterColumn('{{%importer}}','price_date','varchar(15)' );
  17 + $this->dropIndex('price_date', '{{%importer}}');
  18 + }
  19 +
  20 +
  21 +}
... ...
console/migrations/m150925_111922_add_foreign_key_ImportFiles.php 0 → 100644
  1 +<?php
  2 +
  3 +use yii\db\Schema;
  4 +use yii\db\Migration;
  5 +
  6 +class m150925_111922_add_foreign_key_ImportFiles extends Migration
  7 +{
  8 + public function up()
  9 + {
  10 + $this->addForeignKey('importer_fk', '{{%importer_files}}', 'importer_id', '{{%importer}}', 'id');
  11 + }
  12 +
  13 + public function down()
  14 + {
  15 + $this->dropForeignKey('importer_fk', '{{%importer_files}}');
  16 + }
  17 +
  18 +}
... ...