
diff --git a/backend/config/bootstrap.php b/backend/config/bootstrap.php index 7e6294e..3408edf 100755 --- a/backend/config/bootstrap.php +++ b/backend/config/bootstrap.php @@ -2,4 +2,4 @@ Yii::setAlias('@uploadDir', dirname(dirname(__DIR__)) . '/storage/sync'); Yii::setAlias('@uploadFileProducts', 'products.csv'); -Yii::setAlias('@productsDir', 'images/products'); \ No newline at end of file +Yii::setAlias('@productsDir', '@frontend/web/images/products'); \ No newline at end of file diff --git a/backend/views/layouts/main-sidebar.php b/backend/views/layouts/main-sidebar.php index fb6f040..f9016ef 100755 --- a/backend/views/layouts/main-sidebar.php +++ b/backend/views/layouts/main-sidebar.php @@ -45,8 +45,8 @@ use yii\widgets\Menu; 'options' => ['class'=>\Yii::$app->user->can('product') ? '' :'hide'], ], [ - 'label' => 'Статистика импорта', - 'url' => ['/product/manage/import-stat'], + 'label' => 'Импорт товаров', + 'url' => ['/product/manage/import'], 'options' => ['class'=>\Yii::$app->user->can('product') ? '' :'hide'], ], ] diff --git a/common/modules/product/CatalogUrlManager.php b/common/modules/product/CatalogUrlManager.php index acaa7a7..d106b3b 100755 --- a/common/modules/product/CatalogUrlManager.php +++ b/common/modules/product/CatalogUrlManager.php @@ -46,9 +46,9 @@ class CatalogUrlManager implements UrlRuleInterface { // Filter if (strpos($paths[2], 'filter:') === 0) { $this->parseFilter($paths[2], $params); - } elseif (strpos($paths[2], 'word:') === 0) { + }/* elseif (strpos($paths[2], 'word:') === 0) { $params['word'] = substr($paths[2], 5); - } + }*/ } } elseif ($paths[0] == 'product') { $product = ProductSearch::findByAlias($paths[1]); @@ -99,7 +99,7 @@ class CatalogUrlManager implements UrlRuleInterface { } else { $url = 'catalog/'; } - if (!empty($params['word'])) { + /*if (!empty($params['word'])) { if (!is_array($params['word'])) { $params['word'] = [$params['word']]; } @@ -107,7 +107,7 @@ class CatalogUrlManager implements UrlRuleInterface { } if (isset($params['word'])) { unset($params['word']); - } + }*/ $this->setFilterUrl($params, $url); diff --git a/common/modules/product/controllers/ManageController.php b/common/modules/product/controllers/ManageController.php index 9b0fef2..05b1d4a 100755 --- a/common/modules/product/controllers/ManageController.php +++ b/common/modules/product/controllers/ManageController.php @@ -4,6 +4,7 @@ namespace common\modules\product\controllers; use common\modules\product\helpers\ProductHelper; use common\modules\product\models\Category; +use common\modules\product\models\Import; use common\modules\product\models\ProductImage; use common\modules\product\models\ProductVariant; use common\modules\product\models\RemoteProductsSearch; @@ -261,53 +262,16 @@ class ManageController extends Controller } public function actionImport() { - $searchModel = new RemoteProductsSearch(); - $dataProvider = $searchModel->search(Yii::$app->request->queryParams); - - return $this->render('remote-products', [ - 'searchModel' => $searchModel, - 'dataProvider' => $dataProvider, - ]); - } + $model = new Import(); - public function actionImportStat() { - $all_products = $new_products = $linked_products = $orpahed_products = 0; - $remoteProducts = RemoteProducts::find()->all(); - - $not_linked_cats = []; - - foreach($remoteProducts as $product) { - if (!empty($product->product->product_id)) { - $linked_products++; - } elseif (!empty($product->remoteCategory) && !empty($product->remoteCategory->category) && !empty($product->remoteCategory->category->category_id)) { - $new_products++; - } else { - if (!empty($product->remoteCategory)) { - if (empty($not_linked_cats[$product->remoteCategory->ID])) { - $not_linked_cats[$product->remoteCategory->ID] = $product->remoteCategory->Name ." (". $product->remoteCategory->ID .")"; - } - } - $orpahed_products++; - } - $all_products++; + if (Yii::$app->request->isPost) { + $file = UploadedFile::getInstances($model, 'file'); + if (!empty($file[0]) && $model->validate() && $file[0]->saveAs(Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFileProducts'))) { + $model->go(); } - - $op = []; - - $op[] = "Всего $all_products товаров, $new_products новых и $linked_products уже связанных."; - if (!empty($not_linked_cats)) { - $op[] = "$orpahed_products товаров не привязаны к категориям:"; - foreach ($not_linked_cats as $not_linked_cat) { - $op[] = "$not_linked_cat"; - } - } - - return $this->render('import-stat', [ - 'all_products' => $all_products, - 'new_products' => $new_products, - 'linked_products' => $linked_products, - 'orpahed_products' => $orpahed_products, - 'not_linked_cats' => $not_linked_cats, + } + return $this->render('import', [ + 'model' => $model, ]); } diff --git a/common/modules/product/models/BrandQuery.php b/common/modules/product/models/BrandQuery.php index 2ea4e87..74ee37d 100755 --- a/common/modules/product/models/BrandQuery.php +++ b/common/modules/product/models/BrandQuery.php @@ -20,6 +20,7 @@ class BrandQuery extends \yii\db\ActiveQuery */ public function all($db = null) { + $this->with('brandName'); return parent::all($db); } @@ -29,6 +30,7 @@ class BrandQuery extends \yii\db\ActiveQuery */ public function one($db = null) { + $this->with('brandName'); return parent::one($db); } diff --git a/common/modules/product/models/BrandSearch.php b/common/modules/product/models/BrandSearch.php index f2e8f63..a3a54a3 100755 --- a/common/modules/product/models/BrandSearch.php +++ b/common/modules/product/models/BrandSearch.php @@ -117,11 +117,7 @@ class BrandSearch extends Brand } } - $dataProvider = new ActiveDataProvider([ - 'query' => $query, - ]); - - return $dataProvider; + return $query; } public static function findByAlias($alias) { diff --git a/common/modules/product/models/Category.php b/common/modules/product/models/Category.php index bbceea9..9907ecb 100755 --- a/common/modules/product/models/Category.php +++ b/common/modules/product/models/Category.php @@ -133,6 +133,11 @@ class Category extends \yii\db\ActiveRecord return $this->hasOne(ProductUnit::className(), ['product_unit_id' => 'product_unit_id']); } + public function getProducts() { +// return $this->hasMany(Product::className(), ['product_id' => 'product_id'])->viaTable('product_category', ['category_id' => 'category_id']); + return $this->getRelations('product_categories'); + } + /** * @return \yii\db\ActiveQuery */ diff --git a/common/modules/product/models/CategoryQuery.php b/common/modules/product/models/CategoryQuery.php index 8d92bef..7a941c3 100755 --- a/common/modules/product/models/CategoryQuery.php +++ b/common/modules/product/models/CategoryQuery.php @@ -23,6 +23,7 @@ class CategoryQuery extends \yii\db\ActiveQuery */ public function all($db = null) { + $this->with('categoryName'); return parent::all($db); } @@ -32,6 +33,7 @@ class CategoryQuery extends \yii\db\ActiveQuery */ public function one($db = null) { +// $this->joinWith('categoryName'); return parent::one($db); } } diff --git a/common/modules/product/models/CategorySearch.php b/common/modules/product/models/CategorySearch.php index c88758e..9e29a9a 100755 --- a/common/modules/product/models/CategorySearch.php +++ b/common/modules/product/models/CategorySearch.php @@ -74,15 +74,15 @@ class CategorySearch extends Category // grid filtering conditions $query->andFilterWhere([ - 'category_id' => $this->category_id, - 'parent_id' => $this->parent_id, - 'category_name_id' => $this->category_name_id, - 'product_unit_id' => $this->product_unit_id, + 'category.category_id' => $this->category_id, + 'category.parent_id' => $this->parent_id, + 'category.category_name_id' => $this->category_name_id, + 'category.product_unit_id' => $this->product_unit_id, ]); - $query->andFilterWhere(['like', 'alias', $this->alias]); + $query->andFilterWhere(['like', 'category.alias', $this->alias]); - $query->orderBy(['path' => SORT_ASC, 'depth' => SORT_ASC, 'category_id' => SORT_ASC]); + $query->orderBy(['category.path' => SORT_ASC, 'category.depth' => SORT_ASC, 'category.category_id' => SORT_ASC]); return $dataProvider; } diff --git a/common/modules/product/models/import.php b/common/modules/product/models/import.php new file mode 100644 index 0000000..e24d8dc --- /dev/null +++ b/common/modules/product/models/import.php @@ -0,0 +1,362 @@ + Yii::t('product', 'File'), + ]; + } + + public function go() { + + $new_products = $linked_products = 0; + + $db = yii::$app->db; + + if ( !($handle = $this->getProductsFile()) ) { + $this->errors[] = 'File not found'; + return FALSE; + } + + $j = 0; + + while (($data = fgetcsv ($handle, 10000, ";")) !== FALSE) + { + $j++; + /*if ($j > 10) { + return TRUE; + }*/ + + foreach ($data as &$value) + { + //$value = mb_convert_encoding ($value, "UTF-8", mb_detect_encoding ($value)); + $value = iconv ('windows-1251', "UTF-8//TRANSLIT//IGNORE", $value); + $value = trim ($value); + } + + // будет всегда 19 элементов + for ($i = 0; $i <= 18; $i++) + { + if (! isset ($data[$i])) + { + $data[$i] = null; + } + } + + // 1 Группа (категория) + $catalog_name = $data[0]; + if (empty ($catalog_name)) + { + CONTINUE; + } + + // 2 Бренд + $brand_name = $data[1]; + if (empty ($brand_name)) + { + CONTINUE; + } + + // 3 Название товара + $product_name = $data[2]; + if (empty ($product_name)) + { + CONTINUE; + } + + // 4 Описание Укр + $product_body_uk = $data[3]; + + // 5 Описание Рус + $product_body_ru = $data[4]; + + // 6 Фильтр (через запятую) + $filters = explode (',', $data[5]); + + // 7 Доп фильтр через запятую + $filters_extra = explode (',', $data[6]); + + // 8 Пол череззапятую (мужской, женский, детский, унисекс) + $gender = explode (',', $data[7]); + + // 9 Год + $years = explode (',', $data[8]); + + // 10 Цена старая + $product_cost_old = $data[10]; + + // 11 Цена + $product_cost = $data[9]; + + // 12 Акция + $product_akciya = (bool)$data[11]; + + // 13 Сопуд. Тов. + $similar = explode (',', $data[12]); + + // 14 Новинки + $product_new = (bool)$data[13]; + + // 15 Топ продаж + $product_top = (bool)$data[14]; + + // 16 Сетка Характеристик + $feature = explode ('=', $data[15]); + + // 17 ВИДЕО КОД + $product_video = $data[16]; + + // 18 Галлерея фото + $fotos = explode (',', $data[17]); + + // 19 Штрих код товара. + // расшифровал - это модификации товара! + + $product_image = explode ('=', $data[18]); + $product_image = @$product_image[3]; + + if ( ($_product = Product::find()->filterWhere(['ilike', 'name', trim($product_name)])->one()) === null ) { + $_product = new Product(); + } + + $is_new_product = empty($_product->product_id); + + // ==== Set category ==== + if ( ($category = CategoryName::find()->filterWhere(['ilike', 'value', trim($catalog_name)])->one()) === null ) { + // Create category + $category = new Category(); + $category->name = trim($catalog_name); + $category->save(); + } + $_product->categories = [$category->category_id]; + + // ===== Set brand ==== + if ( $brand_name ) { + if ( ($brand = BrandName::find()->filterWhere(['ilike', 'value', trim($brand_name)])->one()) !== null ) { + $_product->brand_id = $brand->brand_id; + } else { + // Create brand + $brand = new Brand(); + $brand->name = trim($brand_name); + $brand->save(); + $_product->brand_id = $brand->brand_id; + } + } + + $_product->name = $product_name; + $_product->video = $product_video; + $_product->description = $product_body_ru; + $_product->is_top = $product_top; + $_product->akciya = $product_akciya; + $_product->is_new = $product_new; + + if (!$_product->save()) { + $this->errors[] = 'Product #'. $_product->name .' not saved'; + continue; + } + + // нужно для проставления характеристик относящихся к модификациям + $MOD_ARRAY = []; + + for ($i = 18; $i < count ($data); $i ++) + { + if (! empty ($data[$i])) + { + $mod_arr = explode ('=', $data[$i]); + $mod_art = $mod_arr[0]; + $mod_size = $mod_arr[1]; + $mod_color = $mod_arr[2]; + $mod_image = $mod_arr[3]; + $mod_cost = floatval($product_cost); + $mod_old_cost = floatval($product_cost_old); + + // Check product variant + if ( ($_productVariant = ProductVariant::find()->andFilterWhere(['ilike', 'sku', $mod_art])->andFilterWhere(['product_id' => $_product->product_id])->one()) === null ) { + $_productVariant = new ProductVariant(); + $_productVariant->product_id = $_product->product_id; + } + $_productVariant->product_unit_id = 1; + + $_productVariant->sku = $mod_art; + $_productVariant->price = $mod_cost; + $_productVariant->price_old = $mod_old_cost; + $_productVariant->stock = 1; + + $product_variant_type_name = ''; + if (! empty ($mod_color)) { + $product_variant_type_name = 'Цвет'; + $_productVariant->name = $mod_color; + } + elseif (! empty ($mod_size)) { + $product_variant_type_name = 'Размер'; + $_productVariant->name = $mod_size; + } + + // ===== Set variant type ==== + if ( $product_variant_type_name ) { + if ( ($product_variant_type = ProductVariantType::find()->filterWhere(['ilike', 'name', $product_variant_type_name])->one()) !== null ) { + $_productVariant->product_variant_type_id = $product_variant_type->product_variant_type_id; + } else { + $product_variant_type = new ProductVariantType(); + $product_variant_type->name = $product_variant_type_name; + $product_variant_type->save(); + $_productVariant->product_variant_type_id = $product_variant_type->product_variant_type_id; + } + } + $_productVariant->save(false); + + $MOD_ARRAY[] = $_productVariant->product_variant_id; + + if ($mod_image) { + $url = 'http://rukzachok.com.ua/upload/mod/' . urlencode($mod_image); + $image = @file_get_contents($url); + if ($image) { + if (($variantImage = ProductImage::find()->andFilterWhere(['ilike', 'image', $mod_image])->andFilterWhere(['product_variant_id' => $_productVariant->product_variant_id])->one()) === null) { + file_put_contents(Yii::getAlias('@productsDir') . "/" . $mod_image, $image); + $variantImage = new ProductImage(); + $variantImage->product_id = $_product->product_id; + $variantImage->product_variant_id = $_productVariant->product_variant_id; + $variantImage->image = $mod_image; + $variantImage->save(); + } + } + } + } + } + + $options = []; + + if (! empty ($filters)) { + // Set Naznachenie (tax_group_id = 20) + foreach($filters as $filter) { + $filter = trim($filter); + if (!$filter) { + continue; + } + if ( ($value = TaxValueString::find()->innerJoinWith('taxOption')->andFilterWhere(['ilike', 'value', $filter])->andFilterWhere(['tax_option.tax_group_id' => 20])->one()) === null ) { + // Create option + $option = new TaxOption(); + $option->tax_group_id = 20; + $option->save(); + + $value = new TaxValueString(); + $value->tax_option_id = $option->tax_option_id; + $value->value = $filter; + $value->save(); + + $option->default_value = $value->tax_value_id; + $option->save(); + } + $options[] = $value->tax_option_id; + } + } + + if (! empty ($years)) { + // Set God (tax_group_id = 21) + foreach($years as $filter) { + $filter = trim($filter); + if (!$filter) { + continue; + } + if ( ($value = TaxValueString::find()->innerJoinWith('taxOption')->andFilterWhere(['ilike', 'value', $filter])->andFilterWhere(['tax_option.tax_group_id' => 21])->one()) === null ) { + // Create option + $option = new TaxOption(); + $option->tax_group_id = 21; + $option->save(); + + $value = new TaxValueString(); + $value->tax_option_id = $option->tax_option_id; + $value->value = $filter; + $value->save(); + + $option->default_value = $value->tax_value_id; + $option->save(); + } + $options[] = $value->tax_option_id; + } + } + + if (! empty ($gender)) { + // Set Pol (tax_group_id = 22) + foreach($gender as $filter) { + $filter = trim($filter); + if (!$filter) { + continue; + } + if ( ($value = TaxValueString::find()->innerJoinWith('taxOption')->andFilterWhere(['ilike', 'value', $filter])->andFilterWhere(['tax_option.tax_group_id' => 22])->one()) === null ) { + // Create option + $option = new TaxOption(); + $option->tax_group_id = 22; + $option->save(); + + $value = new TaxValueString(); + $value->tax_option_id = $option->tax_option_id; + $value->value = $filter; + $value->save(); + + $option->default_value = $value->tax_value_id; + $option->save(); + } + $options[] = $value->tax_option_id; + } + } + + if (!empty($options)) { + $_product->options = $options; + } + + $_product->save(); + + $this->output[] = "$j: Product {$_product->name} #{$_product->product_id} saved (". ($is_new_product ? 'new product' : 'exists product') .")"; + } + + fclose ($handle); + + return TRUE; + } + + private function getProductsFile() { + $filename = Yii::getAlias('@uploadDir') .'/'. Yii::getAlias('@uploadFileProducts'); + if (!is_file($filename)) { + $this->stderr("File $filename not found"); + return FALSE; + } + return fopen ($filename, 'r'); + } +} \ No newline at end of file diff --git a/common/modules/product/views/manage/import.php b/common/modules/product/views/manage/import.php new file mode 100644 index 0000000..ba9868a --- /dev/null +++ b/common/modules/product/views/manage/import.php @@ -0,0 +1,42 @@ + + +
- = Html::a(Yii::t('product', 'Import selected'), ['import'], ['class' => 'btn btn-success']) ?> -
- = GridView::widget([ - 'dataProvider' => $dataProvider, - 'filterModel' => $searchModel, - 'columns' => [ - ['class' => 'yii\grid\SerialColumn'], - - 'Name', - 'ID_chief', - 'Article', - 'Price', - 'Price_old', - 'Brand', - 'ID', - 'Date_create', - 'remoteCategory.category.name', - 'remoteCategory.Name', - // 'local_id', - - ['class' => 'yii\grid\ActionColumn'], - ], - ]); ?> -
- Доставка товара на следующий день после выставления счета. Мы доставим “День в
день” — уточните это у менеджера.
-
Показать все товары из категории "= $category->categoryName->value?>"
- - - - - -