diff --git a/backend/views/layouts/main-sidebar.php b/backend/views/layouts/main-sidebar.php index f389844..f098328 100755 --- a/backend/views/layouts/main-sidebar.php +++ b/backend/views/layouts/main-sidebar.php @@ -34,6 +34,11 @@ use yii\widgets\Menu; 'options' => ['class'=>\Yii::$app->user->can('product') ? '' :'hide'] ], [ + 'label' => 'Модификации', + 'url' => ['/product/variant'], + 'options' => ['class'=>\Yii::$app->user->can('product') ? '' :'hide'] + ], + [ 'label' => 'Категории', 'url' => ['/category'], 'options' => ['class'=>\Yii::$app->user->can('category') ? '' :'hide'], diff --git a/common/config/main.php b/common/config/main.php index 589ca3b..080f92a 100755 --- a/common/config/main.php +++ b/common/config/main.php @@ -207,6 +207,27 @@ return [ 'model' => 'common\modules\product\models\ProductOption', ] ], + 'product_variant_option' => [ + 'name' => Yii::t('product', 'Properties'), + 'field' => 'options', + 'entity1' => [ + 'model' => '\common\modules\product\models\ProductVariant', + 'label' => 'Variant', + 'listField' => 'fullname', + 'key' => 'product_variant_id', + 'linked_key' => 'product_variant_id', + ], + 'entity2' => [ + 'model' => '\common\modules\rubrication\models\TaxOption', + 'label' => 'Option', + 'listField' => 'ValueRenderFlash', + 'key' => 'tax_option_id', + 'linked_key' => 'option_id', + ], + 'via' => [ + 'model' => 'common\modules\product\models\ProductVariantOption', + ] + ], 'tax_group_to_category' => [ 'name' => Yii::t('product', 'Характеристики по категориям'), 'field' => 'group_to_category', diff --git a/common/modules/product/controllers/ManageController.php b/common/modules/product/controllers/ManageController.php index 91feb11..f92ab39 100755 --- a/common/modules/product/controllers/ManageController.php +++ b/common/modules/product/controllers/ManageController.php @@ -117,16 +117,6 @@ class ManageController extends Controller $model = $this->findModel($id); if ($model->load(Yii::$app->request->post())) { $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload'); - $model->variantImagesUpload = UploadedFile::getInstances($model, 'variants'); - /*if (!empty($variantImagesUpload)) { - var_dump($variantImagesUpload);exit; - }*/ - /*$model->variantImagesUpload = []; - foreach ($_POST['Product']['variants'] as $i => $variant) { - if (!empty($variant['product_variant_id'])) { - $model->variantImagesUpload[$variant['product_variant_id']] = $variantImagesUpload[$i]; - } - }*/ if ($model->save()) { // foreach ($model->images as $image) { // $image->delete(); @@ -140,19 +130,6 @@ class ManageController extends Controller } } - if ( ($images = $model->variantImagesUpload()) !== FALSE) { - foreach ($images as $i => $image) { - if (empty($model->_variants[$i])) { - continue; - } - $imageModel = new ProductImage(); - $imageModel->product_id = $model->product_id; - $imageModel->product_variant_id = intval($model->_variants[$i]['product_variant_id']); - $imageModel->image = $image; - $imageModel->save(); - } - } - return $this->redirect(['view', 'id' => $model->product_id]); } } else { diff --git a/common/modules/product/controllers/VariantController.php b/common/modules/product/controllers/VariantController.php new file mode 100644 index 0000000..2d895ac --- /dev/null +++ b/common/modules/product/controllers/VariantController.php @@ -0,0 +1,172 @@ + [ + 'class' => VerbFilter::className(), + 'actions' => [ + 'delete' => ['POST'], + ], + ], + ]; + } + + /** + * Lists all ProductVariant models. + * @return mixed + */ + public function actionIndex() + { + $searchModel = new ProductVariantSearch(); + $dataProvider = $searchModel->search(Yii::$app->request->queryParams); + + if ( ($product = Yii::$app->request->get('product_id')) !== null) { + $product = Product::findOne($product); + } + + return $this->render('index', [ + 'searchModel' => $searchModel, + 'dataProvider' => $dataProvider, + 'product' => $product, + ]); + } + + /** + * Displays a single ProductVariant model. + * @param integer $id + * @return mixed + */ + public function actionView($id) + { + return $this->render('view', [ + 'model' => $this->findModel($id), + ]); + } + + /** + * Creates a new ProductVariant model. + * If creation is successful, the browser will be redirected to the 'view' page. + * @return mixed + */ + public function actionCreate() + { + $model = new ProductVariant(); + + if ($model->load(Yii::$app->request->post())) { + $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload'); + + if ($model->save() && $model->imagesUpload) { + if ( ($images = $model->imagesUpload()) !== FALSE) { + foreach ($images as $image) { + $imageModel = new ProductImage(); + $imageModel->product_id = $model->product_id; + $imageModel->product_variant_id = $model->product_variant_id; + $imageModel->image = $image; + $imageModel->save(); + } + } + + return $this->redirect(['view', 'id' => $model->product_variant_id]); + } + } else { + return $this->render('create', [ + 'model' => $model, + ]); + } + } + + /** + * Updates an existing ProductVariant model. + * If update is successful, the browser will be redirected to the 'view' page. + * @param integer $id + * @return mixed + */ + public function actionUpdate($id) + { + $model = $this->findModel($id); + if ($model->load(Yii::$app->request->post())) { + $model->imagesUpload = UploadedFile::getInstances($model, 'imagesUpload'); + if ($model->save()) { + if ( ($images = $model->imagesUpload()) !== FALSE) { + foreach ($images as $image) { + $imageModel = new ProductImage(); + $imageModel->product_id = $model->product_id; + $imageModel->product_variant_id = $model->product_variant_id; + $imageModel->image = $image; + $imageModel->save(); + } + } + + return $this->redirect(['view', 'id' => $model->product_variant_id]); + } + } else { + $groups = $model->category->getTaxGroups(); + + return $this->render('update', [ + 'model' => $model, + 'groups' => $groups, + ]); + } + } + + /** + * Deletes an existing ProductVariant model. + * If deletion is successful, the browser will be redirected to the 'index' page. + * @param integer $id + * @return mixed + */ + public function actionDelete($id) + { + $this->findModel($id)->delete(); + + return $this->redirect(['index']); + } + + public function actionDelimg($id) + { + $image = ProductImage::findOne($id); + + if ($image) { + $image->delete(); + } + + print '1'; + exit; + } + + /** + * Finds the ProductVariant model based on its primary key value. + * If the model is not found, a 404 HTTP exception will be thrown. + * @param integer $id + * @return ProductVariant the loaded model + * @throws NotFoundHttpException if the model cannot be found + */ + protected function findModel($id) + { + if (($model = ProductVariant::findOne($id)) !== null) { + return $model; + } else { + throw new NotFoundHttpException('The requested page does not exist.'); + } + } +} diff --git a/common/modules/product/helpers/ProductHelper.php b/common/modules/product/helpers/ProductHelper.php index 5c9b7d3..372947c 100755 --- a/common/modules/product/helpers/ProductHelper.php +++ b/common/modules/product/helpers/ProductHelper.php @@ -140,4 +140,63 @@ class ProductHelper extends Object { } return $products; } + + public static function _setQueryParams(&$query, $params, $setPriceLimits = true) { + if (!empty($params['keywords'])) { + if (!is_array($params['keywords'])) { + $params['keywords'] = [$params['keywords']]; + } + foreach ($params['keywords'] as $keyword) { + $query->orFilterWhere(['ilike', Product::tableName() .'.name', $keyword]); + $query->orFilterWhere(['ilike', BrandName::tableName() .'.value', $keyword]); + $query->orFilterWhere(['ilike', CategoryName::tableName() .'.value', $keyword]); + } + } + if (!empty($params['special'])) { + foreach($params['special'] as $key => $value) { + $query->orFilterWhere([Product::tableName() .'.'. $key => $value]); + } + } + if (!empty($params['brands'])) { + $query->andFilterWhere([Product::tableName() .'.brand_id' => $params['brands']]); + } + if (!empty($params['options'])) { + foreach ($params['options'] as $group => $options) { + foreach ($options as &$option) { + $option = "'$option'"; + } + $query->andWhere( + Product::tableName() . '.product_id IN (SELECT product_id AS products FROM product_option INNER JOIN tax_option ON tax_option.tax_option_id = product_option.option_id INNER JOIN tax_group ON tax_group.tax_group_id = tax_option.tax_group_id WHERE tax_group.alias LIKE \''. $group .'\' AND tax_option.alias IN (' . implode(',', $options) . '))' + ); + } + } + + if ($setPriceLimits && !empty($params['prices'])) { + if ($params['prices']['min'] > 0) { + $query->andWhere(['>=', ProductVariant::tableName() .'.price', $params['prices']['min']]); + } + if ($params['prices']['max'] > 0) { + $query->andWhere(['<=', ProductVariant::tableName() .'.price', $params['prices']['max']]); + } + } + } + + public static function productCountQuery($category = null, $params, $excludeKeys = []) { + $p = []; + foreach ($params as $key => $param) { + if (in_array($key, $excludeKeys)) { + $p[$key] = $param; + } + } + /** @var ActiveQuery $query */ + if (!empty($category)) { + $query = $category->getProducts(); + } else { + $query = Product::find(); + } + ProductHelper::_setQueryParams($query, $params); + $query->select(['COUNT(product.product_id)']); + + return $query; + } } \ No newline at end of file diff --git a/common/modules/product/models/BrandSearch.php b/common/modules/product/models/BrandSearch.php index 01e6f1e..3b8e4d2 100755 --- a/common/modules/product/models/BrandSearch.php +++ b/common/modules/product/models/BrandSearch.php @@ -2,6 +2,8 @@ namespace common\modules\product\models; +use common\modules\product\helpers\ProductHelper; +use common\modules\rubrication\models\TaxOption; use Yii; use yii\base\Model; use yii\data\ActiveDataProvider; @@ -89,14 +91,47 @@ class BrandSearch extends Brand } public function getBrands($category = null, $params = []) { +// $queryCount = ProductHelper::productCountQuery($category, $params, ['brands']); + + /*if (!empty($params['prices'])) { + if ($params['prices']['min'] > 0) { + $queryCount->andWhere(['>=', ProductVariant::tableName() .'.price', $params['prices']['min']]); + } + if ($params['prices']['max'] > 0) { + $queryCount->andWhere(['<=', ProductVariant::tableName() .'.price', $params['prices']['max']]); + } + }*/ +// if (!empty($params['options'])) { +// $queryCount->innerJoin(TaxOption::tableName(), TaxOption::tableName()) +// } + $query = Brand::find() ->select([ - Brand::tableName() .'.*', - 'COUNT('. ProductCategory::tableName() .'.product_id) AS _items_count' + Brand::tableName() .'.*' ]) ->innerJoin(Product::tableName(), Product::tableName() .'.brand_id='. Brand::tableName() .'.brand_id') ->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. Product::tableName() .'.product_id') ->with(['brandName']); + + if (!empty($params['options'])) { + $queryCount = ProductOption::find() + ->select(['COUNT(pr.product_id)']) + ->innerJoin('tax_option', 'tax_option.tax_option_id = product_option.option_id') + ->innerJoin('tax_group', 'tax_group.tax_group_id = tax_option.tax_group_id') + ->innerJoin('product AS pr', 'pr.product_id = product_option.product_id') + ->where('pr.brand_id = brand.brand_id'); +// ->groupBy(['product.product_id']); + foreach ($params['options'] as $group => $options) { + $queryCount->andWhere([ + 'tax_group.alias' => $group, + 'tax_option.alias' => $options + ]); + } + $query->addSelect(['_items_count' => $queryCount]); +// $query->addSelect("(SELECT COUNT(product_option.product_id) AS products FROM product_option INNER JOIN tax_option ON tax_option.tax_option_id = product_option.option_id INNER JOIN tax_group ON tax_group.tax_group_id = tax_option.tax_group_id WHERE tax_group.alias LIKE '$group' AND tax_option.alias IN (" . implode(',', $options) . ")) AS _items_count"); + } + + $query->innerJoin('product_variant', 'product_variant.product_id = '. Product::tableName() .'.product_id'); $query->where(['!=', 'product_variant.stock', 0]); $query->groupBy(Product::tableName() .'.product_id'); @@ -106,20 +141,6 @@ class BrandSearch extends Brand ]); } $query->groupBy(Brand::tableName() .'.brand_id'); - if (isset($params['options'])) { - unset($params['options']); - } - if (!empty($params['prices'])) { - if ($params['prices']['min'] > 0 || $params['prices']['max'] > 0) { - $query->innerJoin(ProductVariant::tableName(), ProductVariant::tableName() .'.product_id='. Product::tableName() .'.product_id'); - } - if ($params['prices']['min'] > 0) { - $query->andWhere(['>=', ProductVariant::tableName() .'.price', $params['prices']['min']]); - } - if ($params['prices']['max'] > 0) { - $query->andWhere(['<=', ProductVariant::tableName() .'.price', $params['prices']['max']]); - } - } return $query; } diff --git a/common/modules/product/models/Product.php b/common/modules/product/models/Product.php index d4f24c9..3ebc468 100755 --- a/common/modules/product/models/Product.php +++ b/common/modules/product/models/Product.php @@ -38,7 +38,7 @@ class Product extends \yii\db\ActiveRecord /** @var array $_images */ public $imagesUpload = []; - public $variantImagesUpload = []; + /** * @inheritdoc */ @@ -318,27 +318,6 @@ class Product extends \yii\db\ActiveRecord ProductVariant::deleteAll(['product_id' => $this->product_id]); } - public function variantImagesUpload() - { - if ($this->validate()) { - $images = []; - foreach ($this->variantImagesUpload as $product_variant_id => $image) { - $imageName = $image->baseName .'.'. $image->extension; - $i = 0; - while(file_exists(Yii::getAlias('@imagesDir/products/' . $imageName))) { - $i++; - $imageName = $image->baseName .'_'. $i .'.'. $image->extension; - } - - $image->saveAs(Yii::getAlias('@imagesDir/products/' .$imageName)); - $images[$product_variant_id] = $imageName; - } - return $images; - } else { - return false; - } - } - public function imagesUpload() { if ($this->validate()) { diff --git a/common/modules/product/models/ProductVariant.php b/common/modules/product/models/ProductVariant.php index 531854d..146e6e7 100755 --- a/common/modules/product/models/ProductVariant.php +++ b/common/modules/product/models/ProductVariant.php @@ -2,6 +2,8 @@ namespace common\modules\product\models; +use common\modules\relation\relationBehavior; +use common\modules\rubrication\models\TaxOption; use Yii; use yii\helpers\ArrayHelper; @@ -37,7 +39,23 @@ class ProductVariant extends \yii\db\ActiveRecord public $stocks; /** @var array $_images */ -// public $imagesUpload = []; + public $imagesUpload = []; + + /** + * @inheritdoc + */ + public function behaviors() + { + return [ + [ + 'class' => relationBehavior::className(), + 'relations' => [ + 'product_variant_option' => 'entity1' // Product variant options + ] + ] + ]; + } + /** * @inheritdoc */ @@ -57,6 +75,7 @@ class ProductVariant extends \yii\db\ActiveRecord [['price', 'price_old', 'stock'], 'number'], [['name', 'sku'], 'string', 'max' => 255], [['remote_id'], 'string', 'max' => 20], + [['options', 'imagesUpload'], 'safe'], // [['imagesUpload'], 'safe'], // [['imagesUpload'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg, gif', 'maxFiles' => 50], [['product_unit_id'], 'exist', 'skipOnError' => true, 'targetClass' => ProductUnit::className(), 'targetAttribute' => ['product_unit_id' => 'product_unit_id']], @@ -144,6 +163,34 @@ class ProductVariant extends \yii\db\ActiveRecord return empty($this->product) ? null : ($this->product->name . (empty($this->name) ? '' : ' '. $this->name)); } + public function getImagesHTML() { + $op = []; + if ($this->images) { + foreach ($this->images as $image) { + $op[] = \common\components\artboximage\ArtboxImageHelper::getImage($image->imageUrl, 'admin_thumb'); + } + } + return $op; + } + + public function getImagesConfig() { + $op = []; + if ($this->images) { + foreach ($this->images as $image) { + $op[] = [ + 'caption' => $image->image, + 'width' => '120px', + 'url' => \yii\helpers\Url::to(['/product/manage/delimg', 'id' => $image->product_image_id]), + 'key' => $image->product_image_id, + 'extra' => [ + 'id' => $image->product_image_id, + ], + ]; + } + } + return $op; + } + /** * @return \yii\db\ActiveQuery */ @@ -152,6 +199,24 @@ class ProductVariant extends \yii\db\ActiveRecord return $this->hasMany(ProductImage::className(), ['product_variant_id' => 'product_variant_id']); } + public function getOptions() { + return $this->hasMany(TaxOption::className(), ['tax_option_id' => 'option_id'])->viaTable('product_variant_option', ['product_variant_id' => 'product_variant_id']); + } + + public function getProperties() { + $groups = $options = []; + foreach ($this->options as $option) { + $options[$option->tax_group_id][] = $option; + } + foreach (TaxGroup::find()->where(['tax_group_id' => array_keys($options)])->all() as $group) { + if (!empty($options[$group->tax_group_id])) { + $group->_options = $options[$group->tax_group_id]; + $groups[] = $group; + } + } + return $groups; + } + /** * @inheritdoc * @return ProductVariantQuery the active query used by this AR class. @@ -169,6 +234,10 @@ class ProductVariant extends \yii\db\ActiveRecord $this->stocks = (array) $stocks; } + public function getCategory() { + return $this->hasOne(Category::className(), ['category_id' => 'category_id'])->viaTable('product_category', ['product_id' => 'product_id']); + } + public function afterSave($insert, $changedAttributes) { if (!is_null($this->stocks)) { @@ -187,4 +256,25 @@ class ProductVariant extends \yii\db\ActiveRecord ProductImage::deleteAll(['product_variant_id' => $this->product_variant_id]); ProductStock::deleteAll(['product_variant_id' => $this->product_variant_id]); } + + public function imagesUpload() + { + if ($this->validate()) { + $images = []; + foreach ($this->imagesUpload as $image) { + $imageName = $image->baseName .'.'. $image->extension; + $i = 0; + while(file_exists(Yii::getAlias('@imagesDir/products/' . $imageName))) { + $i++; + $imageName = $image->baseName .'_'. $i .'.'. $image->extension; + } + + $image->saveAs(Yii::getAlias('@imagesDir/products/' .$imageName)); + $images[] = $imageName; + } + return $images; + } else { + return false; + } + } } diff --git a/common/modules/product/models/ProductVariantOption.php b/common/modules/product/models/ProductVariantOption.php new file mode 100644 index 0000000..c1d30ae --- /dev/null +++ b/common/modules/product/models/ProductVariantOption.php @@ -0,0 +1,65 @@ + true, 'targetClass' => ProductVariant::className(), 'targetAttribute' => ['product_variant_id' => 'product_variant_id']], + [['option_id'], 'exist', 'skipOnError' => true, 'targetClass' => TaxOption::className(), 'targetAttribute' => ['option_id' => 'tax_option_id']], + ]; + } + + /** + * @inheritdoc + */ + public function attributeLabels() + { + return [ + 'product_variant_id' => 'Product Variant ID', + 'option_id' => 'Option ID', + ]; + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getProductVariant() + { + return $this->hasOne(ProductVariant::className(), ['product_variant_id' => 'product_variant_id']); + } + + /** + * @return \yii\db\ActiveQuery + */ + public function getOption() + { + return $this->hasOne(TaxOption::className(), ['tax_option_id' => 'option_id']); + } +} diff --git a/common/modules/product/models/ProductVariantSearch.php b/common/modules/product/models/ProductVariantSearch.php index bfb1f25..4c68e73 100755 --- a/common/modules/product/models/ProductVariantSearch.php +++ b/common/modules/product/models/ProductVariantSearch.php @@ -24,7 +24,7 @@ class ProductVariantSearch extends ProductVariant public function rules() { return [ - [['name', 'fullname', 'sku', 'price', 'price_old', 'stock', 'fullname', 'brand_name', 'category_name'], 'safe'], + [['name', 'fullname', 'sku', 'price', 'price_old', 'stock', 'brand_name', 'category_name'], 'safe'], [['product_variant_id', 'product_id'], 'integer'], [['is_top', 'is_new', 'akciya'], 'boolean'], ]; @@ -48,7 +48,7 @@ class ProductVariantSearch extends ProductVariant */ public function search($params) { - $query = Product::find(); + $query = ProductVariant::find(); // add conditions that should always apply here @@ -58,6 +58,10 @@ class ProductVariantSearch extends ProductVariant $this->load($params); + if (!empty($params['product_id'])) { + $this->product_id = $params['product_id']; + } + if (!$this->validate()) { // uncomment the following line if you do not want to return any records when validation fails // $query->where('0=1'); @@ -66,7 +70,12 @@ class ProductVariantSearch extends ProductVariant $dataProvider->setSort([ 'attributes' => [ - 'name', + 'name' => [ + 'asc' => ['product_variant.name' => SORT_ASC], + 'desc' => ['product_variant.value' => SORT_DESC], + 'default' => SORT_DESC, + 'label' => 'Variant name', + ], 'brand_name' => [ 'asc' => ['brand_name.value' => SORT_ASC], 'desc' => ['brand_name.value' => SORT_DESC], @@ -98,12 +107,12 @@ class ProductVariantSearch extends ProductVariant // grid filtering conditions $query->andFilterWhere([ - 'product.product_id' => $this->product_id, + 'product_variant.product_id' => $this->product_id, 'product_variant_id' => $this->product_variant_id, ]); if (!empty($this->fullname)) { - $query->orFilterWhere(['like', 'name', $this->fullname]); + $query->orFilterWhere(['like', 'product_variant.name', $this->fullname]); $query->orFilterWhere(['ilike', 'product.name', $this->fullname]); } $query->andFilterWhere(['ilike', 'product.brand_name.value', $this->brand_name]); @@ -111,7 +120,7 @@ class ProductVariantSearch extends ProductVariant $query->andFilterWhere(['ilike', 'sku', $this->sku]); $query->groupBy(['product_variant_id']); - $query->orderBy('product.product_id', 'DESC'); + $query->orderBy('product_variant.product_id', 'ASC'); return $dataProvider; } diff --git a/common/modules/product/views/manage/_form.php b/common/modules/product/views/manage/_form.php index 5bb218a..0199db9 100755 --- a/common/modules/product/views/manage/_form.php +++ b/common/modules/product/views/manage/_form.php @@ -69,7 +69,7 @@ use kartik\select2\Select2; ], ]); ?> - field($model, 'variants')->widget(MultipleInput::className(), [ + field($model, 'variants')->widget(MultipleInput::className(), [ 'columns' => [ [ 'name' => 'product_variant_id', @@ -119,7 +119,7 @@ use kartik\select2\Select2; ], ], ]); - ?> + */ ?> all() as $group) :?> diff --git a/common/modules/product/views/manage/index.php b/common/modules/product/views/manage/index.php index 5fc4527..3c79fc9 100755 --- a/common/modules/product/views/manage/index.php +++ b/common/modules/product/views/manage/index.php @@ -27,7 +27,6 @@ $this->params['breadcrumbs'][] = $this->title; 'filterModel' => $searchModel, 'columns' => [ ['class' => 'yii\grid\SerialColumn'], -// 'product_id', 'name', [ 'label' => Yii::t('product', 'Brand'), @@ -87,7 +86,7 @@ $this->params['breadcrumbs'][] = $this->title; ], [ 'class' => 'yii\grid\ActionColumn', - 'template' => '{view} |{is_top} {is_new} {akciya} | {update} {delete}', + 'template' => '{items} {view} |{is_top} {is_new} {akciya} | {update} {delete}', 'buttons' => [ 'is_top' => function ($url, $model) { return Html::a('', $url, [ @@ -104,9 +103,18 @@ $this->params['breadcrumbs'][] = $this->title; '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; diff --git a/common/modules/product/views/variant/_form.php b/common/modules/product/views/variant/_form.php new file mode 100644 index 0000000..9aa37c3 --- /dev/null +++ b/common/modules/product/views/variant/_form.php @@ -0,0 +1,121 @@ + + +
+ + ['enctype' => 'multipart/form-data'] + ]); ?> + + field($model, 'name')->textInput(['maxlength' => true]) ?> + + field($model, 'product_id')->hiddenInput()->label(''); ?> + + field($model, 'sku')->textarea(); ?> + field($model, 'price')->textarea(); ?> + field($model, 'price_old')->textarea(); ?> + + field($model, 'imagesUpload[]')->widget(\kartik\file\FileInput::classname(), [ + 'language' => 'ru', + 'options' => [ + 'accept' => 'image/*', + 'multiple' => true, + ], + 'pluginOptions' => [ + 'allowedFileExtensions' => ['jpg', 'gif', 'png'], + 'initialPreview' => !empty($model->imagesHTML) ? $model->imagesHTML : [], + 'initialPreviewConfig' => $model->imagesConfig, + 'overwriteInitial' => false, + 'showRemove' => false, + 'showUpload' => false, +// 'uploadUrl' => empty($model->product_id) ? null : \yii\helpers\Url::to(['/product/manage/uploadImage']), + 'uploadAsync' => !empty($model->product_id), + 'previewFileType' => 'image', + ], + ]); ?> + + field($model, 'variants')->widget(MultipleInput::className(), [ + 'columns' => [ + [ + 'name' => 'product_variant_id', + 'type' => MultipleInputColumn::TYPE_HIDDEN_INPUT, + ], + [ + 'name' => 'name', + 'type' => MultipleInputColumn::TYPE_TEXT_INPUT, + 'title' => Yii::t('product', 'Name'), + ], + [ + 'name' => 'sku', + 'type' => MultipleInputColumn::TYPE_TEXT_INPUT, + 'title' => Yii::t('product', 'SKU'), + ], + [ + 'name' => 'price', + 'type' => MultipleInputColumn::TYPE_TEXT_INPUT, + 'title' => Yii::t('product', 'Price'), + ], + [ + 'name' => 'price_old', + 'type' => MultipleInputColumn::TYPE_TEXT_INPUT, + 'title' => Yii::t('product', 'Old Price'), + ], + [ + 'name' => 'product_unit_id', + 'type' => MultipleInputColumn::TYPE_DROPDOWN, + 'title' => Yii::t('product', 'Unit'), + 'items' => ArrayHelper::map(\common\modules\product\models\ProductUnit::find()->all(), 'product_unit_id', 'name'), + ], + [ + 'name' => 'stock', + 'type' => MultipleInputColumn::TYPE_TEXT_INPUT, + 'title' => Yii::t('product', 'Stock'), + 'options' => [ + 'placeholder' => '∞' + ], + ], + [ + 'name' => 'image', + 'type' => 'fileInput', + 'title' => Yii::t('product', 'Image'), + 'options' => [ + 'multiple' => false + ], + ], + ], + ]); + */ ?> + + + all() as $group) :?> + field($model, 'options')->checkboxList( + ArrayHelper::map($group->options, 'tax_option_id', 'ValueRenderFlash'), + [ + 'multiple' => true, + 'unselect' => null, + ] + )->label($group->name);?> + + + +
+ isNewRecord ? Yii::t('product', 'Create') : Yii::t('product', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> +
+ + + +
diff --git a/common/modules/product/views/variant/_search.php b/common/modules/product/views/variant/_search.php new file mode 100644 index 0000000..00015dc --- /dev/null +++ b/common/modules/product/views/variant/_search.php @@ -0,0 +1,31 @@ + + + diff --git a/common/modules/product/views/variant/create.php b/common/modules/product/views/variant/create.php new file mode 100644 index 0000000..e5f7902 --- /dev/null +++ b/common/modules/product/views/variant/create.php @@ -0,0 +1,21 @@ +title = Yii::t('product', 'Create Product'); +$this->params['breadcrumbs'][] = ['label' => Yii::t('product', 'Products'), 'url' => ['index']]; +$this->params['breadcrumbs'][] = $this->title; +?> +
+ +

title) ?>

+ + render('_form', [ + 'model' => $model, + ]) ?> + +
diff --git a/common/modules/product/views/variant/index.php b/common/modules/product/views/variant/index.php new file mode 100644 index 0000000..696ba91 --- /dev/null +++ b/common/modules/product/views/variant/index.php @@ -0,0 +1,61 @@ +title = Yii::t('product', 'Variants'); +$this->params['breadcrumbs'][] = ['label' => Yii::t('product', 'Products'), 'url' => ['/product/manage']]; +if (!empty($product)) { + $this->params['breadcrumbs'] = [ + ['label' => Yii::t('product', 'Variants'), 'url' => ['/product/variant']], + $product->fullname + ]; +} else { + $this->params['breadcrumbs'][] = $this->title; +} +?> +
+ +

title) ?>

+ render('_search', ['model' => $searchModel]); ?> + +

+ 'btn btn-success']) ?> +

