Commit 772a3ca4c30980bad4e17b998bf80f08a7cd39bf

Authored by Yarik
1 parent 6d9a4125

Big commit

backend/controllers/SliderController.php
... ... @@ -82,8 +82,7 @@
82 82 if ($model->load(Yii::$app->request->post()) && $model->save()) {
83 83 return $this->redirect(
84 84 [
85   - 'view',
86   - 'id' => $model->id,
  85 + 'index',
87 86 ]
88 87 );
89 88 } else {
... ... @@ -112,8 +111,7 @@
112 111 if ($model->load(Yii::$app->request->post()) && $model->save()) {
113 112 return $this->redirect(
114 113 [
115   - 'view',
116   - 'id' => $model->id,
  114 + 'index',
117 115 ]
118 116 );
119 117 } else {
... ...
common/modules/product/controllers/VariantController.php
... ... @@ -234,7 +234,12 @@
234 234 $stocks = Stock::find()
235 235 ->joinWith('lang')
236 236 ->where([ 'stock_lang.title' => $stock_names ])
237   - ->indexBy('title')
  237 + ->indexBy(function($row) {
  238 + /**
  239 + * @var Stock $row
  240 + */
  241 + return $row->lang->title;
  242 + })
238 243 ->all();
239 244 foreach ($productStocks as $stockName => $quantity) {
240 245 $quantity = (int) $quantity;
... ...
common/modules/product/models/Import.php
... ... @@ -8,7 +8,12 @@
8 8 use Yii;
9 9 use yii\base\Model;
10 10 use yii\helpers\ArrayHelper;
11   -
  11 +
  12 + /**
  13 + * Class Import
  14 + *
  15 + * @package common\modules\product\models
  16 + */
12 17 class Import extends Model
13 18 {
14 19 /**
... ... @@ -410,13 +415,13 @@
410 415 /**
411 416 * Save ProductVariants
412 417 *
413   - * @param array $data ProductVariats data
  418 + * @param array $data ProductVariats data
414 419 * @param float $product_cost_old Old price
415   - * @param int $product_id Product ID
416   - * @param array $category_id Ca
  420 + * @param int $product_id Product ID
  421 + * @param array $category_id Ca
417 422 * @param float|null $product_cost
418 423 *
419   - * @return array
  424 + * @return int[] Array of ProductVariants IDs
420 425 * @throws \Exception
421 426 */
422 427 private function saveVariants(
... ... @@ -503,10 +508,14 @@
503 508 return $MOD_ARRAY;
504 509 }
505 510  
506   - // private function debug($start_time, $message) {
507   - // echo $message.': '.(time()-$start_time).'s passed';
508   - // }
509   -
  511 + /**
  512 + * Perform product import
  513 + *
  514 + * @param int $from Begin row
  515 + * @param null $limit Row limit
  516 + *
  517 + * @return array|bool Array if OK, false if error
  518 + */
510 519 public function goProducts($from = 0, $limit = null)
511 520 {
512 521 set_time_limit(0);
... ... @@ -713,6 +722,13 @@
713 722 return $result;
714 723 }
715 724  
  725 + /**
  726 + * Get import file
  727 + *
  728 + * @param string $file_type
  729 + *
  730 + * @return bool|resource false if File not found and file resource if OK
  731 + */
716 732 private function getProductsFile($file_type)
717 733 {
718 734 $filename = Yii::getAlias('@uploadDir') . '/' . Yii::getAlias('@' . $file_type);
... ... @@ -724,11 +740,13 @@
724 740 }
725 741  
726 742 /**
727   - * @param $filters array of filters like [['pol'='ะผัƒะถัะบะพะน'],['god' =
728   - * '2013'],['volume'='25 ะป']*['size'='49 x 30 x
729   - * 20ัะผ'],['composition'='600D ะฟะพะปะธััั‚ะตั€']]
730   - * @param int $level 0 for products and 1 for product variant
731   - * @param $catalog_names array catalogs id
  743 + * Save filters
  744 + *
  745 + * @param array $filters array of filters like [['pol'='ะผัƒะถัะบะพะน'],['god' =
  746 + * '2013'],['volume'='25 ะป']*['size'='49 x 30 x
  747 + * 20ัะผ'],['composition'='600D ะฟะพะปะธััั‚ะตั€']]
  748 + * @param int $level 0 for products and 1 for product variant
  749 + * @param int[] $catalog_names array catalogs id
732 750 *
733 751 * @return array
734 752 * @throws \Exception
... ... @@ -819,4 +837,5 @@
819 837 }
820 838 return $options;
821 839 }
822   - }
823 840 \ No newline at end of file
  841 + }
  842 +
824 843 \ No newline at end of file
... ...
common/modules/product/models/Product.php
... ... @@ -7,46 +7,58 @@
7 7 use common\models\ProductToRating;
8 8 use common\modules\comment\models\CommentModel;
9 9 use common\modules\language\behaviors\LanguageBehavior;
10   - use common\modules\language\models\Language;
11 10 use common\modules\rubrication\models\TaxGroup;
  11 + use common\modules\rubrication\models\TaxGroupToCategory;
12 12 use common\modules\rubrication\models\TaxOption;
13 13 use Yii;
  14 + use yii\base\InvalidParamException;
14 15 use yii\db\ActiveQuery;
15 16 use yii\db\ActiveRecord;
16 17 use yii\helpers\ArrayHelper;
  18 + use yii\web\NotFoundHttpException;
17 19 use yii\web\Request;
18 20  
19 21 /**
20 22 * This is the model class for table "{{%product}}".
21 23 *
22   - * @property integer $brand_id
23   - * @property integer $id
24   - * @property Category $category
25   - * @property Category[] $categories
26   - * @property ProductVariant[] $variants
27   - * @property ProductVariant $variant
28   - * @property boolean $is_top
29   - * @property boolean $is_new
30   - * @property boolean $is_discount
31   - * @property ProductToRating $averageRating
32   - * @property TaxGroup[] $properties
33   - * @property ProductVariant $enabledVariant
34   - * @property ProductVariant[] $enabledVariants
35   - * @property string $video
36   - * @property TaxOption[] $options
37   - * @property Brand $brand
38   - * @property TaxOption[] $filters
39   - * @property ProductVariant[] $variantsWithFilters
40   - * @property string $remote_id
41   - * @property string $fullname
  24 + * @property integer $brand_id
  25 + * @property integer $id
  26 + * @property Category $category
  27 + * @property Category[] $categories
  28 + * @property ProductVariant $variant
  29 + * @property ProductVariant[] $variants
  30 + * @property ProductVariant $productVariant
  31 + * @property ProductVariant[] $productVariants
  32 + * @property boolean $is_top
  33 + * @property boolean $is_new
  34 + * @property boolean $is_discount
  35 + * @property ProductToRating $averageRating
  36 + * @property TaxGroup[] $properties
  37 + * @property ProductVariant $enabledVariant
  38 + * @property ProductVariant[] $enabledVariants
  39 + * @property string $video
  40 + * @property TaxOption[] $options
  41 + * @property Brand $brand
  42 + * @property TaxOption[] $filters
  43 + * @property ProductVariant[] $variantsWithFilters
  44 + * @property string $remote_id
  45 + * @property string $fullname
  46 + * @property float $variantPrice
  47 + * @property float $enabledVariantPrice
  48 + * @property array $categoryNames
  49 + * @property Stock[] $stocks
  50 + * @property ProductStock[] $productStocks
  51 + * @property int $quantity
  52 + * @property TaxGroupToCategory[] $categoriesToGroups
  53 + * @property TaxGroup[] $taxGroupsByLevel
42 54 * * From language behavior *
43   - * @property ProductLang $lang
44   - * @property ProductLang[] $langs
45   - * @property ProductLang $objectLang
46   - * @property string $ownerKey
47   - * @property string $langKey
48   - * @property ProductLang[] $modelLangs
49   - * @property bool $transactionStatus
  55 + * @property ProductLang $lang
  56 + * @property ProductLang[] $langs
  57 + * @property ProductLang $objectLang
  58 + * @property string $ownerKey
  59 + * @property string $langKey
  60 + * @property ProductLang[] $modelLangs
  61 + * @property bool $transactionStatus
50 62 * @method string getOwnerKey()
51 63 * @method void setOwnerKey( string $value )
52 64 * @method string getLangKey()
... ... @@ -60,9 +72,9 @@
60 72 * @method bool getTransactionStatus()
61 73 * * End language behavior *
62 74 * * From multipleImage behavior
63   - * @property ProductImage $image
64   - * @property ProductImage[] $images
65   - * @property array imagesConfig
  75 + * @property ProductImage $image
  76 + * @property ProductImage[] $images
  77 + * @property array imagesConfig
66 78 * @method ActiveQuery getImage()
67 79 * @method ActiveQuery getImages()
68 80 * @method array getImagesConfig()
... ... @@ -86,7 +98,7 @@
86 98 'directory' => 'products',
87 99 'column' => 'image',
88 100 'links' => [
89   - 'product_id' => 'id',
  101 + 'id' => 'product_id',
90 102 ],
91 103 'model' => ProductImage::className(),
92 104 ],
... ... @@ -102,7 +114,7 @@
102 114 'config' => [
103 115 'caption' => 'image',
104 116 'delete_action' => '/product/manage/delete-image',
105   - 'id' => 'product_image_id',
  117 + 'id' => 'id',
106 118 ],
107 119 ],
108 120 'language' => [
... ... @@ -164,9 +176,7 @@
164 176 'id' => Yii::t('product', 'ID'),
165 177 'brand_id' => Yii::t('product', 'Brand'),
166 178 'categories' => Yii::t('product', 'Categories'),
167   - // relation behavior field
168 179 'category' => Yii::t('product', 'Category'),
169   - // relation behavior field
170 180 'image' => Yii::t('product', 'Image'),
171 181 'images' => Yii::t('product', 'Images'),
172 182 'video' => Yii::t('product', 'Video embeded'),
... ... @@ -178,6 +188,8 @@
178 188 }
179 189  
180 190 /**
  191 + * Get Brand query to current Product
  192 + *
181 193 * @return \yii\db\ActiveQuery
182 194 */
183 195 public function getBrand()
... ... @@ -186,6 +198,8 @@
186 198 }
187 199  
188 200 /**
  201 + * Get ProductVariant query to current Product
  202 + *
189 203 * @return \yii\db\ActiveQuery
190 204 */
191 205 public function getVariant()
... ... @@ -194,62 +208,135 @@
194 208 }
195 209  
196 210 /**
  211 + * Synonim of getVariant()
  212 + *
  213 + * @see Product::getVariant()
197 214 * @return \yii\db\ActiveQuery
198 215 */
199   - public function getEnabledVariant()
  216 + public function getProductVariant()
200 217 {
201   - return $this->hasOne(ProductVariant::className(), [ 'product_id' => 'id' ])
202   - ->andOnCondition(
203   - [
204   - '!=',
205   - ProductVariant::tableName() . '.stock',
206   - 0,
207   - ]
208   - );
  218 + return $this->getVariant();
209 219 }
210 220  
211   - public function getVariantPrice()
  221 + /**
  222 + * Get ProductVariants query to current Product
  223 + *
  224 + * @return \yii\db\ActiveQuery
  225 + */
  226 + public function getVariants()
212 227 {
213   - return $this->variant->price;
  228 + return $this->hasMany(ProductVariant::className(), [ 'product_id' => 'id' ]);
214 229 }
215 230  
216   - public function getEnabledVariantPrice()
  231 + /**
  232 + * Synonim of getVariants()
  233 + *
  234 + * @see Product::getVariants()
  235 + * @return \yii\db\ActiveQuery
  236 + */
  237 + public function getProductVariants()
217 238 {
218   - return $this->enabledVariants[ 0 ]->price;
  239 + return $this->getVariant();
219 240 }
220 241  
221 242 /**
  243 + * Get ProductVariant query fetching only available in stock to current Product
  244 + *
  245 + * @see Product::getVariant()
222 246 * @return \yii\db\ActiveQuery
223 247 */
224   - public function getVariants()
  248 + public function getEnabledVariant()
225 249 {
226   - return $this->hasMany(ProductVariant::className(), [ 'product_id' => 'id' ]);
  250 + return $this->hasOne(ProductVariant::className(), [ 'product_id' => 'id' ])
  251 + ->andWhere(
  252 + [
  253 + '!=',
  254 + ProductVariant::tableName() . '.stock',
  255 + 0,
  256 + ]
  257 + );
227 258 }
228 259  
  260 + /**
  261 + * Get ProductVariants query fetching only available in stock to current Product
  262 + *
  263 + * @see Product::getVariants()
  264 + * @return \yii\db\ActiveQuery
  265 + */
229 266 public function getEnabledVariants()
230 267 {
231 268 return $this->hasMany(ProductVariant::className(), [ 'product_id' => 'id' ])
232   - ->andOnCondition(
  269 + ->andWhere(
233 270 [
234 271 '!=',
235 272 ProductVariant::tableName() . '.stock',
236 273 0,
237 274 ]
238   - )
239   - ->joinWith('image');
  275 + );
  276 + }
  277 +
  278 + /**
  279 + * Get random ProductVariant price or 0 if not exist
  280 + *
  281 + * @param bool $exception Whether to throw exception if variant not exist
  282 + *
  283 + * @return float
  284 + * @throws \yii\web\NotFoundHttpException
  285 + */
  286 + public function getVariantPrice(bool $exception = false): float
  287 + {
  288 + if (!empty( $this->variant )) {
  289 + return $this->variant->price;
  290 + } elseif ($exception) {
  291 + throw new NotFoundHttpException('Product with ID ' . $this->id . ' hasn\'t got variants');
  292 + } else {
  293 + return 0;
  294 + }
240 295 }
241 296  
242   - public function setVariants($variants)
  297 + /**
  298 + * Get random ProductVariant that in stock price or 0 or exception if not exist
  299 + *
  300 + * @param bool $exception Whether to throw exception if variant not exist
  301 + *
  302 + * @return float
  303 + * @throws \yii\web\NotFoundHttpException
  304 + */
  305 + public function getEnabledVariantPrice(bool $exception = false): float
243 306 {
244   - $this->variants = $variants;
  307 + if (!empty( $this->enabledVariant )) {
  308 + return $this->enabledVariant->price;
  309 + } elseif ($exception) {
  310 + throw new NotFoundHttpException('Product with ID ' . $this->id . ' hasn\'t got enabled variants');
  311 + } else {
  312 + return 0;
  313 + }
245 314 }
246 315  
247   - public function getFullname()
  316 + /**
  317 + * Get Product name concatenated with Brand name
  318 + *
  319 + * @return string
  320 + */
  321 + public function getFullname():string
248 322 {
249 323 return empty( $this->brand ) ? $this->lang->title : $this->brand->lang->title . ' ' . $this->lang->title;
250 324 }
251 325  
252 326 /**
  327 + * Get Category query for current Product
  328 + *
  329 + * @return ActiveQuery
  330 + */
  331 + public function getCategory()
  332 + {
  333 + return $this->hasOne(Category::className(), [ 'id' => 'category_id' ])
  334 + ->viaTable('product_category', [ 'product_id' => 'id' ]);
  335 + }
  336 +
  337 + /**
  338 + * Get Categories query for current Product
  339 + *
253 340 * @return ActiveQuery
254 341 */
255 342 public function getCategories()
... ... @@ -258,19 +345,30 @@
258 345 ->viaTable('product_category', [ 'product_id' => 'id' ]);
259 346 }
260 347  
261   - public function getCategoriesNames()
  348 + /**
  349 + * @param bool $index
  350 + *
  351 + * @return array
  352 + */
  353 + public function getCategoryNames(bool $index = false): array
262 354 {
263   - $result = [];
264   - foreach ($this->categories as $category) {
265   - $result[] = $category->lang->title;
  355 + if ($index) {
  356 + $result = ArrayHelper::map($this->categories, 'id', 'lang.title');
  357 + } else {
  358 + $result = ArrayHelper::getColumn($this->categories, 'lang.title');
266 359 }
267 360 return $result;
268 361 }
269 362  
  363 + /**
  364 + * Get ProductVariants query with lang, filters and image for current Product
  365 + *
  366 + * @return ActiveQuery
  367 + */
270 368 public function getVariantsWithFilters()
271 369 {
272 370 return $this->hasMany(ProductVariant::className(), [ 'product_id' => 'id' ])
273   - ->joinWith('lang', true, 'INNER JOIN')
  371 + ->joinWith('lang')
274 372 ->with(
275 373 [
276 374 'filters',
... ... @@ -279,50 +377,11 @@
279 377 );
280 378 }
281 379  
282   - public function getVariantsFilter()
283   - {
284   - return $this->hasMany(ProductVariant::className(), [ 'product_id' => 'id' ])
285   - ->joinWith('lang')
286   - ->joinWith(
287   - [
288   - 'options variant_options' => function ($query) {
289   - /**
290   - * @var ActiveQuery $query
291   - */
292   - $query->joinWith([ 'langs variant_options_lang' ])
293   - ->andWhere(
294   - [ 'variant_options_lang.language_id' => Language::getCurrent()->id ]
295   - )
296   - ->joinWith(
297   - [
298   - 'taxGroup variant_options_group' => function ($subquery) {
299   - /**
300   - * @var ActiveQuery $subquery
301   - */
302   - $subquery->joinWith([ 'langs variant_options_group_lang' ])
303   - ->andWhere(
304   - [
305   - 'variant_options_group_lang.language_id' => Language::getCurrent(
306   - )->id,
307   - ]
308   - );
309   - },
310   - ]
311   - );
312   - },
313   - ]
314   - );
315   - }
316   -
317 380 /**
  381 + * Get TaxOptions query for current Product
  382 + *
318 383 * @return ActiveQuery
319 384 */
320   - public function getCategory()
321   - {
322   - return $this->hasOne(Category::className(), [ 'id' => 'category_id' ])
323   - ->viaTable('product_category', [ 'product_id' => 'id' ]);
324   - }
325   -
326 385 public function getOptions()
327 386 {
328 387 return $this->hasMany(TaxOption::className(), [ 'id' => 'option_id' ])
... ... @@ -330,9 +389,24 @@
330 389 }
331 390  
332 391 /**
  392 + * Get TaxOptions query for current Product joined with TaxGroups
  393 + *
  394 + * @see Product::getOptions()
  395 + * @return ActiveQuery
  396 + */
  397 + public function getFilters()
  398 + {
  399 + return $this->getOptions()
  400 + ->joinWith('taxGroup.lang')
  401 + ->joinWith('lang');
  402 + }
  403 +
  404 + /**
  405 + * Get all TaxGroups for current Product filled with $customOptions that satisfy current Product
  406 + *
333 407 * @return TaxGroup[]
334 408 */
335   - public function getProperties()
  409 + public function getProperties(): array
336 410 {
337 411 $groups = $options = [];
338 412 foreach ($this->getOptions()
... ... @@ -341,7 +415,7 @@
341 415 /**
342 416 * @var TaxOption $option
343 417 */
344   - $options[ $option->tax_group_id ][] = $option;
  418 + $options[ $option[ 'tax_group_id' ] ][] = $option;
345 419 }
346 420 foreach (TaxGroup::find()
347 421 ->where([ 'id' => array_keys($options) ])
... ... @@ -351,60 +425,52 @@
351 425 * @var TaxGroup $group
352 426 */
353 427 if (!empty( $options[ $group->id ] )) {
354   - $group->options = $options[ $group->id ];
355   - $groups[] = $group;
356   - }
357   - }
358   - return $groups;
359   - }
360   -
361   - public function getActiveProperties($category_id)
362   - {
363   - $groups = $options = [];
364   - foreach ($this->options as $option) {
365   - $options[ $option->tax_group_id ][] = $option;
366   - }
367   - /**
368   - * @var TaxGroup[] $taxGroups
369   - */
370   - $taxGroups = TaxGroup::find()
371   - ->joinWith('categories')
372   - ->where(
373   - [
374   - 'tax_group.id' => array_keys($options),
375   - 'tax_group.display' => true,
376   - 'category.id' => $category_id,
377   - ]
378   - )
379   - ->all();
380   -
381   - foreach ($taxGroups as $group) {
382   - if (!empty( $options[ $group->id ] )) {
383   - $group->options = $options[ $group->id ];
  428 + $group->customOptions = $options[ $group->id ];
384 429 $groups[] = $group;
385 430 }
386 431 }
387 432 return $groups;
388 433 }
389 434  
  435 + /**
  436 + * Get Stock query where current Product is in stock
  437 + *
  438 + * @return ActiveQuery
  439 + */
390 440 public function getStocks()
391 441 {
392   - return $this->hasMany(Stock::className(), [ 'id' => 'product_id' ])
393   - ->via('variants');
  442 + return $this->hasMany(Stock::className(), [ 'id' => 'stock_id' ])
  443 + ->via('productStocks');
394 444 }
395 445  
  446 + /**
  447 + * Get ProductStocks query for current Product
  448 + *
  449 + * @return ActiveQuery
  450 + */
396 451 public function getProductStocks()
397 452 {
398 453 return $this->hasMany(ProductStock::className(), [ 'product_variant_id' => 'id' ])
399 454 ->via('variants');
400 455 }
401 456  
402   - public function getQuantity()
  457 + /**
  458 + * Get quantity of all ProductVariants for current Product
  459 + *
  460 + * @see Product::getProductStocks()
  461 + * @return int
  462 + */
  463 + public function getQuantity():int
403 464 {
404 465 return $this->getProductStocks()
405 466 ->sum('quantity');
406 467 }
407 468  
  469 + /**
  470 + * Override Categories and TaxOptions
  471 + *
  472 + * @inheritdoc
  473 + */
408 474 public function afterSave($insert, $changedAttributes)
409 475 {
410 476 parent::afterSave($insert, $changedAttributes);
... ... @@ -424,37 +490,15 @@
424 490 $this->link('options', $option);
425 491 }
426 492 }
427   -
428   - if (!empty( $this->variants )) {
429   - $todel = [];
430   - foreach ($this->variants ? : [] as $_variant) {
431   - /**
432   - * @var ProductVariant $_variant
433   - */
434   - $todel[ $_variant->id ] = $_variant->id;
435   - }
436   - foreach ($this->variants as $_variant) {
437   - if (!is_array($_variant)) {
438   - return;
439   - }
440   - if (!empty( $_variant[ 'id' ] )) {
441   - unset( $todel[ $_variant[ 'id' ] ] );
442   - $model = ProductVariant::findOne($_variant[ 'id' ]);
443   - } else {
444   - $model = new ProductVariant();
445   - }
446   - $_variant[ 'product_id' ] = $this->id;
447   - $model->load([ 'ProductVariant' => $_variant ]);
448   - $model->product_id = $this->id;
449   - $model->save();
450   - }
451   - if (!empty( $todel )) {
452   - ProductVariant::deleteAll([ 'id' => $todel ]);
453   - }
454   - }
455 493 }
456 494  
457   - public function recalculateRating()
  495 + /**
  496 + * Recalculate rating for artboxcomment module
  497 + *
  498 + * @todo Rewrite with behavior
  499 + * @return bool
  500 + */
  501 + public function recalculateRating():bool
458 502 {
459 503 /**
460 504 * @var ProductToRating $averageRating
... ... @@ -484,6 +528,12 @@
484 528 }
485 529 }
486 530  
  531 + /**
  532 + * Get CommmentModel query for artboxcomment module
  533 + *
  534 + * @todo Rewrite with behavior
  535 + * @return ActiveQuery
  536 + */
487 537 public function getComments()
488 538 {
489 539 return $this->hasMany(CommentModel::className(), [ 'entity_id' => 'id' ])
... ... @@ -496,39 +546,67 @@
496 546 );
497 547 }
498 548  
  549 + /**
  550 + * Get ProductToRating query in order to get average rating for current Product
  551 + *
  552 + * @return \yii\db\ActiveQuery
  553 + */
499 554 public function getAverageRating()
500 555 {
501 556 return $this->hasOne(ProductToRating::className(), [ 'product_id' => 'id' ]);
502 557 }
503 558  
504   - public function getTaxGroupsByLevel($level)
  559 + /**
  560 + * Get TaxGroupToCategories query via product_category table
  561 + *
  562 + * @return ActiveQuery
  563 + */
  564 + public function getCategoriesToGroups()
505 565 {
506   - $categories = ArrayHelper::getColumn($this->categories, 'id');
507   - return TaxGroup::find()
508   - ->distinct()
509   - ->innerJoin(
510   - 'tax_group_to_category',
511   - 'tax_group_to_category.tax_group_id = tax_group.id'
512   - )
513   - ->andWhere([ 'tax_group_to_category.category_id' => $categories ])
514   - ->andWhere([ 'level' => $level ]);
  566 + return $this->hasMany(TaxGroupToCategory::className(), [ 'category_id' => 'category_id' ])
  567 + ->viaTable('product_category', [ 'product_id' => 'id' ]);
515 568 }
516 569  
  570 + /**
  571 + * Get TaxGroups query for current Product according to level
  572 + * * 0 - Product Tax Groups
  573 + * * 1 - ProductVariant Tax Groups
  574 + *
  575 + * @param int $level
  576 + *
  577 + * @return ActiveQuery
  578 + * @throws InvalidParamException
  579 + */
  580 + public function getTaxGroupsByLevel(int $level = 0)
  581 + {
  582 + if ($level !== 0 && $level !== 1) {
  583 + throw new InvalidParamException(
  584 + 'Level must be 0 for Product Tax Groups or 1 for Product Variant Tax Groups'
  585 + );
  586 + }
  587 + return $this->hasMany(TaxGroup::className(), [ 'id' => 'tax_group_id' ])
  588 + ->via('categoriesToGroups')
  589 + ->where([ 'level' => $level ])
  590 + ->distinct();
  591 + }
  592 +
  593 + /**
  594 + * Setter for Categories
  595 + *
  596 + * @param array $values
  597 + */
517 598 public function setCategories($values)
518 599 {
519 600 $this->categories = $values;
520 601 }
521 602  
  603 + /**
  604 + * Setter for Options
  605 + *
  606 + * @param array $values
  607 + */
522 608 public function setOptions($values)
523 609 {
524 610 $this->options = $values;
525 611 }
526   -
527   - public function getFilters()
528   - {
529   - return $this->hasMany(TaxOption::className(), [ 'id' => 'option_id' ])
530   - ->viaTable('product_option', [ 'product_id' => 'id' ])
531   - ->joinWith('taxGroup.lang', true, 'INNER JOIN')
532   - ->joinWith('lang', true, 'INNER JOIN');
533   - }
534 612 }
... ...
common/modules/product/models/ProductCategory.php
... ... @@ -2,21 +2,17 @@
2 2  
3 3 namespace common\modules\product\models;
4 4  
5   - use common\modules\rubrication\models\TaxOption;
6 5 use Yii;
7 6 use yii\db\ActiveRecord;
8 7  
9 8 /**
10 9 * This is the model class for table "{{%product_category}}".
11   - * @property integer $product_id
12   - * @property integer $category_id
13   - * @property TaxOption $devCategory
  10 + *
  11 + * @property integer $product_id
  12 + * @property integer $category_id
14 13 */
15 14 class ProductCategory extends ActiveRecord
16 15 {
17   -
18   - public $alias = 'product_categories';
19   -
20 16 /**
21 17 * @inheritdoc
22 18 */
... ... @@ -66,4 +62,13 @@
66 62 ];
67 63 }
68 64  
  65 + public function getCategory()
  66 + {
  67 + return $this->hasOne(Category::className(), [ 'id' => 'category_id' ]);
  68 + }
  69 +
  70 + public function getProduct()
  71 + {
  72 + return $this->hasOne(Product::className(), [ 'id' => 'product_id' ]);
  73 + }
