Commit 293f57f9671ade705fed08ea1ad47d5acd97a6bb
1 parent
603a219f
add upload rg group form
Showing
11 changed files
with
365 additions
and
17 deletions
Show diff stats
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 | //формируем заголовок для пользователя, где он сможет выбрать соответсвие полей (выпадающий список) | ... | ... |
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 | ... | ... |
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->beginContent('@app/views/layouts/main.php'); |
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']], | ... | ... |
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 | + | ... | ... |
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": { | ... | ... |