Skip to content

Commit 654453b

Browse files
author
Stanislav Idolov
committed
MAGETWO-64518: \Magento\CatalogRule\Model\Indexer\IndexBuilder method "doReindexFull()" causes temporary missing sale prices
1 parent 944de8d commit 654453b

13 files changed

+886
-10
lines changed

app/code/Magento/CatalogRule/Model/Indexer/ProductPriceCalculator.php

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
namespace Magento\CatalogRule\Model\Indexer;
88

9+
/**
10+
* Product price calculation according rules settings.
11+
*/
912
class ProductPriceCalculator
1013
{
1114
/**
@@ -14,7 +17,6 @@ class ProductPriceCalculator
1417
private $priceCurrency;
1518

1619
/**
17-
* ProductPriceCalculator constructor.
1820
* @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency
1921
*/
2022
public function __construct(\Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency)
@@ -23,6 +25,8 @@ public function __construct(\Magento\Framework\Pricing\PriceCurrencyInterface $p
2325
}
2426

2527
/**
28+
* Calculates product price.
29+
*
2630
* @param array $ruleData
2731
* @param null $productData
2832
* @return float

app/code/Magento/CatalogRule/Model/Indexer/ReindexRuleGroupWebsite.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
namespace Magento\CatalogRule\Model\Indexer;
88

9+
/**
10+
* Reindex information about rule relations with customer groups and websites.
11+
*/
912
class ReindexRuleGroupWebsite
1013
{
1114
/**
@@ -44,6 +47,8 @@ public function __construct(
4447
}
4548

4649
/**
50+
* Prepare and persist information about rule relations with customer groups and websites to index table.
51+
*
4752
* @param bool $useAdditionalTable
4853
* @return bool
4954
*/

app/code/Magento/CatalogRule/Model/Indexer/ReindexRuleProduct.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
namespace Magento\CatalogRule\Model\Indexer;
88

9+
/**
10+
* Reindex rule relations with products.
11+
*/
912
class ReindexRuleProduct
1013
{
1114
/**
@@ -31,6 +34,8 @@ public function __construct(
3134
}
3235

3336
/**
37+
* Reindex information about rule relations with products.
38+
*
3439
* @param \Magento\CatalogRule\Model\Rule $rule
3540
* @param int $batchCount
3641
* @param bool $useAdditionalTable

app/code/Magento/CatalogRule/Model/Indexer/ReindexRuleProductPrice.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
namespace Magento\CatalogRule\Model\Indexer;
88

9+
/**
10+
* Reindex product prices according rule settings.
11+
*/
912
class ReindexRuleProductPrice
1013
{
1114
/**
@@ -55,6 +58,8 @@ public function __construct(
5558
}
5659

5760
/**
61+
* Reindex product prices.
62+
*
5863
* @param int $batchCount
5964
* @param \Magento\Catalog\Model\Product|null $product
6065
* @param bool $useAdditionalTable

app/code/Magento/CatalogRule/Model/Indexer/RuleProductPricesPersistor.php

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
namespace Magento\CatalogRule\Model\Indexer;
88

9+
/**
10+
* Persist product prices to index table.
11+
*/
912
class RuleProductPricesPersistor
1013
{
1114
/**
@@ -39,14 +42,16 @@ public function __construct(
3942
}
4043

4144
/**
42-
* @param array $arrData
45+
* Persist prices data to index table.
46+
*
47+
* @param array $priceData
4348
* @param bool $useAdditionalTable
4449
* @return bool
4550
* @throws \Exception
4651
*/
47-
public function execute(array $arrData, $useAdditionalTable = false)
52+
public function execute(array $priceData, $useAdditionalTable = false)
4853
{
49-
if (empty($arrData)) {
54+
if (empty($priceData)) {
5055
return false;
5156
}
5257

@@ -61,13 +66,13 @@ public function execute(array $arrData, $useAdditionalTable = false)
6166
$productIds = [];
6267

6368
try {
64-
foreach ($arrData as $key => $data) {
69+
foreach ($priceData as $key => $data) {
6570
$productIds['product_id'] = $data['product_id'];
66-
$arrData[$key]['rule_date'] = $this->dateFormat->formatDate($data['rule_date'], false);
67-
$arrData[$key]['latest_start_date'] = $this->dateFormat->formatDate($data['latest_start_date'], false);
68-
$arrData[$key]['earliest_end_date'] = $this->dateFormat->formatDate($data['earliest_end_date'], false);
71+
$priceData[$key]['rule_date'] = $this->dateFormat->formatDate($data['rule_date'], false);
72+
$priceData[$key]['latest_start_date'] = $this->dateFormat->formatDate($data['latest_start_date'], false);
73+
$priceData[$key]['earliest_end_date'] = $this->dateFormat->formatDate($data['earliest_end_date'], false);
6974
}
70-
$connection->insertOnDuplicate($indexTable, $arrData);
75+
$connection->insertOnDuplicate($indexTable, $priceData);
7176
} catch (\Exception $e) {
7277
throw $e;
7378
}

app/code/Magento/CatalogRule/Model/Indexer/RuleProductsSelectBuilder.php

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66

77
namespace Magento\CatalogRule\Model\Indexer;
88

9+
/**
10+
* Build select for rule relation with product.
11+
*/
912
class RuleProductsSelectBuilder
1013
{
1114
/**
@@ -55,6 +58,8 @@ public function __construct(
5558
}
5659

5760
/**
61+
* Build select for indexer according passed parameters.
62+
*
5863
* @param int $websiteId
5964
* @param \Magento\Catalog\Model\Product|null $product
6065
* @param bool $useAdditionalTable
@@ -142,7 +147,7 @@ public function build(
142147
[]
143148
);
144149
$select->columns([
145-
'default_price' =>$connection->getIfNullSql($tableAlias . '.value', 'pp_default.value'),
150+
'default_price' => $connection->getIfNullSql($tableAlias . '.value', 'pp_default.value'),
146151
]);
147152

148153
return $connection->query($select);
Lines changed: 103 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\CatalogRule\Test\Unit\Model\Indexer;
8+
9+
class ProductPriceCalculatorTest extends \PHPUnit_Framework_TestCase
10+
{
11+
/**
12+
* @var \Magento\CatalogRule\Model\Indexer\ProductPriceCalculator
13+
*/
14+
private $model;
15+
16+
/**
17+
* @var \Magento\Framework\Pricing\PriceCurrencyInterface|\PHPUnit_Framework_MockObject_MockObject
18+
*/
19+
private $priceCurrencyMock;
20+
21+
protected function setUp()
22+
{
23+
$this->priceCurrencyMock = $this->getMockBuilder(\Magento\Framework\Pricing\PriceCurrencyInterface::class)
24+
->disableOriginalConstructor()
25+
->getMock();
26+
$this->model = new \Magento\CatalogRule\Model\Indexer\ProductPriceCalculator($this->priceCurrencyMock);
27+
}
28+
29+
public function testCalculateToFixedPrice()
30+
{
31+
$rulePrice = 100;
32+
$actionAmount = 50;
33+
$ruleData = [
34+
'action_operator' => 'to_fixed',
35+
'action_amount' => $actionAmount
36+
];
37+
$productData = ['rule_price' => $rulePrice];
38+
39+
$this->priceCurrencyMock->expects($this->once())
40+
->method('round')
41+
->with($actionAmount)
42+
->willReturn($actionAmount);
43+
44+
$this->assertEquals($actionAmount, $this->model->calculate($ruleData, $productData));
45+
}
46+
47+
public function testCalculateToPercentPrice()
48+
{
49+
$rulePrice = 200;
50+
$actionAmount = 50;
51+
$expectedPrice = 100;
52+
$ruleData = [
53+
'action_operator' => 'to_percent',
54+
'action_amount' => $actionAmount
55+
];
56+
$productData = ['rule_price' => $rulePrice];
57+
58+
$this->priceCurrencyMock->expects($this->once())
59+
->method('round')
60+
->with($expectedPrice)
61+
->willReturn($expectedPrice);
62+
63+
$this->assertEquals($expectedPrice, $this->model->calculate($ruleData, $productData));
64+
}
65+
66+
public function testCalculateByFixedPrice()
67+
{
68+
$rulePrice = 200;
69+
$actionAmount = 50;
70+
$expectedPrice = 150;
71+
$ruleData = [
72+
'action_operator' => 'by_fixed',
73+
'action_amount' => $actionAmount
74+
];
75+
$productData = ['rule_price' => $rulePrice];
76+
77+
$this->priceCurrencyMock->expects($this->once())
78+
->method('round')
79+
->with($expectedPrice)
80+
->willReturn($expectedPrice);
81+
82+
$this->assertEquals($expectedPrice, $this->model->calculate($ruleData, $productData));
83+
}
84+
85+
public function testCalculateByPercentPrice()
86+
{
87+
$rulePrice = 200;
88+
$actionAmount = 50;
89+
$expectedPrice = 100;
90+
$ruleData = [
91+
'action_operator' => 'by_percent',
92+
'action_amount' => $actionAmount
93+
];
94+
$productData = ['rule_price' => $rulePrice];
95+
96+
$this->priceCurrencyMock->expects($this->once())
97+
->method('round')
98+
->with($expectedPrice)
99+
->willReturn($expectedPrice);
100+
101+
$this->assertEquals($expectedPrice, $this->model->calculate($ruleData, $productData));
102+
}
103+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\CatalogRule\Test\Unit\Model\Indexer;
8+
9+
class ReindexRuleGroupWebsiteTest extends \PHPUnit_Framework_TestCase
10+
{
11+
/**
12+
* @var \Magento\CatalogRule\Model\Indexer\ReindexRuleGroupWebsite
13+
*/
14+
private $model;
15+
16+
/**
17+
* @var \Magento\Framework\Stdlib\DateTime\DateTime|\PHPUnit_Framework_MockObject_MockObject
18+
*/
19+
private $dateTimeMock;
20+
21+
/**
22+
* @var \Magento\Framework\App\ResourceConnection|\PHPUnit_Framework_MockObject_MockObject
23+
*/
24+
private $resourceMock;
25+
26+
/**
27+
* @var \Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher|\PHPUnit_Framework_MockObject_MockObject
28+
*/
29+
private $activeTableSwitcherMock;
30+
31+
protected function setUp()
32+
{
33+
$this->dateTimeMock = $this->getMockBuilder(\Magento\Framework\Stdlib\DateTime\DateTime::class)
34+
->disableOriginalConstructor()
35+
->getMock();
36+
$this->resourceMock = $this->getMockBuilder(\Magento\Framework\App\ResourceConnection::class)
37+
->disableOriginalConstructor()
38+
->getMock();
39+
$this->activeTableSwitcherMock =
40+
$this->getMockBuilder(\Magento\Catalog\Model\ResourceModel\Indexer\ActiveTableSwitcher::class)
41+
->disableOriginalConstructor()
42+
->getMock();
43+
$this->model = new \Magento\CatalogRule\Model\Indexer\ReindexRuleGroupWebsite(
44+
$this->dateTimeMock,
45+
$this->resourceMock,
46+
$this->activeTableSwitcherMock
47+
);
48+
}
49+
50+
public function testExecute()
51+
{
52+
$timeStamp = (int)gmdate('U');
53+
$insertString = 'insert_string';
54+
$connectionMock = $this->getMockBuilder(\Magento\Framework\DB\Adapter\AdapterInterface::class)->getMock();
55+
$this->resourceMock->expects($this->at(0))->method('getConnection')->willReturn($connectionMock);
56+
$this->dateTimeMock->expects($this->once())->method('gmtTimestamp')->willReturn($timeStamp);
57+
58+
$this->activeTableSwitcherMock->expects($this->at(0))
59+
->method('getAdditionalTableName')
60+
->with('catalogrule_group_website')
61+
->willReturn('catalogrule_group_website_replica');
62+
$this->activeTableSwitcherMock->expects($this->at(1))
63+
->method('getAdditionalTableName')
64+
->with('catalogrule_product')
65+
->willReturn('catalogrule_product_replica');
66+
67+
$this->resourceMock->expects($this->at(1))
68+
->method('getTableName')
69+
->with('catalogrule_group_website')
70+
->willReturn('catalogrule_group_website');
71+
$this->resourceMock->expects($this->at(2))
72+
->method('getTableName')
73+
->with('catalogrule_product')
74+
->willReturn('catalogrule_product');
75+
$this->resourceMock->expects($this->at(3))
76+
->method('getTableName')
77+
->with('catalogrule_group_website_replica')
78+
->willReturn('catalogrule_group_website_replica');
79+
$this->resourceMock->expects($this->at(4))
80+
->method('getTableName')
81+
->with('catalogrule_product_replica')
82+
->willReturn('catalogrule_product_replica');
83+
84+
$selectMock = $this->getMockBuilder(\Magento\Framework\DB\Select::class)
85+
->disableOriginalConstructor()
86+
->getMock();
87+
88+
$connectionMock->expects($this->once())->method('delete')->with('catalogrule_group_website_replica');
89+
$connectionMock->expects($this->once())->method('select')->willReturn($selectMock);
90+
91+
$selectMock->expects($this->once())->method('distinct')->with(true)->willReturnSelf();
92+
$selectMock->expects($this->once())
93+
->method('from')
94+
->with('catalogrule_product_replica', ['rule_id', 'customer_group_id', 'website_id'])
95+
->willReturnSelf();
96+
$selectMock->expects($this->once())
97+
->method('where')
98+
->with("{$timeStamp} >= from_time AND (({$timeStamp} <= to_time AND to_time > 0) OR to_time = 0)")
99+
->willReturnSelf();
100+
$selectMock->expects($this->once())
101+
->method('insertFromSelect')
102+
->with('catalogrule_group_website_replica', ['rule_id', 'customer_group_id', 'website_id'])
103+
->willReturn($insertString);
104+
$connectionMock->expects($this->once())->method('query')->with($insertString);
105+
106+
$this->assertTrue($this->model->execute(true));
107+
}
108+
}

0 commit comments

Comments
 (0)