Our client offers a series of discount % bands for bulk purchasing of products, due to a number of factors that I won’t get into we needed to implement this discount at the shopping cart. You can offer perecentage discounts using the default promotional rule “Percent of product price discount”, but we found issues when combining multiple percentage bands.
Our approach was to create a new module that provided the promotional rule and an observer that handled the rule functionality.
We started as usual by creating our modules xml file:
<config>
<modules>
<Designthatfits_Percentdiscount>
<active>true</active>
<codePool>community</codePool>
</Designthatfits_Percentdiscount>
</modules>
</config>
For anyone who hasn’t set up a module before, this essentially provides Magento with the location of your module – Designthatfits being the top level folder, Parentdiscount being the module.
Set up the relevant file/folder structure in app/code/community:
- Designthatfits/Percentdiscount/etc/config.xml
- Designthatfits/Percentdiscount/Model/Observer.php
The config.xml file needed to define the classes for our observers for use on the frontend withing the <global> section, and in the admin area so that we can pick the new rule from the list <adminhtml>.
<?xml version=”1.0″ encoding=”UTF-8″?>
<config>
<modules>
<Designthatfits_Percentdiscount>
<version>0.0.1</version>
</Designthatfits_Percentdiscount>
</modules>
<global>
<models>
<percentdiscount>
<class>Designthatfits_Percentdiscount_Model</class>
</percentdiscount>
</models>
<events>
<salesrule_validator_process>
<observers>
<percentdiscount>
<type>model</type>
<class>percentdiscount/observer</class>
<method>salesruleValidatorProcess</method>
</percentdiscount>
</observers>
</salesrule_validator_process>
</events>
</global>
<adminhtml>
<events>
<adminhtml_block_salesrule_actions_prepareform>
<observers>
<percentdiscount>
<type>model</type>
<class>percentdiscount/observer</class>
<method>adminhtmlBlockSalesruleActionsPrepareform</method>
</percentdiscount>
</observers>
</adminhtml_block_salesrule_actions_prepareform>
</events>
</adminhtml>
</config>
Our Observer.php is where the magic happens.
Firstly we define our new rule type as a constant, then set up our first Observer that creates our promotional rule and adds it to the normal selection list in the dashboard.
{literal}
class Designthatfits_Percentdiscount_Model_Observer {
// The new rule type
const PRODUCT_DTF_DISCOUNT = ‘product_dtf_discount’;
/**
* Add the new rule type to the admin menu
*
* @param Varien_Event_Observer $observer
*/
public function adminhtmlBlockSalesruleActionsPrepareform
(Varien_Event_Observer $observer) {
// Extract the form field
$field = $observer->getForm()->getElement(‘simple_action’);
// Extract the field values
$options = $field->getValues();
// Add the new value
$options[] = array(
‘value’ => self::PRODUCT_DTF_DISCOUNT,
‘label’ => ‘Percentage Discount (DTF)’
);
// Set the field
$field->setValues($options);
}
Next we setup our Observer that handles the rule functionality. This observer uses the $rule object to check whether the observer is looking at the new rule we are trying to define, if it is – and our cart item has a qty greater than 1 – we process the rule and calculate the discount amount.
/**
* Apply the discount
* The discount will be applied based on standardised bands
*
* @param Varien_Event_Observer $observer
*/
public function salesruleValidatorProcess(Varien_Event_Observer $observer) {
// $item typeof Mage_Sales_Model_Quote_Item
$item = $observer->getEvent()->getItem();
// $rule typeof Mage_SalesRule_Model_Rule
$rule = $observer->getEvent()->getRule();
// Number of products
$qty = $item->getQty();
// We must check the rule type in order to isolate our rule type
if($rule->getSimpleAction() == self::PRODUCT_DTF_DISCOUNT && $qty > 1) {
// Extract rule details
$discountAmount = $rule->getDiscountAmount();
$discount_band = 0; //no discount
//DTF Possible discount bands.
$possible_discount_bands = array(
5=>array(“low”=>1,”high”=>5),
10=>array(“low”=>6,”high”=>9),
15=>array(“low”=>9,”high”=>99999),
);
foreach($possible_discount_bands as $key=>$band) {
if($qty >= $band[“low”] && $qty <= $band[“high”]) {
$discount_band = $key;
}
}
$totalDiscount_1perc = $item->getPrice() / 100;
$totalDiscount_toband = $totalDiscount_1perc * $discount_band;
$totalDiscount_toqty = $totalDiscount_toband * $qty;
$totalDiscount = $totalDiscount_toqty;
$result = $observer->getResult();
$result->setDiscountAmount($totalDiscount);
$result->setBaseDiscountAmount($totalDiscount);
}
}
}
Most of this code could be amended as you require, the important bit is what actually determines your applied discount (where $totalDiscount is the numerical value you wish to discount your item by):
$result = $observer->getResult();
$result->setDiscountAmount($totalDiscount);
$result->setBaseDiscountAmount($totalDiscount);
{/literal}