Dec 21, 2015

Magento How to filter product collection by product type_id

How to filter product collection by product type_id

$collectionSimple = Mage::getResourceModel('catalog/product_collection')
->addAttributeToFilter('type_id', array('eq' => 'simple'));

$collectionConfigurable = Mage::getResourceModel('catalog/product_collection')
->addAttributeToFilter('type_id', array('eq' => 'configurable'));

$collectionBundle = Mage::getResourceModel('catalog/product_collection')
->addAttributeToFilter('type_id', array('eq' => 'bundle'));

$collectionGrouped = Mage::getResourceModel('catalog/product_collection')
->addAttributeToFilter('type_id', array('eq' => 'grouped'));

$collectionVirtual = Mage::getResourceModel('catalog/product_collection')
->addAttributeToFilter('type_id', array('eq' => 'virtual'));

Magento How to Apply Patches on Magento WebSite

Hello Friends,

I am sharing this post because, I founded this Magecomp patches post very useful and safe way to install Magento patches.

Specially I liked  Method 3: because they provides the compressed files of all the updated patches and we just need to extract and upload on server in the root of your Magento.

Please note take backup of your files and db before applying this patches (Apply patches at your own risk). 

You can choose whichever you like or as per your convenience. Click link below to get the detail post.  

How to Install Magento Security Patches – The Ultimate Guide



Note: You can test/scan your site after applying patches  here https://www.magereport.com/scan/?s=https://www.urdomain.com/ to know your site security level.

Magento How to set cron job using SSH account

In this post I will show you how to set cron job for cron.php file to run in every 5 minutes.

























Please follows the steps below...

Step 1: Open SSH window and log in using your account detail.

Step 2: Check if already there any crons set for this server.

ssh>> export VISUAL=nano; crontab -e

You can see if there any cron after executing the above command.

Step 3: Copy paste below command and execute.

*/5 * * * * /usr/bin/php -f /var/www/urprojectfolder/www/cron.php

Step 4: Run below command to save and exit.

ssh>> CTRL+X

ssh>> Y

You are done!!!

Note::

You can set other crons same as above but please confirm your cron file path.

You can check if your cron set properly or not by running below command again.

ssh>> export VISUAL=nano; crontab -e



Dec 11, 2015

Magento How to add shipping charge to the cart automatically for logged in customer only

Sometime we needs to apply shipping charge on shopping cart page after adding products to cart directly but generally in Magento the shipping cost only apply when the customer manually run shipping cost estimator or in checkout page after selecting country.

In order to get this working, you need a custom module which hooks into the event ‘sales_quote_save_before’. 

Please consider following assumption to create custom module:

 - Namespace as 'Pg'
 - And Module name as 'Cartshipping'

Step 1: Create a custom module definition xml; in path app/etc/modules, create the file Pg_Cartshipping.xml and add code below.

<config>
<modules>
<Pg_Cartshipping>
<active>true</active>
<codePool>local</codePool>
</Pg_Cartshipping>
</modules>
</config>


Step 2: Now creates the following directory structure

app/code/local/Pg
app/code/local/Pg/Cartshipping
app/code/local/Pg/Cartshipping/etc
app/code/local/Pg/Cartshipping/Model


Step 3: Now under the folder "app/code/local/Pg/Cartshipping/etc", create a file "config.xml"" and add the following content:


<?xml version="1.0"?>
<config>
<modules>
<Pg_Cartshipping>
<version>0.1.0</version>
</Pg_Cartshipping>
</modules>
<global>
<models>
<pg_cartshipping>
<class>Pg_Cartshipping_Model</class>
</pg_cartshipping>
</models>
</global>
<frontend>
<events>
<checkout_cart_save_before>
<observers>
<pg_cartshipping_observer>
<type>singleton</type>
<class>pg_cartshipping/observer</class>
<method>addShippingCost</method>
</pg_cartshipping_observer>
</observers>
</checkout_cart_save_before>
</events>
</frontend>
</config>


Step 4: Now under the folder "app/code/local/Pg/Cartshipping/Model", create a file "Observer.php" and add the following content:

class Pg_Cartshipping_Model_Observer {

private $_shippingCode = 'tablerate_tablerate'; // change your default shipping method code here
private $_country = '';

public function addShippingCost($params = null) {

$customer = Mage::getSingleton('customer/session')->getCustomer();
$customerAddressId = $customer->getDefaultShipping();
if ($customerAddressId)
{
$address = Mage::getModel('customer/address')->load($customerAddressId);
$cust_data = $address->getData();
$this->_country = $cust_data['country_id'];
}
if($this->_country != "")
{
if (Mage::registry('checkout_addShipping')) {
Mage::unregister('checkout_addShipping');
return;
}
Mage::register('checkout_addShipping',true);
 
$cart = Mage::getSingleton('checkout/cart');
$quote = $cart->getQuote();
 
if ($quote->getCouponCode() != '') {
$c = Mage::getResourceModel('salesrule/rule_collection');
$c->getSelect()->where("code=?", $quote->getCouponCode());
foreach ($c->getItems() as $item) { $coupon = $item; }
 
if ($coupon->getSimpleFreeShipping() > 0) {
$quote->getShippingAddress()->setShippingMethod($this->_shippingCode)->save();
return true;
}
}
 
try {
$method = $quote->getShippingAddress()->getShippingMethod();
if ($method) return; // don't overwrite if default set
 
if ($quote->getShippingAddress()->getCountryId() == '') {
$quote->getShippingAddress()->setCountryId($this->_country);
}
 
$quote->getShippingAddress()->setCollectShippingRates(true);
$quote->getShippingAddress()->collectShippingRates();
 
$rates = $quote->getShippingAddress()->getAllShippingRates();
$allowed_rates = array();
foreach ($rates as $rate) {
array_push($allowed_rates,$rate->getCode());
}
 
if (!in_array($this->_shippingCode,$allowed_rates) && count($allowed_rates) > 0) {
$shippingCode = $allowed_rates[0];
}

if (!empty($shippingCode)) {
$address = Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress();
if ($address->getCountryId() == '') $address->setCountryId($this->_country);
if ($address->getCity() == '') $address->setCity('');
if ($address->getPostcode() == '') $address->setPostcode('');
if ($address->getRegionId() == '') $address->setRegionId('');
if ($address->getRegion() == '') $address->setRegion('');
$address->setShippingMethod($this->_shippingCode)->setCollectShippingRates(true);
Mage::getSingleton('checkout/session')->getQuote()->save();
} else {
$address = Mage::getSingleton('checkout/session')->getQuote()->getShippingAddress();
if ($address->getCountryId() == '') $address->setCountryId($this->_country);
if ($address->getCity() == '') $address->setCity('');
if ($address->getPostcode() == '') $address->setPostcode('');
if ($address->getRegionId() == '') $address->setRegionId('');
if ($address->getRegion() == '') $address->setRegion('');
$address->setShippingMethod($this->_shippingCode)->setCollectShippingRates(true);
Mage::getSingleton('checkout/session')->getQuote()->save();
}
 
Mage::getSingleton('checkout/session')->resetCheckout();
 
}
catch (Mage_Core_Exception $e) {
Mage::getSingleton('checkout/session')->addError($e->getMessage());
}
catch (Exception $e) {
Mage::getSingleton('checkout/session')->addException($e, Mage::helper('checkout')->__('Load customer quote error'));
}
}


}

public function getQuote() {
        if (empty($this->_quote)) {
            $this->_quote = Mage::getSingleton('checkout/session')->getQuote();
        }
        return $this->_quote;
    }

}



## Done. Clear Cache ##

Magento How to get product group price

How to get product group price in Magento

Here is the code:

$product=Mage::getModel('catalog/product')->load($productId);

