Event Observer – How to Remove Items from Quote When Loaded

event-observerquote

My cart page is broken because of disabled products in the cart. The disabled products remained in the cart for some of my customer in below scenario:

  1. Customer added product (enabled product) in his cart and left the cart.
  2. The product was disabled next day as it was out-of-stock.
  3. Customer returned back after a week using the same session/cart.
  4. Since the product that was already in his cart was disabled the cart page is some how broken.

I want to remove those disabled product from quote items when ever cart is loaded for the customer.Please let me know what observer i can use to know the cart is loaded or any other better way to resolve the issue?

Whenever there is disabled product in the cart, the sales_flat_quote_item table has only one record (for configurable only) for the product. In normal case this table will have two records one as configurable and another as simple for each quote. I actually wanted to remove such single record line form the table caused because of disabled products but i do not want to do this through SQL.

Best Answer

I had similar function like you required but it's auto adding product to quote.

Instead of quote load, I add a observer that is watching the quote save.

Here is some code:

events.xml

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd">
    <event name="sales_quote_save_before">
        <observer name="vendor_module_quote_save_before" instance="Vendor\Module\Observer\BeforeQuoteSave" />
    </event>
</config>

In the observer loops through all items to find you target item:

            foreach($quote->getAllItems() as $_item){
                $stockItem = $this->stockItem->load($_item->getProductId(),'product_id');
                if(!$stockItem->getIsInStock() || !$_item->getProduct()->isInStock()){
                    $quote->deleteItem($_item);
                }
            }
            $quote->setTotalsCollectedFlag(false)->collectTotals();

It should work, remember not to save the quote in before_quote_save, it will cause an infinity loop.

Just update the code, it should target your question now.