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"

The update with the "1640505600" ID doesn't exist. Verify the ID and try again

ISSUE:

Got the error when trying to run the command: bin/magento i:rei catalogrule_product

report.CRITICAL: The update with the "1640505600" ID doesn't exist. Verify the ID and try again. {"exception":"[object] (Magento\\Framework\\Exception\\NoSuchEntityException(code: 0): The update with the \"1640505600\" ID doesn't exist. Verify the ID and try again. at /vendor/magento/module-staging/Model/UpdateRepository.php:103)"} 


REASON:

Unfortunately, this is very old issue and M2 still collect all needed information about possible triggers that cause it. M2 did lot's of fixes already but still sometimes experience it. 

Let me share and explain what they can state now.

When might this happen?

The issue may occur after operations with scheduled updates for store content assets (Content Staging). For example, you may have deleted a Product with a scheduled update, or removed the end date for such an update.

A store content asset may be:

    + Product

    + Category

    + Catalog Price Rule

    + Cart Price Rule

    + CMS Page

    + CMS Block

    + Widget

Some scenarios are discussed in the Possible Trigger section below.

Cause

The `flag` table in the database (DB) contains invalid links to the `staging_update` table.

See an example below:

- select * fromstaging_update;

Empty set(0.00 sec)

- select* fromflag;

+---------+---------------------+-------+-------------------------------------------------+---------------------+

| flag_id | flag_code           | state | flag_data                                       | last_update         |

+---------+---------------------+-------+-------------------------------------------------+---------------------+

|       1 | staging             |     0 | a:1:{s:15:"current_version";s:10:"1490005140";} | 2017-03-20 15:49:07 |

+---------+---------------------+-------+-------------------------------------------------+---------------------+

where:

    `flag_code` points to the `staging_update` table

    `flag_data` points to a record with a scheduled update that is no longer available in the `staging_update` table

Possible trigger: operations involving Content Staging

The problem is related to Content Staging (updates for store content assets scheduled using the Magento_Staging module). Below are two particular scenarios; please note there might be more situations that trigger the issue.

Scenario 1: 
Deleting a store content asset which:
    + has an update scheduled with Content Staging
    + the update has an end date (meaning the expiry date after which the updated asset reverts to its previous version)
    + the end date of the update is in the past

At the same time, the issue might not occur if a deleted asset has no end date for the scheduled update.

Scenario 2: 
Removing the end date/time of a scheduled update.

 

SOLUTION 1: 

1. Remove record in flag table:

select * from flag WHERE flag_code = "staging";

delete from flag WHERE flag_code = "staging";

2. Run reindex for catalogrule_product again.


SOLUTION 2: 

Follow the patch

diff --git a/vendor/magento/module-checkout-staging/Model/PreviewQuotaManager.php 
b/vendor/magento/module-checkout-staging/Model/PreviewQuotaManager.php
index f6d232f999d..e0034a9fbf2 100644
--- a/vendor/magento/module-checkout-staging/Model/PreviewQuotaManager.php
+++ b/vendor/magento/module-checkout-staging/Model/PreviewQuotaManager.php
@@ -90,14 +90,14 @@ class PreviewQuotaManager
                 )
             );
 
-            $this->searchCriteriaBuilder->addFilter('entity_id', $ids, 'in');
+            $this->searchCriteriaBuilder->addFilter('main_table.entity_id', $ids, 'in');
             $this->searchCriteriaBuilder->addFilter(
-                CartInterface::KEY_STORE_ID,
+                'main_table.' . CartInterface::KEY_STORE_ID,
                 $storeId,
                 'eq'
             );
             $this->searchCriteriaBuilder->addFilter(
-                CartInterface::KEY_UPDATED_AT,
+                'main_table.' . CartInterface::KEY_UPDATED_AT,
                 $now->format('Y-m-d H:i:s'),
                 'to'
             );