From 293f57f9671ade705fed08ea1ad47d5acd97a6bb Mon Sep 17 00:00:00 2001 From: Mihail Date: Wed, 28 Oct 2015 13:48:58 +0200 Subject: [PATCH] add upload rg group form --- backend/controllers/ParserController.php | 1 - backend/controllers/RgGrupController.php | 202 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ backend/models/UploadFileRgForm.php | 61 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ backend/views/layouts/column.php | 2 ++ backend/views/rg-grup/index.php | 33 +++++++++++++++++++++++++++++++++ backend/views/rg-grup/results.php | 32 ++++++++++++++++++++++++++++++++ common/components/CustomArrayHelper.php | 9 +++++---- common/components/parsers/config.php | 4 ++-- common/models/Margins.php | 18 ++++++++++++++++++ composer.lock | 10 +++++----- vendor/composer/installed.json | 10 +++++----- 11 files changed, 365 insertions(+), 17 deletions(-) create mode 100644 backend/controllers/RgGrupController.php create mode 100644 backend/models/UploadFileRgForm.php create mode 100644 backend/views/rg-grup/index.php create mode 100644 backend/views/rg-grup/results.php diff --git a/backend/controllers/ParserController.php b/backend/controllers/ParserController.php index 7ae4546..89843d0 100644 --- a/backend/controllers/ParserController.php +++ b/backend/controllers/ParserController.php @@ -144,7 +144,6 @@ class ParserController extends BaseController ], ]); - $last_index = end( array_flip( $data[0] ) ); $header_counts = $last_index + 1; //формируем заголовок для пользователя, где он сможет выбрать соответсвие полей (выпадающий список) diff --git a/backend/controllers/RgGrupController.php b/backend/controllers/RgGrupController.php new file mode 100644 index 0000000..9bd647e --- /dev/null +++ b/backend/controllers/RgGrupController.php @@ -0,0 +1,202 @@ + [ + 'class' => AccessControl::className(), + 'rules' => [ + [ + 'allow' => true, + 'roles' => ['@'], + ], + ], + ], +// 'verbs' => [ +// 'class' => VerbFilter::className(), +// 'actions' => [ +// 'logout' => ['post'], +// ], +// ], + ]; + } + + public function actionIndex() + { + $model = new UploadFileRgForm(); + + return $this->render('index', ['model' => $model]); + } + + public function actionResults() + { + $model = new UploadFileRgForm(); + $data = []; + + if ($model->load(Yii::$app->request->post())) { + $model->file = UploadedFile::getInstance($model, 'file'); + // первый проход - валидируем, сохраняем файл, ложим в кеш отпарсенные данные и параметры модели (потом при записи в базу данных они пригодятся) + if ($model->validate()) { + + $model->file_path = Yii::getAlias('@manual_upload') . '/' . $model->file->name; + $model->file->saveAs($model->file_path); + + //запускаем парсинг + $data = $model->readFile(); + // сохраняем в кеш отпарсенные даные + Yii::$app->getCache()->set('parser_data', json_encode($data)); + // сохраняем в кеш модель - в ней настройки для дальнейшей обработки данных + Yii::$app->getCache()->set('parser_configuration', serialize($model)); + + + } else { + // не прошла валидация форма загрузки файлов + $errors_str = ''; + foreach ($model->getErrors() as $error) { + $errors_str .= implode( array_values($error) ); + } + throw new \ErrorException( $errors_str ); + } + // листаем пагинатором, или повторно вызываем - считываем из кеша отпрасенные данные + } else if (Yii::$app->getCache()->get('parser_data')) { + + $data = json_decode(Yii::$app->getCache()->get('parser_data'), true); + + } + $provider = new ArrayDataProvider([ + 'allModels' => $data, + 'pagination' => [ + 'pageSize' => 10, + ], + ]); + + // создадим модель на столько реквизитов сколько колонок в отпарсенном файле + $last_index = end( array_flip( $data[0] ) ); + $header_counts = $last_index + 1; + $header_model = DynamicFormHelper::CreateDynamicModel( $header_counts ); + + // соберем массив данных из которых будет пользователь выбирать значения в конструкторе (выпадающий список) + $header_array = Margins::getHeader(); + + return $this->render('results', + ['model' => $data, + 'header_model' => $header_model, + // список колонок для выбора + 'basic_column' => $header_array, + 'dataProvider' => $provider]); + } + + public function actionWrite() + { + //получим колонки которые выбрал пользователь + $arr_attributes = Yii::$app->request->post()['DynamicModel']; + //соберем модель по полученным данным + $model = DynamicFormHelper::CreateDynamicModel($arr_attributes); + //добавим правила валидации (колонки должны быть те что в модели) + foreach ($arr_attributes as $key => $value) { + $model->addRule($key, 'in', ['range' => array_keys(Margins::getHeader())]); + } + + // провалидируем выбранные колонки + if ($model->validate()) { + + // валидация успешна у нас есть соответсвие колонок, преобразуем в массив данное соответсвие для дальнейшей работы + $arr = $model->toArray(); + + // получим данные из кеша + if (Yii::$app->getCache()->get('parser_data') && Yii::$app->getCache()->get('parser_configuration')) { + $data = json_decode(Yii::$app->getCache()->get('parser_data'), true); + $configuration = unserialize(Yii::$app->getCache()->get('parser_configuration')); + } else { + throw new \ErrorException('Ошибка кеша'); + } + + array_walk($arr, function(&$val){ + $val = '!'.$val; + }); + + // соотнесем отпарсенные данные с соответсивем полученным от пользователя + // для этого преобразуем массив отпарсенных данных - назначим ключи согласно соответствию + $data = CustomArrayHelper::createAssocArray( $data, $arr , 'attr_' ); + + // в первой строке у нас заголовки - уберем + unset($data[0]); + // подготовим данные для записи в таблицу w_margins_groups + //$arr_values = []; + $group = ''; + $importer_id = $configuration['importer_id']; + foreach ($data as $row_data) { + + if (isset($row_data['!group'])) { + $group = $row_data['!group']; + unset($row_data['!group']); + } + if (isset($row_data['!_null'])) { + unset($row_data['!_null']); + } + + foreach ($row_data as $key => $value) { + if($group) + $row['group'] = trim( $group ); + + $row['importer_id'] = trim( $importer_id ); + $row['margin_id'] = ltrim($key,'!'); + $row['koef'] = \Yii::$app->converter->convertTo( 'float', $value ); + + // сохраним подготовленные данные + $margins_groups = new MarginsGroups(); + $margins_groups->attributes = $row; + + if ( !$margins_groups->save() ) { + $errors_str = ''; + foreach ($margins_groups->getErrors() as $error) { + $errors_str .= implode( array_values($error) ); + } + throw new \ErrorException( $errors_str ); + } + } + + Yii::$app->session->setFlash('success'); + // все прошло успешно - очищаем кеш + Yii::$app->getCache()->delete('parser_data'); + Yii::$app->getCache()->delete('parser_configuration'); + + if( file_exists($configuration['file_path']) ) + unlink($configuration['file_path']); + + return $this->render('index', ['model' => $configuration]); + + + + } + + } + + } +} \ No newline at end of file diff --git a/backend/models/UploadFileRgForm.php b/backend/models/UploadFileRgForm.php new file mode 100644 index 0000000..3d75918 --- /dev/null +++ b/backend/models/UploadFileRgForm.php @@ -0,0 +1,61 @@ + 'Не выбран файл!' ], + ['importer_id', 'required', 'message' => 'Не указан поставщик!' ], + [['file'], 'file', 'extensions' => 'xlsx', 'checkExtensionByMimeType'=>false ] + ]; + } + + public function attributeLabels() + { + return [ + 'file' => Yii::t('app', 'Источник'), + 'importer_id' => Yii::t('app', 'Поставщик'), + ]; + } + + public function readFile( $options = [] ){ + + $data = Yii::$app->multiparser->parse( $this->file_path, $options ); + if( !is_array( $data ) ){ + throw new ErrorException("Ошибка чтения из файла RG групп {$this->file_path}"); + } + + + return $data; + } + + function __destruct() + { + // файл больше не нужен - данные прочитаны и сохранены в кеш + // if( file_exists($this->file_path) ) + // unlink($this->file_path); + } + + +} \ No newline at end of file diff --git a/backend/views/layouts/column.php b/backend/views/layouts/column.php index 048a5c8..0911f48 100644 --- a/backend/views/layouts/column.php +++ b/backend/views/layouts/column.php @@ -283,6 +283,8 @@ $this->beginContent('@app/views/layouts/main.php'); 'options' => ['class' => 'sidebar-menu'], 'items' => [ ['label' => "Загрузка файлов", 'url' => ['#'], 'items' => [ + ['label' => 'Кросс файлы', 'url' => ['crossing-upload/index']], + ['label' => 'Группы RG', 'url' => ['rg-grup/index']], ['label' => 'Файлы на сервере', 'url' => ['parser/server-files']], ['label' => 'Загрузить файл на сервер', 'url' => ['parser/index', 'mode' => 1]], ['label' => 'Ручная загрузка', 'url' => ['parser/index']], diff --git a/backend/views/rg-grup/index.php b/backend/views/rg-grup/index.php new file mode 100644 index 0000000..47addb0 --- /dev/null +++ b/backend/views/rg-grup/index.php @@ -0,0 +1,33 @@ + +
+
+ ['enctype' => 'multipart/form-data',],'action'=>['rg-grup/results']]); + + if ($msg = \Yii::$app->session->getFlash('success')) { // вернулись после успешной загрузки данного файла + echo Html::tag('h3', $msg ,['class'=>'bg-success']); + } + ?> +

Загрузка RG групп поставщиков

+ + + field($model, 'importer_id')->dropDownList(ArrayHelper::map( Importers::find()->all(), 'id','name' )); ?> + + + field($model, 'file')->fileInput()->label(false) ?> +
+ 'btn btn-primary']) ?> +
+ + +
+
+ diff --git a/backend/views/rg-grup/results.php b/backend/views/rg-grup/results.php new file mode 100644 index 0000000..d760491 --- /dev/null +++ b/backend/views/rg-grup/results.php @@ -0,0 +1,32 @@ +title = 'Отпарсенные данные файла'; +$this->params['breadcrumbs'][] = $this->title; +?> +
+ +

