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 |