Wednesday, May 14, 2014

Include the text "Grand Total to be Charged" in Invoice Emails in Magento 1.7

I had this requirement in Magento 1.7 a couple of days back. Suppose, my site has multiple currencies and I check out with GBP whereas my default currency is USD. Now, the Order email has the following texts ::

...                          ... 
Grand Total                  £93.66
Grand Total to be Charged    $169.70

Which means, I purchased items costing £93.66 but I will be charged $169.70 (which is equal to £93.66 as per conversion rate on that day). But when the Invoice mail is generated, the last line "Grand Total to be Charged" is not appearing. I needed that line to appear on all other transaction emails including Invoice emails.

How I found the solution ?

To solve the problem, I started digging into the email template files first. Order_new.html and invoice_new.html were the files I started to delve in. My observations are as shown below :

1. The Invoice email template invoice_new.html has the following line ( which deals with and prints the whole PRICE stuffs ):
     
    {{layout handle="sales_email_order_invoice_items" invoice=$invoice order=$order}}

   whereas the Order email template order_new.html has the following line :

   {{layout handle="sales_email_order_items" order=$order}}

2. In sales.xml, layout handle 'sales_email_order_invoice_items' has a block template 'email/order/invoice/items.phtml'. This item.phtml file has the following line ::

    echo $this->getChildHtml('invoice_totals');

and sales.xml again says ( getChildHtml('invoice_totals') is referring to )::
   
    <block type="sales/order_invoice_totals" name="invoice_totals" template="sales/order/totals.phtml">   

3. Again, in sales.xml, layout handle 'sales_email_order_items' has a block template 'email/order/items.phtml' .. this item.phtml file has the following line ::

   echo $this->getChildHtml('order_totals');

and sales.xml again says getChildHtml('order_totals') is referring to ) :: 
   
<block type="sales/order_totals" name="order_totals" template="sales/order/totals.phtml">

4. So, both Order and Invoice emails dynamically loads "sales/order/totals.phtml" file. Now in totals.phtml file, we have a line like this :: 

foreach ($this->getTotals() as $_code => $_total): 

The above foreach construct takes output (as an array) from getTotals() function and loops through the output array containing whole Pricing structure including base price, shipping expenses, tax, discounts, Base price in other currencies etc. 

5. As the Base Price (with BASE currency as set in Admin Panel ) was coming properly in Order email, I checked the class ( from <block type='sales/order_totals' ) Mage_Sales_Block_Order_Totals found in Mage/Sales/Block/Order/Totals.php. The getTotals() function is just iterating the class property '$this->_totals'. I also checked how this '$this->_totals' array was created through '_initTotals()' method. And within this '_initTotals()' method, $this->_totals['base_grandtotal'] is being created which is responsible for printing the Order price in Base Currency and this is what I was looking for. However, this Base price was not coming in Invoice emails. Hence I opened the Class 'Mage_Sales_Block_Order_Invoice_Totals'.

6. The class 'Mage_Sales_Block_Order_Invoice_Totals' ( existing in file 'app/code/core/Mage/Sales/Block/Order/Invoice/Totals.php' ) inherits from the class 'Mage_Sales_Block_Order_Totals' and overrides the function _initTotals() which created the pricing array _totals. Check the function below :

    protected function _initTotals()
  {
     // Call Parent Mage_Sales_Block_Order_Totals
     // class' _initTotals() to create the 
     // parent class' _totals array
     parent::_initTotals();
        
     // Removing the _totals['base_grandtotal']
     $this->removeTotal('base_grandtotal');
     return $this;
  }
    
    The line $this->removeTotal('base_grandtotal'); is removing the Base Price section from the _totals array. Simply commenting the line finally solved my problem.

Magento 1.8 Notes - III

1. Get Customer's FirstName in transactional Emails in Magento ::
    
    In transactional email template files ( order_new.html/invoice_new.html etc), the following line
   
   Hello, {{htmlescape var=$order.getCustomerFirstName()}}
   
   should give the customer first name. However, in email templates (order_new.html etc) where "Hello, {{htmlescape var=$billing.getName()}}" is used, replacing this with the above mentioned "{{htmlescape var=$order.getCustomerFirstName()}}" may give full name of the  customer. In such situations, the following method would always work.
   
   The class Mage_Sales_Model_Order is defined in app\code\core\Mage\Sales\Model\Order.php file where getCustomerName(), getCustomerFirstName() etc functions are defined. We can add our own method inside this class.
   
   public function getCustomerOnlyFirstName()
 {
   // GET Name
   $name = trim($this->getCustomerName());
 
   // Find if any Space is there within Name
   $pos = strpos($name," ");
 
   // If Space is found, extract till that Space
   if($pos !== false) 
   {
     $name = trim(substr( $name, 0, $pos ));
   }
 
   // return 
   return $name;
 }
   
   and then use the line below to get the customer's first name in email templates ( where $order variable is used ) ::
   
   Hello, {{htmlescape var=$order.getCustomerOnlyFirstName()}}

2. Include Customer IP address in New Order Email template ::
   
   To achieve this, we need to follow steps shown below --
   a. Modify /public_html/app/code/core/Mage/Sales/Model/Order.php
   b. We need to edit the function sendNewOrderEmail()
   c. We nee add a new variable 'remoteaddr' or anything of our choice and set some value to it.
   
   $mailer->setTemplateParams(array(
       'order'        => $this,
       'billing'      => $this->getBillingAddress(),
       'payment_html' => $paymentBlockHtml,
       'remoteaddr'   => $_SERVER['REMOTE_ADDR']
     ));
   
 d. Now we must call the variable from within template file as {{var remoteaddr }}   

3. Get Order Comments in Transaction Email :: 
   
     Use the below line to get Customer Comments in Email Template :-
   
     {{var order.getEmailCustomerNote()}}

4. Run Installation process again : 
   
   Once, I forgot the Admin Password on Local installation of Magento, I wanted to restore it. I thought that it would be better if I could run the Installation process again. Running the Installation process again did not delete my existing data on Database. Which means it did not create new tables on the DB rather used the old ones. So my Admin Panel was intact. 
   
   To go through install wizard again, we need to delete app/etc/local.xml file and reload any magento page, it will be redirected to /install. 

5. Magento Error :: "There was a problem with the subscription: This email address is already assigned to another user."
   
   This is not a bug but an intended behaviour in Magento. This message can be seen in the following scenarios ..
   
   i. When the user is not logged in, however he/she is using an email address with which another customer is already registered.
   ii. When the user is logged in, however he/she is not using his/her own email address, rather an email address with which another customer is already registered.
   
   So, if we use a right email address, this error message can be avoided.
   
6. Get the GIANT XML file programmatically which is created after every module's config.xml file is parsed by Magento and included in the global config. 
   
   echo Mage::app()->getConfig()->getNode()->asXML() ;