diff --git a/common/components/artboxtree/ArtboxTreeQueryTrait.php b/common/components/artboxtree/ArtboxTreeQueryTrait.php index 635812b..b3b46d4 100755 --- a/common/components/artboxtree/ArtboxTreeQueryTrait.php +++ b/common/components/artboxtree/ArtboxTreeQueryTrait.php @@ -31,7 +31,11 @@ trait ArtboxTreeQueryTrait { if ($with) { $this->with($with); } - $data = $this->all(); + $this->orderBy([$model->keyNameDepth => SORT_ASC]); + $data = []; + foreach($this->all() as $item) { + $data[$item->{$model->keyNameId}] = $item; + } if (empty($data)) return []; @@ -61,7 +65,7 @@ trait ArtboxTreeQueryTrait { $this->_recursiveRebuild($tree); } - protected function buildTree(array $data, $parentId = 0) { + /*protected function buildTree(array $data, $parentId = 0) { $model = $this->getModel(); $result = []; @@ -75,6 +79,28 @@ trait ArtboxTreeQueryTrait { } } return $result; + }*/ + + protected function buildTree(array $data, $parentId = 0) { + $model = $this->getModel(); + + $result = []; + foreach ($data as $element) { + + if ($element->{$model->keyNameDepth} == 0) { + $result[$element->{$model->keyNameId}]['item'] = $element; + $result[$element->{$model->keyNameId}]['children'] = []; + continue; + } + $parents = explode(",", trim($element->{$model->keyNamePath}, '{}')); + $node = &$result[$parents[0]]; + for($i=1;$i<$element->{$model->keyNameDepth};$i++) { + $node = &$node['children'][$parents[$i]]; + } + + $node['children'][$element->{$model->keyNameId}]['item'] = $element; + } + return $result; } public function normalizeTreeData(array $data, $parentId = null) diff --git a/common/config/bootstrap.php b/common/config/bootstrap.php index d195e08..34689a9 100755 --- a/common/config/bootstrap.php +++ b/common/config/bootstrap.php @@ -5,3 +5,6 @@ Yii::setAlias('@backend', dirname(dirname(__DIR__)) . '/backend'); Yii::setAlias('@console', dirname(dirname(__DIR__)) . '/console'); Yii::setAlias('@storage', dirname(dirname(__DIR__)) . '/storage'); Yii::setAlias('storage', dirname(dirname(__DIR__)) . '/storage'); +Yii::setAlias('@imagesDir', dirname(dirname(__DIR__)) . '/frontend/web/images'); +Yii::setAlias('@imagesUrl', '/images'); + diff --git a/common/modules/product/controllers/ManageController.php b/common/modules/product/controllers/ManageController.php index f7bdddb..aab14f3 100755 --- a/common/modules/product/controllers/ManageController.php +++ b/common/modules/product/controllers/ManageController.php @@ -164,9 +164,9 @@ class ManageController extends Controller $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload'); if ($model->save()) { - foreach ($model->images as $image) { - $image->delete(); - } +// foreach ($model->images as $image) { +// $image->delete(); +// } if ( ($images = $model->imagesUpload()) !== FALSE) { foreach ($images as $image) { @@ -214,6 +214,26 @@ class ManageController extends Controller exit; } + public function actionIs_top($id) { + $model = $this->findModel($id); + + $model->is_top = intval(empty($model->is_top)); + + $model->save(false, ['is_top']); + + return $this->redirect(['index']); + } + + public function actionIs_new($id) { + $model = $this->findModel($id); + + $model->is_new = intval(empty($model->is_new)); + + $model->save(false, ['is_new']); + + return $this->redirect(['index']); + } + public function actionImport() { $searchModel = new RemoteProductsSearch(); $dataProvider = $searchModel->search(Yii::$app->request->queryParams); diff --git a/common/modules/product/helpers/ProductHelper.php b/common/modules/product/helpers/ProductHelper.php index c16c184..8c019a3 100755 --- a/common/modules/product/helpers/ProductHelper.php +++ b/common/modules/product/helpers/ProductHelper.php @@ -5,6 +5,7 @@ namespace common\modules\product\helpers; use common\modules\product\models\Brand; use common\modules\product\models\Category; use common\modules\product\models\Product; +use common\modules\product\models\ProductVariant; use yii\base\Object; use Yii; @@ -73,4 +74,15 @@ class ProductHelper extends Object { } return $last_products; } + + public static function getSpecialProducts($type, $count, $sort = null) { + $data = [$type => true]; + return Product::find() +// ->joinWith('variants') + ->where($data) +// ->andWhere(['!=', ProductVariant::tableName() .'.stock', 0]) + ->limit($count) + /*->orderBy($sort)*/ + ->all(); + } } \ No newline at end of file diff --git a/common/modules/product/models/Product.php b/common/modules/product/models/Product.php index f9641df..56c1019 100755 --- a/common/modules/product/models/Product.php +++ b/common/modules/product/models/Product.php @@ -203,26 +203,28 @@ class Product extends \yii\db\ActiveRecord // // } - $todel = []; - foreach ($this->variants ? : [] as $_variant) { - $todel[$_variant->product_variant_id] = $_variant->product_variant_id; - } - foreach ($this->_variants as $_variant) { - if (!is_array($_variant)) { - return; + if (!empty($this->_variants)) { + $todel = []; + foreach ($this->variants ?: [] as $_variant) { + $todel[$_variant->product_variant_id] = $_variant->product_variant_id; } - if (!empty($_variant['product_variant_id'])) { - unset($todel[$_variant['product_variant_id']]); - $model = ProductVariant::findOne($_variant['product_variant_id']); - } else { - $model = new ProductVariant(); + foreach ($this->_variants as $_variant) { + if (!is_array($_variant)) { + return; + } + if (!empty($_variant['product_variant_id'])) { + unset($todel[$_variant['product_variant_id']]); + $model = ProductVariant::findOne($_variant['product_variant_id']); + } else { + $model = new ProductVariant(); + } + $_variant['product_id'] = $this->product_id; + $model->load(['ProductVariant' => $_variant]); + $model->save(); + } + if (!empty($todel)) { + ProductVariant::deleteAll(['product_variant_id' => $todel]); } - $_variant['product_id'] = $this->product_id; - $model->load(['ProductVariant' => $_variant]); - $model->save(); - } - if (!empty($todel)) { - ProductVariant::deleteAll(['product_variant_id' => $todel]); } } @@ -254,6 +256,12 @@ class Product extends \yii\db\ActiveRecord } } + public function getImageUrl() + { + $image = empty($this->variant) ? null : $this->variant->image; + return !empty($image) ? $image->imageUrl : '/images/no_photo.png'; + } + public function getImagesHTML() { $op = []; if ($this->images) { diff --git a/common/modules/product/models/ProductImage.php b/common/modules/product/models/ProductImage.php index daa3447..52d8fdd 100755 --- a/common/modules/product/models/ProductImage.php +++ b/common/modules/product/models/ProductImage.php @@ -110,7 +110,6 @@ class ProductImage extends \yii\db\ActiveRecord return isset($this->image) ? '/images/products/'. $this->image : '/images/no_photo.png'; } - /** * Process upload of image * diff --git a/common/modules/product/models/ProductSearch.php b/common/modules/product/models/ProductSearch.php index b74d03a..ab35423 100755 --- a/common/modules/product/models/ProductSearch.php +++ b/common/modules/product/models/ProductSearch.php @@ -48,41 +48,54 @@ class ProductSearch extends Product { $query = Product::find(); - // add conditions that should always apply here + $query->joinWith(['brand', 'brand.brandNames', 'categories', 'categories.categoryNames', 'variant']); + + $query->groupBy(['product.product_id']); + $query->orderBy('product.product_id', 'DESC'); $dataProvider = new ActiveDataProvider([ 'query' => $query, ]); - $this->load($params); - - if (!$this->validate()) { - // uncomment the following line if you do not want to return any records when validation fails - // $query->where('0=1'); + if ( !($this->load($params) && $this->validate()) ) { return $dataProvider; } $dataProvider->setSort([ 'attributes' => [ 'name', - 'brand_name', - 'category_name' + 'brand_name' => [ + 'asc' => ['brand_name.value' => SORT_ASC], + 'desc' => ['brand_name.value' => SORT_DESC], + 'default' => SORT_DESC, + 'label' => 'Brand name', + ], + 'category_name', + 'variant_sku', ] ]); - $query->joinWith(['brand', 'brand.brandNames', 'categories', 'categories.categoryNames']); + if (isset($this->is_top)) { + $query->andFilterWhere([ + 'is_top' => (bool)$this->is_top, + ]); + } + if (isset($this->is_new)) { + $query->andFilterWhere([ + 'is_new' => (bool)$this->is_new, + ]); + } - // grid filtering conditions $query->andFilterWhere([ - 'tax_brand_id' => $this->tax_brand_id, - 'product_id' => $this->product_id, - 'is_top' => (bool)$this->is_top, - 'is_new' => (bool)$this->is_new, + 'product.brand_id' => $this->brand_id, + 'product.product_id' => $this->product_id, + 'product_category.category_id' => $this->category_id ]); - $query->andFilterWhere(['ilike', 'name', $this->name]); + $query->andFilterWhere(['ilike', 'product.name', $this->name]); $query->andFilterWhere(['ilike', 'brand_name.value', $this->brand_name]); $query->andFilterWhere(['ilike', 'category_name.value', $this->category_name]); + $query->andFilterWhere(['ilike', 'product_variant.sku', $this->variant_sku]); return $dataProvider; } diff --git a/common/modules/product/models/ProductVariant.php b/common/modules/product/models/ProductVariant.php index 57f67e7..7a49e4c 100755 --- a/common/modules/product/models/ProductVariant.php +++ b/common/modules/product/models/ProductVariant.php @@ -87,6 +87,20 @@ class ProductVariant extends \yii\db\ActiveRecord } /** + * @return \yii\db\ActiveQuery + */ + public function getImage() + { + return $this->hasOne(ProductImage::className(), ['product_variant_id' => 'product_variant_id']); + } + + public function getImageUrl() + { + // return a default image placeholder if your source image is not found + return !empty($this->image) ? $this->image->imageUrl : '/images/no_photo.png'; + } + + /** * @inheritdoc * @return ProductVariantQuery the active query used by this AR class. */ diff --git a/common/modules/product/views/manage/index.php b/common/modules/product/views/manage/index.php index 41eb978..531f7ea 100755 --- a/common/modules/product/views/manage/index.php +++ b/common/modules/product/views/manage/index.php @@ -2,6 +2,11 @@ use yii\helpers\Html; use yii\grid\GridView; +use kartik\select2\Select2; +use yii\helpers\ArrayHelper; +use common\modules\product\helpers\ProductHelper; +use common\components\artboxtree\ArtboxTreeHelper; + /* @var $this yii\web\View */ /* @var $searchModel common\modules\product\models\ProductSearch */ /* @var $dataProvider yii\data\ActiveDataProvider */ @@ -22,25 +27,66 @@ $this->params['breadcrumbs'][] = $this->title; 'filterModel' => $searchModel, 'columns' => [ ['class' => 'yii\grid\SerialColumn'], -// 'product_id', 'name', [ 'label' => Yii::t('product', 'Brand'), 'attribute' => 'brand_name', 'value' => 'brand.name', + 'format' => 'raw', + 'filter' => Select2::widget([ + 'model' => $searchModel, + 'attribute' => 'brand_id', + 'data' => ArrayHelper::map(ProductHelper::getBrands()->all(), 'brand_id', 'name'), + 'language' => 'ru', + 'options' => [ + 'placeholder' => Yii::t('product', 'Select brand'), + 'multiple' => false, + ], + 'pluginOptions' => [ + 'allowClear' => true + ], + ]) ], [ 'label' => Yii::t('product', 'Category'), 'attribute' => 'category_name', - 'value' => 'category.name', + 'value' => function($model) { + $categories = []; + foreach ($model->categories as $category) { + $categories[] = $category->name; + } + return implode(", ", $categories); + }, + 'format' => 'raw', + 'filter' => Select2::widget([ + 'model' => $searchModel, + 'attribute' => 'category_id', + 'data' => ArtboxTreeHelper::treeMap(ProductHelper::getCategories(), 'category_id', 'name'), + 'language' => 'ru', + 'options' => [ + 'placeholder' => Yii::t('product', 'Select category'), + 'multiple' => false, + ], + 'pluginOptions' => [ + 'allowClear' => true + ], + ]) + ], + [ + 'label' => Yii::t('product', 'SKU'), + 'attribute' => 'variant_sku', + 'value' => 'variant.sku', ], 'variant.price', - 'variant.stock_caption', - - + 'variant.price_old', + [ + 'label' => Yii::t('product', 'Stock'), + 'attribute' => 'variant_stock', + 'value' => 'variant.stock_caption', + ], [ 'class' => 'yii\grid\ActionColumn', - 'template' => '{view} {is_top} {is_new} {update} {delete}', + 'template' => '{items} {view} |{is_top} {is_new} {akciya} | {update} {delete}', 'buttons' => [ 'is_top' => function ($url, $model) { return Html::a('', $url, [ @@ -52,15 +98,32 @@ $this->params['breadcrumbs'][] = $this->title; 'title' => Yii::t('product', ($model->is_new ? 'Set not is new' : 'Set is new')), ]); }, + 'akciya' => function ($url, $model) { + return Html::a('', $url, [ + 'title' => Yii::t('product', ($model->akciya ? 'Set not is promotion' : 'Set is promotion')), + ]); + }, + 'items' => function ($url, $model) { + return Html::a('', $url, [ + 'title' => Yii::t('product', 'Variants'), + ]); + }, + ], 'urlCreator' => function ($action, $model, $key, $index) { switch ($action) { + case 'items': + return \yii\helpers\Url::to(['/product/variant', 'product_id' => $model->product_id]); + break; case 'is_top': return \yii\helpers\Url::to(['manage/is_top', 'id' => $model->product_id]); break; case 'is_new': return \yii\helpers\Url::to(['manage/is_new', 'id' => $model->product_id]); break; + case 'akciya': + return \yii\helpers\Url::to(['manage/akciya', 'id' => $model->product_id]); + break; case 'view': return \yii\helpers\Url::to(['/catalog/product', 'id' => $model->product_id, ['target' => '_blank']]); break; diff --git a/common/modules/product/widgets/specialProducts.php b/common/modules/product/widgets/specialProducts.php new file mode 100644 index 0000000..68d8815 --- /dev/null +++ b/common/modules/product/widgets/specialProducts.php @@ -0,0 +1,48 @@ +type, $this->count, $this->sort); + + if (!$this->title) { + switch($this->type) { + case 'is_top': + $this->title = Yii::t('product', 'Top products'); + break; + case 'is_new': + $this->title = Yii::t('product', 'New products'); + break; + } + } + + return $this->render('products_block', [ + 'title' => $this->title, + 'class' => $this->classs ? $this->classs : $this->type, + 'products' => $products, + ]); + } +} \ No newline at end of file diff --git a/common/modules/product/widgets/views/product_smart.php b/common/modules/product/widgets/views/product_smart.php new file mode 100644 index 0000000..b47be81 --- /dev/null +++ b/common/modules/product/widgets/views/product_smart.php @@ -0,0 +1,64 @@ + +
+
+ + is_top) || !empty($product->is_new) || !empty($product->akciya)) :?> + + + name ?> + + +
+