69 74 }
... ...
common/modules/product/models/ProductImage.php
... ... @@ -9,7 +9,7 @@
9 9 /**
10 10 * This is the model class for table "product_image".
11 11 *
12   - * @property integer $product_image_id
  12 + * @property integer $id
13 13 * @property integer $product_id
14 14 * @property integer $product_variant_id
15 15 * @property string $image
... ... @@ -52,7 +52,7 @@
52 52 ],
53 53 [
54 54 [
55   - 'product_image_id',
  55 + 'id',
56 56 'product_id',
57 57 'product_variant_id',
58 58 ],
... ... @@ -90,7 +90,7 @@
90 90 public function attributeLabels()
91 91 {
92 92 return [
93   - 'product_image_id' => Yii::t('product', 'Product Image ID'),
  93 + 'id' => Yii::t('product', 'Product Image ID'),
94 94 'product_id' => Yii::t('product', 'Product ID'),
95 95 'product_variant_id' => Yii::t('product', 'Product Variant ID'),
96 96 'product' => Yii::t('product', 'Product'),
... ... @@ -107,9 +107,6 @@
107 107 public function getProduct()
108 108 {
109 109 $return = $this->hasOne(Product::className(), [ 'id' => 'product_id' ]);
110   - if (empty( $return )) {
111   - $return = $this->productVariant->product_id;
112   - }
113 110 return $return;
114 111 }
115 112  
... ...
common/modules/product/models/ProductSearch.php
... ... @@ -89,7 +89,6 @@
89 89 */
90 90 public function search($params)
91 91 {
92   -
93 92 $query = Product::find();
94 93 $query->select(
95 94 [
... ... @@ -150,6 +149,14 @@
150 149 ],
151 150 ]
152 151 );
  152 +
  153 + $this->load($params);
  154 +
  155 + if(!$this->validate()) {
  156 + // uncomment the following line if you do not want to return any records when validation fails
  157 + // $query->where('0=1');
  158 + return $dataProvider;
  159 + }
