Skip to content

Commit 60b618b

Browse files
MC-30809: Indexer price calculation for configurable product
1 parent 1bf2d6e commit 60b618b

File tree

4 files changed

+156
-82
lines changed

4 files changed

+156
-82
lines changed

dev/tests/integration/framework/Magento/TestFramework/Catalog/Model/Product/Price/GetDataFromIndexTable.php

Lines changed: 0 additions & 54 deletions
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
declare(strict_types=1);
7+
8+
namespace Magento\TestFramework\Catalog\Model\Product\Price;
9+
10+
use Magento\Catalog\Model\Indexer\Product\Price\PriceTableResolver;
11+
use Magento\Catalog\Model\ResourceModel\Product as ProductResource;
12+
use Magento\Customer\Model\Indexer\CustomerGroupDimensionProvider;
13+
use Magento\Framework\Indexer\DimensionFactory;
14+
use Magento\Store\Model\Indexer\WebsiteDimensionProvider;
15+
16+
/**
17+
* Search and return price data from price index table.
18+
*/
19+
class GetPriceIndexDataByProductId
20+
{
21+
/**
22+
* @var ProductResource
23+
*/
24+
private $productResource;
25+
26+
/**
27+
* @var PriceTableResolver
28+
*/
29+
private $priceTableResolver;
30+
31+
/**
32+
* @var DimensionFactory
33+
*/
34+
private $dimensionFactory;
35+
36+
/**
37+
* @param ProductResource $productResource
38+
* @param PriceTableResolver $priceTableResolver
39+
* @param DimensionFactory $dimensionFactory
40+
*/
41+
public function __construct(
42+
ProductResource $productResource,
43+
PriceTableResolver $priceTableResolver,
44+
DimensionFactory $dimensionFactory
45+
) {
46+
$this->productResource = $productResource;
47+
$this->priceTableResolver = $priceTableResolver;
48+
$this->dimensionFactory = $dimensionFactory;
49+
}
50+
51+
/**
52+
* Returns price data by product id.
53+
*
54+
* @param int $productId
55+
* @param int $groupId
56+
* @param int $websiteId
57+
* @return array
58+
*/
59+
public function execute(int $productId, int $groupId, int $websiteId): array
60+
{
61+
$tableName = $this->priceTableResolver->resolve(
62+
'catalog_product_index_price',
63+
[
64+
$this->dimensionFactory->create(WebsiteDimensionProvider::DIMENSION_NAME, (string)$websiteId),
65+
$this->dimensionFactory->create(CustomerGroupDimensionProvider::DIMENSION_NAME, (string)$groupId),
66+
]
67+
);
68+
69+
$select = $this->productResource->getConnection()->select()
70+
->from($tableName)
71+
->where('entity_id = ?', $productId);
72+
if (isset($groupId)) {
73+
$select->where('customer_group_id = ?', $groupId);
74+
}
75+
if (isset($websiteId)) {
76+
$select->where('website_id = ?', $websiteId);
77+
}
78+
79+
return $this->productResource->getConnection()->fetchAll($select);
80+
}
81+
}

dev/tests/integration/testsuite/Magento/CatalogRuleConfigurable/Model/Product/Type/Configurable/PriceTest.php

Lines changed: 61 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,8 @@
1313
use Magento\ConfigurableProduct\Model\Product\Type\Configurable\Price;
1414
use Magento\Customer\Model\Group;
1515
use Magento\Framework\ObjectManagerInterface;
16-
use Magento\TestFramework\Catalog\Model\Product\Price\GetDataFromIndexTable;
16+
use Magento\Store\Api\WebsiteRepositoryInterface;
17+
use Magento\TestFramework\Catalog\Model\Product\Price\GetPriceIndexDataByProductId;
1718
use Magento\TestFramework\Helper\Bootstrap;
1819
use PHPUnit\Framework\TestCase;
1920

@@ -30,6 +31,11 @@ class PriceTest extends TestCase
3031
*/
3132
private $objectManager;
3233

34+
/**
35+
* @var WebsiteRepositoryInterface
36+
*/
37+
private $websiteRepository;
38+
3339
/**
3440
* @var ProductRepositoryInterface
3541
*/
@@ -41,14 +47,9 @@ class PriceTest extends TestCase
4147
private $priceModel;
4248

