Skip to content

Commit 0d4e154

Browse files
MC-37718: Grouped product remains In Stock On Mass Update
1 parent 1ca6ef5 commit 0d4e154

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed
Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
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\GroupedProduct\Model\Inventory;
9+
10+
use Magento\Catalog\Api\Data\ProductInterface;
11+
use Magento\CatalogInventory\Api\Data\StockItemInterface;
12+
use Magento\CatalogInventory\Api\StockConfigurationInterface;
13+
use Magento\CatalogInventory\Api\StockItemCriteriaInterfaceFactory;
14+
use Magento\CatalogInventory\Api\StockItemRepositoryInterface;
15+
use Magento\Framework\App\ResourceConnection;
16+
use Magento\Framework\EntityManager\MetadataPool;
17+
use Magento\GroupedProduct\Model\Product\Type\Grouped;
18+
use Magento\GroupedProduct\Model\ResourceModel\Product\Link;
19+
20+
/**
21+
* Change stock status of grouped product by child product id
22+
*/
23+
class ChangeParentStockStatus
24+
{
25+
/**
26+
* @var Grouped
27+
*/
28+
private $groupedType;
29+
30+
/**
31+
* @var StockItemRepositoryInterface
32+
*/
33+
private $stockItemRepository;
34+
35+
/**
36+
* @var StockConfigurationInterface
37+
*/
38+
private $stockConfiguration;
39+
40+
/**
41+
* @var StockItemCriteriaInterfaceFactory
42+
*/
43+
private $criteriaInterfaceFactory;
44+
45+
/**
46+
* @var ResourceConnection
47+
*/
48+
private $resource;
49+
50+
/**
51+
* Product metadata pool
52+
*
53+
* @var MetadataPool
54+
*/
55+
private $metadataPool;
56+
57+
/**
58+
* @param Grouped $groupedType
59+
* @param StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory
60+
* @param StockItemRepositoryInterface $stockItemRepository
61+
* @param StockConfigurationInterface $stockConfiguration
62+
* @param ResourceConnection $resource
63+
* @param MetadataPool $metadataPool
64+
*/
65+
public function __construct(
66+
Grouped $groupedType,
67+
StockItemCriteriaInterfaceFactory $criteriaInterfaceFactory,
68+
StockItemRepositoryInterface $stockItemRepository,
69+
StockConfigurationInterface $stockConfiguration,
70+
ResourceConnection $resource,
71+
MetadataPool $metadataPool
72+
) {
73+
$this->groupedType = $groupedType;
74+
$this->criteriaInterfaceFactory = $criteriaInterfaceFactory;
75+
$this->stockConfiguration = $stockConfiguration;
76+
$this->stockItemRepository = $stockItemRepository;
77+
$this->resource = $resource;
78+
$this->metadataPool = $metadataPool;
79+
}
80+
81+
/**
82+
* Change stock item for parent product depending on children stock items
83+
*
84+
* @param int $productId
85+
* @return void
86+
*/
87+
public function execute(int $productId): void
88+
{
89+
$parentIds = $this->getParentEntityIdsByChild($productId);
90+
foreach ($parentIds as $productId) {
91+
$this->changeParentStockStatus((int)$productId);
92+
}
93+
}
94+
95+
/**
96+
* Change stock status of grouped product
97+
*
98+
* @param int $productId
99+
* @return void
100+
*/
101+
private function changeParentStockStatus(int $productId): void
102+
{
103+
$criteria = $this->criteriaInterfaceFactory->create();
104+
$criteria->setScopeFilter($this->stockConfiguration->getDefaultScopeId());
105+
$criteria->setProductsFilter($productId);
106+
$stockItemCollection = $this->stockItemRepository->getList($criteria);
107+
$allItems = $stockItemCollection->getItems();
108+
if (empty($allItems)) {
109+
return;
110+
}
111+
$parentStockItem = array_shift($allItems);
112+
$groupedChildrenIds = $this->groupedType->getChildrenIds($productId);
113+
$criteria->setProductsFilter($groupedChildrenIds);
114+
$stockItemCollection = $this->stockItemRepository->getList($criteria);
115+
$allItems = $stockItemCollection->getItems();
116+
117+
$groupedChildrenIsInStock = false;
118+
119+
foreach ($allItems as $childItem) {
120+
if ($childItem->getIsInStock() === true) {
121+
$groupedChildrenIsInStock = true;
122+
break;
123+
}
124+
}
125+
126+
if ($this->isNeedToUpdateParent($parentStockItem, $groupedChildrenIsInStock)) {
127+
$parentStockItem->setIsInStock($groupedChildrenIsInStock);
128+
$parentStockItem->setStockStatusChangedAuto(1);
129+
$this->stockItemRepository->save($parentStockItem);
130+
}
131+
}
132+
133+
/**
134+
* Check is parent item should be updated
135+
*
136+
* @param StockItemInterface $parentStockItem
137+
* @param bool $childrenIsInStock
138+
* @return bool
139+
*/
140+
private function isNeedToUpdateParent(StockItemInterface $parentStockItem, bool $childrenIsInStock): bool
141+
{
142+
return $parentStockItem->getIsInStock() !== $childrenIsInStock &&
143+
($childrenIsInStock === false || $parentStockItem->getStockStatusChangedAuto());
144+
}
145+
146+
/**
147+
* Retrieve parent ids array by child id
148+
*
149+
* @param int $childId
150+
* @return array
151+
*/
152+
private function getParentEntityIdsByChild(int $childId): array
153+
{
154+
$select = $this->resource->getConnection()
155+
->select()
156+
->from(['l' => $this->resource->getTableName('catalog_product_link')], [])
157+
->join(
158+
['e' => $this->resource->getTableName('catalog_product_entity')],
159+
'e.' .
160+
$this->metadataPool->getMetadata(ProductInterface::class)->getLinkField() . ' = l.product_id',
161+
['e.entity_id']
162+
)
163+
->where('l.linked_product_id = ?', $childId)
164+
->where(
165+
'link_type_id = ?',
166+
Link::LINK_TYPE_GROUPED
167+
);
168+
169+
return $this->resource->getConnection()->fetchCol($select);
170+
}
171+
}

0 commit comments

Comments
 (0)