153 160  
154 161 if (isset( $this->is_top )) {
155 162 $query->andWhere(
... ...
common/modules/product/models/ProductStock.php
... ... @@ -13,10 +13,11 @@
13 13 * @property Product $product
14 14 * @property ProductVariant $productVariant
15 15 * @property Stock $stock
  16 + * @property string $title
16 17 */
17 18 class ProductStock extends ActiveRecord
18 19 {
19   -
  20 + protected $title;
20 21 /**
21 22 * @inheritdoc
22 23 */
... ... @@ -90,17 +91,28 @@
90 91 return $this->hasOne(ProductVariant::className(), [ 'id' => 'product_variant_id' ]);
91 92 }
92 93  
93   - public function getName()
  94 + /**
  95 + * Get Stock title, tries to get from Stock lang
  96 + *
  97 + * @return string
  98 + */
  99 + public function getTitle(): string
94 100 {
95   - return ( !empty( $this->stock ) ) ? $this->stock->title : '';
  101 + if (!empty( $this->title )) {
  102 + return $this->title;
  103 + } elseif (!empty( $this->stock )) {
  104 + return $this->stock->lang->title;
  105 + } else {
  106 + return '';
  107 + }
96 108 }
97 109  
98 110 /**
99   - * @todo Check if needed
  111 + * Set Stock title, will be saved to Stock table
100 112 *
101 113 * @param mixed $value
102 114 */
103   - public function setName($value)
  115 + public function setTitle(string $value)
104 116 {
105 117 $this->title = $value;
106 118 }
... ... @@ -113,6 +125,9 @@
113 125 return $this->hasOne(Stock::className(), [ 'id' => 'stock_id' ]);
114 126 }
115 127  
  128 + /**
  129 + * @inheritdoc
  130 + */
116 131 public static function primaryKey()
117 132 {
118 133 return [
... ...
common/modules/product/models/ProductVariant.php
... ... @@ -8,15 +8,14 @@
8 8 use common\modules\rubrication\models\TaxGroup;
9 9 use common\modules\rubrication\models\TaxOption;
10 10 use Yii;
  11 + use yii\base\InvalidParamException;
11 12 use yii\db\ActiveQuery;
12 13 use yii\db\ActiveRecord;
13   - use yii\helpers\ArrayHelper;
14 14 use yii\web\Request;
15 15  
16 16 /**
17 17 * This is the model class for table "product_variant".
18 18 *
19   - * @todo Refactor
20 19 * @property integer $id
21 20 * @property integer $product_id
22 21 * @property integer $remote_id
... ... @@ -25,12 +24,19 @@
25 24 * @property double $price_old
26 25 * @property double $stock
27 26 * @property integer $product_unit_id
28   - * @property string|null $fullname
  27 + * @property string $fullname
29 28 * @property TaxOption[] $options
30 29 * @property ProductUnit $productUnit
31 30 * @property Product $product
32 31 * @property Category[] $categories
  32 + * @property Category $category
33 33 * @property TaxOption[] $filters
  34 + * @property ProductStock[] $productStocks
  35 + * @property int $quantity
  36 + * @property ProductStock[] $variantStocks
  37 + * @property Stock[] $stocks
  38 + * @property TaxGroup[] $properties
  39 + * @property TaxGroup[] $taxGroupsByLevel
34 40 * * From language behavior *
35 41 * @property ProductVariantLang $lang
36 42 * @property ProductVariantLang[] $langs
... ... @@ -63,10 +69,9 @@
63 69 */
64 70 class ProductVariant extends ActiveRecord
65 71 {
66   - public $sumCost;
67   -
68   - public $productName;
69   -
  72 + /**
  73 + * @var int[] $options
  74 + */
70 75 private $options;
71 76  
72 77 /** @var array $_images */
... ... @@ -98,7 +103,7 @@
98 103 'column' => 'image',
99 104 'links' => [
100 105 'product_id' => 'product_id',
101   - 'product_variant_id' => 'id',
  106 + 'id' => 'product_variant_id',
102 107 ],
103 108 'model' => ProductImage::className(),
104 109 ],
... ... @@ -111,7 +116,7 @@
111 116 'config' => [
112 117 'caption' => 'image',
113 118 'delete_action' => '/product/variant/delete-image',
114   - 'id' => 'product_image_id',
  119 + 'id' => 'id',
115 120 ],
116 121 ],
117 122 ];
... ... @@ -165,6 +170,13 @@
165 170 'targetClass' => ProductUnit::className(),
166 171 'targetAttribute' => [ 'product_unit_id' => 'id' ],
167 172 ],
  173 + [
  174 + [ 'product_id' ],
  175 + 'exist',
  176 + 'skipOnError' => true,
  177 + 'targetClass' => Product::className(),
  178 + 'targetAttribute' => [ 'product_id' => 'id' ],
  179 + ],