+ $dataProvider, + 'filterModel' => $searchModel, + 'columns' => [ + ['class' => 'yii\grid\SerialColumn'], + + [ + 'attribute' => 'product_id', + 'value' => 'fullname', + 'label' => Yii::t('product', 'Name'), + 'filter' => \kartik\select2\Select2::widget([ + 'model' => $searchModel, + 'attribute' => 'product_id', + 'data' => \yii\helpers\ArrayHelper::map(\common\modules\product\models\Product::find()->orderBy(['name' => 'ASC'])->all(), 'product_id', 'name'), + 'language' => 'ru', + 'options' => [ + 'placeholder' => Yii::t('product', 'Select product'), + 'multiple' => false, + ], + 'pluginOptions' => [ + 'allowClear' => true + ], + ]), + ], + 'sku', + 'price', + 'price_old', + 'stock', + + ['class' => 'yii\grid\ActionColumn'], + ], + ]); ?> +
diff --git a/common/modules/product/views/variant/update.php b/common/modules/product/views/variant/update.php new file mode 100644 index 0000000..8603dad --- /dev/null +++ b/common/modules/product/views/variant/update.php @@ -0,0 +1,26 @@ +title = Yii::t('product', 'Update {modelClass}: ', [ + 'modelClass' => 'Product', +]) . ' ' . $model->name; +$this->params['breadcrumbs'][] = ['label' => Yii::t('product', 'Products'), 'url' => ['index']]; +$this->params['breadcrumbs'][] = ['label' => $model->product->name, 'url' => ['view', 'id' => $model->product->product_id]]; +$this->params['breadcrumbs'][] = ['label' => Yii::t('product', 'Variants'), 'url' => ['/product/variant?product_id='. $model->product->product_id]]; +$this->params['breadcrumbs'][] = ['label' => $model->name, 'url' => ['view', 'id' => $model->product_variant_id]]; +$this->params['breadcrumbs'][] = Yii::t('product', 'Update'); +?> +
+ +

