Commit 5ee9ab1fc09bb421a9966f606916a245f6f78700
1 parent
8724ec1f
-
Showing
12 changed files
with
454 additions
and
22 deletions
Show diff stats
backend/config/bootstrap.php
1 | <?php | 1 | <?php |
2 | Yii::setAlias('@uploadDir', dirname(dirname(__DIR__)) . '/storage/sync'); | 2 | Yii::setAlias('@uploadDir', dirname(dirname(__DIR__)) . '/storage/sync'); |
3 | Yii::setAlias('@uploadFileProducts', 'products.csv'); | 3 | Yii::setAlias('@uploadFileProducts', 'products.csv'); |
4 | +Yii::setAlias('@uploadFilePrices', 'prices.csv'); | ||
5 | +Yii::setAlias('@uploadFilePricesAway', 'price_product_away.csv'); | ||
6 | +Yii::setAlias('@uploadFilePricesDuplicate', 'price_duplicate.csv'); | ||
7 | +Yii::setAlias('@uploadFilePricesNoVariant', 'price_no_variant.csv'); | ||
4 | 8 | ||
5 | Yii::setAlias('@productsDir', '@frontend/web/images/products'); | 9 | Yii::setAlias('@productsDir', '@frontend/web/images/products'); |
6 | \ No newline at end of file | 10 | \ No newline at end of file |
common/modules/product/controllers/ManageController.php
@@ -264,12 +264,15 @@ class ManageController extends Controller | @@ -264,12 +264,15 @@ class ManageController extends Controller | ||
264 | public function actionImport() { | 264 | public function actionImport() { |
265 | $model = new Import(); | 265 | $model = new Import(); |
266 | 266 | ||
267 | - if (Yii::$app->request->isPost) { | 267 | + if ($model->load(Yii::$app->request->post())) { |
268 | $file = UploadedFile::getInstances($model, 'file'); | 268 | $file = UploadedFile::getInstances($model, 'file'); |
269 | - if (!empty($file[0]) && $model->validate() && $file[0]->saveAs(Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFileProducts'))) { | ||
270 | - $model->go(); | 269 | + $method = 'go'. ucfirst($model->type); |
270 | + if (!empty($file) && $model->validate()) { | ||
271 | + $file[0]->saveAs(Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFile'. ucfirst($model->type))); | ||
272 | + $model->$method(); | ||
271 | } | 273 | } |
272 | } | 274 | } |
275 | + | ||
273 | return $this->render('import', [ | 276 | return $this->render('import', [ |
274 | 'model' => $model, | 277 | 'model' => $model, |
275 | ]); | 278 | ]); |
common/modules/product/models/Product.php
@@ -188,6 +188,10 @@ class Product extends \yii\db\ActiveRecord | @@ -188,6 +188,10 @@ class Product extends \yii\db\ActiveRecord | ||
188 | return $this->getRelations('product_option'); | 188 | return $this->getRelations('product_option'); |
189 | } | 189 | } |
190 | 190 | ||
191 | + public function getStocks() { | ||
192 | + return $this->hasMany(Stock::className(), ['stock_id' => 'stock_id'])->viaTable(ProductStock::tableName(), ['product_id' => 'product_id']); | ||
193 | + } | ||
194 | + | ||
191 | /** | 195 | /** |
192 | * @inheritdoc | 196 | * @inheritdoc |
193 | * @return ProductQuery the active query used by this AR class. | 197 | * @return ProductQuery the active query used by this AR class. |
1 | +<?php | ||
2 | + | ||
3 | +namespace common\modules\product\models; | ||
4 | + | ||
5 | +use Yii; | ||
6 | + | ||
7 | +/** | ||
8 | + * This is the model class for table "product_stock". | ||
9 | + * | ||
10 | + * @property integer $product_id | ||
11 | + * @property integer $stock_id | ||
12 | + * @property integer $quantity | ||
13 | + * @property integer $product_variant_id | ||
14 | + * | ||
15 | + * @property Product $product | ||
16 | + * @property ProductVariant $productVariant | ||
17 | + * @property Stock $stock | ||
18 | + */ | ||
19 | +class ProductStock extends \yii\db\ActiveRecord | ||
20 | +{ | ||
21 | + /** | ||
22 | + * @inheritdoc | ||
23 | + */ | ||
24 | + public static function tableName() | ||
25 | + { | ||
26 | + return 'product_stock'; | ||
27 | + } | ||
28 | + | ||
29 | + /** | ||
30 | + * @inheritdoc | ||
31 | + */ | ||
32 | + public function rules() | ||
33 | + { | ||
34 | + return [ | ||
35 | + [['product_id', 'stock_id', 'quantity', 'product_variant_id'], 'integer'], | ||
36 | + [['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'product_id']], | ||
37 | + [['product_variant_id'], 'exist', 'skipOnError' => true, 'targetClass' => ProductVariant::className(), 'targetAttribute' => ['product_variant_id' => 'product_variant_id']], | ||
38 | + [['stock_id'], 'exist', 'skipOnError' => true, 'targetClass' => Stock::className(), 'targetAttribute' => ['stock_id' => 'stock_id']], | ||
39 | + ]; | ||
40 | + } | ||
41 | + | ||
42 | + /** | ||
43 | + * @inheritdoc | ||
44 | + */ | ||
45 | + public function attributeLabels() | ||
46 | + { | ||
47 | + return [ | ||
48 | + 'product_id' => 'Product ID', | ||
49 | + 'stock_id' => 'Stock ID', | ||
50 | + 'quantity' => 'Quantity', | ||
51 | + 'product_variant_id' => 'Product Variant ID', | ||
52 | + ]; | ||
53 | + } | ||
54 | + | ||
55 | + /** | ||
56 | + * @return \yii\db\ActiveQuery | ||
57 | + */ | ||
58 | + public function getProduct() | ||
59 | + { | ||
60 | + return $this->hasOne(Product::className(), ['product_id' => 'product_id']); | ||
61 | + } | ||
62 | + | ||
63 | + /** | ||
64 | + * @return \yii\db\ActiveQuery | ||
65 | + */ | ||
66 | + public function getProductVariant() | ||
67 | + { | ||
68 | + return $this->hasOne(ProductVariant::className(), ['product_variant_id' => 'product_variant_id']); | ||
69 | + } | ||
70 | + | ||
71 | + /** | ||
72 | + * @return \yii\db\ActiveQuery | ||
73 | + */ | ||
74 | + public function getStock() | ||
75 | + { | ||
76 | + return $this->hasOne(Stock::className(), ['stock_id' => 'stock_id']); | ||
77 | + } | ||
78 | +} |
common/modules/product/models/ProductVariant.php
@@ -3,6 +3,7 @@ | @@ -3,6 +3,7 @@ | ||
3 | namespace common\modules\product\models; | 3 | namespace common\modules\product\models; |
4 | 4 | ||
5 | use Yii; | 5 | use Yii; |
6 | +use yii\helpers\ArrayHelper; | ||
6 | 7 | ||
7 | /** | 8 | /** |
8 | * This is the model class for table "product_variant". | 9 | * This is the model class for table "product_variant". |
@@ -33,6 +34,7 @@ class ProductVariant extends \yii\db\ActiveRecord | @@ -33,6 +34,7 @@ class ProductVariant extends \yii\db\ActiveRecord | ||
33 | public $translit; | 34 | public $translit; |
34 | public $translit_rubric; | 35 | public $translit_rubric; |
35 | private $data; | 36 | private $data; |
37 | + public $stocks = []; | ||
36 | 38 | ||
37 | /** @var array $_images */ | 39 | /** @var array $_images */ |
38 | // public $imagesUpload = []; | 40 | // public $imagesUpload = []; |
@@ -106,8 +108,12 @@ class ProductVariant extends \yii\db\ActiveRecord | @@ -106,8 +108,12 @@ class ProductVariant extends \yii\db\ActiveRecord | ||
106 | return $this->hasOne(Product::className(), ['product_id' => 'product_id']); | 108 | return $this->hasOne(Product::className(), ['product_id' => 'product_id']); |
107 | } | 109 | } |
108 | 110 | ||
109 | - public function getEnabled() { | ||
110 | - return $this->stock !== 0; | 111 | + public function getQuantity() { |
112 | + return ProductStock::find() | ||
113 | + ->where(['product_variant_id' => $this->product_variant_id]) | ||
114 | + ->sum('quantity'); | ||
115 | +// return $this->hasMany(Stock::className(), ['stock_id' => 'stock_id'])->viaTable(ProductStock::tableName(), ['product_id' => 'product_id'])->sum(ProductStock::tableName() .'.quantity') > 0; | ||
116 | +// return $this->stock !== 0; | ||
111 | } | 117 | } |
112 | 118 | ||
113 | public function getStock_caption() { | 119 | public function getStock_caption() { |
@@ -157,7 +163,36 @@ class ProductVariant extends \yii\db\ActiveRecord | @@ -157,7 +163,36 @@ class ProductVariant extends \yii\db\ActiveRecord | ||
157 | return $this->product_variant_id; | 163 | return $this->product_variant_id; |
158 | } | 164 | } |
159 | 165 | ||
166 | + public function setStocks($stocks) { | ||
167 | + $this->stocks = (array) $stocks; | ||
168 | + } | ||
169 | + | ||
170 | + /*public function getStocks() { | ||
171 | + return $this->hasMany(Stock::className(), ['stock_id' => 'stock_id'])->viaTable(ProductStock::tableName(), ['product_variant_id' => 'product_variant_id']); | ||
172 | + } | ||
173 | + | ||
174 | + public function getStocksIds() { | ||
175 | + return ArrayHelper::getColumn($this->hasMany(Stock::className(), ['stock_id' => 'stock_id'])->viaTable(ProductStock::tableName(), ['product_variant_id' => 'product_variant_id'])->all(), 'stock_id'); | ||
176 | + }*/ | ||
177 | + | ||
178 | + public function afterSave($insert, $changedAttributes) | ||
179 | + { | ||
180 | + if (!empty($this->stocks)) { | ||
181 | + ProductStock::deleteAll(['product_variant_id' => $this->product_variant_id]); | ||
182 | + $values = []; | ||
183 | + foreach ($this->stocks as $id => $quantity) { | ||
184 | + $values[] = [$this->product_id, $this->product_variant_id, $id, $quantity]; | ||
185 | + } | ||
186 | + if ($values) { | ||
187 | + self::getDb()->createCommand() | ||
188 | + ->batchInsert(ProductStock::tableName(), ['product_id', 'product_variant_id', 'stock_id', 'quantity'], $values)->execute(); | ||
189 | + } | ||
190 | + } | ||
191 | + parent::afterSave($insert, $changedAttributes); | ||
192 | + } | ||
193 | + | ||
160 | public function beforeDelete() { | 194 | public function beforeDelete() { |
161 | ProductImage::deleteAll(['product_variant_id' => $this->product_variant_id]); | 195 | ProductImage::deleteAll(['product_variant_id' => $this->product_variant_id]); |
196 | + ProductStock::deleteAll(['product_variant_id' => $this->product_variant_id]); | ||
162 | } | 197 | } |
163 | } | 198 | } |
1 | +<?php | ||
2 | + | ||
3 | +namespace common\modules\product\models; | ||
4 | + | ||
5 | +use Yii; | ||
6 | + | ||
7 | +/** | ||
8 | + * This is the model class for table "stock". | ||
9 | + * | ||
10 | + * @property integer $stock_id | ||
11 | + * @property string $name | ||
12 | + * | ||
13 | + * @property ProductStock[] $productStocks | ||
14 | + */ | ||
15 | +class Stock extends \yii\db\ActiveRecord | ||
16 | +{ | ||
17 | + /** | ||
18 | + * @inheritdoc | ||
19 | + */ | ||
20 | + public static function tableName() | ||
21 | + { | ||
22 | + return 'stock'; | ||
23 | + } | ||
24 | + | ||
25 | + /** | ||
26 | + * @inheritdoc | ||
27 | + */ | ||
28 | + public function rules() | ||
29 | + { | ||
30 | + return [ | ||
31 | + [['name'], 'string', 'max' => 150], | ||
32 | + ]; | ||
33 | + } | ||
34 | + | ||
35 | + /** | ||
36 | + * @inheritdoc | ||
37 | + */ | ||
38 | + public function attributeLabels() | ||
39 | + { | ||
40 | + return [ | ||
41 | + 'stock_id' => Yii::t('product', 'Stock ID'), | ||
42 | + 'name' => Yii::t('product', 'Name'), | ||
43 | + ]; | ||
44 | + } | ||
45 | + | ||
46 | + /** | ||
47 | + * @inheritdoc | ||
48 | + * @return StockQuery the active query used by this AR class. | ||
49 | + */ | ||
50 | + public static function find() | ||
51 | + { | ||
52 | + return new StockQuery(get_called_class()); | ||
53 | + } | ||
54 | +} |
1 | +<?php | ||
2 | + | ||
3 | +namespace common\modules\product\models; | ||
4 | + | ||
5 | +/** | ||
6 | + * This is the ActiveQuery class for [[Stock]]. | ||
7 | + * | ||
8 | + * @see Stock | ||
9 | + */ | ||
10 | +class StockQuery extends \yii\db\ActiveQuery | ||
11 | +{ | ||
12 | + /*public function active() | ||
13 | + { | ||
14 | + return $this->andWhere('[[status]]=1'); | ||
15 | + }*/ | ||
16 | + | ||
17 | + /** | ||
18 | + * @inheritdoc | ||
19 | + * @return Stock[]|array | ||
20 | + */ | ||
21 | + public function all($db = null) | ||
22 | + { | ||
23 | + return parent::all($db); | ||
24 | + } | ||
25 | + | ||
26 | + /** | ||
27 | + * @inheritdoc | ||
28 | + * @return Stock|array|null | ||
29 | + */ | ||
30 | + public function one($db = null) | ||
31 | + { | ||
32 | + return parent::one($db); | ||
33 | + } | ||
34 | +} |
common/modules/product/models/import.php
@@ -18,6 +18,7 @@ use yii\base\Model; | @@ -18,6 +18,7 @@ use yii\base\Model; | ||
18 | 18 | ||
19 | class Import extends Model { | 19 | class Import extends Model { |
20 | public $file; | 20 | public $file; |
21 | + public $type; | ||
21 | 22 | ||
22 | public $errors = []; | 23 | public $errors = []; |
23 | public $output = []; | 24 | public $output = []; |
@@ -28,8 +29,10 @@ class Import extends Model { | @@ -28,8 +29,10 @@ class Import extends Model { | ||
28 | public function rules() | 29 | public function rules() |
29 | { | 30 | { |
30 | return [ | 31 | return [ |
31 | -// [['file'], 'safe'], | ||
32 | - [['file'], 'file'], | 32 | + [['type'], 'required'], |
33 | + [['type'], 'string'], | ||
34 | + [['file'], 'safe'], | ||
35 | + [['file'], 'file', 'extensions' => 'csv'], | ||
33 | ]; | 36 | ]; |
34 | } | 37 | } |
35 | 38 | ||
@@ -43,13 +46,18 @@ class Import extends Model { | @@ -43,13 +46,18 @@ class Import extends Model { | ||
43 | ]; | 46 | ]; |
44 | } | 47 | } |
45 | 48 | ||
46 | - public function go() { | 49 | + public function getType() { |
50 | + if (!$this->type) { | ||
51 | + $this->type = 'products'; | ||
52 | + } | ||
53 | + return $this->type; | ||
54 | + } | ||
47 | 55 | ||
56 | + public function goProducts() { | ||
57 | + set_time_limit(0); | ||
48 | $new_products = $linked_products = 0; | 58 | $new_products = $linked_products = 0; |
49 | 59 | ||
50 | - $db = yii::$app->db; | ||
51 | - | ||
52 | - if ( !($handle = $this->getProductsFile()) ) { | 60 | + if ( !($handle = $this->getProductsFile('uploadFileProducts')) ) { |
53 | $this->errors[] = 'File not found'; | 61 | $this->errors[] = 'File not found'; |
54 | return FALSE; | 62 | return FALSE; |
55 | } | 63 | } |
@@ -351,12 +359,108 @@ class Import extends Model { | @@ -351,12 +359,108 @@ class Import extends Model { | ||
351 | return TRUE; | 359 | return TRUE; |
352 | } | 360 | } |
353 | 361 | ||
354 | - private function getProductsFile() { | ||
355 | - $filename = Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFileProducts'); | 362 | + public function goPrices() { |
363 | + set_time_limit(0); | ||
364 | + $new_products = $linked_products = 0; | ||
365 | + | ||
366 | + if ( !($handle = $this->getProductsFile('uploadFilePrices')) ) { | ||
367 | + $this->errors[] = 'File not found'; | ||
368 | + return FALSE; | ||
369 | + } | ||
370 | + | ||
371 | + $j = 0; | ||
372 | + | ||
373 | + while (($data = fgetcsv ($handle, 10000, ";")) !== FALSE) { | ||
374 | + $j++; | ||
375 | +// if ($j > 10) { | ||
376 | +// return TRUE; | ||
377 | +// } | ||
378 | + | ||
379 | + foreach ($data as &$value) | ||
380 | + { | ||
381 | + //$value = mb_convert_encoding ($value, "UTF-8", mb_detect_encoding ($value)); | ||
382 | + $value = iconv ('windows-1251', "UTF-8//TRANSLIT//IGNORE", $value); | ||
383 | + $value = trim ($value); | ||
384 | + } | ||
385 | + | ||
386 | + // данные строк | ||
387 | + $modification_code = @$data[0]; | ||
388 | + $price = floatval(@$data[1]); | ||
389 | + $price_promo = floatval(@$data[2]); | ||
390 | + $count = intval(@$data[3]); | ||
391 | + $city_name = @$data[4]; | ||
392 | + $product_title = @$data[5]; | ||
393 | + | ||
394 | + if (empty ($modification_code)) { | ||
395 | + CONTINUE; | ||
396 | + } | ||
397 | + // товары в пути | ||
398 | + if (empty ($city_name)) | ||
399 | + { | ||
400 | + $this->saveNotFoundRecord ( | ||
401 | + [$modification_code, $product_title], | ||
402 | + Yii::getAlias('@uploadFilePricesAway') | ||
403 | + ); | ||
404 | + | ||
405 | + $this->output[] = 'Товар '. $product_title . ' в пути'; | ||
406 | + | ||
407 | + CONTINUE; | ||
408 | + } | ||
409 | + | ||
410 | + if ( ($productVariant = ProductVariant::find()->filterWhere(['ilike', 'sku', trim($modification_code)])->one()) === null ) { | ||
411 | + // 'Нет даной модификации в базе'; | ||
412 | + $this->saveNotFoundRecord ( | ||
413 | + [$modification_code, $product_title], | ||
414 | + Yii::getAlias('@uploadFilePricesNoVariant') | ||
415 | + ); | ||
416 | + | ||
417 | + $this->output[] = 'Для товара '. $product_title . ' не найдено соотвествия'; | ||
418 | + | ||
419 | + CONTINUE; | ||
420 | + } | ||
421 | + | ||
422 | + $quantity = 0; | ||
423 | + | ||
424 | + // ===== Set stock ==== | ||
425 | + if ( $city_name ) { | ||
426 | + if ( ($stock = Stock::find()->filterWhere(['ilike', 'name', trim($city_name)])->one()) === null ) { | ||
427 | + // Create stock | ||
428 | + $stock = new Stock(); | ||
429 | + $stock->name = trim($city_name); | ||
430 | + $stock->save(); | ||
431 | + } | ||
432 | + | ||
433 | + $productVariant->stocks[$stock->stock_id] = $count; | ||
434 | + $quantity = $quantity + $count; | ||
435 | + } | ||
436 | + | ||
437 | + $productVariant->price = $price; | ||
438 | + $productVariant->price_old = $price_promo; | ||
439 | + $productVariant->stock = $quantity; | ||
440 | + | ||
441 | + $productVariant->save(); | ||
442 | + | ||
443 | + $this->output[] = '<font style="color:blue">Товар '. $product_title .' успешно сохранен</font>'; | ||
444 | + } | ||
445 | + fclose ($handle); | ||
446 | + } | ||
447 | + | ||
448 | + private function getProductsFile($file_type) { | ||
449 | + $filename = Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@'. $file_type); | ||
356 | if (!is_file($filename)) { | 450 | if (!is_file($filename)) { |
357 | - $this->stderr("File $filename not found"); | 451 | + $this->errors[] = "File $filename not found"; |
358 | return FALSE; | 452 | return FALSE; |
359 | } | 453 | } |
360 | return fopen ($filename, 'r'); | 454 | return fopen ($filename, 'r'); |
361 | } | 455 | } |
456 | + | ||
457 | + private function saveNotFoundRecord (array $line, $filename) | ||
458 | + { | ||
459 | + $str = implode (';', $line)."\n"; | ||
460 | + $str = iconv ("UTF-8//TRANSLIT//IGNORE", "windows-1251", $str); | ||
461 | + | ||
462 | + $fg = fopen (Yii::getAlias('@uploadDir') .'/'. $filename, 'a+'); | ||
463 | + fputs ($fg, $str); | ||
464 | + fclose ($fg); | ||
465 | + } | ||
362 | } | 466 | } |
363 | \ No newline at end of file | 467 | \ No newline at end of file |
common/modules/product/views/manage/import.php
@@ -6,6 +6,7 @@ use yii\widgets\ActiveForm; | @@ -6,6 +6,7 @@ use yii\widgets\ActiveForm; | ||
6 | 6 | ||
7 | <div class="product-import-form"> | 7 | <div class="product-import-form"> |
8 | <?php $form = ActiveForm::begin([ | 8 | <?php $form = ActiveForm::begin([ |
9 | + 'enableClientValidation' => false, | ||
9 | 'options' => ['enctype' => 'multipart/form-data'] | 10 | 'options' => ['enctype' => 'multipart/form-data'] |
10 | ]); ?> | 11 | ]); ?> |
11 | 12 | ||
@@ -16,12 +17,20 @@ use yii\widgets\ActiveForm; | @@ -16,12 +17,20 @@ use yii\widgets\ActiveForm; | ||
16 | <?php endif?> | 17 | <?php endif?> |
17 | 18 | ||
18 | <?php if($model->output) :?> | 19 | <?php if($model->output) :?> |
19 | - <div class="success"> | 20 | + <h2>Лог операции</h2> |
21 | + <div class="success" style="height: 10em;overflow: auto;border: 1px solid #000"> | ||
20 | <?= implode("<br>\n", $model->output);?> | 22 | <?= implode("<br>\n", $model->output);?> |
21 | </div> | 23 | </div> |
22 | <?php endif?> | 24 | <?php endif?> |
23 | 25 | ||
24 | - <?= $form->field($model, 'file')->widget(\kartik\file\FileInput::classname(), [ | 26 | + <?= $form->field($model, 'type')->radioList([ |
27 | + 'products' => Yii::t('product', 'Load products'), | ||
28 | + 'prices' => Yii::t('product', 'Load prices'), | ||
29 | + ]);?> | ||
30 | + | ||
31 | + <?= $form->field($model, 'file')->fileInput(['multiple' => false,])?> | ||
32 | + | ||
33 | + <?php /*= $form->field($model, 'file')->widget(\kartik\file\FileInput::classname(), [ | ||
25 | 'language' => 'ru', | 34 | 'language' => 'ru', |
26 | 'options' => [ | 35 | 'options' => [ |
27 | 'multiple' => false, | 36 | 'multiple' => false, |
@@ -32,7 +41,7 @@ use yii\widgets\ActiveForm; | @@ -32,7 +41,7 @@ use yii\widgets\ActiveForm; | ||
32 | 'showRemove' => false, | 41 | 'showRemove' => false, |
33 | 'showUpload' => false, | 42 | 'showUpload' => false, |
34 | ], | 43 | ], |
35 | - ])?> | 44 | + ])*/?> |
36 | 45 | ||
37 | <div class="form-group"> | 46 | <div class="form-group"> |
38 | <?= Html::submitButton(Yii::t('product', 'Import'), ['class' => 'btn btn-primary']) ?> | 47 | <?= Html::submitButton(Yii::t('product', 'Import'), ['class' => 'btn btn-primary']) ?> |
console/config/bootstrap.php
1 | <?php | 1 | <?php |
2 | Yii::setAlias('@uploadDir', dirname(dirname(__DIR__)) . '/storage/sync'); | 2 | Yii::setAlias('@uploadDir', dirname(dirname(__DIR__)) . '/storage/sync'); |
3 | Yii::setAlias('@uploadFileProducts', 'products.csv'); | 3 | Yii::setAlias('@uploadFileProducts', 'products.csv'); |
4 | +Yii::setAlias('@uploadFilePrices', 'prices.csv'); | ||
5 | +Yii::setAlias('@uploadFilePricesAway', 'price_product_away.csv'); | ||
6 | +Yii::setAlias('@uploadFilePricesDuplicate', 'price_duplicate.csv'); | ||
7 | +Yii::setAlias('@uploadFilePricesNoVariant', 'price_no_variant.csv'); | ||
4 | 8 | ||
5 | -Yii::setAlias('@productsDir', '@frontend/web/images/products'); | 9 | +Yii::setAlias('@productsDir', '@frontend/web/images/products'); |
6 | \ No newline at end of file | 10 | \ No newline at end of file |
console/controllers/ImportController.php
@@ -6,6 +6,7 @@ use common\modules\product\models\Category; | @@ -6,6 +6,7 @@ use common\modules\product\models\Category; | ||
6 | use common\modules\product\models\CategoryName; | 6 | use common\modules\product\models\CategoryName; |
7 | use common\modules\product\models\ProductImage; | 7 | use common\modules\product\models\ProductImage; |
8 | use common\modules\product\models\ProductVariantType; | 8 | use common\modules\product\models\ProductVariantType; |
9 | +use common\modules\product\models\Stock; | ||
9 | use common\modules\rubrication\models\TaxOption; | 10 | use common\modules\rubrication\models\TaxOption; |
10 | use common\modules\rubrication\models\TaxValueString; | 11 | use common\modules\rubrication\models\TaxValueString; |
11 | use Yii; | 12 | use Yii; |
@@ -18,8 +19,8 @@ use yii\console\Controller; | @@ -18,8 +19,8 @@ use yii\console\Controller; | ||
18 | use yii\helpers\Console; | 19 | use yii\helpers\Console; |
19 | 20 | ||
20 | class ImportController extends Controller { | 21 | class ImportController extends Controller { |
21 | - private function getProductsFile() { | ||
22 | - $filename = Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFileProducts'); | 22 | + private function getProductsFile($file_type = 'uploadFileProducts') { |
23 | + $filename = Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@'. $file_type); | ||
23 | if (!is_file($filename)) { | 24 | if (!is_file($filename)) { |
24 | $this->stderr("File $filename not found"); | 25 | $this->stderr("File $filename not found"); |
25 | return FALSE; | 26 | return FALSE; |
@@ -402,4 +403,103 @@ class ImportController extends Controller { | @@ -402,4 +403,103 @@ class ImportController extends Controller { | ||
402 | public function goProducts() { | 403 | public function goProducts() { |
403 | 404 | ||
404 | } | 405 | } |
406 | + | ||
407 | + public function actionPrices() { | ||
408 | + $new_products = $linked_products = 0; | ||
409 | + | ||
410 | + if ( !($handle = $this->getProductsFile('uploadFilePrices')) ) { | ||
411 | + $this->stdout("File not found\n"); | ||
412 | + return Controller::EXIT_CODE_ERROR; | ||
413 | + } | ||
414 | + | ||
415 | + $j = 0; | ||
416 | + | ||
417 | + while (($data = fgetcsv ($handle, 10000, ";")) !== FALSE) { | ||
418 | + $j++; | ||
419 | +// if ($j > 10) { | ||
420 | +// return TRUE; | ||
421 | +// } | ||
422 | + | ||
423 | + foreach ($data as &$value) | ||
424 | + { | ||
425 | + //$value = mb_convert_encoding ($value, "UTF-8", mb_detect_encoding ($value)); | ||
426 | + $value = iconv ('windows-1251', "UTF-8//TRANSLIT//IGNORE", $value); | ||
427 | + $value = trim ($value); | ||
428 | + } | ||
429 | + | ||
430 | + // данные строк | ||
431 | + $modification_code = @$data[0]; | ||
432 | + $price = floatval(@$data[1]); | ||
433 | + $price_promo = floatval(@$data[2]); | ||
434 | + $count = intval(@$data[3]); | ||
435 | + $city_name = @$data[4]; | ||
436 | + $product_title = @$data[5]; | ||
437 | + | ||
438 | + if (empty ($modification_code)) { | ||
439 | + CONTINUE; | ||
440 | + } | ||
441 | + // товары в пути | ||
442 | + if (empty ($city_name)) | ||
443 | + { | ||
444 | + $this->saveNotFoundRecord ( | ||
445 | + [$modification_code, $product_title], | ||
446 | + Yii::getAlias('@uploadFilePricesAway') | ||
447 | + ); | ||
448 | + | ||
449 | +// $this->stdout("Товар $product_title в пути\n"); | ||
450 | + | ||
451 | + CONTINUE; | ||
452 | + } | ||
453 | + | ||
454 | + if ( ($productVariant = ProductVariant::find()->filterWhere(['ilike', 'sku', trim($modification_code)])->one()) === null ) { | ||
455 | + // 'Нет даной модификации в базе'; | ||
456 | + $this->saveNotFoundRecord ( | ||
457 | + [$modification_code, $product_title], | ||
458 | + Yii::getAlias('@uploadFilePricesNoVariant') | ||
459 | + ); | ||
460 | + | ||
461 | +// $this->stdout("Для товара $product_title (#$modification_code) не найдено соотвествия\n"); | ||
462 | + | ||
463 | + CONTINUE; | ||
464 | + } | ||
465 | + | ||
466 | + $quantity = 0; | ||
467 | + | ||
468 | + // ===== Set stock ==== | ||
469 | + if ( $city_name ) { | ||
470 | + if ( ($stock = Stock::find()->filterWhere(['ilike', 'name', trim($city_name)])->one()) === null ) { | ||
471 | + // Create stock | ||
472 | + $stock = new Stock(); | ||
473 | + $stock->name = trim($city_name); | ||
474 | + $stock->save(); | ||
475 | + } | ||
476 | + | ||
477 | + $productVariant->stocks[$stock->stock_id] = $count; | ||
478 | + $quantity = $quantity + $count; | ||
479 | + } | ||
480 | + | ||
481 | + $productVariant->price = $price; | ||
482 | + $productVariant->price_old = $price_promo; | ||
483 | + $productVariant->stock = $quantity; | ||
484 | + | ||
485 | + $productVariant->save(); | ||
486 | + | ||
487 | +// $this->stdout("Товар $product_title успешно сохранен\n"); | ||
488 | + } | ||
489 | + fclose ($handle); | ||
490 | + | ||
491 | + unlink(Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFilePrices')); | ||
492 | + | ||
493 | + return Controller::EXIT_CODE_NORMAL; | ||
494 | + } | ||
495 | + | ||
496 | + private function saveNotFoundRecord (array $line, $filename) | ||
497 | + { | ||
498 | + $str = implode (';', $line)."\n"; | ||
499 | + $str = iconv ("UTF-8//TRANSLIT//IGNORE", "windows-1251", $str); | ||
500 | + | ||
501 | + $fg = fopen (Yii::getAlias('@uploadDir') .'/'. $filename, 'a+'); | ||
502 | + fputs ($fg, $str); | ||
503 | + fclose ($fg); | ||
504 | + } | ||
405 | } | 505 | } |
406 | \ No newline at end of file | 506 | \ No newline at end of file |
frontend/views/catalog/product.php
@@ -96,8 +96,8 @@ $this->registerJs (" | @@ -96,8 +96,8 @@ $this->registerJs (" | ||
96 | <h1><?= $product->fullname ?></h1> | 96 | <h1><?= $product->fullname ?></h1> |
97 | <div class="begin">Цветовые решения</div> | 97 | <div class="begin">Цветовые решения</div> |
98 | <ul class="product_mod"> | 98 | <ul class="product_mod"> |
99 | - <?php foreach (array_reverse($product->variants) as $variant): ?> | ||
100 | - <?php if (!is_null($variant->stock) && empty($variant->stock)) continue;?> | 99 | + <?php foreach ($product->variants as $variant): ?> |
100 | + <?php if ($variant->quantity > 0) continue;?> | ||
101 | <li> | 101 | <li> |
102 | <a id='m<?= $variant->product_variant_id ?>' href="#<?=$variant->product_variant_id ?>" | 102 | <a id='m<?= $variant->product_variant_id ?>' href="#<?=$variant->product_variant_id ?>" |
103 | data-cost="<?= $variant->price ?>" | 103 | data-cost="<?= $variant->price ?>" |
@@ -107,6 +107,9 @@ $this->registerJs (" | @@ -107,6 +107,9 @@ $this->registerJs (" | ||
107 | data-imageoriginal="<?= $variant->imageUrl ?>" | 107 | data-imageoriginal="<?= $variant->imageUrl ?>" |
108 | title="<?= $product->fullname ?>"> | 108 | title="<?= $product->fullname ?>"> |
109 | <?= \common\components\artboximage\ArtboxImageHelper::getImage($variant->imageUrl, 'product_variant')?> | 109 | <?= \common\components\artboximage\ArtboxImageHelper::getImage($variant->imageUrl, 'product_variant')?> |
110 | + <?php | ||
111 | + var_dump($variant->quantity); | ||
112 | + ?> | ||
110 | </a> | 113 | </a> |
111 | </li> | 114 | </li> |
112 | <?php endforeach; ?> | 115 | <?php endforeach; ?> |