168 180 ];
169 181 }
170 182  
... ... @@ -203,63 +215,104 @@
203 215 return $this->hasOne(Product::className(), [ 'id' => 'product_id' ]);
204 216 }
205 217  
206   - public function getProductStock()
  218 + /**
  219 + * @return \yii\db\ActiveQuery
  220 + */
  221 + public function getProductStocks()
207 222 {
208 223 return $this->hasMany(ProductStock::className(), [ 'product_variant_id' => 'id' ]);
209 224 }
210 225  
211   - public function getQuantity()
212   - {
213   - return ProductStock::find()
214   - ->where([ 'product_variant_id' => $this->id ])
215   - ->sum('quantity');
216   - }
217   -
218   - public function getStockCaption()
  226 + /**
  227 + * Get qunatity for current ProductVariant
  228 + * If $recalculate set to true will recalculate stock via product_stock table
  229 + *
  230 + * @param bool $recalculate
  231 + *
  232 + * @return int
  233 + */
  234 + public function getQuantity(bool $recalculate = false): int
219 235 {
220   - return is_null($this->stock) ? 'โˆž' : ( $this->stock > 0 ? Yii::t('product', 'Enable') : Yii::t(
221   - 'product',
222   - 'Disable'
223   - ) );
  236 + if (!$recalculate) {
  237 + return $this->stock;
  238 + } else {
  239 + $quantity = $this->getProductStocks()
  240 + ->sum('quantity');
  241 + if (empty( $quantity )) {
  242 + $this->stock = 0;
  243 + } else {
  244 + $this->stock = (int) $quantity;
  245 + }
  246 + $this->save(false, [ 'stock' ]);
  247 + return $this->stock;
  248 + }
224 249 }
225 250  
  251 + /**
  252 + * Get ProductStocks query woth preloaded Stocks for current ProductVariant
  253 + * **Used in dynamic fields in product variant form**
  254 + *
  255 + * @return ActiveQuery
  256 + */
