I recently performed a downgrade from Magento EE 1.14.2.4 to Magento CE 1.9.3.8 to save a company on the $20k plus annual license fee. While there are many great features EE has over CE, there are plenty of CE plugin solutions that can replace that functionality at a more affordable price point.
One of those features that EE provided was the ability to filter a sales rule based on a customer segments/attribute. A customer segment is a collection of customers that validate against a rule. Read more here. The gist: Customer attributes can be used to create a customer segment, and then the customer segments can be used in sales rule conditions. Thus, discounts can be created based on email addresses, custom attributes defined in local code, etc.
Since I performed this downgrade, I needed to get the ability to apply sales rules conditions to customer attributes based on an employee attribute. In this case – it was to provide automatic discounts to an employee based on the information we know. Normally Magento only provides the following:
But we are going to update it to use a few attributes like this:
Let’s get started!
Note: This post assumes you already know how to create a custom extension, or you already have a custom extension you can easily add to.
To make this work we need to do a few things:
- Observe when the sales rules are combined
- Inject our custom sales rule attributes into the conditions backend (i.e customer attributes)
- Validate the conditions so the rule is applied correctly
I did use this GitHub post for reference to get our end result.
1. Create observer
We are creating an observer to populate additional conditions into a sales rule. In Mage_SalesRule_Model_Rule_Condition_Combine::getNewChildSelectOptions
you will see that it builds a list of conditional arrays and fires the event we want to observe:
Mage::dispatchEvent('salesrule_rule_condition_combine', array('additional' => $additional));
In your extension, setup your etc/config
file to define a model and observe the event:
<?xml version="1.0"?> <config> <modules> <My_Company> <version>1.0.0</version> </My_Company> </modules> <global> <models> <my_company> <class>My_Company_Model</class> </my_company> </models> <events> <salesrule_rule_condition_combine> <observers> <my_company_add_customer_to_salesrules_conditions> <class>My_Company_Model_Observer</class> <method>updateSalesRulesConditionsForCustomerAttributes</method> </my_company_add_customer_to_salesrules_conditions> </observers> </salesrule_rule_condition_combine> </events> </global> </config>
In My_Company_Model_Observer
we now need to tell it add Customer as an attribute condition to select.
<?php class My_Company_Model_Observer extends Varien_Event_Observer { public function updateSalesRulesConditionsForCustomerAttributes(Varien_Event_Observer $observer) { $customerCondition = Mage::getModel('company/rule_condition_customer'); $customerAttributes = $customerCondition->loadAttributeOptions()->getAttributeOption(); $attributes = array(); foreach ($customerAttributes as $code=>$label) { $attributes[] = array('value'=>'company/rule_condition_customer|'.$code, 'label'=>$label); } $additional = $observer->getAdditional(); $conditions = array( array('label'=>'Customer Attribute', 'value'=>$attributes) ); $additional->setConditions($conditions); return $additional; } }
That observer adds the customer attributes as a condition option now. But it won’t work yet. We need to set the model: Mage::getModel('company/rule_condition_customer');
2. Create the model and inject attributes
This is very easy to do and only requires extending the abstract model class and defining the attributes we want to have as options to select for a sales rule condition.
In My_Company_Model_Rule_Condition_Customer
put the following:
<?php class My_Company_Model_Rule_Condition_Customer extends Mage_Rule_Model_Condition_Abstract { /** * @return $this * These are customer attributes we want to use as condition rules for */ public function loadAttributeOptions() { $attributes = array( 'customer_number' => 'Customer Number', 'email' => 'Email Address', 'is_cs_rep' => 'Customer Service (Internal Use Only)' ); $this->setAttributeOption($attributes); return $this; } /** * Validate Customer Rule Condition * * @param Varien_Object $object * @return bool */ public function validate(Varien_Object $object) { $customer = ($object instanceof Mage_Customer_Model_Customer) ? $object : $object->getQuote()->getCustomer(); $customer ->setCustomerNumber($customer->getCustomerNumber()) ->setEmail($customer->getEmail()) ->setIsCsRep($customer->getIsCsRep()); return parent::validate($customer); } }
3. Validate the conditions.
As you can see, in the validate
method:
public function validate(Varien_Object $object) { $customer = ($object instanceof Mage_Customer_Model_Customer) ? $object : $object->getQuote()->getCustomer(); $customer ->setCustomerNumber($customer->getCustomerNumber()) ->setEmail($customer->getEmail()) ->setIsCsRep($customer->getIsCsRep()); return parent::validate($customer); }
we simply set the data that is specified in the loadAttributeOptions
method.
At this point, the attributes should populate in the conditions as available to use. Since we use the built in validate method, everything just works in this case. You should now be able to do conditions like this:
Conclusion
While it may initially seem daunting to add customer attributes for sales rule validation – it really only involves a few files! I hope you found this helpful.