Magento custom total

magento-totals

Have you ever considered that your Magento online shop might need an additional total, for example:

  • customers that pay using cash on delivery, could be charged a special fee, to cover your return in case the sale fails post-delivery;
  • customers that want your product quicker, could be charged a rush fee;
  • customers that want a specific change to a product, making it useless for anybody else, could pay a special fee.

And I think your business has brought to you many other cases when a different total, that’s not part in any way of the product item lines, should be applied in the checkout process.

So how should you add such a total? Well here is how:

Step 1: Add a custom attribute to your invoice and order models which will hold the total value, as part of your module installer:

$installer = $this;
$installer->startSetup();

$installer = new Mage_Sales_Model_Resource_Setup('core_setup');

$installer->addAttribute('quote','total_fee_amount',array('type' => 'varchar', 'grid' => false));

$installer->addAttribute('order','total_fee_amount',array('type' => 'varchar','grid' => false));

$installer->endSetup();

Step 2: Setup the required configuration options in your module XML
 

First – your admin blocks:

<adminhtml>
   <rewrite>
      <sales_order_totals>Mymodule_Mymodule_Block_Adminhtml_Sales_Order_Totals</sales_order_totals>
      <sales_order_invoice_totals>Mymodule_Mymodule_Block_Adminhtml_Sales_Order_Invoice_Totals</sales_order_invoice_totals>
      <sales_order_creditmemo_totals>Mymodule_Mymodule_Block_Adminhtml_Sales_Order_Creditmemo_Totals</sales_order_creditmemo_totals>
   </rewrite>
</adminhtml>

Secondly – your totals classes:

<sales>
 <quote>
	 <totals>
		 <mymodule_mymodule>
			 <class>mymodule/total_interest_quote</class>
			 <after>tax</after>
			 <before>grand_total</before>
		 </mymodule_mymodule>
	 </totals>
 </quote>
 <order_invoice>
	 <totals>
		 <mymodule_mymodule>
			 <class>mymodule/total_interest_invoice</class>
			 <after>tax</after>
			 <before>grand_total</before>
		 </mymodule_mymodule>
	 </totals>
 </order_invoice>
 <order_creditmemo>
	 <totals>
		 <mymodule_mymodule>
			 <class>mymodule/total_interest_creditmemo</class>
			 <after>tax</after>
			 <before>grand_total</before>
		 </mymodule_mymodule>
	 </totals>
 </order_creditmemo>
</sales>

Secondly – the classes definition for the quote total:

class Mymodule_Mymodule_Model_Total_Interest_Quote extends Mage_Sales_Model_Quote_Address_Total_Abstract
{
	public function __construct()
    {
        $this->setCode('mymodule_mymodule');
    }
	
	public function getLabel()
    {
        return Mage::helper('mymodule')->__('New Fee');
    }
	
    public function collect(Mage_Sales_Model_Quote_Address $address)
    {
        parent::collect($address);
        if (($address->getAddressType() == 'billing')) {
            return $this;
        }
		$quote = $address->getQuote();
        $amount = $quote->getData('total_fee_amount');
 
        if (is_numeric($amount) && $amount != 0) {
            $this->_addAmount($amount);
            $this->_addBaseAmount($amount);
        }
 
        return $this;
    }
 
    public function fetch(Mage_Sales_Model_Quote_Address $address)
    {
        if (($address->getAddressType() == 'billing')) {
			
			$quote = $address->getQuote();
			$amount = $quote->getData('total_fee_amount');
			
           if (is_numeric($amount) && $amount != 0) {
                $address->addTotal(array(
                    'code'  => $this->getCode(),
                    'title' => $this->getLabel(),
                    'value' => $amount
                ));
            }
        }
 
        return $this;
    }
}

Similar to that you will have a total for the invoices:

<?php

class Mymodule_Mymodule_Model_Total_Interest_Invoice extends Mage_Sales_Model_Order_Invoice_Total_Abstract
{
	public function __construct()
    {
        $this->setCode('mymodule_mymodule');
    }
	
	public function getLabel()
    {
        return Mage::helper('mymodule')->__('New Fee');
    }
	
    public function collect(Mage_Sales_Model_Order_Address $address)
    {
        parent::collect($address);
        if (($address->getAddressType() == 'billing')) {
            return $this;
        }
		$quote = $address->getOrder();
        $amount = $quote->getData('total_fee_amount');
 
        if (is_numeric($amount) && $amount != 0) {
            $this->_addAmount($amount);
            $this->_addBaseAmount($amount);
        }
 
        return $this;
    }
	
	protected function _addAmount($amount)
    {
        if ($this->_canAddAmountToAddress) {
            $this->_getAddress()->addTotalAmount($this->getCode(),$amount);
        }
        return $this;
    }
	
	protected function _addBaseAmount($baseAmount)
    {
        if ($this->_canAddAmountToAddress) {
            $this->_getAddress()->addBaseTotalAmount($this->getCode(), $baseAmount);
        }
        return $this;
    }

    public function fetch(Mage_Sales_Model_Order_Address $address)
    {
        if (($address->getAddressType() == 'billing')) {
			
            $quote = $address->getOrder();
            $amount = $quote->getData('total_fee_amount');
			
            if (is_numeric($amount) && $amount != 0) {
                $address->addTotal(array(
                    'code'  => $this->getCode(),
                    'title' => $this->getLabel(),
                    'value' => $amount
                ));
            }
        }
 
        return $this;
    }
}

and credit memos:

class Mymodule_Mymodule_Model_Total_Interest_Creditmemo extends Mage_Sales_Model_Order_Creditmemo_Total_Abstract
{
	public function __construct()
    {
        $this->setCode('mymodule_mymodule');
    }
	
	public function getLabel()
    {
        return Mage::helper('mymodule')->__('New Fee');
    }
	
    public function collect(Mage_Sales_Model_Order_Address $address)
    {
        parent::collect($address);
        if (($address->getAddressType() == 'billing')) {
            return $this;
        }
 
       $order = $address->getOrder();
       $amount = $order->getData('total_fee_amount');
 
        if (is_numeric($amount) && $amount != 0) {
            $this->_addAmount($amount);
            $this->_addBaseAmount($amount);
        }
 
        return $this;
    }
	protected function _addAmount($amount)
    {
        if ($this->_canAddAmountToAddress) {
            $this->_getAddress()->addTotalAmount($this->getCode(),$amount);
        }
        return $this;
    }
	
	protected function _addBaseAmount($baseAmount)
    {
        if ($this->_canAddAmountToAddress) {
            $this->_getAddress()->addBaseTotalAmount($this->getCode(), $baseAmount);
        }
        return $this;
    }

    public function fetch(Mage_Sales_Model_Order_Address $address)
    {
        if (($address->getAddressType() == 'billing')) {
            
			$order = $address->getOrder();
			$amount = $order->getData('total_fee_amount');
 
			if (is_numeric($amount) && $amount != 0) {
                $address->addTotal(array(
                    'code'  => $this->getCode(),
                    'title' => $this->getLabel(),
                    'value' => $amount
                ));
            }
        }
 
        return $this;
    }
}

Step 3. Based on the event that the customer takes all you need to do is modify the quote to insert your amount when the appropriate action is carried, by setting the amount in the new attribute ‘total_fee_amount’. The total will be automatically carried over to the order model when the order is placed.

Please feel free to comment if you have any questions.

Leave a Reply

Your email address will not be published. Required fields are marked *

*