226 257 public function getVariantStocks()
227 258 {
228   - return $this->hasMany(ProductStock::className(), [ 'product_variant_id' => 'id' ])
  259 + return $this->getProductStocks()
229 260 ->joinWith('stock');
230 261 }
231 262  
  263 + /**
  264 + * @return ActiveQuery
  265 + */
232 266 public function getStocks()
233 267 {
234 268 return $this->hasMany(Stock::className(), [ 'id' => 'stock_id' ])
235   - ->viaTable(ProductStock::tableName(), [ 'product_variant_id' => 'id' ]);
  269 + ->via('productStocks');
236 270 }
237 271  
238   - public function getFilters()
  272 + /**
  273 + * @return ActiveQuery
  274 + */
  275 + public function getOptions()
239 276 {
240 277 return $this->hasMany(TaxOption::className(), [ 'id' => 'option_id' ])
241   - ->viaTable('product_variant_option', [ 'product_variant_id' => 'id' ])
242   - ->joinWith('taxGroup.lang', true, 'INNER JOIN')
243   - ->joinWith('lang', true, 'INNER JOIN');
  278 + ->viaTable('product_variant_option', [ 'product_variant_id' => 'id' ]);
244 279 }
245 280  
246   - public function getFullname()
  281 + /**
  282 + * Get TaxOptions with preloaded TaxGroups for current ProductVariant
  283 + *
  284 + * @return ActiveQuery
  285 + */
  286 + public function getFilters()
