Commit 293f57f9671ade705fed08ea1ad47d5acd97a6bb

Authored by Mihail
1 parent 603a219f

add upload rg group form

backend/controllers/ParserController.php
@@ -144,7 +144,6 @@ class ParserController extends BaseController @@ -144,7 +144,6 @@ class ParserController extends BaseController
144 ], 144 ],
145 ]); 145 ]);
146 146
147 -  
148 $last_index = end( array_flip( $data[0] ) ); 147 $last_index = end( array_flip( $data[0] ) );
149 $header_counts = $last_index + 1; 148 $header_counts = $last_index + 1;
150 //формируем заголовок для пользователя, где он сможет выбрать соответсвие полей (выпадающий список) 149 //формируем заголовок для пользователя, где он сможет выбрать соответсвие полей (выпадающий список)
backend/controllers/RgGrupController.php 0 → 100644
  1 +<?php
  2 +/**
  3 + * Created by PhpStorm.
  4 + * User: Tsurkanov
  5 + * Date: 27.10.2015
  6 + * Time: 15:22
  7 + */
  8 +
  9 +namespace backend\controllers;
  10 +
  11 +use backend\components\base\BaseController;
  12 +use backend\models\UploadFileRgForm;
  13 +use common\components\CustomVarDamp;
  14 +use common\models\Margins;
  15 +use common\models\MarginsGroups;
  16 +use yii\filters\AccessControl;
  17 +use Yii;
  18 +use yii\web\UploadedFile;
  19 +use yii\data\ArrayDataProvider;
  20 +use yii\multiparser\DynamicFormHelper;
  21 +use common\components\CustomArrayHelper;
  22 +
  23 +class RgGrupController extends BaseController {
  24 + public $layout = "/column";
  25 +
  26 + /**
  27 + * @inheritdoc
  28 + */
  29 + public function behaviors()
  30 + {
  31 + return [
  32 + 'access' => [
  33 + 'class' => AccessControl::className(),
  34 + 'rules' => [
  35 + [
  36 + 'allow' => true,
  37 + 'roles' => ['@'],
  38 + ],
  39 + ],
  40 + ],
  41 +// 'verbs' => [
  42 +// 'class' => VerbFilter::className(),
  43 +// 'actions' => [
  44 +// 'logout' => ['post'],
  45 +// ],
  46 +// ],
  47 + ];
  48 + }
  49 +
  50 + public function actionIndex()
  51 + {
  52 + $model = new UploadFileRgForm();
  53 +
  54 + return $this->render('index', ['model' => $model]);
  55 + }
  56 +
  57 + public function actionResults()
  58 + {
  59 + $model = new UploadFileRgForm();
  60 + $data = [];
  61 +
  62 + if ($model->load(Yii::$app->request->post())) {
  63 + $model->file = UploadedFile::getInstance($model, 'file');
  64 + // первый проход - валидируем, сохраняем файл, ложим в кеш отпарсенные данные и параметры модели (потом при записи в базу данных они пригодятся)
  65 + if ($model->validate()) {
  66 +
  67 + $model->file_path = Yii::getAlias('@manual_upload') . '/' . $model->file->name;
  68 + $model->file->saveAs($model->file_path);
  69 +
  70 + //запускаем парсинг
  71 + $data = $model->readFile();
  72 + // сохраняем в кеш отпарсенные даные
  73 + Yii::$app->getCache()->set('parser_data', json_encode($data));
  74 + // сохраняем в кеш модель - в ней настройки для дальнейшей обработки данных
  75 + Yii::$app->getCache()->set('parser_configuration', serialize($model));
  76 +
  77 +
  78 + } else {
  79 + // не прошла валидация форма загрузки файлов
  80 + $errors_str = '';
  81 + foreach ($model->getErrors() as $error) {
  82 + $errors_str .= implode( array_values($error) );
  83 + }
  84 + throw new \ErrorException( $errors_str );
  85 + }
  86 + // листаем пагинатором, или повторно вызываем - считываем из кеша отпрасенные данные
  87 + } else if (Yii::$app->getCache()->get('parser_data')) {
  88 +
  89 + $data = json_decode(Yii::$app->getCache()->get('parser_data'), true);
  90 +
  91 + }
  92 + $provider = new ArrayDataProvider([
  93 + 'allModels' => $data,
  94 + 'pagination' => [
  95 + 'pageSize' => 10,
  96 + ],
  97 + ]);
  98 +
  99 + // создадим модель на столько реквизитов сколько колонок в отпарсенном файле
  100 + $last_index = end( array_flip( $data[0] ) );
  101 + $header_counts = $last_index + 1;
  102 + $header_model = DynamicFormHelper::CreateDynamicModel( $header_counts );
  103 +
  104 + // соберем массив данных из которых будет пользователь выбирать значения в конструкторе (выпадающий список)
  105 + $header_array = Margins::getHeader();
  106 +
  107 + return $this->render('results',
  108 + ['model' => $data,
  109 + 'header_model' => $header_model,
  110 + // список колонок для выбора
  111 + 'basic_column' => $header_array,
  112 + 'dataProvider' => $provider]);
  113 + }
  114 +
  115 + public function actionWrite()
  116 + {
  117 + //получим колонки которые выбрал пользователь
  118 + $arr_attributes = Yii::$app->request->post()['DynamicModel'];
  119 + //соберем модель по полученным данным
  120 + $model = DynamicFormHelper::CreateDynamicModel($arr_attributes);
  121 + //добавим правила валидации (колонки должны быть те что в модели)
  122 + foreach ($arr_attributes as $key => $value) {
  123 + $model->addRule($key, 'in', ['range' => array_keys(Margins::getHeader())]);
  124 + }
  125 +
  126 + // провалидируем выбранные колонки
  127 + if ($model->validate()) {
  128 +
  129 + // валидация успешна у нас есть соответсвие колонок, преобразуем в массив данное соответсвие для дальнейшей работы
  130 + $arr = $model->toArray();
  131 +
  132 + // получим данные из кеша
  133 + if (Yii::$app->getCache()->get('parser_data') && Yii::$app->getCache()->get('parser_configuration')) {
  134 + $data = json_decode(Yii::$app->getCache()->get('parser_data'), true);
  135 + $configuration = unserialize(Yii::$app->getCache()->get('parser_configuration'));
  136 + } else {
  137 + throw new \ErrorException('Ошибка кеша');
  138 + }
  139 +
  140 + array_walk($arr, function(&$val){
  141 + $val = '!'.$val;
  142 + });
  143 +
  144 + // соотнесем отпарсенные данные с соответсивем полученным от пользователя
  145 + // для этого преобразуем массив отпарсенных данных - назначим ключи согласно соответствию
  146 + $data = CustomArrayHelper::createAssocArray( $data, $arr , 'attr_' );
  147 +
  148 + // в первой строке у нас заголовки - уберем
  149 + unset($data[0]);
  150 + // подготовим данные для записи в таблицу w_margins_groups
  151 + //$arr_values = [];
  152 + $group = '';
  153 + $importer_id = $configuration['importer_id'];
  154 + foreach ($data as $row_data) {
  155 +
  156 + if (isset($row_data['!group'])) {
  157 + $group = $row_data['!group'];
  158 + unset($row_data['!group']);
  159 + }
  160 + if (isset($row_data['!_null'])) {
  161 + unset($row_data['!_null']);
  162 + }
  163 +
  164 + foreach ($row_data as $key => $value) {
  165 + if($group)
  166 + $row['group'] = trim( $group );
  167 +
  168 + $row['importer_id'] = trim( $importer_id );
  169 + $row['margin_id'] = ltrim($key,'!');
  170 + $row['koef'] = \Yii::$app->converter->convertTo( 'float', $value );
  171 +
  172 + // сохраним подготовленные данные
  173 + $margins_groups = new MarginsGroups();
  174 + $margins_groups->attributes = $row;
  175 +
  176 + if ( !$margins_groups->save() ) {
  177 + $errors_str = '';
  178 + foreach ($margins_groups->getErrors() as $error) {
  179 + $errors_str .= implode( array_values($error) );
  180 + }
  181 + throw new \ErrorException( $errors_str );
  182 + }
  183 + }
  184 +
  185 + Yii::$app->session->setFlash('success');
  186 + // все прошло успешно - очищаем кеш
  187 + Yii::$app->getCache()->delete('parser_data');
  188 + Yii::$app->getCache()->delete('parser_configuration');
  189 +
  190 + if( file_exists($configuration['file_path']) )
  191 + unlink($configuration['file_path']);
  192 +
  193 + return $this->render('index', ['model' => $configuration]);
  194 +
  195 +
  196 +
  197 + }
  198 +
  199 + }
  200 +
  201 + }
  202 +}