title) ?>

+ + render('_form', [ + 'model' => $model, + 'groups' => $groups, + ]) ?> + +
diff --git a/common/modules/product/views/variant/view.php b/common/modules/product/views/variant/view.php new file mode 100644 index 0000000..5eaecd8 --- /dev/null +++ b/common/modules/product/views/variant/view.php @@ -0,0 +1,42 @@ +title = $model->name; +$this->params['breadcrumbs'][] = ['label' => Yii::t('product', 'Products'), 'url' => ['index']]; +$this->params['breadcrumbs'][] = ['label' => $model->product->name, 'url' => ['view', 'id' => $model->product->product_id]]; +$this->params['breadcrumbs'][] = ['label' => Yii::t('product', 'Variants'), 'url' => ['/product/variant?product_id='. $model->product->product_id]]; +$this->params['breadcrumbs'][] = $this->title; +?> +
+ +

title) ?>

+ +

+ $model->product_variant_id], ['class' => 'btn btn-primary']) ?> + $model->product_variant_id], [ + 'class' => 'btn btn-danger', + 'data' => [ + 'confirm' => Yii::t('product', 'Are you sure you want to delete this item?'), + 'method' => 'post', + ], + ]) ?> +

+ + $model, + 'attributes' => [ + 'product_id', + 'name', + 'fullname', + 'brand.name', + 'category.name', + 'image.imageUrl:image' + ], + ]) ?> + +
diff --git a/common/translation/ru/product.php b/common/translation/ru/product.php index 262de9a..61312a6 100755 --- a/common/translation/ru/product.php +++ b/common/translation/ru/product.php @@ -24,6 +24,8 @@ return [ 'Price Old' => 'Старая Цена', 'Products' => 'Товары', 'Product' => 'Товар', + 'Variants' => 'Модифицкации', + 'Variant' => 'Модифицкация', 'Create Product' => 'Создать Товар', 'Enable' => 'Доступно', 'Disable' => 'Отсутсвует', diff --git a/frontend/models/ProductFrontendSearch.php b/frontend/models/ProductFrontendSearch.php index 7679eee..f28caae 100755 --- a/frontend/models/ProductFrontendSearch.php +++ b/frontend/models/ProductFrontendSearch.php @@ -2,6 +2,7 @@ namespace frontend\models; +use common\modules\product\helpers\ProductHelper; use common\modules\product\models\Brand; use common\modules\product\models\BrandName; use common\modules\product\models\CategoryName; @@ -86,7 +87,7 @@ class ProductFrontendSearch extends Product { return $dataProvider; } - $this->_setParams($query, $params); + ProductHelper::_setQueryParams($query, $params); $query->andWhere(['!=', ProductVariant::tableName() .'.stock', 0]); @@ -144,7 +145,7 @@ class ProductFrontendSearch extends Product { } $query->joinWith('variant'); - $this->_setParams($query, $params, false); + ProductHelper::_setQueryParams($query, $params, false); // $query->select([ // 'MIN('. ProductVariant::tableName() .'.price) AS priceMIN', @@ -156,46 +157,4 @@ class ProductFrontendSearch extends Product { 'max' => $query->max(ProductVariant::tableName() .'.price'), ]; } - - protected function _setParams(&$query, $params, $setPriceLimits = true) { - if (!empty($params['keywords'])) { - if (!is_array($params['keywords'])) { - $params['keywords'] = [$params['keywords']]; - } - foreach ($params['keywords'] as $keyword) { - $query->orFilterWhere(['ilike', Product::tableName() .'.name', $keyword]); - $query->orFilterWhere(['ilike', BrandName::tableName() .'.value', $keyword]); - $query->orFilterWhere(['ilike', CategoryName::tableName() .'.value', $keyword]); - } - } - if (!empty($params['special'])) { - foreach($params['special'] as $key => $value) { - $query->orFilterWhere([Product::tableName() .'.'. $key => $value]); - } - } - if (!empty($params['brands'])) { - $query->andFilterWhere([Product::tableName() .'.brand_id' => $params['brands']]); - } - if (!empty($params['options'])) { - foreach ($params['options'] as $group => $options) { - foreach ($options as &$option) { - $option = "'$option'"; - } - $query->andWhere( - Product::tableName() . '.product_id IN (SELECT product_id AS products FROM product_option INNER JOIN tax_option ON tax_option.tax_option_id = product_option.option_id INNER JOIN tax_group ON tax_group.tax_group_id = tax_option.tax_group_id WHERE tax_group.alias LIKE \''. $group .'\' AND tax_option.alias IN (' . implode(',', $options) . '))' - ); - } - } - - - - if ($setPriceLimits && !empty($params['prices'])) { - if ($params['prices']['min'] > 0) { - $query->andWhere(['>=', ProductVariant::tableName() .'.price', $params['prices']['min']]); - } - if ($params['prices']['max'] > 0) { - $query->andWhere(['<=', ProductVariant::tableName() .'.price', $params['prices']['max']]); - } - } - } } \ No newline at end of file -- libgit2 0.21.4