247 287 {
248   - return empty( $this->product ) ? null : ( $this->product->lang->title . ( empty( $this->lang->title ) ? '' : ' ' . $this->lang->title ) );
  288 + return $this->getOptions()
  289 + ->joinWith('taxGroup.lang')
  290 + ->joinWith('lang');
249 291 }
250 292  
251   - public function setOptions($values)
  293 + /**
  294 + * Get Product title concanated with current ProductVariant title
  295 + *
  296 + * @return string
  297 + */
  298 + public function getFullname(): string
252 299 {
253   - $this->options = $values;
  300 + return $this->product->lang->title . ' ' . $this->lang->title;
254 301 }
255 302  
256   - public function getOptions()
  303 + /**
  304 + * Set Options to override previous
  305 + *
  306 + * @param int[] $values
  307 + */
  308 + public function setOptions($values)
257 309 {
258   - return $this->hasMany(TaxOption::className(), [ 'id' => 'option_id' ])
259   - ->viaTable('product_variant_option', [ 'product_variant_id' => 'id' ]);
  310 + $this->options = $values;
260 311 }
261 312  
262 313 /**
  314 + * Get all TaxGroups for current ProductVariant filled with $customOptions that satisfy current ProductVariant
  315 + *
263 316 * @return TaxGroup[]
264 317 */
265 318 public function getProperties()
... ... @@ -282,7 +335,7 @@
282 335 * @var TaxGroup $group
283 336 */
284 337 if (!empty( $options[ $group->id ] )) {
285   - $group->options = $options[ $group->id ];
  338 + $group->customOptions = $options[ $group->id ];
286 339 $groups[] = $group;
287 340 }
288 341 }
... ... @@ -290,7 +343,7 @@
290 343 }
291 344  
292 345 /**
293   - * @todo Check if needed
  346 + * Set stocks to override existing in product_stock table
294 347 *
295 348 * @param mixed $stocks
296 349 */
... ... @@ -299,29 +352,37 @@
299 352 $this->stocks = (array) $stocks;
300 353 }
301 354  
  355 + /**
  356 + * @return ActiveQuery
  357 + */
302 358 public function getCategory()
303 359 {
304 360 return $this->hasOne(Category::className(), [ 'id' => 'category_id' ])
305 361 ->viaTable('product_category', [ 'product_id' => 'product_id' ]);
306 362 }
307 363  
  364 + /**
  365 + * @return ActiveQuery
  366 + */
308 367 public function getCategories()
309 368 {
310 369 return $this->hasMany(Category::className(), [ 'id' => 'category_id' ])
311 370 ->viaTable('product_category', [ 'product_id' => 'product_id' ]);
312 371 }
313 372  
314   - public function getTaxGroupsByLevel($level)
  373 + /**
  374 + * Get TaxGroups query for current ProductVariant according to level
  375 + * * 0 - Product Tax Groups
  376 + * * 1 - ProductVariant Tax Groups
  377 + *
  378 + * @param int $level
  379 + *
  380 + * @return ActiveQuery
  381 + * @throws InvalidParamException
  382 + */
  383 + public function getTaxGroupsByLevel(int $level = 0)
315 384 {
316   - $categories = ArrayHelper::getColumn($this->categories, 'id');
317   - return TaxGroup::find()
318   - ->distinct()
319   - ->innerJoin(
320   - 'tax_group_to_category',
321   - 'tax_group_to_category.tax_group_id = tax_group.id'
322   - )
323   - ->where([ 'tax_group_to_category.category_id' => $categories ])
324   - ->where([ 'level' => $level ]);
  385 + return $this->product->getTaxGroupsByLevel($level);
325 386 }
326 387  
327 388 public function afterSave($insert, $changedAttributes)
... ...
common/modules/product/models/ProductVariantSearch.php
... ... @@ -134,20 +134,4 @@
134 134  
135 135 return $dataProvider;
136 136 }
137   -
138   - /**
139   - * @param string $sku
140   - *
141   - * @return ProductVariant|null
142   - */
143   - public static function findBySku($sku)
144   - {
145   - /**
146   - * @var ProductVariant|null $result
147   - */
148   - $result = ProductVariant::find()
149   - ->andWhere([ 'sku' => $sku ])
150   - ->one();
151   - return $result;
152   - }
153 137 }
... ...
common/modules/product/models/Stock.php
... ... @@ -7,20 +7,22 @@
7 7 use yii\db\ActiveQuery;
8 8 use yii\db\ActiveRecord;
9 9 use yii\web\Request;
10   -
  10 +
