One of the most common requests we receive on e-commerce projects where Magento 1.9 is being used as a store is to add a percentage discount that works on the entire cart WITH a cap on the overall discount amount. This article will explain how to add this to your Magento installation. The same technique could be used to create any discount type with a cap.
On your Magento database, run the following SQL. This will create the field for maximum discount amount.
ALTER TABLE SalesRule ADD COLUMN discount_max DECIMAL(12,4);
This will allow the system to distinguish your per-cart-percentage rule from other types. Add:
const CART_PERCENT_ACTION = 'cart_percent';
after:
const CART_FIXED_ACTION = 'cart_fixed';
This is the code that actually processes this rule type for each item.
case Mage_SalesRule_Model_Rule::CART_PERCENT_ACTION:
if (empty($this->_rulesItemTotals[$rule->getId()])) {
Mage::throwException(Mage::helper('salesrule')->__('Item totals are not set for rule.'));
}
//Get the running cart total discount
$cartDiscountAmount = $this->_rulesItemTotals[$rule->getId()]['cart_total_discount'];
//percentage multiplier for maths
$_rulePct = $rulePercent/100;
// prevent applying whole cart discount for every shipping order, but only for first order
if ($quote->getIsMultiShipping()) {
$usedForAddressId = $this->getCartFixedRuleUsedForAddress($rule->getId());
if ($usedForAddressId && $usedForAddressId != $address->getId()) {
break;
} else {
$this->setCartFixedRuleUsedForAddress($rule->getId(), $address->getId());
}
}
$cartRules = $address->getCartFixedRules();
if (!isset($cartRules[$rule->getId()])) {
$cartRules[$rule->getId()] = $rule->getDiscountAmount();
}
//Have we exceeded the per-cart limit?
if ($cartDiscountAmount < $rule->getDiscountMax()) {
//If not, what's our maximum remaining
$maxAllowed = $rule->getDiscountMax()-$cartDiscountAmount;
//This item's discount is the smaller of the two
$discountAmount = $quote->getStore()->convertPrice(min($maxAllowed, (($baseItemPrice * $qty)*$_rulePct)));
$quoteAmount = $quote->getStore()->convertPrice($discountAmount);
$this->_rulesItemTotals[$rule->getId()]['cart_total_discount']+=$discountAmount;
$cartRules[$rule->getId()] = $discountAmount;
}
$address->setCartFixedRules($cartRules);
break;
We need to make sure that running totals are created for this new rule type, so change:
if (Mage_SalesRule_Model_Rule::CART_FIXED_ACTION == $rule->getSimpleAction()
to:
if ((Mage_SalesRule_Model_Rule::CART_FIXED_ACTION == $rule->getSimpleAction()||Mage_SalesRule_Model_Rule::CART_PERCENT_ACTION == $rule->getSimpleAction())
We’ll need to initialize our running total when the rule begins processing, so after:
$validItemsCount = 0;
add:
$cartDiscountTotalForThisRule = 0;
and after:
'items_price' => $ruleTotalItemsPrice,
add
'cart_total_discount' => $cartDiscountTotalForThisRule,
Next, we move on to updates for the management interface.(You did want to be able to edit this, right?)
First, we’ll need to add an option to the Discount Type dropdown on the SalesRule editor, so add:
Mage_SalesRule_Model_Rule::CART_PERCENT_ACTION => Mage::helper('salesrule')->__('Fixed percentage discount for whole cart'),
after:
Mage_SalesRule_Model_Rule::CART_FIXED_ACTION => Mage::helper('salesrule')->__('Fixed amount discount for whole cart'),
If you are working in code instead of /include, this is already done. If not, add:
const CART_PERCENT_ACTION = 'cart_percent';
after:
const CART_FIXED_ACTION = 'cart_fixed';
This will need to be added to prepareForm(), which is pretty straightforward. Add this:
$fieldset->addField('discount_max', 'text', array(
'name' => 'discount_max',
'label' => Mage::helper('salesrule')->__('Maximum Cart-wide Discount Amount'),
));
$model->setDiscountMax($model->getDiscountMax()*1);
after:
$model->setDiscountQty($model->getDiscountQty()*1);
And with that, you are done. Flush your cache, add your new SalesRule in the management interface, and enjoy!
While building the front page for this site, I found myself stuck on the title graphic.
I had the following requirements:
Initially, I looked at trianglify – but I was already using that for the site backdrop. After some further searching, I settled on geopattern. There is a demo page here.
Usage is simple – just include the script and either use the GeoPattern global, or the jQuery plugin.
// Use the global...
var pattern = GeoPattern.generate('GitHub');
$('#geopattern').css('background-image', pattern.toDataUrl());
// ...or the plugin
$('#geopattern').geopattern('GitHub');
There are options for the pattern seed, color, basecolor, and pattern generator:
//Generate yellow octagons
GeoPattern.generate("seed string",{color: '#997700',baseColor:'#997722', generator: "ocatagons"});
//Generate green chevrons
GeoPattern.generate("seed string2",{color: '#22FF44',baseColor:'#000000', generator: "chevrons"});
Applying the resulting image to an object in your DOM is simple with jQuery:
$('#objectid').css('background-image', pattern.toDataUrl());
This was one of the simplest pieces I’ve worked with yet – it’s really just plug and play. As long as you don’t MUNG the script somehow, you’re good. I didn’t bother with using npm or bower to include it – I just dropped it in my page and started working.
This canvas is patterned with a random seed. Refresh to see a new pattern.