magento2: Unable to update simple product custom option in cart when quantity is 1

Preconditions (*)

  1. Magento CE 2.2.5, Updated(9/19/2019) can be reproduced on 2.3
  2. Although reproduced in 2.2.2-2.2.4
  3. Backorders disabled, minimum order qty is 1.
  4. A simple product with at least one custom option, e.g. size - 1,2,3; price type fixed.

Steps to reproduce (*)

  1. Go to product page and select options and click add to cart. || Update 9/19/2019: The quantity of the product added must be more than a half of its Stock quantity! ||
  2. Go to cart and select “Edit/Update Item”
  3. Select different option from original and click update.

Expected result (*)

  1. Redirected back to cart
  2. Product custom option updated.

Actual result (*)

  1. Error message on product page. image || Update 9/19/2019: (Those messages haven’t been observed at now. Only the one below still appears) || The requested qty is not available

Notes

It manifests as well if you have configurable product, where associated product has 1 stock, and configurable has custom option. Once selected and added to cart. If you try to update only custom option, the result is the same.

It appears that the code in Magento/Quote/Model/Quote.php#updateItem updates product item or adds new one if product item with matching custom/configurable options does not exist and later removes old item. Problem is inside updateItem(), call to to addProduct() throws, because actual product qty is 1.

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Comments: 46 (18 by maintainers)

Commits related to this issue

Most upvoted comments

i fixed with those plugins

Magento 2.3.4 (tested)

i knew this is not right way but for now it will work (We will check when new version released)

your custom module

Custom/Module/etc/frontend/di.xml

<!-- this plugin fix_if_stock_is_one_error_qty_is_not_available custom options -->
   <type name="Magento\Quote\Model\Quote\Item">
       <plugin name="fix_if_stock_is_one_error_qty_is_not_available" type="Custom\Module\Plugin\Quote\ExtendedItem" disabled="false" sortOrder="10"/>
   </type>


   <!-- this plugin fix_if_stock_is_one_error_qty_is_not_available -->
   <type name="Magento\CatalogInventory\Model\Quote\Item\QuantityValidator\QuoteItemQtyList">
       <plugin name="fix_if_stock_is_one_error_qty_is_not_available_quote_item" type="Custom\Module\Plugin\Quote\Item\QuantityValidator\QuoteItemQtyList" disabled="false" sortOrder="10"/>
   </type>

Custom\Module\Plugin\Quote\ExtendedItem.php

<?php

namespace Custom\Module\Plugin\Quote;

use Magento\Quote\Model\Quote\Item;

class ExtendedItem
{


    /**
     * @param Item $subject
     * @param  $result
     * @param $qty
     * @return mixed
     */
    public function afterAddQty(Item $subject,$result,$qty){

        if($subject->getQty()!=$qty)
        {
          $result->setQty($qty);
        }
        return $result;
    }
}
 

Custom\Module\Plugin\Quote\Item\QuantityValidator\QuoteItemQtyList.php

<?php


namespace Custom\Module\Plugin\Quote\Item\QuantityValidator;

use Magento\CatalogInventory\Model\Quote\Item\QuantityValidator\QuoteItemQtyList as CoreQuoteItemQtyList;

class QuoteItemQtyList
{


    /**
     * @param CoreQuoteItemQtyList $subject
     * @param $productId
     * @param $quoteItemId
     * @param $quoteId
     * @param $itemQty
     * @return array
     */
    public function beforeGetQty(CoreQuoteItemQtyList $subject,$productId, $quoteItemId, $quoteId, $itemQty)
    {

        /**  we are using 0 because original qty was processed */
        if($itemQty!=0){
            $itemQty=0;
        }

        return [$productId, $quoteItemId, $quoteId, $itemQty];
    }
}

This is still an issue in 2.3.4

Hi, any update on this issue ?

i fixed with those plugins

Magento 2.3.4 (tested)

i knew this is not right way but for now it will work (We will check when new version released)

your custom module

Custom/Module/etc/frontend/di.xml

<!-- this plugin fix_if_stock_is_one_error_qty_is_not_available custom options -->
   <type name="Magento\Quote\Model\Quote\Item">
       <plugin name="fix_if_stock_is_one_error_qty_is_not_available" type="Custom\Module\Plugin\Quote\ExtendedItem" disabled="false" sortOrder="10"/>
   </type>


   <!-- this plugin fix_if_stock_is_one_error_qty_is_not_available -->
   <type name="Magento\CatalogInventory\Model\Quote\Item\QuantityValidator\QuoteItemQtyList">
       <plugin name="fix_if_stock_is_one_error_qty_is_not_available_quote_item" type="Custom\Module\Plugin\Quote\Item\QuantityValidator\QuoteItemQtyList" disabled="false" sortOrder="10"/>
   </type>

Custom\Module\Plugin\Quote\ExtendedItem.php

<?php

namespace Custom\Module\Plugin\Quote;

use Magento\Quote\Model\Quote\Item;

class ExtendedItem
{


    /**
     * @param Item $subject
     * @param  $result
     * @param $qty
     * @return mixed
     */
    public function afterAddQty(Item $subject,$result,$qty){

        if($subject->getQty()!=$qty)
        {
          $result->setQty($qty);
        }
        return $result;
    }
}
 

Custom\Module\Plugin\Quote\Item\QuantityValidator\QuoteItemQtyList.php

<?php


namespace Custom\Module\Plugin\Quote\Item\QuantityValidator;

use Magento\CatalogInventory\Model\Quote\Item\QuantityValidator\QuoteItemQtyList as CoreQuoteItemQtyList;

class QuoteItemQtyList
{


    /**
     * @param CoreQuoteItemQtyList $subject
     * @param $productId
     * @param $quoteItemId
     * @param $quoteId
     * @param $itemQty
     * @return array
     */
    public function beforeGetQty(CoreQuoteItemQtyList $subject,$productId, $quoteItemId, $quoteId, $itemQty)
    {

        /**  we are using 0 because original qty was processed */
        if($itemQty!=0){
            $itemQty=0;
        }

        return [$productId, $quoteItemId, $quoteId, $itemQty];
    }
}

This one worked in 2.3.5-p1. Thanks @prabhakaran777