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 144 ],
145 145 ]);
146 146  
147   -
148 147 $last_index = end( array_flip( $data[0] ) );
149 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 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 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 283 'options' => ['class' => 'sidebar-menu'],
284 284 'items' => [
285 285 ['label' => "Загрузка файлов", 'url' => ['#'], 'items' => [
  286 + ['label' => 'Кросс файлы', 'url' => ['crossing-upload/index']],
  287 + ['label' => 'Группы RG', 'url' => ['rg-grup/index']],
286 288 ['label' => 'Файлы на сервере', 'url' => ['parser/server-files']],
287 289 ['label' => 'Загрузить файл на сервер', 'url' => ['parser/index', 'mode' => 1]],
288 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 33 \ No newline at end of file
... ...
common/components/CustomArrayHelper.php
... ... @@ -34,8 +34,8 @@ class CustomArrayHelper extends \yii\helpers\ArrayHelper {
34 34 return $value !== '';
35 35 });
36 36 }
  37 + array_walk( $value_arr,
37 38  
38   - array_walk($value_arr,
39 39 function (&$value, $key, $key_array) {
40 40 $res = $value;
41 41 foreach ($res as $sub_key => $sub_value) {
... ... @@ -46,12 +46,13 @@ class CustomArrayHelper extends \yii\helpers\ArrayHelper {
46 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 57 return $value_arr;
57 58 }
... ...
common/components/parsers/config.php
... ... @@ -71,8 +71,8 @@
71 71 ['web' =>
72 72 ['class' => 'yii\multiparser\XlsxParser',
73 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 76 'converter_conf' => [
77 77 'class' => 'common\components\parsers\CustomConverter',
78 78 'configuration' => ["string" => []],
... ...
common/models/Margins.php
... ... @@ -45,4 +45,22 @@ class Margins extends \yii\db\ActiveRecord
45 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 }
... ...
composer.lock
... ... @@ -12,13 +12,13 @@
12 12 "version": "dev-master",
13 13 "source": {
14 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 18 "dist": {
19 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 22 "shasum": ""
23 23 },
24 24 "require": {
... ... @@ -50,7 +50,7 @@
50 50 "xml",
51 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 56 "name": "bower-asset/bootstrap",
... ...
vendor/composer/installed.json
... ... @@ -1050,19 +1050,19 @@
1050 1050 "version_normalized": "9999999-dev",
1051 1051 "source": {
1052 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 1056 "dist": {
1057 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 1060 "shasum": ""
1061 1061 },
1062 1062 "require": {
1063 1063 "yiisoft/yii2": "*"
1064 1064 },
1065   - "time": "2015-10-27 11:59:34",
  1065 + "time": "2015-10-28 09:28:22",
1066 1066 "type": "library",
1067 1067 "installation-source": "dist",
1068 1068 "autoload": {
... ...