title) ?>

+ render('_search', ['model' => $searchModel]); + + + $form = ActiveForm::begin(['action' => 'write']); + ?> + + +
+ 'btn btn-primary']) ?> +
+ + + 'btn btn-primary', 'name' => 'Return',]) ?> + +
\ No newline at end of file diff --git a/common/components/CustomArrayHelper.php b/common/components/CustomArrayHelper.php index bd76aa6..32612a2 100644 --- a/common/components/CustomArrayHelper.php +++ b/common/components/CustomArrayHelper.php @@ -34,8 +34,8 @@ class CustomArrayHelper extends \yii\helpers\ArrayHelper { return $value !== ''; }); } + array_walk( $value_arr, - array_walk($value_arr, function (&$value, $key, $key_array) { $res = $value; foreach ($res as $sub_key => $sub_value) { @@ -46,12 +46,13 @@ class CustomArrayHelper extends \yii\helpers\ArrayHelper { $res[$new_key] = $value[$sub_key]; } } - unset($res[$sub_key]); - $value = $res; + unset($res[$sub_key]); + $value = $res; } }, - $key_array); + + $key_array ); return $value_arr; } diff --git a/common/components/parsers/config.php b/common/components/parsers/config.php index b273c29..b67f9bf 100644 --- a/common/components/parsers/config.php +++ b/common/components/parsers/config.php @@ -71,8 +71,8 @@ ['web' => ['class' => 'yii\multiparser\XlsxParser', 'path_for_extract_files' => \Yii::getAlias('@temp_upload') . '/xlsx/', - 'has_header_row' => true, - 'active_sheet' => 2, + // 'has_header_row' => true, + 'active_sheet' => 1, 'converter_conf' => [ 'class' => 'common\components\parsers\CustomConverter', 'configuration' => ["string" => []], diff --git a/common/models/Margins.php b/common/models/Margins.php index 2ded5c0..209853e 100644 --- a/common/models/Margins.php +++ b/common/models/Margins.php @@ -45,4 +45,22 @@ class Margins extends \yii\db\ActiveRecord 'koef' => 'Коэффициент', ]; } + + // возвращает массив для выбора в динамических формах (конструкторах) + public static function getHeader() + { + $header_array = self::find()->asArray()->all(); + + $id_arr = array_column($header_array,'id'); + $name_arr = array_column($header_array,'name'); + $header_array = array_combine( $id_arr, $name_arr ); + $header_array['_null'] = null; // первая колонка пустая + $header_array['group'] = 'Группа RG'; + ksort($header_array); + + return $header_array; + } + + + } diff --git a/composer.lock b/composer.lock index 36ad68f..74c912a 100644 --- a/composer.lock +++ b/composer.lock @@ -12,13 +12,13 @@ "version": "dev-master", "source": { "type": "git", - "url": "git@github.com:tsurkanovm/yii-multiparser.git", - "reference": "d1fac7a9ab175babccfe47e9a448528b154db928" + "url": "https://github.com/tsurkanovm/yii-multiparser.git", + "reference": "0c6fd004d8739f106a58f584661e1e5327958b34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tsurkanovm/yii-multiparser/zipball/d1fac7a9ab175babccfe47e9a448528b154db928", - "reference": "d1fac7a9ab175babccfe47e9a448528b154db928", + "url": "https://api.github.com/repos/tsurkanovm/yii-multiparser/zipball/0c6fd004d8739f106a58f584661e1e5327958b34", + "reference": "0c6fd004d8739f106a58f584661e1e5327958b34", "shasum": "" }, "require": { @@ -50,7 +50,7 @@ "xml", "yii2" ], - "time": "2015-10-27 11:59:34" + "time": "2015-10-28 09:28:22" }, { "name": "bower-asset/bootstrap", diff --git a/vendor/composer/installed.json b/vendor/composer/installed.json index 151269b..28ec5be 100644 --- a/vendor/composer/installed.json +++ b/vendor/composer/installed.json @@ -1050,19 +1050,19 @@ "version_normalized": "9999999-dev", "source": { "type": "git", - "url": "git@github.com:tsurkanovm/yii-multiparser.git", - "reference": "d1fac7a9ab175babccfe47e9a448528b154db928" + "url": "https://github.com/tsurkanovm/yii-multiparser.git", + "reference": "0c6fd004d8739f106a58f584661e1e5327958b34" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tsurkanovm/yii-multiparser/zipball/d1fac7a9ab175babccfe47e9a448528b154db928", - "reference": "d1fac7a9ab175babccfe47e9a448528b154db928", + "url": "https://api.github.com/repos/tsurkanovm/yii-multiparser/zipball/0c6fd004d8739f106a58f584661e1e5327958b34", + "reference": "0c6fd004d8739f106a58f584661e1e5327958b34", "shasum": "" }, "require": { "yiisoft/yii2": "*" }, - "time": "2015-10-27 11:59:34", + "time": "2015-10-28 09:28:22", "type": "library", "installation-source": "dist", "autoload": { -- libgit2 0.21.4