How to create an "extra fee" or a negative amount in Shopping Cart Price Rule

If you have ever needed to create a shopping cart price rule but the value needed to be negative, Magento prevents this by default.  You may want this to create an extra fee based on some rules like if there is a certain sku in the cart, or whatever.

To overcome Magento's check to see if that number entered is negative we have to overload one magento core file, and create a rewrite of another.  Hold on to your hat, here we go.

Overload a core Magento abstract class

Step 1 Create a file app/code/local/Mage/Rule/Model/Abstract.php

Step 2 copy the contents from app/code/core/Mage/Rule/Model/Abstract.php and paste it into our new file we created on Step 1.

Rewrite Mage_Adminhtml_Block_Promo_Quote_Edit_Tab_Actions

Step 1 Create a module instantiation file app/etc/modules/Russellalbin_Adminhtml.xml

<?xml version="1.0"?>

Step 2 Create the config file app/code/local/Russellalbin/Adminhtml/etc/config.xml

<?xml version="1.0" ?>

Step 3 Create the rewrite file app/code/local/Russellalbin/Adminhtml/Block/Promo/Quote/Edit/Tab/Action.php


class Fsw_Adminhtml_Block_Promo_Quote_Edit_Tab_Actions
extends Mage_Adminhtml_Block_Promo_Quote_Edit_Tab_Actions

protected function _prepareForm()
$model = Mage::registry('current_promo_quote_rule');

//$form = new Varien_Data_Form(array('id' => 'edit_form1', 'action' => $this->getData('action'), 'method' => 'post'));
$form = new Varien_Data_Form();


$fieldset = $form->addFieldset('action_fieldset', array('legend'=>Mage::helper('salesrule')->__('Update prices using the following information')));

$fieldset->addField('simple_action', 'select', array(
'label' => Mage::helper('salesrule')->__('Apply'),
'name' => 'simple_action',
'options' => array(
Mage_SalesRule_Model_Rule::BY_PERCENT_ACTION => Mage::helper('salesrule')->__('Percent of product price discount'),
Mage_SalesRule_Model_Rule::BY_FIXED_ACTION => Mage::helper('salesrule')->__('Fixed amount discount'),
Mage_SalesRule_Model_Rule::CART_FIXED_ACTION => Mage::helper('salesrule')->__('Fixed amount discount for whole cart'),
Mage_SalesRule_Model_Rule::BUY_X_GET_Y_ACTION => Mage::helper('salesrule')->__('Buy X get Y free (discount amount is Y)'),
$fieldset->addField('discount_amount', 'text', array(
'name' => 'discount_amount',
'required' => true,
//'class' => 'validate-not-negative-number',
'label' => Mage::helper('salesrule')->__('Discount Amount (negative number for increase in price)'),

$fieldset->addField('discount_qty', 'text', array(
'name' => 'discount_qty',
'label' => Mage::helper('salesrule')->__('Maximum Qty Discount is Applied To'),

$fieldset->addField('discount_step', 'text', array(
'name' => 'discount_step',
'label' => Mage::helper('salesrule')->__('Discount Qty Step (Buy X)'),

$fieldset->addField('apply_to_shipping', 'select', array(
'label' => Mage::helper('salesrule')->__('Apply to Shipping Amount'),
'title' => Mage::helper('salesrule')->__('Apply to Shipping Amount'),
'name' => 'apply_to_shipping',
'values' => Mage::getSingleton('adminhtml/system_config_source_yesno')->toOptionArray(),

$fieldset->addField('simple_free_shipping', 'select', array(
'label' => Mage::helper('salesrule')->__('Free Shipping'),
'title' => Mage::helper('salesrule')->__('Free Shipping'),
'name' => 'simple_free_shipping',
'options' => array(
0 => Mage::helper('salesrule')->__('No'),
Mage_SalesRule_Model_Rule::FREE_SHIPPING_ITEM => Mage::helper('salesrule')->__('For matching items only'),
Mage_SalesRule_Model_Rule::FREE_SHIPPING_ADDRESS => Mage::helper('salesrule')->__('For shipment with matching items'),

$fieldset->addField('stop_rules_processing', 'select', array(
'label' => Mage::helper('salesrule')->__('Stop Further Rules Processing'),
'title' => Mage::helper('salesrule')->__('Stop Further Rules Processing'),
'name' => 'stop_rules_processing',
'options' => array(
'1' => Mage::helper('salesrule')->__('Yes'),
'0' => Mage::helper('salesrule')->__('No'),

$renderer = Mage::getBlockSingleton('adminhtml/widget_form_renderer_fieldset')

$fieldset = $form->addFieldset('actions_fieldset', array(
'legend'=>Mage::helper('salesrule')->__('Apply the rule only to cart items matching the following conditions (leave blank for all items)')

$fieldset->addField('actions', 'text', array(
'name' => 'actions',
'label' => Mage::helper('salesrule')->__('Apply To'),
'title' => Mage::helper('salesrule')->__('Apply To'),
'required' => true,

Mage::dispatchEvent('adminhtml_block_salesrule_actions_prepareform', array('form' => $form));


if ($model->isReadonly()) {
foreach ($fieldset->getElements() as $element) {
$element->setReadonly(true, true);


$_form = Mage::getBlockSingleton('adminhtml/widget_form');
return $_form::_prepareForm();


Step 4: You need to overload the Magento Abstract class that is doing the check to see if the value is greater than zero.

Magento Abstract classes are not something you can do a rewrite on.

The only way to get it to work is to make a copy of the file in your local folder of app/code/local

Here is how I did an overload of Mage_Rule_Model_Abstract:

Overload Step 1 Create a file app/code/local/Mage/Rule/Model/Abstract.php

Overload Step 2 copy the contents from app/code/core/Mage/Rule/Model/Abstract.php and paste it into our new file we created on Overload Step 1.

Thats it!

You should now be all set and using our version of the abstract class instead of the core file, now you can edit it to suit your needs, like I did for allowing a negative number in the shopping cart rules.