Commit 5aa7418e91ad61ac033b90ef0263d30c2aec5160
1 parent
b15c889e
Base-product#3 functional
Showing
17 changed files
with
463 additions
and
22 deletions
Show diff stats
common/config/main.php
@@ -100,6 +100,27 @@ return [ | @@ -100,6 +100,27 @@ return [ | ||
100 | 'model' => '\common\modules\product\models\ProductCategory', | 100 | 'model' => '\common\modules\product\models\ProductCategory', |
101 | ] | 101 | ] |
102 | ], | 102 | ], |
103 | + 'product_option' => [ | ||
104 | + 'name' => Yii::t('product', 'Properties'), | ||
105 | + 'field' => 'options', | ||
106 | + 'entity1' => [ | ||
107 | + 'model' => '\common\modules\product\models\Product', | ||
108 | + 'label' => 'Product', | ||
109 | + 'listField' => 'fullname', | ||
110 | + 'key' => 'product_id', | ||
111 | + 'linked_key' => 'product_id', | ||
112 | + ], | ||
113 | + 'entity2' => [ | ||
114 | + 'model' => '\common\modules\rubrication\models\TaxOption', | ||
115 | + 'label' => 'Option', | ||
116 | + 'listField' => 'ValueeRenderFlash', | ||
117 | + 'key' => 'tax_option_id', | ||
118 | + 'linked_key' => 'option_id', | ||
119 | + ], | ||
120 | + 'via' => [ | ||
121 | + 'model' => 'common\modules\product\models\ProductOption', | ||
122 | + ] | ||
123 | + ], | ||
103 | 'tax_group_to_category' => [ | 124 | 'tax_group_to_category' => [ |
104 | 'name' => Yii::t('product', 'Характеристики по категориям'), | 125 | 'name' => Yii::t('product', 'Характеристики по категориям'), |
105 | 'field' => 'group_to_category', | 126 | 'field' => 'group_to_category', |
common/modules/product/controllers/ManageController.php
@@ -33,6 +33,24 @@ class ManageController extends Controller | @@ -33,6 +33,24 @@ class ManageController extends Controller | ||
33 | } | 33 | } |
34 | 34 | ||
35 | public function actionTest() { | 35 | public function actionTest() { |
36 | + return; | ||
37 | + foreach(Product::find()->all() as $product) { | ||
38 | + if (!$product->variant) { | ||
39 | + $product->save(); | ||
40 | + $variantModel = new ProductVariant(); | ||
41 | + $variantModel->product_id = $product->product_id; | ||
42 | + $variantModel->name = 'test-'. uniqid(); | ||
43 | + $variantModel->sku = $variantModel->name; | ||
44 | + $variantModel->price = rand(5, 200000); | ||
45 | + $variantModel->price_old = rand(0, 5) > 3 ? $variantModel->price* (1+rand(0, 10) / 10) : $variantModel->price; | ||
46 | + $variantModel->product_unit_id = rand(1, 5); | ||
47 | + $variantModel->stock = rand(0, 50); | ||
48 | + $variantModel->save(); | ||
49 | + } | ||
50 | + } | ||
51 | + | ||
52 | + return; | ||
53 | + | ||
36 | $categories = Category::find()->where(['depth' => 2])->all(); | 54 | $categories = Category::find()->where(['depth' => 2])->all(); |
37 | $cats_ids = []; | 55 | $cats_ids = []; |
38 | foreach($categories as $cat) { | 56 | foreach($categories as $cat) { |
@@ -122,8 +140,11 @@ class ManageController extends Controller | @@ -122,8 +140,11 @@ class ManageController extends Controller | ||
122 | if ($model->load(Yii::$app->request->post()) && $model->save()) { | 140 | if ($model->load(Yii::$app->request->post()) && $model->save()) { |
123 | return $this->redirect(['view', 'id' => $model->product_id]); | 141 | return $this->redirect(['view', 'id' => $model->product_id]); |
124 | } else { | 142 | } else { |
143 | + $groups = $model->category->getTaxGroups(); | ||
144 | + | ||
125 | return $this->render('update', [ | 145 | return $this->render('update', [ |
126 | 'model' => $model, | 146 | 'model' => $model, |
147 | + 'groups' => $groups, | ||
127 | ]); | 148 | ]); |
128 | } | 149 | } |
129 | } | 150 | } |
common/modules/product/models/Product.php
@@ -2,6 +2,7 @@ | @@ -2,6 +2,7 @@ | ||
2 | 2 | ||
3 | namespace common\modules\product\models; | 3 | namespace common\modules\product\models; |
4 | 4 | ||
5 | +use common\behaviors\Slug; | ||
5 | use common\modules\rubrication\models\TaxOption; | 6 | use common\modules\rubrication\models\TaxOption; |
6 | use Yii; | 7 | use Yii; |
7 | use common\modules\relation\relationBehavior; | 8 | use common\modules\relation\relationBehavior; |
@@ -23,6 +24,9 @@ class Product extends \yii\db\ActiveRecord | @@ -23,6 +24,9 @@ class Product extends \yii\db\ActiveRecord | ||
23 | { | 24 | { |
24 | /** @var array $variants */ | 25 | /** @var array $variants */ |
25 | public $_variants = []; | 26 | public $_variants = []; |
27 | + | ||
28 | + /** @var array $_images */ | ||
29 | + public $imagesUpload = []; | ||
26 | /** | 30 | /** |
27 | * @inheritdoc | 31 | * @inheritdoc |
28 | */ | 32 | */ |
@@ -32,9 +36,16 @@ class Product extends \yii\db\ActiveRecord | @@ -32,9 +36,16 @@ class Product extends \yii\db\ActiveRecord | ||
32 | [ | 36 | [ |
33 | 'class' => relationBehavior::className(), | 37 | 'class' => relationBehavior::className(), |
34 | 'relations' => [ | 38 | 'relations' => [ |
35 | - 'product_categories' => 'entity1' // Product category | 39 | + 'product_categories' => 'entity1', // Product category |
40 | + 'product_option' => 'entity1' // Product category | ||
36 | ] | 41 | ] |
37 | ], | 42 | ], |
43 | + [ | ||
44 | + 'class' => Slug::className(), | ||
45 | + 'in_attribute' => 'name', | ||
46 | + 'out_attribute' => 'alias', | ||
47 | + 'translit' => true | ||
48 | + ] | ||
38 | ]; | 49 | ]; |
39 | } | 50 | } |
40 | 51 | ||
@@ -54,7 +65,10 @@ class Product extends \yii\db\ActiveRecord | @@ -54,7 +65,10 @@ class Product extends \yii\db\ActiveRecord | ||
54 | return [ | 65 | return [ |
55 | [['brand_id'], 'integer'], | 66 | [['brand_id'], 'integer'], |
56 | [['name'], 'string', 'max' => 150], | 67 | [['name'], 'string', 'max' => 150], |
57 | - [['categories', 'variants'], 'safe'], | 68 | + [['alias'], 'string', 'max' => 250], |
69 | + [['categories', 'variants', 'options'], 'safe'], | ||
70 | + [['imagesUpload'], 'file', 'skipOnEmpty' => false, 'extensions' => 'png, jpg, gif'], | ||
71 | + [['description', 'video'], 'safe'], | ||
58 | // [['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'product_id']], | 72 | // [['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'product_id']], |
59 | ]; | 73 | ]; |
60 | } | 74 | } |
@@ -70,6 +84,8 @@ class Product extends \yii\db\ActiveRecord | @@ -70,6 +84,8 @@ class Product extends \yii\db\ActiveRecord | ||
70 | 'brand_id' => Yii::t('product', 'Brand'), | 84 | 'brand_id' => Yii::t('product', 'Brand'), |
71 | 'categories' => Yii::t('product', 'Categories'), // relation behavior field | 85 | 'categories' => Yii::t('product', 'Categories'), // relation behavior field |
72 | 'category' => Yii::t('product', 'Category'), // relation behavior field | 86 | 'category' => Yii::t('product', 'Category'), // relation behavior field |
87 | + 'image' => Yii::t('product', 'Image'), | ||
88 | + 'images' => Yii::t('product', 'Images'), | ||
73 | ]; | 89 | ]; |
74 | } | 90 | } |
75 | 91 | ||
@@ -97,6 +113,10 @@ class Product extends \yii\db\ActiveRecord | @@ -97,6 +113,10 @@ class Product extends \yii\db\ActiveRecord | ||
97 | return $this->hasMany(ProductImage::className(), ['product_id' => 'product_id']); | 113 | return $this->hasMany(ProductImage::className(), ['product_id' => 'product_id']); |
98 | } | 114 | } |
99 | 115 | ||
116 | + public function setImages($images) { | ||
117 | + $this->_images = $images; | ||
118 | + } | ||
119 | + | ||
100 | /** | 120 | /** |
101 | * @return \yii\db\ActiveQuery | 121 | * @return \yii\db\ActiveQuery |
102 | */ | 122 | */ |
@@ -146,6 +166,10 @@ class Product extends \yii\db\ActiveRecord | @@ -146,6 +166,10 @@ class Product extends \yii\db\ActiveRecord | ||
146 | return $categories->one(); | 166 | return $categories->one(); |
147 | } | 167 | } |
148 | 168 | ||
169 | + public function getOptions() { | ||
170 | + return $this->getRelations('product_option'); | ||
171 | + } | ||
172 | + | ||
149 | /** | 173 | /** |
150 | * @inheritdoc | 174 | * @inheritdoc |
151 | * @return ProductQuery the active query used by this AR class. | 175 | * @return ProductQuery the active query used by this AR class. |
@@ -159,11 +183,18 @@ class Product extends \yii\db\ActiveRecord | @@ -159,11 +183,18 @@ class Product extends \yii\db\ActiveRecord | ||
159 | { | 183 | { |
160 | parent::afterSave($insert, $changedAttributes); | 184 | parent::afterSave($insert, $changedAttributes); |
161 | 185 | ||
186 | + foreach($this->imagesUpload as $image) { | ||
187 | + $image->saveAs('/images/items/' . $image->baseName .'_'. uniqid() . '.' . $image->extension); | ||
188 | + } | ||
189 | + | ||
162 | $todel = []; | 190 | $todel = []; |
163 | foreach ($this->variants ? : [] as $_variant) { | 191 | foreach ($this->variants ? : [] as $_variant) { |
164 | $todel[$_variant->product_variant_id] = $_variant->product_variant_id; | 192 | $todel[$_variant->product_variant_id] = $_variant->product_variant_id; |
165 | } | 193 | } |
166 | foreach ($this->_variants as $_variant) { | 194 | foreach ($this->_variants as $_variant) { |
195 | + if (!is_array($_variant)) { | ||
196 | + return; | ||
197 | + } | ||
167 | if (!empty($_variant['product_variant_id'])) { | 198 | if (!empty($_variant['product_variant_id'])) { |
168 | unset($todel[$_variant['product_variant_id']]); | 199 | unset($todel[$_variant['product_variant_id']]); |
169 | $model = ProductVariant::findOne($_variant['product_variant_id']); | 200 | $model = ProductVariant::findOne($_variant['product_variant_id']); |
1 | +<?php | ||
2 | + | ||
3 | +namespace common\modules\product\models; | ||
4 | + | ||
5 | +use Yii; | ||
6 | + | ||
7 | +/** | ||
8 | + * This is the model class for table "product_option". | ||
9 | + * | ||
10 | + * @property integer $product_id | ||
11 | + * @property integer $option_id | ||
12 | + * | ||
13 | + * @property Product $product | ||
14 | + * @property TaxOption $option | ||
15 | + */ | ||
16 | +class ProductOption extends \yii\db\ActiveRecord | ||
17 | +{ | ||
18 | + /** | ||
19 | + * @inheritdoc | ||
20 | + */ | ||
21 | + public static function tableName() | ||
22 | + { | ||
23 | + return 'product_option'; | ||
24 | + } | ||
25 | + | ||
26 | + /** | ||
27 | + * @inheritdoc | ||
28 | + */ | ||
29 | + public function rules() | ||
30 | + { | ||
31 | + return [ | ||
32 | + [['product_id', 'option_id'], 'required'], | ||
33 | + [['product_id', 'option_id'], 'integer'], | ||
34 | + [['product_id'], 'exist', 'skipOnError' => true, 'targetClass' => Product::className(), 'targetAttribute' => ['product_id' => 'product_id']], | ||
35 | + [['option_id'], 'exist', 'skipOnError' => true, 'targetClass' => TaxOption::className(), 'targetAttribute' => ['option_id' => 'tax_option_id']], | ||
36 | + ]; | ||
37 | + } | ||
38 | + | ||
39 | + /** | ||
40 | + * @inheritdoc | ||
41 | + */ | ||
42 | + public function attributeLabels() | ||
43 | + { | ||
44 | + return [ | ||
45 | + 'product_id' => Yii::t('product', 'Product ID'), | ||
46 | + 'option_id' => Yii::t('product', 'Option ID'), | ||
47 | + ]; | ||
48 | + } | ||
49 | + | ||
50 | + /** | ||
51 | + * @return \yii\db\ActiveQuery | ||
52 | + */ | ||
53 | + public function getProduct() | ||
54 | + { | ||
55 | + return $this->hasOne(Product::className(), ['product_id' => 'product_id']); | ||
56 | + } | ||
57 | + | ||
58 | + /** | ||
59 | + * @return \yii\db\ActiveQuery | ||
60 | + */ | ||
61 | + public function getOption() | ||
62 | + { | ||
63 | + return $this->hasOne(TaxOption::className(), ['tax_option_id' => 'option_id']); | ||
64 | + } | ||
65 | +} |
common/modules/product/models/ProductSearch.php
@@ -6,6 +6,7 @@ use Yii; | @@ -6,6 +6,7 @@ use Yii; | ||
6 | use yii\base\Model; | 6 | use yii\base\Model; |
7 | use yii\data\ActiveDataProvider; | 7 | use yii\data\ActiveDataProvider; |
8 | use common\modules\product\models\Product; | 8 | use common\modules\product\models\Product; |
9 | +use yii\web\NotFoundHttpException; | ||
9 | 10 | ||
10 | /** | 11 | /** |
11 | * ProductSearch represents the model behind the search form about `common\modules\product\models\Product`. | 12 | * ProductSearch represents the model behind the search form about `common\modules\product\models\Product`. |
@@ -70,7 +71,7 @@ class ProductSearch extends Product | @@ -70,7 +71,7 @@ class ProductSearch extends Product | ||
70 | 71 | ||
71 | public static function findByAlias($alias) { | 72 | public static function findByAlias($alias) { |
72 | /** @var ProductQuery $query */ | 73 | /** @var ProductQuery $query */ |
73 | - $query = Category::find(); | 74 | + $query = Product::find(); |
74 | $query->byAlias($alias); | 75 | $query->byAlias($alias); |
75 | if (($model = $query->one()) !== null) { | 76 | if (($model = $query->one()) !== null) { |
76 | return $model; | 77 | return $model; |
common/modules/product/views/manage/_form.php
@@ -20,6 +20,9 @@ use unclead\widgets\MultipleInputColumn; | @@ -20,6 +20,9 @@ use unclead\widgets\MultipleInputColumn; | ||
20 | 20 | ||
21 | <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?> | 21 | <?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?> |
22 | 22 | ||
23 | + <?= $form->field($model, 'description')->widget(\mihaildev\ckeditor\CKEditor::className(),['editorOptions' => [ 'preset' => 'full', 'inline' => false, ], ]); ?> | ||
24 | + <?= $form->field($model, 'video')->textarea()->label('Video embeded'); ?> | ||
25 | + | ||
23 | <?= $form->field($model, 'brand_id')->dropDownList( | 26 | <?= $form->field($model, 'brand_id')->dropDownList( |
24 | ArrayHelper::map(ProductHelper::getBrands()->all(), 'brand_id', 'name'), | 27 | ArrayHelper::map(ProductHelper::getBrands()->all(), 'brand_id', 'name'), |
25 | [ | 28 | [ |
@@ -30,21 +33,18 @@ use unclead\widgets\MultipleInputColumn; | @@ -30,21 +33,18 @@ use unclead\widgets\MultipleInputColumn; | ||
30 | <?= $form->field($model, 'categories')->dropDownList( | 33 | <?= $form->field($model, 'categories')->dropDownList( |
31 | ArtboxTreeHelper::treeMap(ProductHelper::getCategories(), 'category_id', 'name'), | 34 | ArtboxTreeHelper::treeMap(ProductHelper::getCategories(), 'category_id', 'name'), |
32 | [ | 35 | [ |
33 | -// 'prompt' => Yii::t('product', 'Select category'), | ||
34 | 'multiple' => true | 36 | 'multiple' => true |
35 | ] | 37 | ] |
36 | ) ?> | 38 | ) ?> |
37 | 39 | ||
38 | - <?php /*= $form->field($model, 'images[]')->widget(FileInput::classname(), [ | 40 | + |
41 | + | ||
42 | + <?php /*= $form->field($model, 'imagesUpload[]')->widget(FileInput::classname(), [ | ||
39 | 'options' => [ | 43 | 'options' => [ |
40 | 'accept' => 'image/*', | 44 | 'accept' => 'image/*', |
41 | 'multiple' => true, | 45 | 'multiple' => true, |
42 | ], | 46 | ], |
43 | - 'pluginOptions' => [ | ||
44 | -// 'uploadUrl' => \yii\helpers\Url::to(['/site/file-upload']), | ||
45 | - ] | ||
46 | - ]); | ||
47 | - */?> | 47 | + ]);*/?> |
48 | 48 | ||
49 | <?= $form->field($model, 'variants')->widget(MultipleInput::className(), [ | 49 | <?= $form->field($model, 'variants')->widget(MultipleInput::className(), [ |
50 | 'columns' => [ | 50 | 'columns' => [ |
@@ -90,6 +90,16 @@ use unclead\widgets\MultipleInputColumn; | @@ -90,6 +90,16 @@ use unclead\widgets\MultipleInputColumn; | ||
90 | ]); | 90 | ]); |
91 | ?> | 91 | ?> |
92 | 92 | ||
93 | + <?php foreach($groups->all() as $group) :?> | ||
94 | + <?= $form->field($model, 'options')->checkboxList( | ||
95 | + ArrayHelper::map($group->options, 'tax_option_id', 'ValueRenderFlash'), | ||
96 | + [ | ||
97 | + 'multiple' => true, | ||
98 | + 'unselect' => null, | ||
99 | + ] | ||
100 | + )->label($group->name);?> | ||
101 | + <?php endforeach?> | ||
102 | + | ||
93 | <div class="form-group"> | 103 | <div class="form-group"> |
94 | <?= Html::submitButton($model->isNewRecord ? Yii::t('product', 'Create') : Yii::t('product', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> | 104 | <?= Html::submitButton($model->isNewRecord ? Yii::t('product', 'Create') : Yii::t('product', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?> |
95 | </div> | 105 | </div> |
common/modules/product/views/manage/update.php
@@ -18,6 +18,7 @@ $this->params['breadcrumbs'][] = Yii::t('product', 'Update'); | @@ -18,6 +18,7 @@ $this->params['breadcrumbs'][] = Yii::t('product', 'Update'); | ||
18 | 18 | ||
19 | <?= $this->render('_form', [ | 19 | <?= $this->render('_form', [ |
20 | 'model' => $model, | 20 | 'model' => $model, |
21 | + 'groups' => $groups, | ||
21 | ]) ?> | 22 | ]) ?> |
22 | 23 | ||
23 | </div> | 24 | </div> |
common/modules/rubrication/helpers/RubricationHelper.php
@@ -40,4 +40,12 @@ class RubricationHelper { | @@ -40,4 +40,12 @@ class RubricationHelper { | ||
40 | return $module->types; | 40 | return $module->types; |
41 | 41 | ||
42 | } | 42 | } |
43 | + | ||
44 | + public function checkboxList($items, $options = []) | ||
45 | + { | ||
46 | + $this->adjustLabelFor($options); | ||
47 | + $this->parts['{input}'] = Html::activeCheckboxList($this->model, $this->attribute, $items, $options); | ||
48 | + | ||
49 | + return $this; | ||
50 | + } | ||
43 | } | 51 | } |
44 | \ No newline at end of file | 52 | \ No newline at end of file |
common/modules/rubrication/models/TaxGroup.php
console/migrations/m160304_065108_product.php
@@ -69,7 +69,10 @@ class m160304_065108_product extends Migration | @@ -69,7 +69,10 @@ class m160304_065108_product extends Migration | ||
69 | $this->createTable('{{%product}}', [ | 69 | $this->createTable('{{%product}}', [ |
70 | 'product_id' => $this->primaryKey(), | 70 | 'product_id' => $this->primaryKey(), |
71 | 'name' => $this->string(255)->notNull(), | 71 | 'name' => $this->string(255)->notNull(), |
72 | + 'alias' => $this->string(255), | ||
72 | 'brand_id' => $this->integer(), | 73 | 'brand_id' => $this->integer(), |
74 | + 'description' => $this->text(), | ||
75 | + 'video' => $this->text(), | ||
73 | ], $tableOptions); | 76 | ], $tableOptions); |
74 | 77 | ||
75 | $this->addForeignKey('fki_product_id', 'product_category', 'product_id', 'product', 'product_id', 'NO ACTION', 'NO ACTION'); | 78 | $this->addForeignKey('fki_product_id', 'product_category', 'product_id', 'product', 'product_id', 'NO ACTION', 'NO ACTION'); |
console/migrations/m160324_075409_product_option.php
0 → 100644
1 | +<?php | ||
2 | + | ||
3 | +use yii\db\Migration; | ||
4 | + | ||
5 | +class m160324_075409_product_option extends Migration | ||
6 | +{ | ||
7 | + public function up() | ||
8 | + { | ||
9 | + $tableOptions = null; | ||
10 | + if ($this->db->driverName === 'mysql') { | ||
11 | + // Only for MySQL | ||
12 | + $tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB'; | ||
13 | + | ||
14 | + // @todo https://habrahabr.ru/post/138947/ | ||
15 | + } elseif ($this->db->driverName === 'pgsql') { | ||
16 | + // Only for PostgreSQL | ||
17 | + // @todo use intarray field for tax_options | ||
18 | + } | ||
19 | + | ||
20 | + $this->createTable('{{%product_option}}', [ | ||
21 | + 'product_id' => $this->integer()->notNull(), | ||
22 | + 'option_id' => $this->integer()->notNull(), | ||
23 | + ], $tableOptions); | ||
24 | + $this->addPrimaryKey('product_option_pkey', 'product_option', ['product_id', 'option_id']); | ||
25 | + $this->addForeignKey('product_option_product_fkey', 'product_option', 'product_id', 'product', 'product_id', 'NO ACTION', 'NO ACTION'); | ||
26 | + $this->addForeignKey('product_option_option_fkey', 'product_option', 'option_id', 'tax_option', 'tax_option_id', 'NO ACTION', 'NO ACTION'); | ||
27 | + } | ||
28 | + | ||
29 | + public function down() | ||
30 | + { | ||
31 | + $this->dropTable('{{%product_option}}'); | ||
32 | + } | ||
33 | + | ||
34 | + /* | ||
35 | + // Use safeUp/safeDown to run migration code within a transaction | ||
36 | + public function safeUp() | ||
37 | + { | ||
38 | + } | ||
39 | + | ||
40 | + public function safeDown() | ||
41 | + { | ||
42 | + } | ||
43 | + */ | ||
44 | +} |
frontend/controllers/CatalogController.php
@@ -7,8 +7,11 @@ use common\modules\product\models\Category; | @@ -7,8 +7,11 @@ use common\modules\product\models\Category; | ||
7 | use common\modules\product\models\CategorySearch; | 7 | use common\modules\product\models\CategorySearch; |
8 | use common\modules\product\models\Product; | 8 | use common\modules\product\models\Product; |
9 | use common\modules\product\models\ProductCategory; | 9 | use common\modules\product\models\ProductCategory; |
10 | +use common\modules\product\models\ProductOption; | ||
10 | use common\modules\product\models\ProductSearch; | 11 | use common\modules\product\models\ProductSearch; |
11 | use common\modules\product\models\ProductVariant; | 12 | use common\modules\product\models\ProductVariant; |
13 | +use common\modules\rubrication\models\TaxGroup; | ||
14 | +use common\modules\rubrication\models\TaxOption; | ||
12 | use yii\data\ActiveDataProvider; | 15 | use yii\data\ActiveDataProvider; |
13 | use yii\data\Pagination; | 16 | use yii\data\Pagination; |
14 | use yii\data\Sort; | 17 | use yii\data\Sort; |
@@ -56,10 +59,34 @@ class CatalogController extends \yii\web\Controller | @@ -56,10 +59,34 @@ class CatalogController extends \yii\web\Controller | ||
56 | ]); | 59 | ]); |
57 | $all_count = $query->count(); | 60 | $all_count = $query->count(); |
58 | 61 | ||
62 | + $brandsQuery = Brand::find() | ||
63 | + ->innerJoinWith('products') | ||
64 | + ->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. Product::tableName() .'.product_id') | ||
65 | + ->where([ | ||
66 | + ProductCategory::tableName() .'.category_id' => $category->category_id | ||
67 | + ]) | ||
68 | + ->groupBy(Brand::tableName() .'.brand_id'); | ||
69 | + $brands = $brandsQuery->all(); | ||
70 | + $brands_count = $brandsQuery->count(); | ||
71 | + | ||
72 | + $optionsQuery = TaxOption::find() | ||
73 | +// ->select([TaxOption::tableName() .'.tax_option_id', TaxOption::tableName() .'.alias']) | ||
74 | + ->innerJoin(ProductOption::tableName(), ProductOption::tableName() .'.option_id='. TaxOption::tableName() .'.tax_option_id') | ||
75 | + ->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. ProductOption::tableName() .'.product_id') | ||
76 | + ->where([ | ||
77 | + ProductCategory::tableName() .'.category_id' => $category->category_id | ||
78 | + ]) | ||
79 | + ->groupBy(TaxOption::tableName() .'.tax_option_id'); | ||
80 | + $all_options = []; | ||
81 | + foreach($optionsQuery->all() as $_option) { | ||
82 | + $all_options[] = $_option; | ||
83 | + } | ||
84 | + | ||
59 | $priceQuery = clone $query; | 85 | $priceQuery = clone $query; |
60 | $priceMin = $priceMinCurr = $priceQuery->min(ProductVariant::tableName() .'.price'); | 86 | $priceMin = $priceMinCurr = $priceQuery->min(ProductVariant::tableName() .'.price'); |
61 | $priceMax = $priceMaxCurr = $priceQuery->max(ProductVariant::tableName() .'.price'); | 87 | $priceMax = $priceMaxCurr = $priceQuery->max(ProductVariant::tableName() .'.price'); |
62 | 88 | ||
89 | + // Prices | ||
63 | if (($price_interval = \Yii::$app->request->get('price_interval')) != false) { | 90 | if (($price_interval = \Yii::$app->request->get('price_interval')) != false) { |
64 | $price_interval = explode(';', $price_interval); | 91 | $price_interval = explode(';', $price_interval); |
65 | $price_interval = [ | 92 | $price_interval = [ |
@@ -75,21 +102,40 @@ class CatalogController extends \yii\web\Controller | @@ -75,21 +102,40 @@ class CatalogController extends \yii\web\Controller | ||
75 | $priceMaxCurr = $price_interval[1]; | 102 | $priceMaxCurr = $price_interval[1]; |
76 | } | 103 | } |
77 | } | 104 | } |
105 | + | ||
106 | + $groups = []; | ||
107 | + foreach($category->getTaxGroups()->all() as $_group) { | ||
108 | + $groups[$_group->tax_group_id] = $_group; | ||
109 | + } | ||
110 | + foreach ($all_options as $option) { | ||
111 | + $groups[$option->tax_group_id]->_options[] = $option; | ||
112 | + } | ||
113 | + foreach($groups as $i => $group) { | ||
114 | + if (empty($group->_options)) | ||
115 | + unset($groups[$i]); | ||
116 | + } | ||
117 | + | ||
118 | + // Options | ||
119 | + if (($options = \Yii::$app->request->get('option')) != false) { | ||
120 | + $query->innerJoin(ProductOption::tableName(), ProductOption::tableName() .'.product_id='. Product::tableName() .'.product_id'); | ||
121 | + $query->innerJoin(TaxOption::tableName(), TaxOption::tableName() .'.tax_option_id='. ProductOption::tableName() .'.option_id'); | ||
122 | + foreach($options as $group_alias => $option_alias) { | ||
123 | + $group = TaxGroup::find()->where(['like', 'alias', $group_alias])->one(); | ||
124 | + if (!$group) { | ||
125 | + continue; | ||
126 | + } | ||
127 | + $query->andWhere([TaxOption::tableName() .'.tax_group_id' => $group->tax_group_id, TaxOption::tableName() .'.alias' => $option_alias]); | ||
128 | + } | ||
129 | + } | ||
130 | + | ||
78 | $count = $query->count(); | 131 | $count = $query->count(); |
132 | + | ||
79 | $pages = new Pagination(['totalCount' => $count, 'pageSize' => $per_page]); | 133 | $pages = new Pagination(['totalCount' => $count, 'pageSize' => $per_page]); |
80 | $query->offset($pages->offset) | 134 | $query->offset($pages->offset) |
81 | ->orderBy($sort->orders) | 135 | ->orderBy($sort->orders) |
82 | ->limit($pages->limit); | 136 | ->limit($pages->limit); |
83 | $products = $query->all(); | 137 | $products = $query->all(); |
84 | 138 | ||
85 | - $brandsQuery = Brand::find()->innerJoinWith('products')->innerJoin(ProductCategory::tableName(), ProductCategory::tableName() .'.product_id='. Product::tableName() .'.product_id')->where([ | ||
86 | - ProductCategory::tableName() .'.category_id' => $category->category_id | ||
87 | - ])->groupBy(Brand::tableName() .'.brand_id'); | ||
88 | - $brands = $brandsQuery->all(); | ||
89 | - $brands_count = $brandsQuery->count(); | ||
90 | - | ||
91 | - $groups = $category->getTaxGroups()->all(); | ||
92 | - | ||
93 | return $this->render( | 139 | return $this->render( |
94 | 'products', | 140 | 'products', |
95 | [ | 141 | [ |
@@ -107,6 +153,7 @@ class CatalogController extends \yii\web\Controller | @@ -107,6 +153,7 @@ class CatalogController extends \yii\web\Controller | ||
107 | 'brands' => $brands, | 153 | 'brands' => $brands, |
108 | 'brands_count' => $brands_count, | 154 | 'brands_count' => $brands_count, |
109 | 'groups' => $groups, | 155 | 'groups' => $groups, |
156 | + 'options' => $options, | ||
110 | ] | 157 | ] |
111 | ); | 158 | ); |
112 | } | 159 | } |
@@ -118,7 +165,22 @@ class CatalogController extends \yii\web\Controller | @@ -118,7 +165,22 @@ class CatalogController extends \yii\web\Controller | ||
118 | if (empty($product->product_id)) { | 165 | if (empty($product->product_id)) { |
119 | throw new HttpException(404 ,'Page not found'); | 166 | throw new HttpException(404 ,'Page not found'); |
120 | } | 167 | } |
121 | - return $this->render('product'); | 168 | + $groups = []; |
169 | + foreach($product->category->getTaxGroups()->all() as $_group) { | ||
170 | + $groups[$_group->tax_group_id] = $_group; | ||
171 | + } | ||
172 | + foreach ($product->options as $option) { | ||
173 | + $groups[$option->tax_group_id]->_options[] = $option; | ||
174 | + } | ||
175 | + foreach($groups as $i => $group) { | ||
176 | + if (empty($group->_options)) | ||
177 | + unset($groups[$i]); | ||
178 | + } | ||
179 | + | ||
180 | + return $this->render('product', [ | ||
181 | + 'product' => $product, | ||
182 | + 'properties' => $groups, | ||
183 | + ]); | ||
122 | } | 184 | } |
123 | 185 | ||
124 | public function actionBrands() | 186 | public function actionBrands() |
1 | +<?php | ||
2 | +/** @var $this \yii\web\View */ | ||
3 | +/** @var $dataProvider \yii\data\ActiveDataProvider */ | ||
4 | + | ||
5 | +$this->title = $product->name; | ||
6 | +foreach($product->category->getParents()->all() as $parent) { | ||
7 | + $this->params['breadcrumbs'][] = ['label' => $parent->name, 'url' => ['catalog/category', 'alias' => $parent->alias]]; | ||
8 | +} | ||
9 | +$this->params['breadcrumbs'][] = ['label' => $product->category->name, 'url' => ['catalog/category', 'alias' => $product->category->alias]]; | ||
10 | +$this->params['breadcrumbs'][] = $product->name .' #'. $product->variant->sku; | ||
11 | +?> | ||
12 | +<h1 class="open_card_item_title"><?= $product->name .' '. $product->variant->name?></h1> | ||
13 | + | ||
14 | +<div class="item_3_blocks_wrap"> <!-- flex container --> | ||
15 | + <div class="item_img_block"> <!-- блок с фотографиями --> | ||
16 | + <div class="main_img"> | ||
17 | + <?php if (empty($product->image)) :?> | ||
18 | + <img src="/images/no_photo_big.png" alt="<?= $product->name?>"> | ||
19 | + <?php else :?> | ||
20 | + <img src="/images/<?= $product->image->image?>" alt="<?= $product->image->alt ? $product->image->alt : $product->name?>"> | ||
21 | + <?php endif?> | ||
22 | + <!--<span class="new">НОВИНКА</span> | ||
23 | + <span class="top">ТОП</span>--> | ||
24 | + </div> | ||
25 | + <?php if (!empty($product->images)) :?> | ||
26 | + <div class="main_img_slide"> | ||
27 | + <?php foreach($product->images as $image) :?> | ||
28 | + <div class="small_img_block active"> | ||
29 | + <img src="/images/<?= $image->image?>" alt="<?= $image->alt ? $image->alt : $product->name?>"> | ||
30 | + </div> | ||
31 | + <?php endforeach?> | ||
32 | + | ||
33 | + <img class="slider_arrow_right" src="/images/slider_right.png" alt=""> | ||
34 | + <img class="slider_arrow_left" src="/images/slider_left.png" alt=""> | ||
35 | + </div> | ||
36 | + <?php endif?> | ||
37 | + | ||
38 | + </div> <!-- конец блока с фотографиями --> | ||
39 | + | ||
40 | + | ||
41 | + <div class="busket_block"> <!-- блок с счетчиком и кнопкой добавить в корзину --> | ||
42 | + <div class="top_code"> | ||
43 | + <span class="code">Код: <?= $product->variant->sku?></span> | ||
44 | + <span class="have"><img src="/images/ok_icon_green.png" alt=""><?= $product->stock !== 0 ? ' есть в наличии' : ' нет в наличии'?></span> | ||
45 | + </div> | ||
46 | + | ||
47 | + <div class="grey_bg"> | ||
48 | + <div class="counter"> | ||
49 | + <div class="price"><?= $product->variant->price?></div> | ||
50 | + <div class="sign">грн.</div> | ||
51 | + <div class="count_block"> | ||
52 | + <div class="count_number">1</div> | ||
53 | + <div class="count_buttons"> | ||
54 | + <div class="button_plus">+</div> | ||
55 | + <div class="button_minus">-</div> | ||
56 | + </div> | ||
57 | + </div> | ||
58 | + </div> | ||
59 | + | ||
60 | + <div class="in_cart_btn"> | ||
61 | + <a href="#"> | ||
62 | + <button class="cart_btn" data-id="<?= $product->variant->product_variant_id?>"> в корзину <img src="/images/ico_basket_white.png" alt=""></button> | ||
63 | + </a> | ||
64 | + </div> | ||
65 | + | ||
66 | + <!--<div class="to_compare_link"> | ||
67 | + <img src="/images/ico_scales.png" alt=""> | ||
68 | + <a href="#" class="add_to_compare">добавить к сравнению</a> | ||
69 | + </div>--> | ||
70 | + </div> | ||
71 | + <div class="quick_order"> | ||
72 | + <form action=""> | ||
73 | + <span class="text">БЫСТРЫЙ ЗАКАЗ</span> | ||
74 | + <input type="text" class="quick_order_phone" name="quick_order_phone" placeholder="(0XX) XXX-XX-XX"> | ||
75 | + <button type="submit">заказать</button> | ||
76 | + </form> | ||
77 | + </div> | ||
78 | + | ||
79 | + <div class="delivery"> | ||
80 | + <p> | ||
81 | + Доставка товара на следующий день после выставления счета. Мы доставим “День в <br> день” — уточните это у менеджера. | ||
82 | + </p> | ||
83 | + <a href="#">Подробно о доставке</a> | ||
84 | + </div> | ||
85 | + | ||
86 | + </div><!-- конец блока с счетчиком и кнопкой добавить в корзину --> | ||
87 | + | ||
88 | + <div class="character_block"> <!-- блок с характеристиками --> | ||
89 | + <?php if (!empty($properties)) :?> | ||
90 | + <h3>Характеристики</h3> | ||
91 | + <ul> | ||
92 | + <?php foreach($properties as $group) :?> | ||
93 | + <li> | ||
94 | + <div class="each"> | ||
95 | + <div class="title"><?= $group->name?></div> | ||
96 | + <div class="tech"> | ||
97 | + <?php foreach($group->_options as $option) :?> <?= $option->ValueRenderHTML?><?php endforeach?> | ||
98 | + </div> | ||
99 | + </div> | ||
100 | + </li> | ||
101 | + <?php endforeach?> | ||
102 | + </ul> | ||
103 | + <?php endif?> | ||
104 | + | ||
105 | + <!--<div class="tech_links"> | ||
106 | + <a href="#">Описание</a> | ||
107 | + <a href="#">Видео</a> | ||
108 | + <a href="#">Отзывы(12)</a> | ||
109 | + </div>--> | ||
110 | + | ||
111 | + </div><!-- закрытие блока с характеристиками --> | ||
112 | + | ||
113 | + <div class="tabs_block"> <!-- Табы с описанием видео и отзывами --> | ||
114 | + <div class="ionTabs" id="tabs_1" data-name="Tabs_Group_name"> | ||
115 | + <ul class="ionTabs__head"> | ||
116 | + <?php if (!empty($properties)) :?> | ||
117 | + <li class="ionTabs__tab" data-target="Tab_1_name">Характеристики</li> | ||
118 | + <?php endif?> | ||
119 | + <?php if (!empty($product->description)) :?> | ||
120 | + <li class="ionTabs__tab" data-target="Tab_2_name">Описание</li> | ||
121 | + <?php endif?> | ||
122 | + <?php if (!empty($product->description)) :?> | ||
123 | + <li class="ionTabs__tab" data-target="Tab_3_name">Видео</li> | ||
124 | + <?php endif?> | ||
125 | +<!-- <li class="ionTabs__tab" data-target="Tab_4_name">Отзывы(12)</li>--> | ||
126 | + </ul> | ||
127 | + <div class="ionTabs__body"> | ||
128 | + <?php if (!empty($properties)) :?> | ||
129 | + <div class="ionTabs__item" data-name="Tab_1_name"> | ||
130 | + <ul> | ||
131 | + <?php foreach($properties as $group) :?> | ||
132 | + <li> | ||
133 | + <div class="each"> | ||
134 | + <div class="title"><?= $group->name?></div> | ||
135 | + <div class="tech"> | ||
136 | + <?php foreach($group->_options as $option) :?> <?= $option->ValueRenderHTML?><?php endforeach?> | ||
137 | + </div> | ||
138 | + </div> | ||
139 | + </li> | ||
140 | + <?php endforeach?> | ||
141 | + </ul> | ||
142 | + </div> | ||
143 | + <?php endif?> | ||
144 | + <?php if (!empty($product->description)) :?> | ||
145 | + <div class="ionTabs__item" data-name="Tab_2_name"> | ||
146 | + <?= $product->description?> | ||
147 | + </div> | ||
148 | + <?php endif?> | ||
149 | + <?php if (!empty($product->video)) :?> | ||
150 | + <div class="ionTabs__item" data-name="Tab_3_name"> | ||
151 | + <?= $product->video?> | ||
152 | + </div> | ||
153 | + <?php endif?> | ||
154 | + <!--<div class="ionTabs__item" data-name="Tab_4_name"> | ||
155 | + <span class="tabs_item_name">Отзывы</span> | ||
156 | + </div>--> | ||
157 | + | ||
158 | + <div class="ionTabs__preloader"></div> | ||
159 | + </div> | ||
160 | + </div> | ||
161 | + | ||
162 | + </div> <!-- конец табов с описанием видео и отзывами --> | ||
163 | + | ||
164 | +</div> <!-- end flex container --> |
frontend/views/catalog/product_item.php
@@ -4,12 +4,21 @@ | @@ -4,12 +4,21 @@ | ||
4 | <div class="item" data-id="<?= $product->product_id?>"> | 4 | <div class="item" data-id="<?= $product->product_id?>"> |
5 | <!--<div class="new">АКЦИЯ</div> | 5 | <!--<div class="new">АКЦИЯ</div> |
6 | <div class="top">Toп</div>--> | 6 | <div class="top">Toп</div>--> |
7 | - <a href="#" class="item_link"><div class="pic"><img src="/images/items/01.jpg"></div> | 7 | + <a href="<?= \yii\helpers\Url::to(['catalog/product', 'alias' => $product->alias])?>" class="item_link"> |
8 | + <div class="pic"> | ||
9 | + <?php if (empty($product->image)) :?> | ||
10 | + <img src="/images/no_photo.png"> | ||
11 | + <?php else :?> | ||
12 | + <img src="/images/<?= $product->image->image?>" alt="<?= $product->image->alt ? $product->image->alt : $product->name?>"> | ||
13 | + <?php endif?> | ||
14 | + </div> | ||
8 | <div class="title_item"><?= $product->name?></div></a> | 15 | <div class="title_item"><?= $product->name?></div></a> |
9 | <div class="brand">Бренд: <span><?= $product->brand->name?></span></div> | 16 | <div class="brand">Бренд: <span><?= $product->brand->name?></span></div> |
10 | <div class="type"><?= implode(', ', $product->categoriesNames)?></div> | 17 | <div class="type"><?= implode(', ', $product->categoriesNames)?></div> |
18 | + <?php if($product->variant) :?> | ||
11 | <div class="price"><?= $product->variant->price?> <span>грн.</span></div> | 19 | <div class="price"><?= $product->variant->price?> <span>грн.</span></div> |
12 | <button class="basket_add_but" data-id="<?= $product->variant->product_variant_id?>">в корзину</button> | 20 | <button class="basket_add_but" data-id="<?= $product->variant->product_variant_id?>">в корзину</button> |
21 | + <?php endif?> | ||
13 | <a href="#" class="compare_add_but" data-id="<?= $product->product_id?>"><span>добавить к сравнению</span></a> | 22 | <a href="#" class="compare_add_but" data-id="<?= $product->product_id?>"><span>добавить к сравнению</span></a> |
14 | <img class="item_bottom_img" src="/images/nc_item_bottom.png" alt=""> | 23 | <img class="item_bottom_img" src="/images/nc_item_bottom.png" alt=""> |
15 | </div> | 24 | </div> |
16 | \ No newline at end of file | 25 | \ No newline at end of file |
frontend/views/catalog/products.php
@@ -74,9 +74,9 @@ $this->params['breadcrumbs'][] = $category->name; | @@ -74,9 +74,9 @@ $this->params['breadcrumbs'][] = $category->name; | ||
74 | <li><?= $group->name?> | 74 | <li><?= $group->name?> |
75 | <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> | 75 | <div class="arrow"><img src="/images/head_down.png" alt=""></i></div> |
76 | <div class="price_filter"> | 76 | <div class="price_filter"> |
77 | - <?php foreach($group->options as $option) :?> | 77 | + <?php foreach($group->_options as $option) :?> |
78 | <div class="checkbox"> | 78 | <div class="checkbox"> |
79 | - <label><input type="checkbox" name="option[<?= $group->alias?>][]" value="<?= $option->alias?>" /></label> | 79 | + <label><input type="checkbox" name="option[<?= $group->alias?>][]" value="<?= $option->alias?>"<?= (isset($options[$group->alias]) && in_array($option->alias, $options[$group->alias])) ? ' checked' : ''?> /></label> |
80 | <a href="#"><?= $option->ValueRenderHTML?></a> | 80 | <a href="#"><?= $option->ValueRenderHTML?></a> |
81 | </div> | 81 | </div> |
82 | <?php endforeach?> | 82 | <?php endforeach?> |
23.4 KB
9.21 KB