Search

Mar 29, 2023

Viewing customer shopping cart in admin shows all products in catalog when there is no active quote

Steps to reproduce: 

View a customer in the admin for whom there is no active quote. 

Click on the 'Shopping Cart' tab. 

Expected result: Nothing shows in the grid, as there is no active quote for which to show items.

Actual result: All products added to Magento show, giving the false impression that this is the contents of the customer's basket, whereas actually it's the contents of the catalog.


Solution 1: 

We're using Magento ver 2.3.4-p2, and found a fix in 2.4.x: 26437


Solution 2: 

Follow the patch for m2.3.5

diff --git a/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php b/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
index 3709f4914c4..ec4bd93ee4f 100644
--- a/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
+++ b/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
@@ -105,14 +105,13 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
     {
         $quote = $this->getQuote();
 
-        if ($quote) {
+        if ($quote && $quote->getId()) {
             $collection = $quote->getItemsCollection(false);
+            $collection->addFieldToFilter('parent_item_id', ['null' => true]);
         } else {
             $collection = $this->_dataCollectionFactory->create();
         }
 
-        $collection->addFieldToFilter('parent_item_id', ['null' => true]);
-
         $this->setCollection($collection);
 
         return parent::_prepareCollection();


Solution 3: 

Follow the patch for m2.3.5

diff --git a/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php b/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
index 3709f4914c4..656a78d1165 100644
--- a/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
+++ b/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
@@ -5,37 +5,51 @@
  */
 namespace Magento\Customer\Block\Adminhtml\Edit\Tab;
 
-use Magento\Catalog\Model\Product;
+use Magento\Backend\Block\Template\Context;
+use Magento\Backend\Block\Widget\Form;
+use Magento\Backend\Block\Widget\Grid\Extended;
+use Magento\Backend\Helper\Data;
+use Magento\Customer\Block\Adminhtml\Edit\Tab\View\Grid\Renderer\Item;
+use Magento\Customer\Block\Adminhtml\Grid\Renderer\Multiaction;
 use Magento\Customer\Controller\RegistryConstants;
-use Magento\Directory\Model\Currency;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Data\CollectionFactory;
+use Magento\Framework\Data\FormFactory;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\Registry;
+use Magento\Quote\Api\CartRepositoryInterface;
+use Magento\Quote\Model\Quote;
+use Magento\Quote\Model\QuoteFactory;
+use Magento\Store\Model\System\Store as SystemStore;
 
 /**
  * Adminhtml customer orders grid block
  *
  * @api
  * @since 100.0.2
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
-class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
+class Cart extends Extended
 {
     /**
      * Core registry
      *
-     * @var \Magento\Framework\Registry
+     * @var Registry
      */
     protected $_coreRegistry = null;
 
     /**
-     * @var \Magento\Framework\Data\CollectionFactory
+     * @var CollectionFactory
      */
     protected $_dataCollectionFactory;
 
     /**
-     * @var \Magento\Quote\Api\CartRepositoryInterface
+     * @var CartRepositoryInterface
      */
     protected $quoteRepository;
 
     /**
-     * @var \Magento\Quote\Model\Quote
+     * @var Quote
      */
     protected $quote = null;
 
@@ -45,32 +59,46 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
     protected $_parentTemplate;
 
     /**
-     * @var \Magento\Quote\Model\QuoteFactory
+     * @var QuoteFactory
      */
     protected $quoteFactory;
+    /**
+     * @var SystemStore
+     */
+    private $systemStore;
+    /**
+     * @var FormFactory
+     */
+    private $formFactory;
 
     /**
-     * @param \Magento\Backend\Block\Template\Context $context
-     * @param \Magento\Backend\Helper\Data $backendHelper
-     * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository
-     * @param \Magento\Framework\Data\CollectionFactory $dataCollectionFactory
-     * @param \Magento\Framework\Registry $coreRegistry
-     * @param \Magento\Quote\Model\QuoteFactory $quoteFactory
+     * @param Context $context
+     * @param Data $backendHelper
+     * @param CartRepositoryInterface $quoteRepository
+     * @param CollectionFactory $dataCollectionFactory
+     * @param Registry $coreRegistry
+     * @param QuoteFactory $quoteFactory
      * @param array $data
+     * @param SystemStore|null $systemStore
+     * @param FormFactory|null $formFactory
      */
     public function __construct(
-        \Magento\Backend\Block\Template\Context $context,
-        \Magento\Backend\Helper\Data $backendHelper,
-        \Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
-        \Magento\Framework\Data\CollectionFactory $dataCollectionFactory,
-        \Magento\Framework\Registry $coreRegistry,
-        \Magento\Quote\Model\QuoteFactory $quoteFactory,
-        array $data = []
+        Context $context,
+        Data $backendHelper,
+        CartRepositoryInterface $quoteRepository,
+        CollectionFactory $dataCollectionFactory,
+        Registry $coreRegistry,
+        QuoteFactory $quoteFactory,
+        array $data = [],
+        ?SystemStore $systemStore = null,
+        ?FormFactory $formFactory = null
     ) {
         $this->_dataCollectionFactory = $dataCollectionFactory;
         $this->_coreRegistry = $coreRegistry;
         $this->quoteRepository = $quoteRepository;
         $this->quoteFactory = $quoteFactory;
+        $this->systemStore = $systemStore ?? ObjectManager::getInstance()->get(SystemStore::class);
+        $this->formFactory = $formFactory ?? ObjectManager::getInstance()->get(FormFactory::class);
         parent::__construct($context, $backendHelper, $data);
     }
 
@@ -92,8 +120,11 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
      */
     protected function _prepareGrid()
     {
-        $this->setId('customer_cart_grid' . $this->getWebsiteId());
+        $this->setId('customer_cart_grid');
         parent::_prepareGrid();
+        if (!$this->_storeManager->isSingleStoreMode()) {
+            $this->prepareWebsiteFilter();
+        }
     }
 
     /**
@@ -105,14 +136,13 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
     {
         $quote = $this->getQuote();
 
-        if ($quote) {
+        if ($quote && $quote->getId()) {
             $collection = $quote->getItemsCollection(false);
+            $collection->addFieldToFilter('parent_item_id', ['null' => true]);
         } else {
             $collection = $this->_dataCollectionFactory->create();
         }
 
-        $collection->addFieldToFilter('parent_item_id', ['null' => true]);
-
         $this->setCollection($collection);
 
         return parent::_prepareCollection();
@@ -130,7 +160,7 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
             [
                 'header' => __('Product'),
                 'index' => 'name',
-                'renderer' => \Magento\Customer\Block\Adminhtml\Edit\Tab\View\Grid\Renderer\Item::class
+                'renderer' => Item::class
             ]
         );
 
@@ -168,7 +198,7 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
             [
                 'header' => __('Action'),
                 'index' => 'quote_item_id',
-                'renderer' => \Magento\Customer\Block\Adminhtml\Grid\Renderer\Multiaction::class,
+                'renderer' => Multiaction::class,
                 'filter' => false,
                 'sortable' => false,
                 'actions' => [
@@ -246,10 +276,59 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
 
             try {
                 $this->quote = $this->quoteRepository->getForCustomer($customerId, $storeIds);
-            } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
+            } catch (NoSuchEntityException $e) {
                 $this->quote = $this->quoteFactory->create()->setSharedStoreIds($storeIds);
             }
         }
         return $this->quote;
     }
+
+    /**
+     * Add website filter block to the layout
+     *
+     * @return void
+     */
+    private function prepareWebsiteFilter(): void
+    {
+        $form = $this->formFactory->create();
+        $form->addField(
+            'website_filter',
+            'select',
+            [
+                'name' => 'website_id',
+                'values' => $this->systemStore->getWebsiteOptionHash(),
+                'value' => $this->getWebsiteId() ?? $this->_storeManager->getWebsite()->getId(),
+                'no_span' => true,
+                'onchange' => "{$this->getJsObjectName()}.loadByElement(this);",
+            ]
+        );
+        /**
+         * @var Form $formWidget
+         */
+        $formWidget = $this->getLayout()->createBlock(Form::class);
+        $formWidget->setForm($form);
+        $formWidget->setTemplate('Magento_Customer::tab/cart_website_filter_form.phtml');
+        $this->setChild(
+            'website_filter_block',
+            $formWidget
+        );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function getMainButtonsHtml()
+    {
+        return $this->getWebsiteFilterHtml() . parent::getMainButtonsHtml();
+    }
+
+    /**
+     * Generate website filter
+     *
+     * @return string
+     */
+    private function getWebsiteFilterHtml(): string
+    {
+        return $this->getChildHtml('website_filter_block');
+    }
 }
diff --git a/vendor/magento/module-customer/Controller/Adminhtml/Index/Cart.php b/vendor/magento/module-customer/Controller/Adminhtml/Index/Cart.php
index 4008635cd7c..910f4e94b90 100644
--- a/vendor/magento/module-customer/Controller/Adminhtml/Index/Cart.php
+++ b/vendor/magento/module-customer/Controller/Adminhtml/Index/Cart.php
@@ -5,84 +5,116 @@
  */
 namespace Magento\Customer\Controller\Adminhtml\Index;
 
+use Magento\Backend\App\Action\Context;
+use Magento\Backend\Model\View\Result\ForwardFactory;
 use Magento\Customer\Api\AccountManagementInterface;
 use Magento\Customer\Api\AddressRepositoryInterface;
 use Magento\Customer\Api\CustomerRepositoryInterface;
 use Magento\Customer\Api\Data\AddressInterfaceFactory;
 use Magento\Customer\Api\Data\CustomerInterfaceFactory;
+use Magento\Customer\Controller\Adminhtml\Index as BaseAction;
+use Magento\Customer\Helper\View;
 use Magento\Customer\Model\Address\Mapper;
-use Magento\Framework\DataObjectFactory as ObjectFactory;
+use Magento\Customer\Model\AddressFactory;
+use Magento\Customer\Model\CustomerFactory;
+use Magento\Customer\Model\Metadata\FormFactory;
 use Magento\Framework\Api\DataObjectHelper;
+use Magento\Framework\Api\ExtensibleDataObjectConverter;
+use Magento\Framework\App\Action\HttpGetActionInterface;
+use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
+use Magento\Framework\App\Response\Http\FileFactory;
+use Magento\Framework\Controller\Result\JsonFactory;
+use Magento\Framework\DataObjectFactory as ObjectFactory;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\Math\Random;
+use Magento\Framework\Reflection\DataObjectProcessor;
+use Magento\Framework\Registry;
+use Magento\Framework\View\Result\Layout;
+use Magento\Framework\View\Result\LayoutFactory;
+use Magento\Framework\View\Result\PageFactory;
+use Magento\Newsletter\Model\SubscriberFactory;
+use Magento\Quote\Api\CartRepositoryInterface;
+use Magento\Quote\Model\Quote;
+use Magento\Quote\Model\QuoteFactory;
+use Magento\Store\Model\StoreManagerInterface;
 
 /**
+ * Admin customer shopping cart controller
+ *
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  * @deprecated 101.0.0
  */
-class Cart extends \Magento\Customer\Controller\Adminhtml\Index
+class Cart extends BaseAction implements HttpGetActionInterface, HttpPostActionInterface
 {
     /**
-     * @var \Magento\Quote\Model\QuoteFactory
+     * @var QuoteFactory
      */
     private $quoteFactory;
+    /**
+     * @var StoreManagerInterface
+     */
+    private $storeManager;
 
     /**
      * Constructor
      *
-     * @param \Magento\Backend\App\Action\Context $context
-     * @param \Magento\Framework\Registry $coreRegistry
-     * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory
-     * @param \Magento\Customer\Model\CustomerFactory $customerFactory
-     * @param \Magento\Customer\Model\AddressFactory $addressFactory
-     * @param \Magento\Customer\Model\Metadata\FormFactory $formFactory
-     * @param \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory
-     * @param \Magento\Customer\Helper\View $viewHelper
-     * @param \Magento\Framework\Math\Random $random
+     * @param Context $context
+     * @param Registry $coreRegistry
+     * @param FileFactory $fileFactory
+     * @param CustomerFactory $customerFactory
+     * @param AddressFactory $addressFactory
+     * @param FormFactory $formFactory
+     * @param SubscriberFactory $subscriberFactory
+     * @param View $viewHelper
+     * @param Random $random
      * @param CustomerRepositoryInterface $customerRepository
-     * @param \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter
+     * @param ExtensibleDataObjectConverter $extensibleDataObjectConverter
      * @param Mapper $addressMapper
      * @param AccountManagementInterface $customerAccountManagement
      * @param AddressRepositoryInterface $addressRepository
      * @param CustomerInterfaceFactory $customerDataFactory
      * @param AddressInterfaceFactory $addressDataFactory
      * @param \Magento\Customer\Model\Customer\Mapper $customerMapper
-     * @param \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor
+     * @param DataObjectProcessor $dataObjectProcessor
      * @param DataObjectHelper $dataObjectHelper
      * @param ObjectFactory $objectFactory
      * @param \Magento\Framework\View\LayoutFactory $layoutFactory
-     * @param \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory
-     * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
-     * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory
-     * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
-     * @param \Magento\Quote\Model\QuoteFactory|null $quoteFactory
+     * @param LayoutFactory $resultLayoutFactory
+     * @param PageFactory $resultPageFactory
+     * @param ForwardFactory $resultForwardFactory
+     * @param JsonFactory $resultJsonFactory
+     * @param QuoteFactory|null $quoteFactory
+     * @param StoreManagerInterface|null $storeManager
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
-        \Magento\Backend\App\Action\Context $context,
-        \Magento\Framework\Registry $coreRegistry,
-        \Magento\Framework\App\Response\Http\FileFactory $fileFactory,
-        \Magento\Customer\Model\CustomerFactory $customerFactory,
-        \Magento\Customer\Model\AddressFactory $addressFactory,
-        \Magento\Customer\Model\Metadata\FormFactory $formFactory,
-        \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory,
-        \Magento\Customer\Helper\View $viewHelper,
-        \Magento\Framework\Math\Random $random,
+        Context $context,
+        Registry $coreRegistry,
+        FileFactory $fileFactory,
+        CustomerFactory $customerFactory,
+        AddressFactory $addressFactory,
+        FormFactory $formFactory,
+        SubscriberFactory $subscriberFactory,
+        View $viewHelper,
+        Random $random,
         CustomerRepositoryInterface $customerRepository,
-        \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter,
+        ExtensibleDataObjectConverter $extensibleDataObjectConverter,
         Mapper $addressMapper,
         AccountManagementInterface $customerAccountManagement,
         AddressRepositoryInterface $addressRepository,
         CustomerInterfaceFactory $customerDataFactory,
         AddressInterfaceFactory $addressDataFactory,
         \Magento\Customer\Model\Customer\Mapper $customerMapper,
-        \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor,
+        DataObjectProcessor $dataObjectProcessor,
         DataObjectHelper $dataObjectHelper,
         ObjectFactory $objectFactory,
         \Magento\Framework\View\LayoutFactory $layoutFactory,
-        \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory,
-        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
-        \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory,
-        \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
-        \Magento\Quote\Model\QuoteFactory $quoteFactory = null
+        LayoutFactory $resultLayoutFactory,
+        PageFactory $resultPageFactory,
+        ForwardFactory $resultForwardFactory,
+        JsonFactory $resultJsonFactory,
+        QuoteFactory $quoteFactory = null,
+        ?StoreManagerInterface $storeManager = null
     ) {
         parent::__construct(
             $context,
@@ -111,13 +143,14 @@ class Cart extends \Magento\Customer\Controller\Adminhtml\Index
             $resultForwardFactory,
             $resultJsonFactory
         );
-        $this->quoteFactory = $quoteFactory ?: $this->_objectManager->get(\Magento\Quote\Model\QuoteFactory::class);
+        $this->quoteFactory = $quoteFactory ?: $this->_objectManager->get(QuoteFactory::class);
+        $this->storeManager = $storeManager ?? $this->_objectManager->get(StoreManagerInterface::class);
     }
 
     /**
      * Handle and then get cart grid contents
      *
-     * @return \Magento\Framework\View\Result\Layout
+     * @return Layout
      */
     public function execute()
     {
@@ -127,16 +160,17 @@ class Cart extends \Magento\Customer\Controller\Adminhtml\Index
         // delete an item from cart
         $deleteItemId = $this->getRequest()->getPost('delete');
         if ($deleteItemId) {
-            /** @var \Magento\Quote\Api\CartRepositoryInterface $quoteRepository */
-            $quoteRepository = $this->_objectManager->create(\Magento\Quote\Api\CartRepositoryInterface::class);
-            /** @var \Magento\Quote\Model\Quote $quote */
+            /** @var CartRepositoryInterface $quoteRepository */
+            $quoteRepository = $this->_objectManager->create(CartRepositoryInterface::class);
+            /** @var Quote $quote */
             try {
-                $quote = $quoteRepository->getForCustomer($customerId);
-            } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
+                $storeIds = $this->storeManager->getWebsite($websiteId)->getStoreIds();
+                $quote = $quoteRepository->getForCustomer($customerId, $storeIds);
+            } catch (NoSuchEntityException $e) {
                 $quote = $this->quoteFactory->create();
             }
             $quote->setWebsite(
-                $this->_objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)->getWebsite($websiteId)
+                $this->storeManager->getWebsite($websiteId)
             );
             $item = $quote->getItemById($deleteItemId);
             if ($item && $item->getId()) {
diff --git a/vendor/magento/module-customer/view/adminhtml/templates/tab/cart_website_filter_form.phtml b/vendor/magento/module-customer/view/adminhtml/templates/tab/cart_website_filter_form.phtml
new file mode 100644
index 00000000000..ec903fa978f
--- /dev/null
+++ b/vendor/magento/module-customer/view/adminhtml/templates/tab/cart_website_filter_form.phtml
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/** @var $block \Magento\Backend\Block\Widget\Form */
+?>
+<?= $block->getFormHtml() ?>
+<?= $block->getChildHtml('form_after') ?>


SOLUTION 4:

diff --git a/vendor/magento/module-configurable-product/Model/Product/Type/Configurable.php b/vendor/magento/module-configurable-product/Model/Product/Type/Configurable.php
index 1cc08ee961e..384b1ffd20d 100644
--- a/vendor/magento/module-configurable-product/Model/Product/Type/Configurable.php
+++ b/vendor/magento/module-configurable-product/Model/Product/Type/Configurable.php
@@ -35,7 +35,7 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
     /**
      * Product type code
      */
-    const TYPE_CODE = 'configurable';
+    public const TYPE_CODE = 'configurable';
 
     /**
      * Cache key for Used Product Attribute Ids
@@ -102,51 +102,45 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
      */
     protected $_canConfigure = true;
 
+    /**
+     * Local cache
+     *
+     * @var array
+     */
+    protected $isSaleableBySku = [];
+
     /**
      * @var \Magento\Framework\App\Config\ScopeConfigInterface
      */
     protected $_scopeConfig;
 
     /**
-     * Catalog product type configurable
-     *
      * @var \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable
      */
     protected $_catalogProductTypeConfigurable;
 
     /**
-     * Attribute collection factory
-     *
-     * @var
-     * \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\CollectionFactory
+     * @var \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Attribute\CollectionFactory
      */
     protected $_attributeCollectionFactory;
 
     /**
-     * Product collection factory
-     *
      * @var \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\CollectionFactory
      */
     protected $_productCollectionFactory;
 
     /**
-     * Configurable attribute factory
-     *
      * @var \Magento\ConfigurableProduct\Model\Product\Type\Configurable\AttributeFactory
      * @since 100.1.0
      */
     protected $configurableAttributeFactory;
 
     /**
-     * Eav attribute factory
-     *
      * @var \Magento\Catalog\Model\ResourceModel\Eav\AttributeFactory
      */
     protected $_eavAttributeFactory;
 
     /**
-     * Type configurable factory
-     *
      * @var \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\ConfigurableFactory
      * @since 100.1.0
      */
@@ -183,8 +177,6 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
     private $customerSession;
 
     /**
-     * Product factory
-     *
      * @var ProductInterfaceFactory
      */
     private $productFactory;
@@ -585,7 +577,7 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
      * @param  \Magento\Catalog\Model\Product $product
      * @return \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection
      */
-    public function getUsedProductCollection($product)
+    protected function getLinkedProductCollection($product)
     {
         $collection = $this->_productCollectionFactory->create()->setFlag(
             'product_children',
@@ -600,6 +592,17 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
         return $collection;
     }
 
+    /**
+     * Retrieve related products collection. Extension point for listing
+     *
+     * @param  \Magento\Catalog\Model\Product $product
+     * @return \Magento\ConfigurableProduct\Model\ResourceModel\Product\Type\Configurable\Product\Collection
+     */
+    public function getUsedProductCollection($product)
+    {
+        return $this->getLinkedProductCollection($product);
+    }
+
     /**
      * Before save process
      *
@@ -744,15 +747,30 @@ class Configurable extends \Magento\Catalog\Model\Product\Type\AbstractType
      */
     public function isSalable($product)
     {
+        $storeId = $this->getStoreFilter($product);
+        if ($storeId instanceof \Magento\Store\Model\Store) {
+            $storeId = $storeId->getId();
+        }
+        if ($storeId === null && $product->getStoreId()) {
+            $storeId = $product->getStoreId();
+        }
+
+        $sku = $product->getSku();
+        if (isset($this->isSaleableBySku[$storeId][$sku])) {
+            return $this->isSaleableBySku[$storeId][$sku];
+        }
+
         $salable = parent::isSalable($product);
 
         if ($salable !== false) {
-            $collection = $this->getUsedProductCollection($product);
-            $collection->addStoreFilter($this->getStoreFilter($product));
+            $collection = $this->getLinkedProductCollection($product);
+            $collection->addStoreFilter($storeId);
             $collection = $this->salableProcessor->process($collection);
             $salable = 0 !== $collection->getSize();
         }
 
+        $this->isSaleableBySku[$storeId][$sku] = $salable;
+
         return $salable;
     }
 
diff --git a/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php b/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
index 3709f4914c4..656a78d1165 100644
--- a/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
+++ b/vendor/magento/module-customer/Block/Adminhtml/Edit/Tab/Cart.php
@@ -5,37 +5,51 @@
  */
 namespace Magento\Customer\Block\Adminhtml\Edit\Tab;
 
-use Magento\Catalog\Model\Product;
+use Magento\Backend\Block\Template\Context;
+use Magento\Backend\Block\Widget\Form;
+use Magento\Backend\Block\Widget\Grid\Extended;
+use Magento\Backend\Helper\Data;
+use Magento\Customer\Block\Adminhtml\Edit\Tab\View\Grid\Renderer\Item;
+use Magento\Customer\Block\Adminhtml\Grid\Renderer\Multiaction;
 use Magento\Customer\Controller\RegistryConstants;
-use Magento\Directory\Model\Currency;
+use Magento\Framework\App\ObjectManager;
+use Magento\Framework\Data\CollectionFactory;
+use Magento\Framework\Data\FormFactory;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\Registry;
+use Magento\Quote\Api\CartRepositoryInterface;
+use Magento\Quote\Model\Quote;
+use Magento\Quote\Model\QuoteFactory;
+use Magento\Store\Model\System\Store as SystemStore;
 
 /**
  * Adminhtml customer orders grid block
  *
  * @api
  * @since 100.0.2
+ * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  */
-class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
+class Cart extends Extended
 {
     /**
      * Core registry
      *
-     * @var \Magento\Framework\Registry
+     * @var Registry
      */
     protected $_coreRegistry = null;
 
     /**
-     * @var \Magento\Framework\Data\CollectionFactory
+     * @var CollectionFactory
      */
     protected $_dataCollectionFactory;
 
     /**
-     * @var \Magento\Quote\Api\CartRepositoryInterface
+     * @var CartRepositoryInterface
      */
     protected $quoteRepository;
 
     /**
-     * @var \Magento\Quote\Model\Quote
+     * @var Quote
      */
     protected $quote = null;
 
@@ -45,32 +59,46 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
     protected $_parentTemplate;
 
     /**
-     * @var \Magento\Quote\Model\QuoteFactory
+     * @var QuoteFactory
      */
     protected $quoteFactory;
+    /**
+     * @var SystemStore
+     */
+    private $systemStore;
+    /**
+     * @var FormFactory
+     */
+    private $formFactory;
 
     /**
-     * @param \Magento\Backend\Block\Template\Context $context
-     * @param \Magento\Backend\Helper\Data $backendHelper
-     * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository
-     * @param \Magento\Framework\Data\CollectionFactory $dataCollectionFactory
-     * @param \Magento\Framework\Registry $coreRegistry
-     * @param \Magento\Quote\Model\QuoteFactory $quoteFactory
+     * @param Context $context
+     * @param Data $backendHelper
+     * @param CartRepositoryInterface $quoteRepository
+     * @param CollectionFactory $dataCollectionFactory
+     * @param Registry $coreRegistry
+     * @param QuoteFactory $quoteFactory
      * @param array $data
+     * @param SystemStore|null $systemStore
+     * @param FormFactory|null $formFactory
      */
     public function __construct(
-        \Magento\Backend\Block\Template\Context $context,
-        \Magento\Backend\Helper\Data $backendHelper,
-        \Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
-        \Magento\Framework\Data\CollectionFactory $dataCollectionFactory,
-        \Magento\Framework\Registry $coreRegistry,
-        \Magento\Quote\Model\QuoteFactory $quoteFactory,
-        array $data = []
+        Context $context,
+        Data $backendHelper,
+        CartRepositoryInterface $quoteRepository,
+        CollectionFactory $dataCollectionFactory,
+        Registry $coreRegistry,
+        QuoteFactory $quoteFactory,
+        array $data = [],
+        ?SystemStore $systemStore = null,
+        ?FormFactory $formFactory = null
     ) {
         $this->_dataCollectionFactory = $dataCollectionFactory;
         $this->_coreRegistry = $coreRegistry;
         $this->quoteRepository = $quoteRepository;
         $this->quoteFactory = $quoteFactory;
+        $this->systemStore = $systemStore ?? ObjectManager::getInstance()->get(SystemStore::class);
+        $this->formFactory = $formFactory ?? ObjectManager::getInstance()->get(FormFactory::class);
         parent::__construct($context, $backendHelper, $data);
     }
 
@@ -92,8 +120,11 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
      */
     protected function _prepareGrid()
     {
-        $this->setId('customer_cart_grid' . $this->getWebsiteId());
+        $this->setId('customer_cart_grid');
         parent::_prepareGrid();
+        if (!$this->_storeManager->isSingleStoreMode()) {
+            $this->prepareWebsiteFilter();
+        }
     }
 
     /**
@@ -105,14 +136,13 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
     {
         $quote = $this->getQuote();
 
-        if ($quote) {
+        if ($quote && $quote->getId()) {
             $collection = $quote->getItemsCollection(false);
+            $collection->addFieldToFilter('parent_item_id', ['null' => true]);
         } else {
             $collection = $this->_dataCollectionFactory->create();
         }
 
-        $collection->addFieldToFilter('parent_item_id', ['null' => true]);
-
         $this->setCollection($collection);
 
         return parent::_prepareCollection();
@@ -130,7 +160,7 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
             [
                 'header' => __('Product'),
                 'index' => 'name',
-                'renderer' => \Magento\Customer\Block\Adminhtml\Edit\Tab\View\Grid\Renderer\Item::class
+                'renderer' => Item::class
             ]
         );
 
@@ -168,7 +198,7 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
             [
                 'header' => __('Action'),
                 'index' => 'quote_item_id',
-                'renderer' => \Magento\Customer\Block\Adminhtml\Grid\Renderer\Multiaction::class,
+                'renderer' => Multiaction::class,
                 'filter' => false,
                 'sortable' => false,
                 'actions' => [
@@ -246,10 +276,59 @@ class Cart extends \Magento\Backend\Block\Widget\Grid\Extended
 
             try {
                 $this->quote = $this->quoteRepository->getForCustomer($customerId, $storeIds);
-            } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
+            } catch (NoSuchEntityException $e) {
                 $this->quote = $this->quoteFactory->create()->setSharedStoreIds($storeIds);
             }
         }
         return $this->quote;
     }
+
+    /**
+     * Add website filter block to the layout
+     *
+     * @return void
+     */
+    private function prepareWebsiteFilter(): void
+    {
+        $form = $this->formFactory->create();
+        $form->addField(
+            'website_filter',
+            'select',
+            [
+                'name' => 'website_id',
+                'values' => $this->systemStore->getWebsiteOptionHash(),
+                'value' => $this->getWebsiteId() ?? $this->_storeManager->getWebsite()->getId(),
+                'no_span' => true,
+                'onchange' => "{$this->getJsObjectName()}.loadByElement(this);",
+            ]
+        );
+        /**
+         * @var Form $formWidget
+         */
+        $formWidget = $this->getLayout()->createBlock(Form::class);
+        $formWidget->setForm($form);
+        $formWidget->setTemplate('Magento_Customer::tab/cart_website_filter_form.phtml');
+        $this->setChild(
+            'website_filter_block',
+            $formWidget
+        );
+    }
+
+    /**
+     * @inheritDoc
+     */
+    public function getMainButtonsHtml()
+    {
+        return $this->getWebsiteFilterHtml() . parent::getMainButtonsHtml();
+    }
+
+    /**
+     * Generate website filter
+     *
+     * @return string
+     */
+    private function getWebsiteFilterHtml(): string
+    {
+        return $this->getChildHtml('website_filter_block');
+    }
 }
diff --git a/vendor/magento/module-customer/Controller/Adminhtml/Cart/Product/Composite/Cart.php b/vendor/magento/module-customer/Controller/Adminhtml/Cart/Product/Composite/Cart.php
index 2603ac193e0..c57b53a56db 100644
--- a/vendor/magento/module-customer/Controller/Adminhtml/Cart/Product/Composite/Cart.php
+++ b/vendor/magento/module-customer/Controller/Adminhtml/Cart/Product/Composite/Cart.php
@@ -8,11 +8,13 @@ namespace Magento\Customer\Controller\Adminhtml\Cart\Product\Composite;
 
 use Magento\Backend\App\Action;
 use Magento\Framework\Exception\LocalizedException;
+use Magento\Quote\Api\CartRepositoryInterface;
+use Magento\Quote\Model\Quote\Item;
+use Magento\Quote\Model\QuoteFactory;
+use Magento\Quote\Model\ResourceModel\QuoteItemRetriever;
 
 /**
  * Catalog composite product configuration controller
- *
- * @author      Magento Core Team <core@magentocommerce.com>
  */
 abstract class Cart extends \Magento\Backend\App\Action
 {
@@ -21,7 +23,7 @@ abstract class Cart extends \Magento\Backend\App\Action
      *
      * @see _isAllowed()
      */
-    const ADMIN_RESOURCE = 'Magento_Customer::manage';
+    public const ADMIN_RESOURCE = 'Magento_Customer::manage';
 
     /**
      * Customer we're working with
@@ -40,32 +42,39 @@ abstract class Cart extends \Magento\Backend\App\Action
     /**
      * Quote item we're working with
      *
-     * @var \Magento\Quote\Model\Quote\Item
+     * @var Item
      */
     protected $_quoteItem = null;
 
     /**
-     * @var \Magento\Quote\Api\CartRepositoryInterface
+     * @var CartRepositoryInterface
      */
     protected $quoteRepository;
 
     /**
-     * @var \Magento\Quote\Model\QuoteFactory
+     * @var QuoteFactory
      */
     protected $quoteFactory;
 
+    /**
+     * @var QuoteItemRetriever
+     */
+    private $quoteItemRetriever;
     /**
      * @param Action\Context $context
-     * @param \Magento\Quote\Api\CartRepositoryInterface $quoteRepository
-     * @param \Magento\Quote\Model\QuoteFactory $quoteFactory
+     * @param CartRepositoryInterface $quoteRepository
+     * @param QuoteFactory $quoteFactory
+     * @param QuoteItemRetriever $quoteItemRetriever
      */
     public function __construct(
         Action\Context $context,
-        \Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
-        \Magento\Quote\Model\QuoteFactory $quoteFactory
+        CartRepositoryInterface $quoteRepository,
+        QuoteFactory $quoteFactory,
+        QuoteItemRetriever $quoteItemRetriever
     ) {
         $this->quoteRepository = $quoteRepository;
         $this->quoteFactory = $quoteFactory;
+        $this->quoteItemRetriever = $quoteItemRetriever;
         parent::__construct($context);
     }
 
@@ -86,7 +95,9 @@ abstract class Cart extends \Magento\Backend\App\Action
         $websiteId = (int)$this->getRequest()->getParam('website_id');
 
         try {
-            $this->_quote = $this->quoteRepository->getForCustomer($this->_customerId);
+            /** @var Item $quoteItem */
+            $quoteItem = $this->quoteItemRetriever->getById($quoteItemId);
+            $this->_quote = $this->quoteRepository->getForCustomer($this->_customerId, [$quoteItem->getStoreId()]);
         } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
             $this->_quote = $this->quoteFactory->create();
         }
diff --git a/vendor/magento/module-customer/Controller/Adminhtml/Index/Cart.php b/vendor/magento/module-customer/Controller/Adminhtml/Index/Cart.php
index 4008635cd7c..910f4e94b90 100644
--- a/vendor/magento/module-customer/Controller/Adminhtml/Index/Cart.php
+++ b/vendor/magento/module-customer/Controller/Adminhtml/Index/Cart.php
@@ -5,84 +5,116 @@
  */
 namespace Magento\Customer\Controller\Adminhtml\Index;
 
+use Magento\Backend\App\Action\Context;
+use Magento\Backend\Model\View\Result\ForwardFactory;
 use Magento\Customer\Api\AccountManagementInterface;
 use Magento\Customer\Api\AddressRepositoryInterface;
 use Magento\Customer\Api\CustomerRepositoryInterface;
 use Magento\Customer\Api\Data\AddressInterfaceFactory;
 use Magento\Customer\Api\Data\CustomerInterfaceFactory;
+use Magento\Customer\Controller\Adminhtml\Index as BaseAction;
+use Magento\Customer\Helper\View;
 use Magento\Customer\Model\Address\Mapper;
-use Magento\Framework\DataObjectFactory as ObjectFactory;
+use Magento\Customer\Model\AddressFactory;
+use Magento\Customer\Model\CustomerFactory;
+use Magento\Customer\Model\Metadata\FormFactory;
 use Magento\Framework\Api\DataObjectHelper;
+use Magento\Framework\Api\ExtensibleDataObjectConverter;
+use Magento\Framework\App\Action\HttpGetActionInterface;
+use Magento\Framework\App\Action\HttpPostActionInterface as HttpPostActionInterface;
+use Magento\Framework\App\Response\Http\FileFactory;
+use Magento\Framework\Controller\Result\JsonFactory;
+use Magento\Framework\DataObjectFactory as ObjectFactory;
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Framework\Math\Random;
+use Magento\Framework\Reflection\DataObjectProcessor;
+use Magento\Framework\Registry;
+use Magento\Framework\View\Result\Layout;
+use Magento\Framework\View\Result\LayoutFactory;
+use Magento\Framework\View\Result\PageFactory;
+use Magento\Newsletter\Model\SubscriberFactory;
+use Magento\Quote\Api\CartRepositoryInterface;
+use Magento\Quote\Model\Quote;
+use Magento\Quote\Model\QuoteFactory;
+use Magento\Store\Model\StoreManagerInterface;
 
 /**
+ * Admin customer shopping cart controller
+ *
  * @SuppressWarnings(PHPMD.CouplingBetweenObjects)
  * @deprecated 101.0.0
  */
-class Cart extends \Magento\Customer\Controller\Adminhtml\Index
+class Cart extends BaseAction implements HttpGetActionInterface, HttpPostActionInterface
 {
     /**
-     * @var \Magento\Quote\Model\QuoteFactory
+     * @var QuoteFactory
      */
     private $quoteFactory;
+    /**
+     * @var StoreManagerInterface
+     */
+    private $storeManager;
 
     /**
      * Constructor
      *
-     * @param \Magento\Backend\App\Action\Context $context
-     * @param \Magento\Framework\Registry $coreRegistry
-     * @param \Magento\Framework\App\Response\Http\FileFactory $fileFactory
-     * @param \Magento\Customer\Model\CustomerFactory $customerFactory
-     * @param \Magento\Customer\Model\AddressFactory $addressFactory
-     * @param \Magento\Customer\Model\Metadata\FormFactory $formFactory
-     * @param \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory
-     * @param \Magento\Customer\Helper\View $viewHelper
-     * @param \Magento\Framework\Math\Random $random
+     * @param Context $context
+     * @param Registry $coreRegistry
+     * @param FileFactory $fileFactory
+     * @param CustomerFactory $customerFactory
+     * @param AddressFactory $addressFactory
+     * @param FormFactory $formFactory
+     * @param SubscriberFactory $subscriberFactory
+     * @param View $viewHelper
+     * @param Random $random
      * @param CustomerRepositoryInterface $customerRepository
-     * @param \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter
+     * @param ExtensibleDataObjectConverter $extensibleDataObjectConverter
      * @param Mapper $addressMapper
      * @param AccountManagementInterface $customerAccountManagement
      * @param AddressRepositoryInterface $addressRepository
      * @param CustomerInterfaceFactory $customerDataFactory
      * @param AddressInterfaceFactory $addressDataFactory
      * @param \Magento\Customer\Model\Customer\Mapper $customerMapper
-     * @param \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor
+     * @param DataObjectProcessor $dataObjectProcessor
      * @param DataObjectHelper $dataObjectHelper
      * @param ObjectFactory $objectFactory
      * @param \Magento\Framework\View\LayoutFactory $layoutFactory
-     * @param \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory
-     * @param \Magento\Framework\View\Result\PageFactory $resultPageFactory
-     * @param \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory
-     * @param \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory
-     * @param \Magento\Quote\Model\QuoteFactory|null $quoteFactory
+     * @param LayoutFactory $resultLayoutFactory
+     * @param PageFactory $resultPageFactory
+     * @param ForwardFactory $resultForwardFactory
+     * @param JsonFactory $resultJsonFactory
+     * @param QuoteFactory|null $quoteFactory
+     * @param StoreManagerInterface|null $storeManager
      * @SuppressWarnings(PHPMD.ExcessiveParameterList)
      */
     public function __construct(
-        \Magento\Backend\App\Action\Context $context,
-        \Magento\Framework\Registry $coreRegistry,
-        \Magento\Framework\App\Response\Http\FileFactory $fileFactory,
-        \Magento\Customer\Model\CustomerFactory $customerFactory,
-        \Magento\Customer\Model\AddressFactory $addressFactory,
-        \Magento\Customer\Model\Metadata\FormFactory $formFactory,
-        \Magento\Newsletter\Model\SubscriberFactory $subscriberFactory,
-        \Magento\Customer\Helper\View $viewHelper,
-        \Magento\Framework\Math\Random $random,
+        Context $context,
+        Registry $coreRegistry,
+        FileFactory $fileFactory,
+        CustomerFactory $customerFactory,
+        AddressFactory $addressFactory,
+        FormFactory $formFactory,
+        SubscriberFactory $subscriberFactory,
+        View $viewHelper,
+        Random $random,
         CustomerRepositoryInterface $customerRepository,
-        \Magento\Framework\Api\ExtensibleDataObjectConverter $extensibleDataObjectConverter,
+        ExtensibleDataObjectConverter $extensibleDataObjectConverter,
         Mapper $addressMapper,
         AccountManagementInterface $customerAccountManagement,
         AddressRepositoryInterface $addressRepository,
         CustomerInterfaceFactory $customerDataFactory,
         AddressInterfaceFactory $addressDataFactory,
         \Magento\Customer\Model\Customer\Mapper $customerMapper,
-        \Magento\Framework\Reflection\DataObjectProcessor $dataObjectProcessor,
+        DataObjectProcessor $dataObjectProcessor,
         DataObjectHelper $dataObjectHelper,
         ObjectFactory $objectFactory,
         \Magento\Framework\View\LayoutFactory $layoutFactory,
-        \Magento\Framework\View\Result\LayoutFactory $resultLayoutFactory,
-        \Magento\Framework\View\Result\PageFactory $resultPageFactory,
-        \Magento\Backend\Model\View\Result\ForwardFactory $resultForwardFactory,
-        \Magento\Framework\Controller\Result\JsonFactory $resultJsonFactory,
-        \Magento\Quote\Model\QuoteFactory $quoteFactory = null
+        LayoutFactory $resultLayoutFactory,
+        PageFactory $resultPageFactory,
+        ForwardFactory $resultForwardFactory,
+        JsonFactory $resultJsonFactory,
+        QuoteFactory $quoteFactory = null,
+        ?StoreManagerInterface $storeManager = null
     ) {
         parent::__construct(
             $context,
@@ -111,13 +143,14 @@ class Cart extends \Magento\Customer\Controller\Adminhtml\Index
             $resultForwardFactory,
             $resultJsonFactory
         );
-        $this->quoteFactory = $quoteFactory ?: $this->_objectManager->get(\Magento\Quote\Model\QuoteFactory::class);
+        $this->quoteFactory = $quoteFactory ?: $this->_objectManager->get(QuoteFactory::class);
+        $this->storeManager = $storeManager ?? $this->_objectManager->get(StoreManagerInterface::class);
     }
 
     /**
      * Handle and then get cart grid contents
      *
-     * @return \Magento\Framework\View\Result\Layout
+     * @return Layout
      */
     public function execute()
     {
@@ -127,16 +160,17 @@ class Cart extends \Magento\Customer\Controller\Adminhtml\Index
         // delete an item from cart
         $deleteItemId = $this->getRequest()->getPost('delete');
         if ($deleteItemId) {
-            /** @var \Magento\Quote\Api\CartRepositoryInterface $quoteRepository */
-            $quoteRepository = $this->_objectManager->create(\Magento\Quote\Api\CartRepositoryInterface::class);
-            /** @var \Magento\Quote\Model\Quote $quote */
+            /** @var CartRepositoryInterface $quoteRepository */
+            $quoteRepository = $this->_objectManager->create(CartRepositoryInterface::class);
+            /** @var Quote $quote */
             try {
-                $quote = $quoteRepository->getForCustomer($customerId);
-            } catch (\Magento\Framework\Exception\NoSuchEntityException $e) {
+                $storeIds = $this->storeManager->getWebsite($websiteId)->getStoreIds();
+                $quote = $quoteRepository->getForCustomer($customerId, $storeIds);
+            } catch (NoSuchEntityException $e) {
                 $quote = $this->quoteFactory->create();
             }
             $quote->setWebsite(
-                $this->_objectManager->get(\Magento\Store\Model\StoreManagerInterface::class)->getWebsite($websiteId)
+                $this->storeManager->getWebsite($websiteId)
             );
             $item = $quote->getItemById($deleteItemId);
             if ($item && $item->getId()) {
diff --git a/vendor/magento/module-customer/view/adminhtml/templates/tab/cart_website_filter_form.phtml b/vendor/magento/module-customer/view/adminhtml/templates/tab/cart_website_filter_form.phtml
new file mode 100644
index 00000000000..ec903fa978f
--- /dev/null
+++ b/vendor/magento/module-customer/view/adminhtml/templates/tab/cart_website_filter_form.phtml
@@ -0,0 +1,10 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+
+/** @var $block \Magento\Backend\Block\Widget\Form */
+?>
+<?= $block->getFormHtml() ?>
+<?= $block->getChildHtml('form_after') ?>
diff --git a/vendor/magento/module-quote/Model/ResourceModel/QuoteItemRetriever.php b/vendor/magento/module-quote/Model/ResourceModel/QuoteItemRetriever.php
new file mode 100644
index 00000000000..7595bbbf7d8
--- /dev/null
+++ b/vendor/magento/module-quote/Model/ResourceModel/QuoteItemRetriever.php
@@ -0,0 +1,54 @@
+<?php
+/**
+ * Copyright © Magento, Inc. All rights reserved.
+ * See COPYING.txt for license details.
+ */
+declare(strict_types=1);
+
+namespace Magento\Quote\Model\ResourceModel;
+
+use Magento\Framework\Exception\NoSuchEntityException;
+use Magento\Quote\Model\Quote\Item;
+use Magento\Quote\Model\Quote\ItemFactory;
+
+/**
+ * Class is used to Retrieve Quote Item by id
+ */
+class QuoteItemRetriever
+{
+    /**
+     * @var ItemFactory
+     */
+    private $quoteItemFactory;
+
+    /**
+     * Constructor
+     *
+     * @param ItemFactory $quoteItemFactory
+     */
+    public function __construct(
+        ItemFactory $quoteItemFactory
+    ) {
+        $this->quoteItemFactory = $quoteItemFactory;
+    }
+
+    /**
+     * Retrieve Quote Item Model
+     *
+     * @param int $quoteItemId
+     * @return Item
+     * @throws NoSuchEntityException
+     */
+    public function getById(int $quoteItemId): Item
+    {
+        $quoteItem = $this->quoteItemFactory->create()->load($quoteItemId);
+        if (!$quoteItem->getId()) {
+            // Quote Item does not exist
+            throw new \Magento\Framework\Exception\NoSuchEntityException(
+                __('Invalid Quote Item id %1', $quoteItemId)
+            );
+        }
+
+        return $quoteItem;
+    }
+}
diff --git a/vendor/magento/module-quote/i18n/en_US.csv b/vendor/magento/module-quote/i18n/en_US.csv
index b2417929749..41c47fa0cb1 100644
--- a/vendor/magento/module-quote/i18n/en_US.csv
+++ b/vendor/magento/module-quote/i18n/en_US.csv
@@ -67,3 +67,4 @@ Carts,Carts
 "Invalid state change requested","Invalid state change requested"
 "Validated Country Code","Validated Country Code"
 "Validated Vat Number","Validated Vat Number"
+"Invalid Quote Item id %1","Invalid Quote Item id %1"

No comments:

Post a Comment