Skip to content

Commit 43b5806

Browse files
authored
LYNX-485 - Bundle products still shows "IN_STOCK" when one of its bundled product out of stock fix (#280)
1 parent 5fabb9d commit 43b5806

File tree

2 files changed

+329
-55
lines changed

2 files changed

+329
-55
lines changed

app/code/Magento/CatalogInventoryGraphQl/Model/Resolver/StockStatusProvider.php

Lines changed: 76 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,51 @@
88
namespace Magento\CatalogInventoryGraphQl\Model\Resolver;
99

1010
use Magento\Catalog\Api\Data\ProductInterface;
11+
use Magento\Catalog\Api\ProductRepositoryInterface;
1112
use Magento\CatalogInventory\Api\Data\StockStatusInterface;
1213
use Magento\CatalogInventory\Api\StockStatusRepositoryInterface;
1314
use Magento\Framework\Exception\LocalizedException;
15+
use Magento\Framework\Exception\NoSuchEntityException;
1416
use Magento\Framework\GraphQl\Schema\Type\ResolveInfo;
1517
use Magento\Framework\GraphQl\Config\Element\Field;
1618
use Magento\Framework\GraphQl\Query\ResolverInterface;
19+
use Magento\Quote\Model\Quote\Item;
1720

1821
/**
1922
* @inheritdoc
2023
*/
2124
class StockStatusProvider implements ResolverInterface
2225
{
2326
/**
24-
* @var StockStatusRepositoryInterface
27+
* Bundle product type code
2528
*/
26-
private $stockStatusRepository;
29+
private const PRODUCT_TYPE_BUNDLE = "bundle";
2730

2831
/**
32+
* Configurable product type code
33+
*/
34+
private const PRODUCT_TYPE_CONFIGURABLE = "configurable";
35+
36+
/**
37+
* In Stock return code
38+
*/
39+
private const IN_STOCK = "IN_STOCK";
40+
41+
/**
42+
* Out of Stock return code
43+
*/
44+
private const OUT_OF_STOCK = "OUT_OF_STOCK";
45+
46+
/**
47+
* StockStatusProvider Constructor
48+
*
2949
* @param StockStatusRepositoryInterface $stockStatusRepository
50+
* @param ProductRepositoryInterface $productRepositoryInterface
3051
*/
31-
public function __construct(StockStatusRepositoryInterface $stockStatusRepository)
32-
{
33-
$this->stockStatusRepository = $stockStatusRepository;
52+
public function __construct(
53+
private readonly StockStatusRepositoryInterface $stockStatusRepository,
54+
private readonly ProductRepositoryInterface $productRepositoryInterface,
55+
) {
3456
}
3557

3658
/**
@@ -41,13 +63,58 @@ public function resolve(Field $field, $context, ResolveInfo $info, array $value
4163
if (!array_key_exists('model', $value) || !$value['model'] instanceof ProductInterface) {
4264
throw new LocalizedException(__('"model" value should be specified'));
4365
}
66+
/** @var Item $cartItem */
67+
$cartItem = $value['cart_item'] ?? [];
68+
if (!$cartItem instanceof Item) {
69+
$product = $value['model'];
70+
$stockStatus = $this->stockStatusRepository->get($product->getId());
4471

45-
/* @var $product ProductInterface */
46-
$product = $value['model'];
72+
return ((int)$stockStatus->getStockStatus()) ? self::IN_STOCK : self::OUT_OF_STOCK;
73+
}
74+
75+
if ($cartItem->getProductType() === self::PRODUCT_TYPE_BUNDLE) {
76+
return $this->getBundleProductStockStatus($cartItem);
77+
}
4778

79+
$product = $this->getVariantProduct($cartItem) ?? $cartItem->getProduct();
4880
$stockStatus = $this->stockStatusRepository->get($product->getId());
49-
$productStockStatus = (int)$stockStatus->getStockStatus();
5081

51-
return $productStockStatus === StockStatusInterface::STATUS_IN_STOCK ? 'IN_STOCK' : 'OUT_OF_STOCK';
82+
return ((int)$stockStatus->getStockStatus()) ? self::IN_STOCK : self::OUT_OF_STOCK;
83+
}
84+
85+
/**
86+
* Get stock status of added bundle options
87+
*
88+
* @param Item $cartItem
89+
* @return string
90+
*/
91+
private function getBundleProductStockStatus(Item $cartItem): string
92+
{
93+
$qtyOptions = $cartItem->getQtyOptions();
94+
foreach ($qtyOptions as $qtyOption) {
95+
$stockStatus = $this->stockStatusRepository->get($qtyOption->getProduct()->getId());
96+
if (!(int)$stockStatus->getStockStatus()) {
97+
return self::OUT_OF_STOCK;
98+
}
99+
}
100+
101+
return self::IN_STOCK;
102+
}
103+
104+
/**
105+
* Returns variant product if available
106+
*
107+
* @param Item $cartItem
108+
* @return ProductInterface|null
109+
* @throws NoSuchEntityException
110+
*/
111+
private function getVariantProduct(Item $cartItem): ?ProductInterface
112+
{
113+
if ($cartItem->getProductType() === self::PRODUCT_TYPE_CONFIGURABLE) {
114+
if ($cartItem->getChildren()[0] !== null) {
115+
return $this->productRepositoryInterface->get($cartItem->getSku());
116+
}
117+
}
118+
return null;
52119
}
53120
}

0 commit comments

Comments
 (0)