if(!is_null($product->getGroupPrice()){
$groupPrice = $product->getGroupPrice();
}

Dec 10, 2015

Magento How To Delete/Truncate All Test Product, Orders, Sales, Customer & Newsletter Subscribers Data Using SQL Script

Warning: Before run below script take backup of your database and then try.

## DELETE Product Script ##

SET FOREIGN_KEY_CHECKS = 0;
TRUNCATE TABLE `catalog_product_bundle_option`;
TRUNCATE TABLE `catalog_product_bundle_option_value`;
TRUNCATE TABLE `catalog_product_bundle_selection`;
TRUNCATE TABLE `catalog_product_entity_datetime`;
TRUNCATE TABLE `catalog_product_entity_decimal`;
TRUNCATE TABLE `catalog_product_entity_gallery`;
TRUNCATE TABLE `catalog_product_entity_int`;
TRUNCATE TABLE `catalog_product_entity_media_gallery`;
TRUNCATE TABLE `catalog_product_entity_media_gallery_value`;
TRUNCATE TABLE `catalog_product_entity_text`;
TRUNCATE TABLE `catalog_product_entity_tier_price`;
TRUNCATE TABLE `catalog_product_entity_varchar`;
TRUNCATE TABLE `catalog_product_link`;
TRUNCATE TABLE `catalog_product_link_attribute`;
TRUNCATE TABLE `catalog_product_link_attribute_decimal`;
TRUNCATE TABLE `catalog_product_link_attribute_int`;
TRUNCATE TABLE `catalog_product_link_attribute_varchar`;
TRUNCATE TABLE `catalog_product_link_type`;
TRUNCATE TABLE `catalog_product_option`;
TRUNCATE TABLE `catalog_product_option_price`;
TRUNCATE TABLE `catalog_product_option_title`;
TRUNCATE TABLE `catalog_product_option_type_price`;
TRUNCATE TABLE `catalog_product_option_type_title`;
TRUNCATE TABLE `catalog_product_option_type_value`;
TRUNCATE TABLE `catalog_product_super_attribute_label`;
TRUNCATE TABLE `catalog_product_super_attribute_pricing`;
TRUNCATE TABLE `catalog_product_super_attribute`;
TRUNCATE TABLE `catalog_product_super_link`;
TRUNCATE TABLE `catalog_product_enabled_index`;
TRUNCATE TABLE `catalog_product_website`;
TRUNCATE TABLE `catalog_category_product_index`;
TRUNCATE TABLE `catalog_category_product`;
TRUNCATE TABLE `cataloginventory_stock_item`;
TRUNCATE TABLE `cataloginventory_stock_status`;
TRUNCATE TABLE `cataloginventory_stock`;
INSERT  INTO `catalog_product_link_type`(`link_type_id`,`code`) VALUES (1,'relation'),(2,'bundle'),(3,'super'),(4,'up_sell'),(5,'cross_sell');
INSERT  INTO `catalog_product_link_attribute`(`product_link_attribute_id`,`link_type_id`,`product_link_attribute_code`,`data_type`) VALUES (1,2,'qty','decimal'),(2,1,'position','int'),(3,4,'position','int'),(4,5,'position','int'),(6,1,'qty','decimal'),(7,3,'position','int'),(8,3,'qty','decimal');
INSERT  INTO `cataloginventory_stock`(`stock_id`,`stock_name`) VALUES (1,'Default');
TRUNCATE TABLE `catalog_product_entity`;
SET FOREIGN_KEY_CHECKS = 1;


## Delete all Orders, Sales & Customer Data Script ##

SET FOREIGN_KEY_CHECKS=0;

##############################
# SALES RELATED TABLES
##############################
TRUNCATE `sales_flat_creditmemo`;
TRUNCATE `sales_flat_creditmemo_comment`;
TRUNCATE `sales_flat_creditmemo_grid`;
TRUNCATE `sales_flat_creditmemo_item`;
TRUNCATE `sales_flat_invoice`;
TRUNCATE `sales_flat_invoice_comment`;
TRUNCATE `sales_flat_invoice_grid`;
TRUNCATE `sales_flat_invoice_item`;
TRUNCATE `sales_flat_order`;
TRUNCATE `sales_flat_order_address`;
TRUNCATE `sales_flat_order_grid`;
TRUNCATE `sales_flat_order_item`;
TRUNCATE `sales_flat_order_payment`;
TRUNCATE `sales_flat_order_status_history`;
TRUNCATE `sales_flat_quote`;
TRUNCATE `sales_flat_quote_address`;
TRUNCATE `sales_flat_quote_address_item`;
TRUNCATE `sales_flat_quote_item`;
TRUNCATE `sales_flat_quote_item_option`;
TRUNCATE `sales_flat_quote_payment`;
TRUNCATE `sales_flat_quote_shipping_rate`;
TRUNCATE `sales_flat_shipment`;
TRUNCATE `sales_flat_shipment_comment`;
TRUNCATE `sales_flat_shipment_grid`;
TRUNCATE `sales_flat_shipment_item`;
TRUNCATE `sales_flat_shipment_track`;
TRUNCATE `sales_invoiced_aggregated`;            # ??
TRUNCATE `sales_invoiced_aggregated_order`;        # ??
TRUNCATE `log_quote`;

ALTER TABLE `sales_flat_creditmemo_comment` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_creditmemo_grid` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_creditmemo_item` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_invoice` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_invoice_comment` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_invoice_grid` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_invoice_item` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_order` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_order_address` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_order_grid` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_order_item` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_order_payment` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_order_status_history` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote_address` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote_address_item` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote_item` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote_item_option` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote_payment` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_quote_shipping_rate` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_shipment` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_shipment_comment` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_shipment_grid` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_shipment_item` AUTO_INCREMENT=1;
ALTER TABLE `sales_flat_shipment_track` AUTO_INCREMENT=1;
ALTER TABLE `sales_invoiced_aggregated` AUTO_INCREMENT=1;
ALTER TABLE `sales_invoiced_aggregated_order` AUTO_INCREMENT=1;
ALTER TABLE `log_quote` AUTO_INCREMENT=1;

#########################################
# DOWNLOADABLE PURCHASED
#########################################
TRUNCATE `downloadable_link_purchased`;
TRUNCATE `downloadable_link_purchased_item`;

ALTER TABLE `downloadable_link_purchased` AUTO_INCREMENT=1;
ALTER TABLE `downloadable_link_purchased_item` AUTO_INCREMENT=1;

#########################################
# RESET ID COUNTERS
#########################################
TRUNCATE `eav_entity_store`;
ALTER TABLE  `eav_entity_store` AUTO_INCREMENT=1;


##############################
# CUSTOMER RELATED TABLES
##############################
TRUNCATE `customer_address_entity`;
TRUNCATE `customer_address_entity_datetime`;
TRUNCATE `customer_address_entity_decimal`;
TRUNCATE `customer_address_entity_int`;
TRUNCATE `customer_address_entity_text`;
TRUNCATE `customer_address_entity_varchar`;
TRUNCATE `customer_entity`;
TRUNCATE `customer_entity_datetime`;
TRUNCATE `customer_entity_decimal`;
TRUNCATE `customer_entity_int`;
TRUNCATE `customer_entity_text`;
TRUNCATE `customer_entity_varchar`;
TRUNCATE `tag`;
TRUNCATE `tag_relation`;
TRUNCATE `tag_summary`;
TRUNCATE `tag_properties`;            ## CHECK ME
TRUNCATE `wishlist`;
TRUNCATE `log_customer`;

ALTER TABLE `customer_address_entity` AUTO_INCREMENT=1;
ALTER TABLE `customer_address_entity_datetime` AUTO_INCREMENT=1;
ALTER TABLE `customer_address_entity_decimal` AUTO_INCREMENT=1;
ALTER TABLE `customer_address_entity_int` AUTO_INCREMENT=1;
ALTER TABLE `customer_address_entity_text` AUTO_INCREMENT=1;
ALTER TABLE `customer_address_entity_varchar` AUTO_INCREMENT=1;
ALTER TABLE `customer_entity` AUTO_INCREMENT=1;
ALTER TABLE `customer_entity_datetime` AUTO_INCREMENT=1;
ALTER TABLE `customer_entity_decimal` AUTO_INCREMENT=1;
ALTER TABLE `customer_entity_int` AUTO_INCREMENT=1;
ALTER TABLE `customer_entity_text` AUTO_INCREMENT=1;
ALTER TABLE `customer_entity_varchar` AUTO_INCREMENT=1;
ALTER TABLE `tag` AUTO_INCREMENT=1;
ALTER TABLE `tag_relation` AUTO_INCREMENT=1;
ALTER TABLE `tag_summary` AUTO_INCREMENT=1;
ALTER TABLE `tag_properties` AUTO_INCREMENT=1;
ALTER TABLE `wishlist` AUTO_INCREMENT=1;
ALTER TABLE `log_customer` AUTO_INCREMENT=1;


##############################
# ADDITIONAL LOGS
##############################
TRUNCATE `log_url`;
TRUNCATE `log_url_info`;
TRUNCATE `log_visitor`;
TRUNCATE `log_visitor_info`;
TRUNCATE `report_event`;
TRUNCATE `report_viewed_product_index`;
TRUNCATE `sendfriend_log`;
### ??? TRUNCATE `log_summary`

ALTER TABLE `log_url` AUTO_INCREMENT=1;
ALTER TABLE `log_url_info` AUTO_INCREMENT=1;
ALTER TABLE `log_visitor` AUTO_INCREMENT=1;
ALTER TABLE `log_visitor_info` AUTO_INCREMENT=1;
ALTER TABLE `report_event` AUTO_INCREMENT=1;
ALTER TABLE `report_viewed_product_index` AUTO_INCREMENT=1;
ALTER TABLE `sendfriend_log` AUTO_INCREMENT=1;
### ??? ALTER TABLE `log_summary` AUTO_INCREMENT=1;


TRUNCATE catalogsearch_query;
TRUNCATE catalogsearch_fulltext;
TRUNCATE catalogsearch_result;
ALTER TABLE catalogsearch_query AUTO_INCREMENT=1;
ALTER TABLE catalogsearch_fulltext AUTO_INCREMENT=1;
ALTER TABLE catalogsearch_result AUTO_INCREMENT=1;

TRUNCATE TABLE sales_bestsellers_aggregated_daily;
TRUNCATE TABLE sales_bestsellers_aggregated_monthly;
TRUNCATE TABLE sales_bestsellers_aggregated_yearly;
ALTER TABLE sales_bestsellers_aggregated_daily AUTO_INCREMENT=1;
ALTER TABLE sales_bestsellers_aggregated_monthly AUTO_INCREMENT=1;
ALTER TABLE sales_bestsellers_aggregated_yearly AUTO_INCREMENT=1;

SET FOREIGN_KEY_CHECKS=1;



## Delete Newsletter Subscribers Data Script ##

SET FOREIGN_KEY_CHECKS=0;

TRUNCATE newsletter_problem;
TRUNCATE newsletter_queue;
TRUNCATE newsletter_queue_link;
TRUNCATE newsletter_queue_store_link;
TRUNCATE newsletter_subscriber;
TRUNCATE newsletter_template;

ALTER TABLE newsletter_problem AUTO_INCREMENT=1;
ALTER TABLE newsletter_queue AUTO_INCREMENT=1;
ALTER TABLE newsletter_queue_link AUTO_INCREMENT=1;
ALTER TABLE newsletter_queue_store_link AUTO_INCREMENT=1;
ALTER TABLE newsletter_subscriber AUTO_INCREMENT=1;
ALTER TABLE newsletter_template AUTO_INCREMENT=1;

SET FOREIGN_KEY_CHECKS=1;



## Done ##

Magento Adminside Access Denied errors for all custom modules after installing Security Patches SUPEE-6285


If your Admin account is restricted and some menus of third party extensions or your custom modules might not work any more.

The reason behind this is that the default return value of Mage_Adminhtml_Controller_Action::_isAllowed() has been changed from 'true' to Mage::getSingleton('admin/session')->isAllowed('admin').

Extensions or custom modules that do not override this method in their custom modules or extensions admin controllers because they don't use the ACL, now need the "ALL" privilege.

The solution for this is to patch the extensions or custom modules and add this method to all their admin controllers, please note admin controller not the front-end:

protected function _isAllowed()
{
    return true;
}

Or if they actually have an ACL resource defined in etc/adminhtml.xml:

protected function _isAllowed()
{
    return Mage::getSingleton('admin/session')->isAllowed('ENTER RESOURCE IDENTIFIER HERE');
}


For more detail you can refer post of stackexchange http://magento.stackexchange.com/questions/73646/access-denied-errors-after-installing-supee-6285

Javascript How To Set Cookie Globally for all pages

Javascript How To Set Cookie Globally for all pages 

For one page we can set Cookie as follows:

document.cookie = "myVarName=YourValue;";


For global we can set Cookie as follows just added extra 'path=/':

document.cookie = "myVarName=YourValue; path=/";

Dec 6, 2015

Magento How to get category and child/sub categories by category ID

This is one of the easy way to get category and child or sub categories using category id.
You can use following code anywhere in Magento module files.


<?php
$parentCategoryId = 4; // Note: Change you category id here
$allCats = Mage::getModel('catalog/category')->getCollection()
->addAttributeToSelect('*')
->addAttributeToFilter('is_active','1')
->addAttributeToFilter('include_in_menu','1')
->addAttributeToFilter('parent_id',array('eq' => $parentCategoryId))
->addAttributeToSort('position', 'asc');

foreach($allCats as $_category) {
try {
$_subcategories = $category->getChildrenCategories();
if (count($_subcategories) > 0){
echo 'Parent Category Name: '.$_category->getName();
echo 'Parent Category Id: '.$_category->getId();      
foreach($_subcategories as $_subcategory){
echo 'Child Category Name: '. $_subcategory->getName();
echo 'Child Category Id: '.$_subcategory->getId();
}
}
} catch (Exception $ex) {// log your exception here}
}
?>

Dec 4, 2015

Magento How to add unit price and product image in new order email template

In new order confirmation email template product unit price does not show by default. Sometimes we need customization in order email template as per our client requirements. In this post, I will guide you to customize order email template in easy steps.

The output of the customization will look like as follows:




Here we will change 3 files, you have to copy these files into the folder of your current theme in same folder structure.

1) app/design/frontend/base/default/template/email/order/items.phtml

See line 32, find the following code (it might be different if you already customized it):

    <tr>
    <th align="left" bgcolor="#EAEAEA" style="font-size:13px; padding:3px 9px"><?php echo $this->__('Item') ?></th>
    <th align="left" bgcolor="#EAEAEA" style="font-size:13px; padding:3px 9px"><?php echo $this->__('Sku') ?></th>
    <th align="center" bgcolor="#EAEAEA" style="font-size:13px; padding:3px 9px"><?php echo $this->__('Qty') ?></th>
    <th align="right" bgcolor="#EAEAEA" style="font-size:13px; padding:3px 9px"><?php echo $this->__('Subtotal') ?></th>
    </tr>

And replace with following code

    <thead>
    <tr>
<th align="left" bgcolor="#EAEAEA" style="font-size:13px; padding:3px 9px">&nbsp;</th>
    <th align="left" bgcolor="#EAEAEA" style="font-size:13px; padding:3px 9px"><?php echo $this->__('Item') ?></th>
    <th align="left" bgcolor="#EAEAEA" style="font-size:13px; padding:3px 9px"><?php echo $this->__('Sku') ?></th>
    <th align="left" bgcolor="#EAEAEA" style="font-size:13px; padding:3px 9px"><?php echo $this->__('Unit Price') ?></th>
    <th align="center" bgcolor="#EAEAEA" style="font-size:13px; padding:3px 9px"><?php echo $this->__('Qty') ?></th>
    <th align="right" bgcolor="#EAEAEA" style="font-size:13px; padding:3px 9px"><?php echo $this->__('Subtotal') ?></th>
    </tr>
    </thead>

2. app/design/frontend/base/default/template/email/order/items/order/default.phtml

See line 28, below this line of code (it might be different if you already customized it):

<?php $_order = $this->getItem()->getOrder() ?>

Add the following code

<!-- Show product image -->
<?php
$productid = $_item->getProductId();
$product_id = $productid;
$parentIds = Mage::getModel('catalog/product_type_grouped')->getParentIdsByChild($_item->getProductId()); // check for grouped product
if(count($parentIds)>0 && isset($parentIds[0]))
{
$product_id = isset($parentIds[0])?$parentIds[0]:$productid;
}
        $_product = Mage::getModel('catalog/product')
        ->setStoreId($_item->getOrder()->getStoreId())
        ->load($product_id);
?>
<!-- End Show product image -->

See line 30, above this line of code (it might be different if you already customized it):

<td align="left" valign="top" style="font-size:11px; padding:3px 9px; border-bottom:1px dotted #CCCCCC;">
        <strong style="font-size:11px;"><?php echo $this->escapeHtml($_item->getName()) ?></strong>

Add the following code

<!-- Show product image -->
<td style="vertical-align: middle;">
<a href="<?php echo $_product->getProductUrl(); ?>" ><img src="<?php echo Mage::helper('catalog/image')->init($_product, 'image')->resize(80); ?>" height="80" alt="" /></a>
</td>
<!-- End Show product image -->


See line 48, below this line of code (it might be different if you already customized it):

    <td align="left" valign="top" style="font-size:11px; padding:3px 9px; border-bottom:1px dotted #CCCCCC;"><?php echo $this->htmlEscape($this->getSku($_item)) ?></td>

Add the following code

    <td align="center" valign="top" style="font-size:11px; padding:3px 9px; border-bottom:1px dotted #CCCCCC;">
    <!-- Show Unit Price -->
    <?php
    if ($this->helper('tax')->displaySalesPriceInclTax($_order->getStore())) {
    $itemprice = $this->helper('checkout')->getPriceInclTax($_item) ;
    echo $this->helper('checkout')->formatPrice($itemprice);
    } else {
    echo $this->helper('checkout')->formatPrice($_item->getPrice()) ;
    }
    ?>
    <!-- END Unit Price -->
    </td>

3. app/design/frontend/base/default/layout/sales.xml

Open the above file and find for "sales_email_order_items".

    <action method="setLabelProperties"><value>colspan="3" align="right" style="padding:3px 9px"</value></action>

and replaced with following or just change colspan as per your extra columns added.

    <action method="setLabelProperties"><value>colspan="5" align="right" style="padding:3px 9px"</value></action>

Upload all files, clear cache and get expected output! :)