Skip to content

Commit 7282eb4

Browse files
committed
Merge branch 'MAGETWO-99930' of https://github.com/magento-tango/magento2ce into PR_2019_06_18
2 parents e057627 + b547c55 commit 7282eb4

File tree

3 files changed

+161
-1
lines changed

3 files changed

+161
-1
lines changed

app/code/Magento/CatalogInventory/Observer/SaveInventoryDataObserver.php

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,11 @@ class SaveInventoryDataObserver implements ObserverInterface
3939
*/
4040
private $stockItemValidator;
4141

42+
/**
43+
* @var array
44+
*/
45+
private $parentItemProcessorPool;
46+
4247
/**
4348
* @var array
4449
*/
@@ -77,15 +82,18 @@ class SaveInventoryDataObserver implements ObserverInterface
7782
* @param StockConfigurationInterface $stockConfiguration
7883
* @param StockRegistryInterface $stockRegistry
7984
* @param StockItemValidator $stockItemValidator
85+
* @param array $parentItemProcessorPool
8086
*/
8187
public function __construct(
8288
StockConfigurationInterface $stockConfiguration,
8389
StockRegistryInterface $stockRegistry,
84-
StockItemValidator $stockItemValidator = null
90+
StockItemValidator $stockItemValidator = null,
91+
array $parentItemProcessorPool = []
8592
) {
8693
$this->stockConfiguration = $stockConfiguration;
8794
$this->stockRegistry = $stockRegistry;
8895
$this->stockItemValidator = $stockItemValidator ?: ObjectManager::getInstance()->get(StockItemValidator::class);
96+
$this->parentItemProcessorPool = $parentItemProcessorPool;
8997
}
9098

9199
/**
@@ -99,7 +107,10 @@ public function __construct(
99107
*/
100108
public function execute(EventObserver $observer)
101109
{
110+
/** @var Product $product */
102111
$product = $observer->getEvent()->getProduct();
112+
113+
/** @var Item $stockItem */
103114
$stockItem = $this->getStockItemToBeUpdated($product);
104115

105116
if ($product->getStockData() !== null) {
@@ -108,6 +119,7 @@ public function execute(EventObserver $observer)
108119
}
109120
$this->stockItemValidator->validate($product, $stockItem);
110121
$this->stockRegistry->updateStockItemBySku($product->getSku(), $stockItem);
122+
$this->processParents($product);
111123
}
112124

