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; ?> |