0 \ No newline at end of file 203 \ No newline at end of file
backend/models/UploadFileRgForm.php 0 → 100644
  1 +<?php
  2 +namespace backend\models;
  3 +
  4 +use yii\base\ErrorException;
  5 +use yii\base\Model;
  6 +use yii\web\UploadedFile;
  7 +use Yii;
  8 +use common\components\CustomVarDamp;
  9 +
  10 +/**
  11 + * UploadForm is the model behind the upload form.
  12 + */
  13 +class UploadFileRgForm extends Model
  14 +{
  15 + /**
  16 + * @var UploadedFile file attribute
  17 + */
  18 + // атрибуты формы
  19 + public $file;
  20 + public $file_path;
  21 + public $importer_id;
  22 +
  23 +
  24 +
  25 + public function rules()
  26 + {
  27 + return [
  28 + ['file', 'required', 'message' => 'Не выбран файл!' ],
  29 + ['importer_id', 'required', 'message' => 'Не указан поставщик!' ],
  30 + [['file'], 'file', 'extensions' => 'xlsx', 'checkExtensionByMimeType'=>false ]
  31 + ];
  32 + }
  33 +
  34 + public function attributeLabels()
  35 + {
  36 + return [
  37 + 'file' => Yii::t('app', 'Источник'),
  38 + 'importer_id' => Yii::t('app', 'Поставщик'),
  39 + ];
  40 + }
  41 +
  42 + public function readFile( $options = [] ){
  43 +
  44 + $data = Yii::$app->multiparser->parse( $this->file_path, $options );
  45 + if( !is_array( $data ) ){
  46 + throw new ErrorException("Ошибка чтения из файла RG групп {$this->file_path}");
  47 + }
  48 +
  49 +
  50 + return $data;
  51 + }
  52 +
  53 + function __destruct()
  54 + {
  55 + // файл больше не нужен - данные прочитаны и сохранены в кеш
  56 + // if( file_exists($this->file_path) )
  57 + // unlink($this->file_path);
  58 + }
  59 +
  60 +
  61 +}
