Commit 7253a9a0d9a9c0dee8591493c006887a508be538
1 parent
118c6c59
Export fix
Showing
5 changed files
with
366 additions
and
117 deletions
Show diff stats
| 1 | +1. Запускаем миграцию: | ||
| 2 | +php yii migrate --migrationPath=common/modules/comment/migrations | ||
| 3 | +2. Добавляем модуль в конфиг модуль: | ||
| 4 | +'modules' => [ | ||
| 5 | + ... | ||
| 6 | + 'artbox-comment' => [ | ||
| 7 | + 'class' => 'common\modules\comment\Module', | ||
| 8 | + ], | ||
| 9 | +], | ||
| 10 | +3. Добавляем в конфиг переводы: | ||
| 11 | +'i18n' => [ | ||
| 12 | + 'translations' => [ | ||
| 13 | + ... | ||
| 14 | + 'artbox-comment' => [ | ||
| 15 | + 'class' => 'yii\i18n\PhpMessageSource', | ||
| 16 | + 'basePath' => '@common/modules/comment/messages', | ||
| 17 | + ], | ||
| 18 | + ], | ||
| 19 | +], | ||
| 20 | +4. Для управления добавляем в конфиги админки карту контроллера: | ||
| 21 | +'controllerMap' => [ | ||
| 22 | + ... | ||
| 23 | + 'artbox-comments' => [ | ||
| 24 | + 'class' => 'common\modules\comment\controllers\ManageController', | ||
| 25 | + 'viewPath' => '@common/modules/comment/views/manage', | ||
| 26 | + ], | ||
| 27 | +], | ||
| 28 | +5. В конфиге админке поменять пользователя на покупателя: | ||
| 29 | +'modules' => [ | ||
| 30 | + ... | ||
| 31 | + 'artbox-comment' => [ | ||
| 32 | + 'class' => 'common\modules\comment\Module', | ||
| 33 | + 'userIdentityClass' => 'common\models\Customer', | ||
| 34 | + ], | ||
| 35 | +], | ||
| 36 | +6. Вывод виджета: | ||
| 37 | +echo CommentWidget::widget([ | ||
| 38 | + 'model' => $product, | ||
| 39 | +]); | ||
| 40 | +7. Добавляем в нужную модель методы: | ||
| 41 | +public function getComments() { | ||
| 42 | + return $this->hasMany(CommentModel::className(), ['entity_id' => 'product_id'])->where(['artbox_comment.entity' => self::className(), 'artbox_comment.status' => CommentModel::STATUS_ACTIVE, 'artbox_comment.artbox_comment_pid' => NULL]); | ||
| 43 | +} | ||
| 44 | +/** Не обязательно для рейтинга PG ONLY **/ | ||
| 45 | + public function recalculateRating() { | ||
| 46 | + $average = $this->getComments()->joinWith('rating')->select(['average' => 'avg(artbox_comment_rating.value)::float'])->scalar(); | ||
| 47 | + if(!$average) { | ||
| 48 | + $average = 0; | ||
| 49 | + } | ||
| 50 | + $averageRating = $this->averageRating; | ||
| 51 | + if(!empty($averageRating)) { | ||
| 52 | + $averageRating->value = $average; | ||
| 53 | + } else { | ||
| 54 | + $averageRating = new ProductToRating(['product_id' => $this->product_id, 'value' => $average]); // Заменить модель | ||
| 55 | + } | ||
| 56 | + if($averageRating->save()) { | ||
| 57 | + return true; | ||
| 58 | + } else { | ||
| 59 | + return false; | ||
| 60 | + } | ||
| 61 | + } | ||
| 62 | + public function getAverageRating() { | ||
| 63 | + return $this->hasOne(ProductToRating::className(), ['product_id' => 'product_id']); // Заменить модель | ||
| 64 | + } | ||
| 0 | \ No newline at end of file | 65 | \ No newline at end of file |
common/modules/product/controllers/ManageController.php
| @@ -225,13 +225,38 @@ class ManageController extends Controller | @@ -225,13 +225,38 @@ class ManageController extends Controller | ||
| 225 | return $model->goPrices($from, 10); | 225 | return $model->goPrices($from, 10); |
| 226 | } | 226 | } |
| 227 | } | 227 | } |
| 228 | - | ||
| 229 | - public function actionExport() { | 228 | + |
| 229 | + public function actionExportProcess($from, $filename) | ||
| 230 | + { | ||
| 231 | + | ||
| 230 | $model = new Export(); | 232 | $model = new Export(); |
| 231 | - if (($file = $model->process(Yii::getAlias('@uploadDir')))) { | ||
| 232 | - return Yii::$app->response->sendFile($file)->send(); | 233 | + if(Yii::$app->request->isAjax) { |
| 234 | + Yii::$app->response->format = \yii\web\Response::FORMAT_JSON; | ||
| 235 | + return $model->process($filename,$from); | ||
| 233 | } | 236 | } |
| 234 | - throw new NotFoundHttpException('Error'); | 237 | + } |
| 238 | + | ||
| 239 | + public function actionExport() | ||
| 240 | + { | ||
| 241 | + $model = new Export(); | ||
| 242 | + | ||
| 243 | + if($model->load(Yii::$app->request->post())) { | ||
| 244 | + // PROCESS PAGE | ||
| 245 | + return $this->render('export-process', [ | ||
| 246 | + 'model' => $model, | ||
| 247 | + 'method' => 'export', | ||
| 248 | + ]); | ||
| 249 | + } | ||
| 250 | + | ||
| 251 | + return $this->render('export', [ | ||
| 252 | + 'model' => $model, | ||
| 253 | + ]); | ||
| 254 | + // $model = new Export(); | ||
| 255 | + // if(( $file = $model->process(Yii::getAlias('@uploadDir')) )) { | ||
| 256 | + // return Yii::$app->response->sendFile($file) | ||
| 257 | + // ->send(); | ||
| 258 | + // } | ||
| 259 | + // throw new NotFoundHttpException('Error'); | ||
| 235 | } | 260 | } |
| 236 | 261 | ||
| 237 | /** | 262 | /** |
| 1 | <?php | 1 | <?php |
| 2 | - | ||
| 3 | -namespace common\modules\product\models; | ||
| 4 | - | ||
| 5 | -use common\modules\product\helpers\ProductHelper; | ||
| 6 | -use yii\base\Model; | ||
| 7 | -use yii\helpers\ArrayHelper; | ||
| 8 | - | ||
| 9 | -class Export extends Model { | ||
| 10 | - public $errors = []; | ||
| 11 | - public $output = []; | ||
| 12 | - | ||
| 13 | - public function process($dirName, $filename = null, $use_not_enables = false) { | ||
| 14 | - set_time_limit(0); | ||
| 15 | - ini_set('max_execution_time', 900); | ||
| 16 | - ini_set('memory_limit', '1024M'); | ||
| 17 | - if (is_null($filename)) { | ||
| 18 | - $filename = 'products_'. date('d_m_Y_H_i') .'.csv'; | ||
| 19 | - } | ||
| 20 | - setlocale(LC_ALL, 'ru_RU.CP1251'); | ||
| 21 | - $handle = fopen($dirName .'/'. $filename, "w"); | ||
| 22 | - ///$products = Product::find()->joinWith(['variants'])->where(['!=', ProductVariant::tableName() .'.stock', 0])->select('product.product_id')->all(); | ||
| 23 | - $products = Product::find() | ||
| 24 | - ->joinWith(['variantsWithFilters','brand','categories'])->with('filters')->all(); | ||
| 25 | - | ||
| 26 | - foreach ($products as $product) | 2 | + |
| 3 | + namespace common\modules\product\models; | ||
| 4 | + | ||
| 5 | + use yii\base\Model; | ||
| 6 | + | ||
| 7 | + class Export extends Model | ||
| 8 | + { | ||
| 9 | + | ||
| 10 | + public $lang; | ||
| 11 | + | ||
| 12 | + public $file; | ||
| 13 | + | ||
| 14 | + public $errors = []; | ||
| 15 | + | ||
| 16 | + public $output = []; | ||
| 17 | + | ||
| 18 | + public function process($filename = NULL, $from = 0) | ||
| 27 | { | 19 | { |
| 28 | - | ||
| 29 | - | ||
| 30 | - | ||
| 31 | - /*if ($i>1e2) { | ||
| 32 | - break; | ||
| 33 | - }*/ | ||
| 34 | - $mods = []; | ||
| 35 | - | ||
| 36 | - $filterString = $this->convertFilterToString($product->filters); | ||
| 37 | - | ||
| 38 | - foreach ($product->variantsWithFilters as $variant) | ||
| 39 | - { | ||
| 40 | - | ||
| 41 | - $color = $variant->name; | ||
| 42 | - | ||
| 43 | - $mods[] = $variant->sku . | ||
| 44 | - '=' . $this->convertFilterToString($variant->filters) . | ||
| 45 | - '=' . $color . | ||
| 46 | - '=' . ((!empty($variant->image)) ? $variant->image->image: ''). | ||
| 47 | - '=' . $variant->stock; | 20 | + if(empty( $filename )) { |
| 21 | + $filename = 'products_' . date('d_m_Y_H_i') . '.csv'; | ||
| 22 | + $handle = fopen(\Yii::getAlias('@storage/sync/') . $filename, "w"); | ||
| 23 | + } else { | ||
| 24 | + $handle = fopen(\Yii::getAlias('@storage/sync/') . $filename, "a"); | ||
| 25 | + } | ||
| 26 | + | ||
| 27 | + | ||
| 28 | + $products = Product::find() | ||
| 29 | + ->joinWith([ | ||
| 30 | + 'variantsWithFilters', | ||
| 31 | + 'brand', | ||
| 32 | + 'categories', | ||
| 33 | + ]) | ||
| 34 | + ->with('filters') | ||
| 35 | + ->limit(1000) | ||
| 36 | + ->offset($from) | ||
| 37 | + ->all(); | ||
| 38 | + $filesize = Product::find() | ||
| 39 | + ->count(); | ||
| 40 | + foreach($products as $product) { | ||
| 41 | + | ||
| 42 | + $mods = []; | ||
| 43 | + $filterString = $this->convertFilterToString($product->filters); | ||
| 44 | + | ||
| 45 | + foreach($product->variantsWithFilters as $variant) { | ||
| 46 | + $color = $variant->name; | ||
| 47 | + $mods[] = $variant->sku . '=' . $this->convertFilterToString($variant->filters) . '=' . $color . '=' . ( ( !empty( $variant->image ) ) ? $variant->image->image : '' ) . '=' . $variant->stock; | ||
| 48 | + } | ||
| 49 | + | ||
| 50 | + $fotos = []; | ||
| 51 | + | ||
| 52 | + $categories = []; | ||
| 53 | + foreach($product->categories as $value) { | ||
| 54 | + $categories[] = $value->name; | ||
| 55 | + } | ||
| 56 | + | ||
| 57 | + $categories = implode(',', $categories); | ||
| 58 | + | ||
| 59 | + $list = [ | ||
| 60 | + $categories, | ||
| 61 | + $product->brand->name, | ||
| 62 | + $product->name, | ||
| 63 | + '', | ||
| 64 | + ( ( !empty( $product->description ) ) ? $product->description : '' ), | ||
| 65 | + $filterString, | ||
| 66 | + ( !empty( $product->variant ) ) ? $product->variant->price_old : '', | ||
| 67 | + ( !empty( $product->variant ) ) ? $product->variant->price : '', | ||
| 68 | + intval($product->akciya), | ||
| 69 | + '', | ||
| 70 | + intval($product->is_new), | ||
| 71 | + intval($product->is_top), | ||
| 72 | + $product->video, | ||
| 73 | + implode(',', $fotos), | ||
| 74 | + ]; | ||
| 75 | + $to_write = array_merge($list, $mods); | ||
| 76 | + fputcsv($handle, $to_write, ';'); | ||
| 77 | + unset( $product ); | ||
| 48 | } | 78 | } |
| 49 | - | ||
| 50 | - | ||
| 51 | - $fotos = []; | ||
| 52 | - | ||
| 53 | -// foreach ($product->images as $image) | ||
| 54 | -// { | ||
| 55 | -// $fotos[] = $image->imageUrl; | ||
| 56 | -// } | ||
| 57 | - | ||
| 58 | -// $filters = $product->properties; | ||
| 59 | - $categories = []; | ||
| 60 | - foreach($product->categories as $value){ | ||
| 61 | - | ||
| 62 | - $categories[] = $value->name; | ||
| 63 | - | 79 | + |
| 80 | + fclose($handle); | ||
| 81 | + | ||
| 82 | + $from += 1000; | ||
| 83 | + $end = false; | ||
| 84 | + if($from > $filesize) { | ||
| 85 | + $end = true; | ||
| 64 | } | 86 | } |
| 65 | - | ||
| 66 | - | ||
| 67 | - $categories = implode(',',$categories); | ||
| 68 | - | ||
| 69 | - $list = [ | ||
| 70 | - | ||
| 71 | - $categories, | ||
| 72 | - $product->brand->name, | ||
| 73 | - $product->name, | ||
| 74 | - '', | ||
| 75 | - ((! empty($product->description)) ? $product->description : ''), | ||
| 76 | - $filterString, | ||
| 77 | - (!empty($product->variant)) ? $product->variant->price_old : '', | ||
| 78 | - (!empty($product->variant)) ? $product->variant->price : '', | ||
| 79 | - intval($product->akciya), | ||
| 80 | - '', | ||
| 81 | - intval($product->is_new), | ||
| 82 | - intval($product->is_top), | ||
| 83 | - $product->video, | ||
| 84 | - implode (',', $fotos), | 87 | + |
| 88 | + $result = [ | ||
| 89 | + 'end' => $end, | ||
| 90 | + 'from' => $from, | ||
| 91 | + 'totalsize' => $filesize, | ||
| 92 | + 'filename' => $filename, | ||
| 85 | ]; | 93 | ]; |
| 86 | - | ||
| 87 | - $to_write = array_merge ($list, $mods); | ||
| 88 | - foreach($to_write as &$cell) { | ||
| 89 | - $cell = iconv("UTF-8", "WINDOWS-1251", $cell); | 94 | + |
| 95 | + if($end) { | ||
| 96 | + $result = array_merge($result, [ | ||
| 97 | + 'link' => '/storage/sync/'.$filename, | ||
| 98 | + ]); | ||
| 90 | } | 99 | } |
| 91 | - | ||
| 92 | - | ||
| 93 | - fputcsv($handle, $to_write, ';'); | ||
| 94 | - unset($product); | ||
| 95 | - | ||
| 96 | - } | ||
| 97 | - | ||
| 98 | - | ||
| 99 | - | ||
| 100 | - fclose ($handle); | ||
| 101 | - | ||
| 102 | - return $dirName .'/'. $filename; | ||
| 103 | - } | ||
| 104 | - | ||
| 105 | - | ||
| 106 | - public function convertFilterToString($filters){ | ||
| 107 | - $fittersArray = []; | ||
| 108 | - foreach($filters as $filter){ | ||
| 109 | - $fittersArray[$filter->taxGroup->alias][] = $filter->name; | 100 | + |
| 101 | + return $result; | ||
| 102 | + | ||
| 110 | } | 103 | } |
| 111 | - $filterString=[]; | ||
| 112 | - | ||
| 113 | - foreach($fittersArray as $filterName =>$filterRows ){ | ||
| 114 | - $row = implode(',',$filterRows); | ||
| 115 | - $filterString[] = "[{$filterName}:{$row}]"; | ||
| 116 | - | 104 | + |
| 105 | + public function convertFilterToString($filters) | ||
| 106 | + { | ||
| 107 | + $fittersArray = []; | ||
| 108 | + foreach($filters as $filter) { | ||
| 109 | + $fittersArray[ $filter->taxGroup->alias ][] = $filter->value; | ||
| 110 | + } | ||
| 111 | + $filterString = []; | ||
| 112 | + | ||
| 113 | + foreach($fittersArray as $filterName => $filterRows) { | ||
| 114 | + $row = implode(',', $filterRows); | ||
| 115 | + $filterString[] = "[{$filterName}:{$row}]"; | ||
| 116 | + } | ||
| 117 | + return implode('*', $filterString); | ||
| 117 | } | 118 | } |
| 118 | - return implode('*',$filterString); | ||
| 119 | - } | ||
| 120 | -} | ||
| 121 | \ No newline at end of file | 119 | \ No newline at end of file |
| 120 | + } | ||
| 122 | \ No newline at end of file | 121 | \ No newline at end of file |
common/modules/product/views/manage/export-process.php
0 → 100644
| 1 | +<?php | ||
| 2 | + /** | ||
| 3 | + * @var View $this | ||
| 4 | + */ | ||
| 5 | + | ||
| 6 | +use yii\helpers\Html; | ||
| 7 | + use yii\web\View; | ||
| 8 | + use yii\widgets\ActiveForm; | ||
| 9 | + | ||
| 10 | +?> | ||
| 11 | +<?php | ||
| 12 | +$this->registerJs("var in_process=true; | ||
| 13 | + var count=1; | ||
| 14 | + var filename = null; | ||
| 15 | + | ||
| 16 | + doExport(0,filename); | ||
| 17 | + | ||
| 18 | + function doExport(from,filename) { | ||
| 19 | + from = typeof(from) != 'undefined' ? from : 0; | ||
| 20 | + | ||
| 21 | + $.ajax({ | ||
| 22 | + method: 'get', | ||
| 23 | + url: '".Yii::$app->request->baseUrl .'/product/manage/export-process'."', | ||
| 24 | + data: { | ||
| 25 | + from:from, | ||
| 26 | + filename: filename | ||
| 27 | + }, | ||
| 28 | + dataType: 'json', | ||
| 29 | + success: function(data){ | ||
| 30 | + | ||
| 31 | + var per = Math.round(100*data.from/data.totalsize)+'%'; | ||
| 32 | + $('#progressbar div').css({width: per}); | ||
| 33 | + | ||
| 34 | + if(data != false && !data.end) | ||
| 35 | + { | ||
| 36 | + doExport(data.from,data.filename); | ||
| 37 | + } | ||
| 38 | + else | ||
| 39 | + { | ||
| 40 | + console.log(data.link); | ||
| 41 | + $(progressbar).hide('fast'); | ||
| 42 | + $('#result_link').attr('href', data.link).removeClass('hidden'); | ||
| 43 | + in_process = false; | ||
| 44 | + } | ||
| 45 | + }, | ||
| 46 | + error: function(xhr, status, errorThrown) { | ||
| 47 | + } | ||
| 48 | + }); | ||
| 49 | + }"); | ||
| 50 | +?> | ||
| 51 | + | ||
| 52 | +<!--<script>--> | ||
| 53 | +<!-- var in_process=true;--> | ||
| 54 | +<!-- var count=1;--> | ||
| 55 | +<!-- var filename = null;--> | ||
| 56 | +<!-- --> | ||
| 57 | +<!-- doExport(0,filename);--> | ||
| 58 | +<!-- --> | ||
| 59 | +<!-- function doExport(from,filename) {--> | ||
| 60 | +<!-- from = typeof(from) != 'undefined' ? from : 0;--> | ||
| 61 | +<!-- --> | ||
| 62 | +<!-- $.ajax({--> | ||
| 63 | +<!-- method: 'get',--> | ||
| 64 | +<!-- url: '".Yii::$app->request->baseUrl .'/product/manage/export-process'."',--> | ||
| 65 | +<!-- data: {--> | ||
| 66 | +<!-- from:from,--> | ||
| 67 | +<!-- filename: filename--> | ||
| 68 | +<!-- },--> | ||
| 69 | +<!-- dataType: 'json',--> | ||
| 70 | +<!-- success: function(data){--> | ||
| 71 | +<!-- --> | ||
| 72 | +<!-- var per = Math.round(100*data.from/data.totalsize)+'%';--> | ||
| 73 | +<!-- $('#progressbar div').css({width: per});--> | ||
| 74 | +<!-- --> | ||
| 75 | +<!-- if(data != false && !data.end)--> | ||
| 76 | +<!-- {--> | ||
| 77 | +<!-- doExport(data.from,data.filename);--> | ||
| 78 | +<!-- }--> | ||
| 79 | +<!-- else--> | ||
| 80 | +<!-- {--> | ||
| 81 | +<!-- console.log(data.link);--> | ||
| 82 | +<!-- progressbar.hide('fast');--> | ||
| 83 | +<!-- in_process = false;--> | ||
| 84 | +<!-- }--> | ||
| 85 | +<!-- },--> | ||
| 86 | +<!-- error: function(xhr, status, errorThrown) {--> | ||
| 87 | +<!-- }--> | ||
| 88 | +<!-- });--> | ||
| 89 | +<!-- }--> | ||
| 90 | +<!--</script>--> | ||
| 91 | + | ||
| 92 | +<div class="product-import-process-form"> | ||
| 93 | + <h1>Экспорт данных товаров</h1> | ||
| 94 | + | ||
| 95 | + <?= \yii\jui\ProgressBar::widget([ | ||
| 96 | + 'clientOptions' => [ | ||
| 97 | + 'value' => 100, | ||
| 98 | + 'label' => '' | ||
| 99 | + ], | ||
| 100 | + 'options' => [ | ||
| 101 | + 'id' => 'progressbar' | ||
| 102 | + ], | ||
| 103 | + ]);?> | ||
| 104 | + <ul id="process-result"></ul> | ||
| 105 | + <a id="result_link" href="" class="hidden">Ссылка на файл!</a> | ||
| 106 | +</div> |
| 1 | +<?php | ||
| 2 | + | ||
| 3 | + use yii\helpers\Html; | ||
| 4 | + use yii\widgets\ActiveForm; | ||
| 5 | + | ||
| 6 | +?> | ||
| 7 | + | ||
| 8 | +<div class="product-import-form"> | ||
| 9 | + <?php $form = ActiveForm::begin([ | ||
| 10 | + 'enableClientValidation' => false, | ||
| 11 | + 'options' => [ 'enctype' => 'multipart/form-data' ], | ||
| 12 | + ]); ?> | ||
| 13 | + | ||
| 14 | + <?php if($model->errors) : ?> | ||
| 15 | + <div class="error"> | ||
| 16 | + <?= implode("<br>\n", $model->errors); ?> | ||
| 17 | + </div> | ||
| 18 | + <?php endif ?> | ||
| 19 | + | ||
| 20 | + <?php if($model->output) : ?> | ||
| 21 | + <h2>Лог операции</h2> | ||
| 22 | + <div class="success" style="height: 10em;overflow: auto;border: 1px solid #000"> | ||
| 23 | + <?= implode("<br>\n", $model->output); ?> | ||
| 24 | + </div> | ||
| 25 | + <?php endif ?> | ||
| 26 | + | ||
| 27 | + <?= $form->field($model, 'lang') | ||
| 28 | + ->hiddenInput([ | ||
| 29 | + 'options' => [ | ||
| 30 | + 'value' => 1, | ||
| 31 | + ], | ||
| 32 | + ])->label(false); ?> | ||
| 33 | + | ||
| 34 | + | ||
| 35 | + | ||
| 36 | + | ||
| 37 | + <?php /*= $form->field($model, 'file')->widget(\kartik\file\FileInput::classname(), [ | ||
| 38 | + 'language' => 'ru', | ||
| 39 | + 'options' => [ | ||
| 40 | + 'multiple' => false, | ||
| 41 | + ], | ||
| 42 | + 'pluginOptions' => [ | ||
| 43 | + 'allowedFileExtensions' => ['csv'], | ||
| 44 | + 'overwriteInitial' => true, | ||
| 45 | + 'showRemove' => false, | ||
| 46 | + 'showUpload' => false, | ||
| 47 | + ], | ||
| 48 | + ])*/ ?> | ||
| 49 | + | ||
| 50 | + <div class="form-group"> | ||
| 51 | + <?= Html::submitButton(Yii::t('product', 'Export'), [ 'class' => 'btn btn-primary' ]) ?> | ||
| 52 | + </div> | ||
| 53 | + | ||
| 54 | + <?php ActiveForm::end(); ?> | ||
| 55 | +</div> | ||
| 0 | \ No newline at end of file | 56 | \ No newline at end of file |