1
1
<?php
2
2
/**
3
- * Copyright 2023 Adobe
3
+ * Copyright 2024 Adobe
4
4
* All Rights Reserved.
5
5
*/
6
6
declare (strict_types=1 );
7
7
8
8
namespace Magento \QuoteGraphQl \Model \CartItem ;
9
9
10
10
use Magento \Catalog \Api \Data \ProductInterface ;
11
+ use Magento \CatalogInventory \Model \StockState ;
11
12
use Magento \Catalog \Api \ProductRepositoryInterface ;
12
13
use Magento \Framework \Exception \NoSuchEntityException ;
13
14
use Magento \Quote \Model \Quote \Item ;
15
+ use Magento \CatalogInventory \Api \StockConfigurationInterface ;
14
16
15
17
/**
16
18
* Product Stock class to check availability of product
@@ -31,9 +33,13 @@ class ProductStock
31
33
* ProductStock constructor
32
34
*
33
35
* @param ProductRepositoryInterface $productRepositoryInterface
36
+ * @param StockState $stockState
37
+ * @param StockConfigurationInterface $stockConfiguration
34
38
*/
35
39
public function __construct (
36
40
private readonly ProductRepositoryInterface $ productRepositoryInterface ,
41
+ private readonly StockState $ stockState ,
42
+ private readonly StockConfigurationInterface $ stockConfiguration
37
43
) {
38
44
}
39
45
@@ -46,37 +52,30 @@ public function __construct(
46
52
*/
47
53
public function isProductAvailable (Item $ cartItem ): bool
48
54
{
49
- $ requestedQty = 0 ;
50
- $ previousQty = 0 ;
51
55
/**
52
56
* @var ProductInterface $variantProduct
53
57
* Configurable products cannot have stock, only its variants can. If the user adds a configurable product
54
58
* using its SKU and the selected options, we need to get the variant it refers to from the quote.
55
59
*/
56
60
$ variantProduct = null ;
57
61
58
- foreach ($ cartItem ->getQuote ()-> getItems () as $ item ) {
59
- if ($ item -> getItemId () !== $ cartItem -> getItemId () ) {
60
- continue ;
62
+ if ($ cartItem ->getProductType () === self :: PRODUCT_TYPE_CONFIGURABLE ) {
63
+ if ($ cartItem -> getChildren ()[ 0 ] !== null ) {
64
+ $ variantProduct = $ this -> productRepositoryInterface -> get ( $ cartItem -> getSku ()) ;
61
65
}
62
- if ($ cartItem ->getProductType () === self ::PRODUCT_TYPE_CONFIGURABLE ) {
63
- if ($ cartItem ->getChildren ()[0 ] !== null ) {
64
- $ variantProduct = $ this ->productRepositoryInterface ->get ($ item ->getSku ());
65
- }
66
- }
67
- $ requestedQty = $ item ->getQtyToAdd () ?? $ item ->getQty ();
68
- $ previousQty = $ item ->getPreviousQty () ?? 0 ;
69
66
}
67
+ $ requestedQty = $ cartItem ->getQtyToAdd () ?? $ cartItem ->getQty ();
68
+ $ previousQty = $ cartItem ->getPreviousQty () ?? 0 ;
70
69
71
70
if ($ cartItem ->getProductType () === self ::PRODUCT_TYPE_BUNDLE ) {
72
71
return $ this ->isStockAvailableBundle ($ cartItem , $ previousQty , $ requestedQty );
73
72
}
74
73
75
74
$ requiredItemQty = $ requestedQty + $ previousQty ;
76
75
if ($ variantProduct !== null ) {
77
- return $ this ->isStockQtyAvailable ($ variantProduct , $ requiredItemQty );
76
+ return $ this ->isStockQtyAvailable ($ variantProduct , $ requestedQty , $ requiredItemQty, $ previousQty );
78
77
}
79
- return $ this ->isStockQtyAvailable ($ cartItem ->getProduct (), $ requiredItemQty );
78
+ return $ this ->isStockQtyAvailable ($ cartItem ->getProduct (), $ requestedQty , $ requiredItemQty, $ previousQty );
80
79
}
81
80
82
81
/**
@@ -96,30 +95,36 @@ public function isStockAvailableBundle(Item $cartItem, int $previousQty, $reques
96
95
if ($ totalRequestedQty ) {
97
96
$ requiredItemQty = $ requiredItemQty * $ totalRequestedQty ;
98
97
}
99
- if (!$ this ->isStockQtyAvailable ($ qtyOption ->getProduct (), $ requiredItemQty )) {
98
+ if (!$ this ->isStockQtyAvailable ($ qtyOption ->getProduct (), $ requestedQty , $ requiredItemQty, $ previousQty )) {
100
99
return false ;
101
100
}
102
101
}
103
102
return true ;
104
103
}
105
104
106
105
/**
107
- * Check if product is available in stock using quantity from Catalog Inventory Stock Item
106
+ * Check if product is available in stock
108
107
*
109
108
* @param ProductInterface $product
109
+ * @param float $itemQty
110
110
* @param float $requiredQuantity
111
- * @throws NoSuchEntityException
111
+ * @param float $prevQty
112
112
* @return bool
113
113
*/
114
- private function isStockQtyAvailable (ProductInterface $ product , float $ requiredQuantity ): bool
115
- {
116
- $ stockItem = $ product ->getExtensionAttributes ()->getStockItem ();
117
- if ($ stockItem === null ) {
118
- return true ;
119
- }
120
- if ((int ) $ stockItem ->getProductId () !== (int ) $ product ->getId ()) {
121
- throw new NoSuchEntityException (__ ('Stock item \'s product ID does not match requested product ID ' ));
122
- }
123
- return $ stockItem ->getQty () >= $ requiredQuantity ;
114
+ private function isStockQtyAvailable (
115
+ ProductInterface $ product ,
116
+ float $ itemQty ,
117
+ float $ requiredQuantity ,
118
+ float $ prevQty
119
+ ): bool {
120
+ $ stockStatus = $ this ->stockState ->checkQuoteItemQty (
121
+ $ product ->getId (),
122
+ $ itemQty ,
123
+ $ requiredQuantity ,
124
+ $ prevQty ,
125
+ $ this ->stockConfiguration ->getDefaultScopeId ()
126
+ );
127
+
128
+ return ((bool ) $ stockStatus ->getHasError ()) === false ;
124
129
}
125
130
}
0 commit comments