4349
/**
44-
* @var GetDataFromIndexTable
45-
*/
46-
private $getDataFromIndexTable;
47-
48-
/**
49-
* @var array
50+
* @var GetPriceIndexDataByProductId
5051
*/
51-
private $priceIndexFields = ['price', 'final_price', 'min_price', 'max_price', 'tier_price'];
52+
private $getPriceIndexDataByProductId;
5253

5354
/**
5455
* @inheritdoc
@@ -57,9 +58,10 @@ protected function setUp()
5758
{
5859
$this->objectManager = Bootstrap::getObjectManager();
5960
$this->priceModel = $this->objectManager->create(Price::class);
61+
$this->websiteRepository = $this->objectManager->get(WebsiteRepositoryInterface::class);
6062
$this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
6163
$this->productRepository->cleanCache();
62-
$this->getDataFromIndexTable = $this->objectManager->get(GetDataFromIndexTable::class);
64+
$this->getPriceIndexDataByProductId = $this->objectManager->get(GetPriceIndexDataByProductId::class);
6365
}
6466

6567
/**
@@ -69,9 +71,27 @@ protected function setUp()
6971
public function testGetFinalPriceWithCustomOptionAndCatalogRule(): void
7072
{
7173
$indexPrices = [
72-
'simple_10' => [10, 9, 9, 9, null],
73-
'simple_20' => [20, 15, 15, 15, 15],
74-
'configurable' => [0, 0, 9, 30, 15],
74+
'simple_10' => [
75+
'price' => 10,
76+
'final_price' => 9,
77+
'min_price' => 9,
78+
'max_price' => 9,
79+
'tier_price' => null
80+
],
81+
'simple_20' => [
82+
'price' => 20,
83+
'final_price' => 15,
84+
'min_price' => 15,
85+
'max_price' => 15,
86+
'tier_price' => 15
87+
],
88+
'configurable' => [
89+
'price' => 0,
90+
'final_price' => 0,
91+
'min_price' => 9,
92+
'max_price' => 30,
93+
'tier_price' => 15
94+
],
7595
];
7696
$this->assertConfigurableProductPrice(20, 25, $indexPrices);
7797
}
@@ -83,9 +103,27 @@ public function testGetFinalPriceWithCustomOptionAndCatalogRule(): void
83103
public function testGetFinalPriceWithCustomOptionAndCatalogRulesForChildren(): void
84104
{
85105
$indexPrices = [
86-
'simple_10' => [10, 4.5, 4.5, 9, null],
87-
'simple_20' => [20, 8, 8, 15, 15],
88-
'configurable' => [0, 0, 4.5, 23, 15],
106+
'simple_10' => [
107+
'price' => 10,
108+
'final_price' => 4.5,
109+
'min_price' => 4.5,
110+
'max_price' => 9,
111+
'tier_price' => null
112+
],
113+
'simple_20' => [
114+
'price' => 20,
115+
'final_price' => 8,
116+
'min_price' => 8,
117+
'max_price' => 15,
118+
'tier_price' => 15
119+
],
120+
'configurable' => [
121+
'price' => 0,
122+
'final_price' => 0,
123+
'min_price' => 4.5,
124+
'max_price' => 23,
125+
'tier_price' => 15
126+
],
89127
];
90128
$this->assertConfigurableProductPrice(19.5, 23, $indexPrices);
91129
}
@@ -104,28 +142,28 @@ private function assertConfigurableProductPrice(
104142
array $indexPrices
105143
): void {
106144
foreach ($indexPrices as $sku => $prices) {
107-
$this->assertIndexTableData($sku, array_combine($this->priceIndexFields, $prices));
145+
$this->assertIndexTableData($sku, $prices);
108146
}
109147
$configurable = $this->productRepository->get('configurable');
110148
//Add tier price option
111149
$optionId = $configurable->getOptions()[0]->getId();
112150
$configurable->addCustomOption(AbstractType::OPTION_PREFIX . $optionId, 'text');
113151
$configurable->addCustomOption('option_ids', $optionId);
114152
//First simple rule price + Option price
115-
$this->assertFinalPrice($priceWithFirstSimple, $configurable);
153+
$this->assertFinalPrice($configurable, $priceWithFirstSimple);
116154
$configurable->addCustomOption('simple_product', 20, $this->productRepository->get('simple_20'));
117155
//Second simple rule price + Option price
118-
$this->assertFinalPrice($priceWithSecondSimple, $configurable);
156+
$this->assertFinalPrice($configurable, $priceWithSecondSimple);
119157
}
120158

121159
/**
122160
* Asserts product final price.
123161
*
124-
* @param float $expectedPrice
125162
* @param ProductInterface $product
163+
* @param float $expectedPrice
126164
* @return void
127165
*/
128-
private function assertFinalPrice(float $expectedPrice, ProductInterface $product): void
166+
private function assertFinalPrice(ProductInterface $product, float $expectedPrice): void
129167
{
130168
$this->assertEquals(
131169
round($expectedPrice, 2),
@@ -142,9 +180,10 @@ private function assertFinalPrice(float $expectedPrice, ProductInterface $produc
142180
*/
143181
private function assertIndexTableData(string $sku, array $expectedPrices): void
144182
{
145-
$data = $this->getDataFromIndexTable->execute(
183+
$data = $this->getPriceIndexDataByProductId->execute(
146184
(int)$this->productRepository->get($sku)->getId(),
147-
Group::NOT_LOGGED_IN_ID
185+
Group::NOT_LOGGED_IN_ID,
186+
(int)$this->websiteRepository->get('base')->getId()
148187
);
149188
$data = reset($data);
150189
foreach ($expectedPrices as $column => $price) {

dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/Product/Type/Configurable/PriceTest.php

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,8 @@
1212
use Magento\Catalog\Model\Product\Type\AbstractType;
1313
use Magento\Customer\Model\Group;
1414
use Magento\Framework\ObjectManagerInterface;
15-
use Magento\TestFramework\Catalog\Model\Product\Price\GetDataFromIndexTable;
15+
use Magento\Store\Api\WebsiteRepositoryInterface;
16+
use Magento\TestFramework\Catalog\Model\Product\Price\GetPriceIndexDataByProductId;
1617
use Magento\TestFramework\Helper\Bootstrap;
1718
use PHPUnit\Framework\TestCase;
1819

@@ -39,9 +40,14 @@ class PriceTest extends TestCase
3940
private $priceModel;
4041

4142
/**
42-
* @var GetDataFromIndexTable
43+
* @var GetPriceIndexDataByProductId
4344
*/
44-
private $getDataFromIndexTable;
45+
private $getPriceIndexDataByProductId;
46+
47+
/**
48+
* @var WebsiteRepositoryInterface
49+
*/
50+
private $websiteRepository;
4551

4652
/**
4753
* @inheritdoc
@@ -52,7 +58,8 @@ protected function setUp()
5258
$this->priceModel = $this->objectManager->create(Price::class);
5359
$this->productRepository = $this->objectManager->get(ProductRepositoryInterface::class);
5460
$this->productRepository->cleanCache();
55-
$this->getDataFromIndexTable = $this->objectManager->get(GetDataFromIndexTable::class);
61+
$this->getPriceIndexDataByProductId = $this->objectManager->get(GetPriceIndexDataByProductId::class);
62+
$this->websiteRepository = $this->objectManager->get(WebsiteRepositoryInterface::class);
5663
}
5764

5865
/**
@@ -162,9 +169,10 @@ public function testGetFinalPriceWithCustomOptionAndSimpleTierPrice(): void
162169
*/
163170
private function assertIndexTableData(string $sku, array $expectedPrices): void
164171
{
165-
$data = $this->getDataFromIndexTable->execute(
172+
$data = $this->getPriceIndexDataByProductId->execute(
166173
(int)$this->productRepository->get($sku)->getId(),
167-
Group::NOT_LOGGED_IN_ID
174+
Group::NOT_LOGGED_IN_ID,
175+
(int)$this->websiteRepository->get('base')->getId()
168176
);
169177
$data = reset($data);
170178
foreach ($expectedPrices as $column => $price) {

0 commit comments

Comments
 (0)