Commit fee083955a68a98a72172736f79b2c266f2aa0ce
1 parent
f9304a62
add upload rg group form
Showing
10 changed files
with
360 additions
and
12 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", | ... | ... |