+ enabledVariants[0]->price_old != 0 && $product->enabledVariants[0]->price_old != $product->enabledVariants[0]->price) :?> + enabledVariants[0]->price_old ?> грн.  + + enabledVariants[0]->price?> грн.

+
+
+ + Купить + +
+ +
+
\ No newline at end of file diff --git a/common/modules/product/widgets/views/products_block.php b/common/modules/product/widgets/views/products_block.php new file mode 100644 index 0000000..7d239a7 --- /dev/null +++ b/common/modules/product/widgets/views/products_block.php @@ -0,0 +1,41 @@ + + +
+
+
+
+ + +
+ is_new) :?> +
Новинка
+ + is_top) :?> +
Toп
+ + +
+ image)) :?> + + + image->imageUrl, 'product_list')?> + +
+
name?>
+
+ brand) :?> +
Бренд: brand->name?>
+ +
categoriesNames)?>
+
variant ? $product->variant->price : 0?> грн.
+ + добавить к сравнению +
+ +
+
+
+
+ \ No newline at end of file diff --git a/composer.json b/composer.json index 2ad5a4f..5de4bf6 100755 --- a/composer.json +++ b/composer.json @@ -41,7 +41,9 @@ "kartik-v/yii2-widget-fileinput": "@dev", "maxmirazh33/yii2-uploadable-cropable-image": "*", "iutbay/yii2-imagecache": "*", - "yurkinx/yii2-image": "dev-master" + "yurkinx/yii2-image": "dev-master", + "mongosoft/yii2-upload-behavior": "*", + "cics/yii2-video-embed-widget": "dev-master" }, "require-dev": { "yiisoft/yii2-codeception": "*", diff --git a/console/controllers/ImportController.php b/console/controllers/ImportController.php index e1126ee..f92dae8 100755 --- a/console/controllers/ImportController.php +++ b/console/controllers/ImportController.php @@ -2,8 +2,8 @@ namespace console\controllers; -use common\modules\product\models\Brand; -use common\modules\product\models\BrandName; +//use common\modules\product\models\Brand; +//use common\modules\product\models\BrandName; use common\modules\product\models\Product; use common\modules\product\models\ProductVariant; use common\modules\product\models\RemoteProducts; @@ -27,7 +27,7 @@ class ImportController extends Controller { public function goClear() { foreach(Product::find()->all() as $product) { if (empty($product->variant)) { - if (!$product->delete()) { + if (FALSE && !$product->delete()) { $this->stdout("#$product->product_id '$product->name'\n"); exit; } else { @@ -40,7 +40,7 @@ class ImportController extends Controller { public function goGo() { $new_products = $linked_products = 0; foreach(RemoteProducts::find()->all() as $product) { - $product->Brand = trim($product->Brand); +// $product->Brand = trim($product->Brand); if (empty($product->remoteCategory) || empty($product->remoteCategory->category)) { continue; } @@ -52,16 +52,16 @@ class ImportController extends Controller { $_product = Product::findOne($product->product->product_id); - $brand = Brand::find()->filterWhere(['ilike', 'remote_id', trim($product->Brand)])->one(); +// $brand = Brand::find()->filterWhere(['ilike', 'remote_id', trim($product->Brand)])->one(); if ( $_product->name != $product->Name || - $_product->categories[0]->category_id != $product->remoteCategory->category->category_id || - ($product->Brand && $brand !== null && $_product->brand_id != $brand->brand_id) + $_product->categories[0]->category_id != $product->remoteCategory->category->category_id + /*|| ($product->Brand && $brand !== null && $_product->brand_id != $brand->brand_id)*/ ) { $_product->name = $product->Name; $_product->categories = [$product->remoteCategory->category->category_id]; - if ( $product->Brand ) { + /*if ( $product->Brand ) { if ( $brand !== null ) { $_product->brand_id = $brand->brand_id; } else { @@ -72,21 +72,27 @@ class ImportController extends Controller { $brand->save(); $_product->brand_id = $brand->brand_id; } - } + }*/ $_product->save(); } + $price = floatval($product->Price); + $price_old = floatval($product->Price_old); + $stock = (bool)$product->In_stock ? NULL : 0; + if ( - $_productVariant->price != floatval($product->Price) || - $_productVariant->price_old != floatval($product->Price_old) || - (!empty($product->Article) && $_productVariant->sku != $product->Article) + $_productVariant->price != $price || + $_productVariant->price_old != $price_old || + (!empty($product->Article) && $_productVariant->sku != $product->Article) || + $_productVariant->stock !== $stock ) { $_productVariant->price = floatval($product->Price); $_productVariant->price_old = floatval($product->Price_old); $_productVariant->sku = empty($product->Article) ? uniqid('gds_') : $product->Article; - if (!$_productVariant->price) { - $_productVariant->stock = 0; - } + $_productVariant->stock = $stock; +// if (!$_productVariant->price) { +// $_productVariant->stock = 0; +// } $_productVariant->save(); } } @@ -98,7 +104,7 @@ class ImportController extends Controller { $_product->name = $product->Name; $_product->categories = [$product->remoteCategory->category->category_id]; - if ( $product->Brand ) { + /*if ( $product->Brand ) { if ( ($brand = Brand::find()->filterWhere(['ilike', 'remote_id', trim($product->Brand)])->one()) !== null ) { $_product->brand_id = $brand->brand_id; } else { @@ -108,7 +114,7 @@ class ImportController extends Controller { $brand->save(); $_product->brand_id = $brand->brand_id; } - } + }*/ $_productVariant->price = floatval($product->Price); $_productVariant->price_old = floatval($product->Price_old); $_productVariant->sku = empty($product->Article) ? uniqid('gds_') : $product->Article; @@ -125,7 +131,7 @@ class ImportController extends Controller { } } - $product->delete(); +// $product->delete(); } // $this->goStat(); diff --git a/frontend/views/catalog/product.php b/frontend/views/catalog/product.php index 2763f7d..87cab7c 100755 --- a/frontend/views/catalog/product.php +++ b/frontend/views/catalog/product.php @@ -29,8 +29,8 @@ $this->params['breadcrumbs'][] = $product->name .' #'. $product->variant->sku; imageUrl, 'product_trumb')?> - +
name?>
brand) :?> -
Бренд: brand->name?>
+
Бренд: brand->name?>
categoriesNames)?>
variant) :?> diff --git a/frontend/views/site/index.php b/frontend/views/site/index.php index 9867294..db21238 100755 --- a/frontend/views/site/index.php +++ b/frontend/views/site/index.php @@ -14,59 +14,11 @@ $this->title = 'My Yii Application'; - - -
-
-
Новинки
-
-
-
Новинка
-
Toп
-
-
Штукатурка гипсовая Кнауф Ротбанд 30 кг белая
-
Бренд: Knauf
-
Штукатурки
-
102.05 грн.
- - добавить к сравнению -
-
-
Новинка
-
-
Ceresit CR 65 гидроизоляционная смесь, 25кг
-
Бренд: Ceresit
-
Гидроизоляция
-
187.00 грн.
- - добавить к сравнению -
-
-
Новинка
-
Toп
-
-
Ruukki Металлочерепица Monterrey Standard 0,5мм, ПЭ глянец
-
Бренд: Rukki
-
Металлочерепица
-
168.40 грн.
- - добавить к сравнению -
-
-
Новинка
-
Toп
-
-
Авеню Плитка тротуарная Брусчатка, 200x100x40, вишня
-
Бренд: Авеню
-
Тротуарная плитка
-
120.00 грн.
- - добавить к сравнению -
-
-
-
-
+ 'is_new', + 'title' => 'Новинки', + 'classs' => 'novelty' +])?>
diff --git a/frontend/web/images/no_photo.png b/frontend/web/images/no_photo.png index aef9e08..fc71420 100755 Binary files a/frontend/web/images/no_photo.png and b/frontend/web/images/no_photo.png differ -- libgit2 0.21.4