11 11 /**
12 12 * This is the model class for table "stock".
13 13 *
14   - * @property integer $id
15   - * @property ProductStock[] $productStocks
  14 + * @property integer $id
  15 + * @property ProductStock[] $productStocks
  16 + * @property ProductVariant[] $productVariants
  17 + * @property Product[] $products
16 18 * * From language behavior *
17   - * @property StockLang $lang
18   - * @property StockLang[] $langs
19   - * @property StockLang $objectLang
20   - * @property string $ownerKey
21   - * @property string $langKey
22   - * @property StockLang[] $modelLangs
23   - * @property bool $transactionStatus
  19 + * @property StockLang $lang
  20 + * @property StockLang[] $langs
  21 + * @property StockLang $objectLang
  22 + * @property string $ownerKey
  23 + * @property string $langKey
  24 + * @property StockLang[] $modelLangs
  25 + * @property bool $transactionStatus
24 26 * @method string getOwnerKey()
25 27 * @method void setOwnerKey( string $value )
26 28 * @method string getLangKey()
... ... @@ -36,7 +38,6 @@
36 38 */
37 39 class Stock extends ActiveRecord
38 40 {
39   -
40 41 /**
41 42 * @inheritdoc
42 43 */
... ... @@ -44,7 +45,7 @@
44 45 {
45 46 return 'stock';
46 47 }
47   -
  48 +
48 49 public function behaviors()
49 50 {
50 51 return [
... ... @@ -60,21 +61,30 @@
60 61 public function attributeLabels()
61 62 {
62 63 return [
63   - 'id' => Yii::t('product', 'Stock ID'),
  64 + 'id' => Yii::t('product', 'Stock ID'),
64 65 ];
65 66 }
66 67  
  68 + /**
  69 + * @return \yii\db\ActiveQuery
  70 + */
67 71 public function getProductStocks()
68 72 {
69 73 return $this->hasMany(ProductStock::className(), [ 'stock_id' => 'id' ]);
70 74 }
71 75  
  76 + /**
  77 + * @return ActiveQuery
  78 + */
72 79 public function getProductVariants()
73 80 {
74 81 return $this->hasMany(ProductVariant::className(), [ 'id' => 'product_variant_id' ])
75 82 ->via('productStocks');
76 83 }
77 84  
  85 + /**
  86 + * @return ActiveQuery
  87 + */
78 88 public function getProducts()
79 89 {
80 90 return $this->hasMany(Product::className(), [ 'id' => 'product_id' ])
... ...
common/modules/product/models/StockLang.php
... ... @@ -68,7 +68,7 @@
68 68 'exist',
69 69 'skipOnError' => true,
70 70 'targetClass' => Stock::className(),
71   - 'targetAttribute' => [ 'id' => 'stock_id' ],
  71 + 'targetAttribute' => [ 'stock_id' => 'id' ],
72 72 ],
73 73 [
74 74 [ 'language_id' ],
... ...
common/modules/product/views/manage/_form.php
1 1 <?php
2 2  
3 3 use common\modules\language\widgets\LanguageForm;
  4 + use common\modules\product\models\Brand;
4 5 use common\modules\product\models\ProductLang;
5 6 use common\modules\rubrication\models\TaxGroup;
6 7 use yii\db\ActiveQuery;
... ... @@ -41,9 +42,9 @@
41 42 <?= $form->field($model, 'brand_id')
42 43 ->dropDownList(
43 44 ArrayHelper::map(
44   - ProductHelper::getBrands()
45   - ->with('lang')
46   - ->all(),
  45 + Brand::find()
  46 + ->with('lang')
  47 + ->all(),
47 48 'id',
48 49 'lang.title'
49 50 ),
... ...
common/modules/product/views/variant/_form.php
... ... @@ -167,10 +167,7 @@ $(&quot;.dynamicform_wrapper&quot;).on(&quot;limitReached&quot;, function(e, item) {
167 167 ->all(),
168 168 'id',
169 169 'lang.title'
170   - ),
171   - [
172   - 'prompt' => Yii::t('product', 'Unit'),
173   - ]
  170 + )
174 171 )
175 172 ->label(Yii::t('product', 'Unit')) ?>
176 173  
... ...
common/modules/product/widgets/brandsCarouselWidget.php
... ... @@ -18,8 +18,12 @@
18 18 $brands = Brand::find()
19 19 ->with('lang')
20 20 ->all();
21   - return $this->render('brandsCarousel', [
22   - 'brands' => $brands,
23   - ]);
  21 + return $this->render(
  22 + 'brandsCarousel',
  23 + [
  24 + 'brands' => $brands,
  25 + ]
  26 + );
24 27 }
25   - }
26 28 \ No newline at end of file
  29 + }
  30 +
27 31 \ No newline at end of file
... ...
common/modules/product/widgets/lastProducts.php
... ... @@ -15,10 +15,14 @@
15 15  
16 16 public function run()
17 17 {
18   - return $this->render('products_block', [
19   - 'title' => \Yii::t('product', 'ะ’ั‹ ะฝะตะดะฐะฒะฝะพ ะฟั€ะพัะผะฐั‚ั€ะธะฒะฐะปะธ'),
20   - 'class' => 'last-products',
21   - 'products' => ProductHelper::getLastProducts(true),
22   - ]);
  18 + return $this->render(
  19 + 'products_block',
  20 + [
  21 + 'title' => \Yii::t('product', 'ะ’ั‹ ะฝะตะดะฐะฒะฝะพ ะฟั€ะพัะผะฐั‚ั€ะธะฒะฐะปะธ'),
  22 + 'class' => 'last-products',
  23 + 'products' => ProductHelper::getLastProducts(true),
  24 + ]
  25 + );
23 26 }
24   - }
25 27 \ No newline at end of file
  28 + }
  29 +
26 30 \ No newline at end of file
... ...
common/modules/product/widgets/similarProducts.php
... ... @@ -24,14 +24,18 @@
24 24 {
25 25 $products = ProductHelper::getSimilarProducts($this->product, $this->count);
26 26  
27   - if(!$this->title) {
  27 + if (!$this->title) {
28 28 $this->title = Yii::t('product', 'Similar products');
29 29 }
30 30  
31   - return $this->render('products_block', [
32   - 'title' => $this->title,
33   - 'class' => 'similar-products',
34   - 'products' => $products,
35   - ]);
  31 + return $this->render(
  32 + 'products_block',
  33 + [
  34 + 'title' => $this->title,
  35 + 'class' => 'similar-products',
  36 + 'products' => $products,
  37 + ]
  38 + );
36 39 }
37   - }
38 40 \ No newline at end of file
  41 + }
  42 +
39 43 \ No newline at end of file
... ...
common/modules/product/widgets/specialProducts.php
... ... @@ -13,8 +13,6 @@
13 13  
14 14 public $count = 8;
15 15  
16   - public $sort = 'default';
17   -
18 16 public $title;
19 17  
20 18 public function init()
... ... @@ -24,10 +22,10 @@
24 22  
25 23 public function run()
26 24 {
27   - $products = ProductHelper::getSpecialProducts($this->type, $this->count, $this->sort);
  25 + $products = ProductHelper::getSpecialProducts($this->type, $this->count);
28 26  
29   - if(!$this->title) {
30   - switch($this->type) {
  27 + if (!$this->title) {
  28 + switch ($this->type) {
31 29 case 'top':
32 30 $this->title = Yii::t('product', 'Top products');
33 31 break;
... ... @@ -40,10 +38,14 @@
40 38 }
41 39 }
42 40  
43   - return $this->render('products_block', [
44   - 'title' => $this->title,
45   - 'class' => $this->type,
46   - 'products' => $products,
47   - ]);
  41 + return $this->render(
  42 + 'products_block',
  43 + [
  44 + 'title' => $this->title,
  45 + 'class' => $this->type,
  46 + 'products' => $products,
  47 + ]
  48 + );
48 49 }
49   - }
50 50 \ No newline at end of file
  51 + }
  52 +
51 53 \ No newline at end of file
... ...
common/modules/product/widgets/views/product_smart.php
... ... @@ -69,9 +69,9 @@
69 69  
70 70 <li><span>ะ‘ั€ะตะฝะด:</span> <?= $product->brand->lang->title ?></li>
71 71  
72   - <?php foreach ($product->getActiveProperties($product->category->id) as $group): ?>
  72 + <?php foreach ($product->getProperties() as $group): ?>
73 73 <li>
74   - <span><?= $group->title ?> <?php foreach ( $group->options as $option ) : ?>&nbsp;</span><?= $option->value ?><?php endforeach ?>
  74 + <span><?= $group->lang->title ?> <?php foreach ( $group->customOptions as $option ) : ?>&nbsp;</span><?= $option->lang->value ?><?php endforeach ?>
