Skip to content

Commit 57d3194

Browse files
committed
Merge remote-tracking branch 'origin/MAGETWO-96364' into 2.3-develop-pr13
2 parents 619f2db + e10c08d commit 57d3194

File tree

2 files changed

+122
-34
lines changed
  • app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price
  • dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price

2 files changed

+122
-34
lines changed

app/code/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/Configurable.php

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\Query\BaseFinalPrice;
1313
use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\IndexTableStructureFactory;
1414
use Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\IndexTableStructure;
15+
use Magento\Framework\App\Config\ScopeConfigInterface;
16+
use Magento\Store\Model\ScopeInterface;
17+
use Magento\Framework\App\ObjectManager;
18+
use Magento\CatalogInventory\Model\Stock;
19+
use Magento\CatalogInventory\Model\Configuration;
1520

1621
/**
1722
* Configurable Products Price Indexer Resource model
@@ -65,6 +70,11 @@ class Configurable implements DimensionalIndexerInterface
6570
*/
6671
private $basePriceModifier;
6772

73+
/**
74+
* @var ScopeConfigInterface
75+
*/
76+
private $scopeConfig;
77+
6878
/**
6979
* @param BaseFinalPrice $baseFinalPrice
7080
* @param IndexTableStructureFactory $indexTableStructureFactory
@@ -74,6 +84,7 @@ class Configurable implements DimensionalIndexerInterface
7484
* @param BasePriceModifier $basePriceModifier
7585
* @param bool $fullReindexAction
7686
* @param string $connectionName
87+
* @param ScopeConfigInterface $scopeConfig
7788
*/
7889
public function __construct(
7990
BaseFinalPrice $baseFinalPrice,
@@ -83,7 +94,8 @@ public function __construct(
8394
\Magento\Framework\App\ResourceConnection $resource,
8495
BasePriceModifier $basePriceModifier,
8596
$fullReindexAction = false,
86-
$connectionName = 'indexer'
97+
$connectionName = 'indexer',
98+
ScopeConfigInterface $scopeConfig = null
8799
) {
88100
$this->baseFinalPrice = $baseFinalPrice;
89101
$this->indexTableStructureFactory = $indexTableStructureFactory;
@@ -93,10 +105,11 @@ public function __construct(
93105
$this->resource = $resource;
94106
$this->fullReindexAction = $fullReindexAction;
95107
$this->basePriceModifier = $basePriceModifier;
108+
$this->scopeConfig = $scopeConfig ?: ObjectManager::getInstance()->get(ScopeConfigInterface::class);
96109
}
97110

98111
/**
99-
* {@inheritdoc}
112+
* @inheritdoc
100113
*
101114
* @throws \Exception
102115
*/
@@ -184,7 +197,19 @@ private function fillTemporaryOptionsTable(string $temporaryOptionsTableName, ar
184197
['le' => $this->getTable('catalog_product_entity')],
185198
'le.' . $linkField . ' = l.parent_id',
186199
[]
187-
)->columns(
200+
);
201+
202+
// Does not make sense to extend query if out of stock products won't appear in tables for indexing
203+
if ($this->isConfigShowOutOfStock()) {
204+
$select->join(
205+
['si' => $this->getTable('cataloginventory_stock_item')],
206+
'si.product_id = l.product_id',
207+
[]
208+
);
209+
$select->where('si.is_in_stock = ?', Stock::STOCK_IN_STOCK);
210+
}
211+
212+
$select->columns(
188213
[
189214
'le.entity_id',
190215
'customer_group_id',
@@ -250,7 +275,7 @@ private function getMainTable($dimensions)
250275
/**
251276
* Get connection
252277
*
253-
* return \Magento\Framework\DB\Adapter\AdapterInterface
278+
* @return \Magento\Framework\DB\Adapter\AdapterInterface
254279
* @throws \DomainException
255280
*/
256281
private function getConnection(): \Magento\Framework\DB\Adapter\AdapterInterface
@@ -272,4 +297,17 @@ private function getTable($tableName)
272297
{
273298
return $this->resource->getTableName($tableName, $this->connectionName);
274299
}
300+
301+
/**
302+
* Is flag Show Out Of Stock setted
303+
*
304+
* @return bool
305+
*/
306+
private function isConfigShowOutOfStock(): bool
307+
{
308+
return $this->scopeConfig->isSetFlag(
309+
Configuration::XML_PATH_SHOW_OUT_OF_STOCK,
310+
ScopeInterface::SCOPE_STORE
311+
);
312+
}
275313
}

dev/tests/integration/testsuite/Magento/ConfigurableProduct/Model/ResourceModel/Product/Indexer/Price/ConfigurableTest.php

Lines changed: 80 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,18 @@
1212
use Magento\Store\Model\Store;
1313
use Magento\Store\Model\StoreManagerInterface;
1414
use Magento\TestFramework\Helper\Bootstrap;
15+
use Magento\CatalogInventory\Model\Stock;
16+
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
17+
use PHPUnit\Framework\TestCase;
18+
use Magento\Catalog\Api\Data\ProductInterface;
1519

1620
/**
21+
* Configurable test
22+
*
23+
* @SuppressWarnings(PHPMD.CouplingBetweenObjects)
1724
* @magentoAppArea adminhtml
1825
*/
19-
class ConfigurableTest extends \PHPUnit\Framework\TestCase
26+
class ConfigurableTest extends TestCase
2027
{
2128
/**
2229
* @var StoreManagerInterface
@@ -28,26 +35,36 @@ class ConfigurableTest extends \PHPUnit\Framework\TestCase
2835
*/
2936
private $productRepository;
3037

31-
protected function setUp()
38+
/**
39+
* @var StockItemRepositoryInterface
40+
*/
41+
private $stockRepository;
42+
43+
/**
44+
* @inheritdoc
45+
*/
46+
protected function setUp(): void
3247
{
3348
$this->storeManager = Bootstrap::getObjectManager()->get(StoreManagerInterface::class);
3449
$this->productRepository = Bootstrap::getObjectManager()->get(ProductRepositoryInterface::class);
50+
$this->stockRepository = Bootstrap::getObjectManager()->get(StockItemRepositoryInterface::class);
3551
}
3652

3753
/**
54+
* Test get product final price if one of child is disabled
55+
*
3856
* @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
3957
* @magentoDbIsolation disabled
58+
*
59+
* @return void
60+
* @throws \Magento\Framework\Exception\CouldNotSaveException
61+
* @throws \Magento\Framework\Exception\InputException
62+
* @throws \Magento\Framework\Exception\NoSuchEntityException
63+
* @throws \Magento\Framework\Exception\StateException
4064
*/
41-
public function testGetProductFinalPriceIfOneOfChildIsDisabled()
65+
public function testGetProductFinalPriceIfOneOfChildIsDisabled(): void
4266
{
43-
/** @var Collection $collection */
44-
$collection = Bootstrap::getObjectManager()->get(CollectionFactory::class)
45-
->create();
46-
$configurableProduct = $collection
47-
->addIdFilter([1])
48-
->addMinimalPrice()
49-
->load()
50-
->getFirstItem();
67+
$configurableProduct = $this->getConfigurableProductFromCollection();
5168
$this->assertEquals(10, $configurableProduct->getMinimalPrice());
5269

5370
$childProduct = $this->productRepository->getById(10, false, null, true);
@@ -58,34 +75,28 @@ public function testGetProductFinalPriceIfOneOfChildIsDisabled()
5875
$this->productRepository->save($childProduct);
5976
$this->storeManager->setCurrentStore($currentStoreId);
6077

61-
/** @var Collection $collection */
62-
$collection = Bootstrap::getObjectManager()->get(CollectionFactory::class)
63-
->create();
64-
$configurableProduct = $collection
65-
->addIdFilter([1])
66-
->addMinimalPrice()
67-
->load()
68-
->getFirstItem();
78+
$configurableProduct = $this->getConfigurableProductFromCollection();
6979
$this->assertEquals(20, $configurableProduct->getMinimalPrice());
7080
}
7181

7282
/**
83+
* Test get product final price if one of child is disabled per store
84+
*
7385
* @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
7486
* @magentoDbIsolation disabled
87+
*
88+
* @return void
89+
* @throws \Magento\Framework\Exception\CouldNotSaveException
90+
* @throws \Magento\Framework\Exception\InputException
91+
* @throws \Magento\Framework\Exception\NoSuchEntityException
92+
* @throws \Magento\Framework\Exception\StateException
7593
*/
76-
public function testGetProductFinalPriceIfOneOfChildIsDisabledPerStore()
94+
public function testGetProductFinalPriceIfOneOfChildIsDisabledPerStore(): void
7795
{
78-
/** @var Collection $collection */
79-
$collection = Bootstrap::getObjectManager()->get(CollectionFactory::class)
80-
->create();
81-
$configurableProduct = $collection
82-
->addIdFilter([1])
83-
->addMinimalPrice()
84-
->load()
85-
->getFirstItem();
96+
$configurableProduct = $this->getConfigurableProductFromCollection();
8697
$this->assertEquals(10, $configurableProduct->getMinimalPrice());
8798

88-
$childProduct = $this->productRepository->getById(10, false, null, true);
99+
$childProduct = $this->productRepository->get('simple_10', false, null, true);
89100
$childProduct->setStatus(Status::STATUS_DISABLED);
90101

91102
// update in default store scope
@@ -95,14 +106,53 @@ public function testGetProductFinalPriceIfOneOfChildIsDisabledPerStore()
95106
$this->productRepository->save($childProduct);
96107
$this->storeManager->setCurrentStore($currentStoreId);
97108

109+
$configurableProduct = $this->getConfigurableProductFromCollection();
110+
$this->assertEquals(20, $configurableProduct->getMinimalPrice());
111+
}
112+
113+
/**
114+
* Test get product minimal price if one child is out of stock
115+
*
116+
* @magentoConfigFixture current_store cataloginventory/options/show_out_of_stock 1
117+
* @magentoDataFixture Magento/ConfigurableProduct/_files/product_configurable.php
118+
* @magentoDbIsolation disabled
119+
*
120+
* @return void
121+
* @throws \Magento\Framework\Exception\NoSuchEntityException
122+
*/
123+
public function testGetProductMinimalPriceIfOneOfChildIsOutOfStock(): void
124+
{
125+
$configurableProduct = $this->getConfigurableProductFromCollection();
126+
$this->assertEquals(10, $configurableProduct->getMinimalPrice());
127+
128+
$childProduct = $this->productRepository->getById(10, false, null, true);
129+
$stockItem = $childProduct->getExtensionAttributes()->getStockItem();
130+
$stockItem->setIsInStock(Stock::STOCK_OUT_OF_STOCK);
131+
$this->stockRepository->save($stockItem);
132+
133+
$configurableProduct = $this->getConfigurableProductFromCollection();
134+
$this->assertEquals(20, $configurableProduct->getMinimalPrice());
135+
}
136+
137+
/**
138+
* Retrieve configurable product.
139+
* Returns Configurable product that was created by Magento/ConfigurableProduct/_files/product_configurable.php
140+
* fixture
141+
*
142+
* @return ProductInterface
143+
*/
144+
private function getConfigurableProductFromCollection(): ProductInterface
145+
{
98146
/** @var Collection $collection */
99147
$collection = Bootstrap::getObjectManager()->get(CollectionFactory::class)
100148
->create();
149+
/** @var ProductInterface $configurableProduct */
101150
$configurableProduct = $collection
102151
->addIdFilter([1])
103152
->addMinimalPrice()
104153
->load()
105154
->getFirstItem();
106-
$this->assertEquals(20, $configurableProduct->getMinimalPrice());
155+
156+
return $configurableProduct;
107157
}
108158
}

0 commit comments

Comments
 (0)