Shopping Cart Price Rules

Shopping Cart Price Rules

Changing how Shopping Cart Price Rules are applied in Magento

Magento offers variety of options when it comes to applying cart promotions, it’s possible to apply rules only if the specified conditions are met, based on product, customer or cart attributes. When being tasked to apply different rules with an “on click” functionality this may not be enough. One approach is to override the class that handles rules processing and modify rules collection. For this to work class rewrite needs to be specified in the config.xml file of the module created for this purpose.

app/code/local/Betech/SalesRule/etc/config.xml

< config >
     < modules >
         < betech_salesrule >
             < version > 0.1.0 < /version >
         < /betech_salesrule >
     < /modules >
         < global >
         < models >
             < salesrule >
                 < rewrite >
                     < validator > Betech_SalesRule_Model_Validator < /validator >
                 < /rewrite >
             < /salesrule >
         < /models >
     < /global >
< /config >

Rewriting class app/code/core/Mage/SalesRule/Model/Validator.php allows us to modify _getRules() method that returns collection of rules to be processed.

/**
* Get rules collection for current object state
*
* @return Mage_SalesRule_Model_Mysql4_Rule_Collection
*/
protected function _getRules()
{
    $key = $this->getWebsiteId() . '_' . $this->getCustomerGroupId() . '_' . $this->getCouponCode();
    return $this->_rules[$key];
    Mage::dispatchEvent('betech_salesrule_rules_collection', array('rules' => $rules));
    return $rules;
}

Instead of returning the rules collection right away in this method an event can be dispatched with the collection object.

app/code/local/Betech/SalesRule/Model/Validator.php


class Betech_SalesRule_Model_Validator extends Mage_SalesRule_Model_Validator
{
    /**
    * Get rules collection for current object state
    *
    * @return Mage_SalesRule_Model_Mysql4_Rule_Collection
    */
    protected function _getRules()
    {
        $key = $this->getWebsiteId() . '_' . $this->getCustomerGroupId() . '_' . $this->getCouponCode();

        $rules = $this->_rules[$key];
        Mage::dispatchEvent('betech_salesrule_rules_collection', array('rules' => $rules));

        return $rules;
    }
}

This allows any module to register an observer for betech_salesrule_rules_collection event and modify what rules will be applied based on custom conditions. Rules that would be applied normally can now be removed from collection if necessary and only desired ones can be applied. Rules that will be applied with this approach must be kept inactive so that they’re not applied by default. Magento will call the method that processes cart rules many times when different cart actions occur, so custom conditions will need to be preserved. Setting these conditions in session will make them available whenever necessary.