75 75 </li>
76 76 <?php endforeach; ?>
77 77  
... ...
common/modules/rubrication/controllers/TaxGroupController.php
... ... @@ -2,7 +2,6 @@
2 2  
3 3 namespace common\modules\rubrication\controllers;
4 4  
5   - use common\modules\rubrication\models\TaxOption;
6 5 use Yii;
7 6 use common\modules\rubrication\models\TaxGroup;
8 7 use yii\data\ActiveDataProvider;
... ... @@ -130,16 +129,6 @@
130 129 ]);
131 130 }
132 131  
133   - /*
134   - * Rebuilp MP-params for group options
135   - */
136   - public function actionRebuild($id)
137   - {
138   - TaxOption::find()
139   - ->rebuildMP($id);
140   - return $this->redirect([ 'index' ]);
141   - }
142   -
143 132 /**
144 133 * Finds the TaxGroup model based on its primary key value.
145 134 * If the model is not found, a 404 HTTP exception will be thrown.
... ...
common/modules/rubrication/controllers/TaxOptionController.php
... ... @@ -113,8 +113,6 @@
113 113 $model->generateLangs();
114 114 if ($model->load(Yii::$app->request->post())) {
115 115 $model->loadLangs(\Yii::$app->request);
116   - // TaxOption::find()
117   - // ->rebuildMP($model->tax_group_id);
118 116 if ($model->save() && $model->transactionStatus) {
119 117 return $this->redirect(
120 118 [
... ...
common/modules/rubrication/models/TaxGroup.php
... ... @@ -5,6 +5,7 @@
5 5 use common\modules\language\behaviors\LanguageBehavior;
6 6 use common\modules\language\models\Language;
7 7 use common\modules\product\models\Category;
  8 + use yii\base\InvalidValueException;
8 9 use yii\db\ActiveQuery;
9 10 use yii\db\ActiveRecord;
10 11 use yii\web\Request;
... ... @@ -22,6 +23,8 @@
22 23 * @property TaxOption[] $taxOptions
23 24 * @property Category[] $categories
24 25 * @property TaxOption[] $options
  26 + * @property TaxOption[] $customOptions
  27 + * @property string $alias
25 28 * * From language behavior *
26 29 * @property TaxGroupLang $lang
27 30 * @property TaxGroupLang[] $langs
... ... @@ -52,7 +55,7 @@
52 55 /**
53 56 * @var TaxOption[] $options
54 57 */
55   - public $options = [];
  58 + protected $customOptions = [];
56 59  
57 60 /**
58 61 * @inheritdoc
... ... @@ -116,17 +119,28 @@
116 119 ];
117 120 }
118 121  
  122 + /**
  123 + * @return ActiveQuery
  124 + */
119 125 public function getCategories()
120 126 {
121 127 return $this->hasMany(Category::className(), [ 'id' => 'category_id' ])
122 128 ->viaTable('tax_group_to_category', [ 'tax_group_id' => 'id' ]);
123 129 }
124 130  
125   - public function setCategories($values)
  131 + /**
  132 + * Set categories to override tax_group_to_category table data
  133 + *
  134 + * @param int[] $values
  135 + */
  136 + public function setCategories(array $values)
126 137 {
127 138 $this->categories = $values;
128 139 }
129 140  
  141 + /**
  142 + * @inheritdoc
  143 + */
130 144 public function afterSave($insert, $changedAttributes)
131 145 {
132 146 parent::afterSave($insert, $changedAttributes);
... ... @@ -141,6 +155,18 @@
141 155 }
142 156  
143 157 /**
  158 + * @return ActiveQuery
  159 + */
  160 + public function getTaxOptions()
  161 + {
  162 + return $this->hasMany(TaxOption::className(), [ 'tax_group_id' => 'id' ])
  163 + ->inverseOf('taxGroup');
  164 + }
  165 +
  166 + /**
  167 + * Synonim for getTaxOptions()
  168 + *
  169 + * @see TaxGroup::getTaxOptions()
144 170 * @return \yii\db\ActiveQuery
145 171 */
146 172 public function getOptions()
... ... @@ -148,12 +174,44 @@
148 174 return $this->getTaxOptions();
149 175 }
150 176  
151   - public function getTaxOptions()
  177 + /**
  178 + * Get customOptins that were filled dynamically.
  179 + * If $fillDefault is true then fill $customOptions with TaxOptions for current TaxGroup
  180 + *
  181 + * @param bool $fillDefault
  182 + *
  183 + * @return TaxOption[]
  184 + */
  185 + public function getCustomOptions(bool $fillDefault = false): array
152 186 {
153   - return $this->hasMany(TaxOption::className(), [ 'tax_group_id' => 'id' ])
154   - ->inverseOf('taxGroup');
  187 + if ($fillDefault && empty( $this->custom_options )) {
  188 + $this->customOptions = $this->getTaxOptions()
  189 + ->with('lang')
  190 + ->all();
  191 + }
  192 + return $this->customOptions;
  193 + }
  194 +
  195 + /**
  196 + * Set customOptions
  197 + *
  198 + * @param TaxOption[] $value
  199 + */
  200 + public function setCustomOptions(array $value)
  201 + {
  202 + foreach ($value as $item) {
  203 + if (!( $item instanceof TaxOption )) {
  204 + throw new InvalidValueException('All elements must be instances of ' . TaxOption::className());
  205 + }
  206 + }
  207 + $this->customOptions = $value;
155 208 }
156 209  
  210 + /**
  211 + * Get default lang alias
  212 + *
  213 + * @return string
  214 + */
157 215 public function getAlias()
158 216 {
159 217 $default_lang = Language::getDefaultLanguage();
... ...
common/modules/rubrication/models/TaxOption.php
... ... @@ -20,6 +20,7 @@
20 20 * @property integer $sort
21 21 * @property string $image
22 22 * @property TaxGroup $taxGroup
  23 + * @property TaxGroup $group
23 24 * @property Product[] $products
24 25 * @property ProductVariant[] $productVariants
25 26 * * From language behavior *
... ... @@ -52,8 +53,6 @@
52 53 class TaxOption extends ActiveRecord
53 54 {
54 55  
55   - public $itemsCount;
56   -
57 56 /**
58 57 * @inheritdoc
59 58 */
... ... @@ -122,26 +121,35 @@
122 121 /**
123 122 * @return \yii\db\ActiveQuery
124 123 */
125   - public function getGroup()
  124 + public function getTaxGroup()
126 125 {
127   - return $this->getTaxGroup();
  126 + return $this->hasOne(TaxGroup::className(), [ 'id' => 'tax_group_id' ])
  127 + ->inverseOf('taxOptions');
128 128 }
129 129  
130 130 /**
  131 + * Synonim for TaxOption::getTaxGroup()
  132 + *
  133 + * @see TaxOption::getTaxGroup()
131 134 * @return \yii\db\ActiveQuery
132 135 */
133   - public function getTaxGroup()
  136 + public function getGroup()
134 137 {
135   - return $this->hasOne(TaxGroup::className(), [ 'id' => 'tax_group_id' ])
136   - ->inverseOf('taxOptions');
  138 + return $this->getTaxGroup();
137 139 }
138 140  
  141 + /**
  142 + * @return ActiveQuery
  143 + */
139 144 public function getProducts()
140 145 {
141 146 return $this->hasMany(Product::className(), [ 'id' => 'product_id' ])
142 147 ->viaTable('product_option', [ 'option_id' => 'id' ]);
143 148 }
144 149  
  150 + /**
  151 + * @return ActiveQuery
  152 + */
145 153 public function getProductVariants()
146 154 {
147 155 return $this->hasMany(ProductVariant::className(), [ 'id' => 'product_variant_id' ])
... ...
common/modules/rubrication/models/TaxOptionQuery.php deleted
1   -<?php
2   -
3   - namespace common\modules\rubrication\models;
4   -
5   - use common\components\artboxtree\ArtboxTreeQueryTrait;
6   - use yii\db\ActiveQuery;
7   -
8   - /**
9   - * This is the ActiveQuery class for [[TaxOption]].
10   - * @see TaxOption
11   - */
12   - class TaxOptionQuery extends ActiveQuery
13   - {
14   -
15   - use ArtboxTreeQueryTrait;
16   -
17   - /**
18   - * @inheritdoc
19   - * @return TaxOption[]|array
20   - */
21   - public function all($db = NULL)
22   - {
23   - return parent::all($db);
24   - }
25   -
26   - /**
27   - * @inheritdoc
28   - * @return TaxOption|array|null
29   - */
30   - public function one($db = NULL)
31   - {
32   - return parent::one($db);
33   - }
34   - }