Skip to content

Commit

Permalink
is_available attribute in CartItemInterface returns true even when sa…
Browse files Browse the repository at this point in the history
…lable stock is lower than the quantity of the product (#231)
  • Loading branch information
bl4de authored and glo74186 committed May 7, 2024
1 parent 3cc3991 commit 21f483a
Showing 1 changed file with 25 additions and 28 deletions.
53 changes: 25 additions & 28 deletions app/code/Magento/QuoteGraphQl/Model/CartItem/ProductStock.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@

use Magento\Catalog\Api\Data\ProductInterface;
use Magento\Catalog\Api\ProductRepositoryInterface;
use Magento\CatalogInventory\Api\StockStatusRepositoryInterface;
use Magento\Framework\Exception\NoSuchEntityException;
use Magento\Quote\Model\Quote\Item;

Expand All @@ -28,20 +27,13 @@ class ProductStock
*/
private const PRODUCT_TYPE_CONFIGURABLE = "configurable";

/**
* Simple product type code
*/
private const PRODUCT_TYPE_SIMPLE = "simple";

/**
* ProductStock constructor
*
* @param StockStatusRepositoryInterface $stockStatusRepository
* @param ProductRepositoryInterface $productRepositoryInterface
*/
public function __construct(
private readonly StockStatusRepositoryInterface $stockStatusRepository,
private readonly ProductRepositoryInterface $productRepositoryInterface
private readonly ProductRepositoryInterface $productRepositoryInterface,
) {
}

Expand All @@ -57,7 +49,7 @@ public function isProductAvailable(Item $cartItem): bool
$requestedQty = 0;
$previousQty = 0;
/**
* @var ProductInterface $variantProduct
* @var ProductInterface $variantProduct
* Configurable products cannot have stock, only its variants can. If the user adds a configurable product
* using its SKU and the selected options, we need to get the variant it refers to from the quote.
*/
Expand All @@ -81,24 +73,10 @@ public function isProductAvailable(Item $cartItem): bool
}

$requiredItemQty = $requestedQty + $previousQty;
$productId = (int) $cartItem->getProduct()->getId();
if ($variantProduct !== null) {
$productId = (int)$variantProduct->getId();
return $this->isStockQtyAvailable($variantProduct, $requiredItemQty);
}
return $this->isStockAvailable($productId, $requiredItemQty);
}

/**
* Check if is required product available in stock
*
* @param int $productId
* @param float $requiredQuantity
* @return bool
*/
private function isStockAvailable(int $productId, float $requiredQuantity): bool
{
$stock = $this->stockStatusRepository->get($productId);
return $stock->getQty() >= $requiredQuantity;
return $this->isStockQtyAvailable($cartItem->getProduct(), $requiredItemQty);
}

/**
Expand All @@ -114,15 +92,34 @@ public function isStockAvailableBundle(Item $cartItem, int $previousQty, $reques
$qtyOptions = $cartItem->getQtyOptions();
$totalRequestedQty = $previousQty + $requestedQty;
foreach ($qtyOptions as $qtyOption) {
$productId = (int)$qtyOption->getProductId();
$requiredItemQty = $qtyOption->getValue();
if ($totalRequestedQty) {
$requiredItemQty = $requiredItemQty * $totalRequestedQty;
}
if (!$this->isStockAvailable($productId, $requiredItemQty)) {
if (!$this->isStockQtyAvailable($qtyOption->getProduct(), $requiredItemQty)) {
return false;
}
}
return true;
}

/**
* Check if product is available in stock using quantity from Catalog Inventory Stock Item
*
* @param ProductInterface $product
* @param float $requiredQuantity
* @throws NoSuchEntityException
* @return bool
*/
private function isStockQtyAvailable(ProductInterface $product, float $requiredQuantity): bool
{
$stockItem = $product->getExtensionAttributes()->getStockItem();
if ($stockItem === null) {
return true;
}
if ((int) $stockItem->getProductId() !== (int) $product->getId()) {
throw new NoSuchEntityException(__('Stock item\'s product ID does not match requested product ID'));
}
return $stockItem->getQty() >= $requiredQuantity;
}
}

0 comments on commit 21f483a

Please sign in to comment.