Magento – How to exclude products being added to cart based on products attributes

addtocartcartevent-observermagento-1.9overrides

How can i set a condition, if pre-ordered products are purchased, no other products can be added to cart?

How can I set a condition like, if some of the "non-pre-order" products
is in the cart, not to be able to add a "pre-order" product. Visa verse if
my cart consists "pre-order" products, not allow "non-pre-order"
products to be added?

How can I do that?

Best Answer

You can use checkout_cart_product_add_after event to allow or disallow products being added ...

app/code/local/My/Module/etc/config.xml

<?xml version="1.0" encoding="UTF-8"?>
<config>
    <modules>
        <My_Module>
            <version>0.0.1</version>
        </My_Module>
    </modules>
    <global>
        <models>
            <my_module>
                <class>My_Module_Model</class>
            </my_module>
        </models>
        <events>
            <checkout_cart_product_add_after>
                <observers>
                    <test>
                        <class>my_module/observer</class>
                        <method>disallowProductAddToCart</method>
                    </test>
                </observers>
            </checkout_cart_product_add_after>
        </events>
        <!-- make custom attrribute available in quote item product -->
        <sales>
            <quote>
                <item>
                    <product_attributes>
                        <preorder />
                    </product_attributes>
                </item>
            </quote>
        </sales>
    </global>
</config>

app/code/local/My/Module/Model/Observer.php

class My_Module_Model_Observer extends Mage_Core_Model_Observer
{
    public function disallowProductAddToCart(Varien_Event_Observer $observer)
    {
        $quote = $observer->getQuoteItem();
        $cartItems = $quote->getQuote()->getAllItems();

        if (count($cartItems) > 1) {
            $product = $observer->getProduct();
            $isPreorder = $product->getPreorder();

            if ($isPreorder) {
                $quote->getQuote()->removeItem($quote->getId());
                Mage::throwException(
                    Mage::helper('sales')->__('Can not add pre-order product to existing cart.')
                );
            }

            foreach ($cartItems as $item) {
                if (!$isPreorder && $item->getProduct()->getPreorder()) {
                    $quote->getQuote()->removeItem($quote->getId());
                    Mage::throwException(
                        Mage::helper('sales')->__('Cart already contains an pre-ordered product.')
                    );
                    break;
                }
            }
        }
    }
}

Edit: allow multiple "pre-order" products in cart

public function disallowProductAddToCart(Varien_Event_Observer $observer)
{
    $quote = $observer->getQuoteItem();
    $cartItems = $quote->getQuote()->getAllItems();

    if (count($cartItems) > 1) {
        $product = $observer->getProduct();
        $isPreorder = $product->getPreorder();

        foreach ($cartItems as $item) {
            if ($isPreorder != $item->getProduct()->getPreorder()) {
                $quote->getQuote()->removeItem($quote->getId());
                $message = $isPreorder ? 'Can not add pre-order product to existing cart.' : 'Cart already contains pre-ordered products.';
                Mage::throwException(
                    Mage::helper('sales')->__($message)
                );
                break;
            }
        }
    }
}

If your are curious why using checkout_cart_product_add_after and remove item from cart later $quote->getQuote()->removeItem($quote->getId()) ... it is just because there is no checkout_cart_product_add_before event dispatched in Mage_Checkout_Model_Cart::addProduct() :(

Related Topic