113125
/**
@@ -156,4 +168,17 @@ private function getStockData(Product $product)
156168
}
157169
return $stockData;
158170
}
171+
172+
/**
173+
* Process stock data for parent products
174+
*
175+
* @param Product $product
176+
* @return void
177+
*/
178+
private function processParents(Product $product)
179+
{
180+
foreach ($this->parentItemProcessorPool as $processor) {
181+
$processor->process($product);
182+
}
183+
}
159184
}
Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
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\ConfigurableProduct\Model\Inventory;
9+
10+
use Magento\ConfigurableProduct\Model\Product\Type\Configurable;
11+
use Magento\Catalog\Model\Product;
12+
use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory;
13+
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
14+
use Magento\CatalogInventory\Api\StockConfigurationInterface;
15+
use Magento\CatalogInventory\Api\Data\StockItemInterface;
16+
17+
/**
18+
* Process parent stock item
19+
*/
20+
class ParentItemProcessor
21+
{
22+
/**
23+
* @var Configurable
24+
*/
25+
private $configurableType;
26+
27+
/**
28+
* @var StockItemCriteriaInterfaceFactory
29+
*/
30+
private $criteriaInterfaceFactory;
31+
32+
/**
33+
* @var StockItemRepositoryInterface
34+
*/
35+
private $stockItemRepository;
36+
37+
/**
38+
* @var StockConfigurationInterface
39+
*/
40+
private $stockConfiguration;
41+
42+
/**
43+
* @param Configurable $configurableType
44+
* @param StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory
45+
* @param StockItemRepositoryInterface $stockItemRepository
46+
* @param StockConfigurationInterface $stockConfiguration
47+
*/
48+
public function __construct(
49+
Configurable $configurableType,
50+
StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory,
51+
StockItemRepositoryInterface $stockItemRepository,
52+
StockConfigurationInterface $stockConfiguration
53+
) {
54+
$this->configurableType = $configurableType;
55+
$this->criteriaInterfaceFactory = $criteriaInterfaceFactory;
56+
$this->stockItemRepository = $stockItemRepository;
57+
$this->stockConfiguration = $stockConfiguration;
58+
}
59+
60+
/**
61+
* Process parent products
62+
*
63+
* @param Product $product
64+
* @return void
65+
*/
66+
public function process(Product $product)
67+
{
68+
$parentIds = $this->configurableType->getParentIdsByChild($product->getId());
69+
foreach ($parentIds as $productId) {
70+
$this->processStockForParent((int)$productId);
71+
}
72+
}
73+
74+
/**
75+
* Change stock item for parent product depending on children stock items
76+
*
77+
* @param int $productId
78+
* @return void
79+
*/
80+
private function processStockForParent(int $productId)
81+
{
82+
$criteria = $this->criteriaInterfaceFactory->create();
83+
$criteria->setScopeFilter($this->stockConfiguration->getDefaultScopeId());
84+
85+
$criteria->setProductsFilter($productId);
86+
$stockItemCollection = $this->stockItemRepository->getList($criteria);
87+
$allItems = $stockItemCollection->getItems();
88+
if (empty($allItems)) {
89+
return;
90+
}
91+
$parentStockItem = array_shift($allItems);
92+
93+
$childrenIds = $this->configurableType->getChildrenIds($productId);
94+
$criteria->setProductsFilter($childrenIds);
95+
$stockItemCollection = $this->stockItemRepository->getList($criteria);
96+
$allItems = $stockItemCollection->getItems();
97+
98+
$childrenIsInStock = false;
99+
100+
foreach ($allItems as $childItem) {
101+
if ($childItem->getIsInStock() === true) {
102+
$childrenIsInStock = true;
103+
break;
104+
}
105+
}
106+
107+
if ($this->isNeedToUpdateParent($parentStockItem, $childrenIsInStock)) {
108+
$parentStockItem->setIsInStock($childrenIsInStock);
109+
$parentStockItem->setStockStatusChangedAuto(1);
110+
$this->stockItemRepository->save($parentStockItem);
111+
}
112+
}
113+
114+
/**
115+
* Check is parent item should be updated
116+
*
117+
* @param StockItemInterface $parentStockItem
118+
* @param bool $childrenIsInStock
119+
* @return bool
120+
*/
121+
private function isNeedToUpdateParent(
122+
StockItemInterface $parentStockItem,
123+
bool $childrenIsInStock
124+
): bool {
125+
return $parentStockItem->getIsInStock() !== $childrenIsInStock &&
126+
($childrenIsInStock === false || $parentStockItem->getStockStatusChangedAuto());
127+
}
128+
}

app/code/Magento/ConfigurableProduct/etc/di.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,13 @@
4343
</argument>
4444
</arguments>
4545
</type>
46+
<type name="Magento\CatalogInventory\Observer\SaveInventoryDataObserver">
47+
<arguments>
48+
<argument name="parentItemProcessorPool" xsi:type="array">
49+
<item name="configurable" xsi:type="object"> Magento\ConfigurableProduct\Model\Inventory\ParentItemProcessor</item>
50+
</argument>
51+
</arguments>
52+
</type>
4653
<type name="Magento\Sales\Model\ResourceModel\Report\Bestsellers">
4754
<arguments>
4855
<argument name="ignoredProductTypes" xsi:type="array">

0 commit comments

Comments
 (0)