0 \ No newline at end of file 62 \ No newline at end of file
backend/views/layouts/column.php
@@ -283,6 +283,8 @@ $this-&gt;beginContent(&#39;@app/views/layouts/main.php&#39;); @@ -283,6 +283,8 @@ $this-&gt;beginContent(&#39;@app/views/layouts/main.php&#39;);
283 'options' => ['class' => 'sidebar-menu'], 283 'options' => ['class' => 'sidebar-menu'],
284 'items' => [ 284 'items' => [
285 ['label' => "Загрузка файлов", 'url' => ['#'], 'items' => [ 285 ['label' => "Загрузка файлов", 'url' => ['#'], 'items' => [
  286 + ['label' => 'Кросс файлы', 'url' => ['crossing-upload/index']],
  287 + ['label' => 'Группы RG', 'url' => ['rg-grup/index']],
286 ['label' => 'Файлы на сервере', 'url' => ['parser/server-files']], 288 ['label' => 'Файлы на сервере', 'url' => ['parser/server-files']],
287 ['label' => 'Загрузить файл на сервер', 'url' => ['parser/index', 'mode' => 1]], 289 ['label' => 'Загрузить файл на сервер', 'url' => ['parser/index', 'mode' => 1]],
288 ['label' => 'Ручная загрузка', 'url' => ['parser/index']], 290 ['label' => 'Ручная загрузка', 'url' => ['parser/index']],
backend/views/rg-grup/index.php 0 → 100644
  1 +<?php
  2 +use yii\widgets\ActiveForm;
  3 +use yii\helpers\Html;
  4 +use backend\models\Importers;
  5 +use yii\helpers\ArrayHelper;
  6 +
  7 +$button_label = 'Прочитать';
  8 +
  9 +
  10 +?>
  11 +<div class="row">
  12 + <div class="col-lg-5">
  13 + <?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data',],'action'=>['rg-grup/results']]);
  14 +
  15 + if ($msg = \Yii::$app->session->getFlash('success')) { // вернулись после успешной загрузки данного файла
  16 + echo Html::tag('h3', $msg ,['class'=>'bg-success']);
  17 + }
  18 + ?>
  19 + <h3>Загрузка RG групп поставщиков</h3>
  20 +
  21 +
  22 + <?= $form->field($model, 'importer_id')->dropDownList(ArrayHelper::map( Importers::find()->all(), 'id','name' )); ?>
  23 +
  24 +
  25 + <?= $form->field($model, 'file')->fileInput()->label(false) ?>
  26 + <div class="form-group">
  27 + <?= Html::submitButton(Yii::t( 'app', $button_label ), ['class' => 'btn btn-primary']) ?>
  28 + </div>
  29 +
  30 + <?php ActiveForm::end() ?>
  31 + </div>
  32 +</div>
  33 +
backend/views/rg-grup/results.php 0 → 100644
  1 +<?php
  2 +
  3 +use yii\helpers\Html;
  4 +use yii\multiparser\DynamicFormHelper;
  5 +use yii\widgets\ActiveForm;
  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 +<div class="catalog-index">
  16 +
  17 + <h1><?= Html::encode($this->title) ?></h1>
  18 + <?php // echo $this->render('_search', ['model' => $searchModel]);
  19 +
  20 +
  21 + $form = ActiveForm::begin(['action' => 'write']);
  22 + ?>
  23 + <?= DynamicFormHelper::CreateGridWithDropDownListHeader( $dataProvider, $form, $header_model, $basic_column )?>
  24 +
  25 + <div class="form-group">
  26 + <?= Html::submitButton(Yii::t('app', 'Записать в БД'), ['class' => 'btn btn-primary']) ?>
  27 + </div>
  28 +
  29 + <?php ActiveForm::end() ?>
  30 + <?= Html::a('Вернуться', ['rg-grup/index'], ['class' => 'btn btn-primary', 'name' => 'Return',]) ?>
  31 +
  32 +</div>
0 \ No newline at end of file 33 \ No newline at end of file
common/components/CustomArrayHelper.php
@@ -34,8 +34,8 @@ class CustomArrayHelper extends \yii\helpers\ArrayHelper { @@ -34,8 +34,8 @@ class CustomArrayHelper extends \yii\helpers\ArrayHelper {
34 return $value !== ''; 34 return $value !== '';
35 }); 35 });
36 } 36 }
  37 + array_walk( $value_arr,
37 38
38 - array_walk($value_arr,  
39 function (&$value, $key, $key_array) { 39 function (&$value, $key, $key_array) {
40 $res = $value; 40 $res = $value;
41 foreach ($res as $sub_key => $sub_value) { 41 foreach ($res as $sub_key => $sub_value) {
@@ -46,12 +46,13 @@ class CustomArrayHelper extends \yii\helpers\ArrayHelper { @@ -46,12 +46,13 @@ class CustomArrayHelper extends \yii\helpers\ArrayHelper {
46 $res[$new_key] = $value[$sub_key]; 46 $res[$new_key] = $value[$sub_key];
47 } 47 }
48 } 48 }
49 - unset($res[$sub_key]);  
50 - $value = $res; 49 + unset($res[$sub_key]);
  50 + $value = $res;
51 } 51 }
52 52
53 }, 53 },
54 - $key_array); 54 +
  55 + $key_array );
55 56
56 return $value_arr; 57 return $value_arr;
57 } 58 }
common/components/parsers/config.php
@@ -71,8 +71,8 @@ @@ -71,8 +71,8 @@
71 ['web' => 71 ['web' =>
72 ['class' => 'yii\multiparser\XlsxParser', 72 ['class' => 'yii\multiparser\XlsxParser',
73 'path_for_extract_files' => \Yii::getAlias('@temp_upload') . '/xlsx/', 73 'path_for_extract_files' => \Yii::getAlias('@temp_upload') . '/xlsx/',
74 - 'has_header_row' => true,  
75 - 'active_sheet' => 2, 74 + // 'has_header_row' => true,
  75 + 'active_sheet' => 1,
76 'converter_conf' => [ 76 'converter_conf' => [
77 'class' => 'common\components\parsers\CustomConverter', 77 'class' => 'common\components\parsers\CustomConverter',
78 'configuration' => ["string" => []], 78 'configuration' => ["string" => []],
common/models/Margins.php
@@ -45,4 +45,22 @@ class Margins extends \yii\db\ActiveRecord @@ -45,4 +45,22 @@ class Margins extends \yii\db\ActiveRecord
45 'koef' => 'Коэффициент', 45 'koef' => 'Коэффициент',
46 ]; 46 ];
47 } 47 }
  48 +
  49 + // возвращает массив для выбора в динамических формах (конструкторах)
  50 + public static function getHeader()
  51 + {
  52 + $header_array = self::find()->asArray()->all();
  53 +
  54 + $id_arr = array_column($header_array,'id');
  55 + $name_arr = array_column($header_array,'name');
  56 + $header_array = array_combine( $id_arr, $name_arr );
  57 + $header_array['_null'] = null; // первая колонка пустая
  58 + $header_array['group'] = 'Группа RG';
  59 + ksort($header_array);
  60 +
  61 + return $header_array;
  62 + }
  63 +
  64 +
  65 +
48 } 66 }
@@ -12,13 +12,13 @@ @@ -12,13 +12,13 @@
12 "version": "dev-master", 12 "version": "dev-master",
13 "source": { 13 "source": {
14 "type": "git", 14 "type": "git",
15 - "url": "git@github.com:tsurkanovm/yii-multiparser.git",  
16 - "reference": "d1fac7a9ab175babccfe47e9a448528b154db928" 15 + "url": "https://github.com/tsurkanovm/yii-multiparser.git",
  16 + "reference": "0c6fd004d8739f106a58f584661e1e5327958b34"
17 }, 17 },
18 "dist": { 18 "dist": {
19 "type": "zip", 19 "type": "zip",
20 - "url": "https://api.github.com/repos/tsurkanovm/yii-multiparser/zipball/d1fac7a9ab175babccfe47e9a448528b154db928",  
21 - "reference": "d1fac7a9ab175babccfe47e9a448528b154db928", 20 + "url": "https://api.github.com/repos/tsurkanovm/yii-multiparser/zipball/0c6fd004d8739f106a58f584661e1e5327958b34",
  21 + "reference": "0c6fd004d8739f106a58f584661e1e5327958b34",
22 "shasum": "" 22 "shasum": ""
23 }, 23 },
24 "require": { 24 "require": {
@@ -50,7 +50,7 @@ @@ -50,7 +50,7 @@
50 "xml", 50 "xml",
51 "yii2" 51 "yii2"
52 ], 52 ],
53 - "time": "2015-10-27 11:59:34" 53 + "time": "2015-10-28 09:28:22"
54 }, 54 },
55 { 55 {
56 "name": "bower-asset/bootstrap", 56 "name": "bower-asset/bootstrap",
vendor/composer/installed.json
@@ -1050,19 +1050,19 @@ @@ -1050,19 +1050,19 @@
1050 "version_normalized": "9999999-dev", 1050 "version_normalized": "9999999-dev",
1051 "source": { 1051 "source": {
1052 "type": "git", 1052 "type": "git",
1053 - "url": "git@github.com:tsurkanovm/yii-multiparser.git",  
1054 - "reference": "d1fac7a9ab175babccfe47e9a448528b154db928" 1053 + "url": "https://github.com/tsurkanovm/yii-multiparser.git",
  1054 + "reference": "0c6fd004d8739f106a58f584661e1e5327958b34"
1055 }, 1055 },
1056 "dist": { 1056 "dist": {
1057 "type": "zip", 1057 "type": "zip",
1058 - "url": "https://api.github.com/repos/tsurkanovm/yii-multiparser/zipball/d1fac7a9ab175babccfe47e9a448528b154db928",  
1059 - "reference": "d1fac7a9ab175babccfe47e9a448528b154db928", 1058 + "url": "https://api.github.com/repos/tsurkanovm/yii-multiparser/zipball/0c6fd004d8739f106a58f584661e1e5327958b34",
  1059 + "reference": "0c6fd004d8739f106a58f584661e1e5327958b34",
1060 "shasum": "" 1060 "shasum": ""
1061 }, 1061 },
1062 "require": { 1062 "require": {
1063 "yiisoft/yii2": "*" 1063 "yiisoft/yii2": "*"
1064 }, 1064 },
1065 - "time": "2015-10-27 11:59:34", 1065 + "time": "2015-10-28 09:28:22",
1066 "type": "library", 1066 "type": "library",
1067 "installation-source": "dist", 1067 "installation-source": "dist",
1068 "autoload": { 1068 "autoload": {