Product level shipping in Magento

By default Magento don’t let you set shipping cost per product level. You can do it by using some technique with flatrate shipping method.

Step 1: Create attribute.
Create a attribute from admin panel catalog->attributes, lets give it a name shipping_world and add this attribute to your default “attribute set” to do that go to catalog -> “attribute set” click your default attribute set then drag shipping_world attribute and drop in attribute tree in left.

Step 2: Edit Flatrate Module.
overwrite/extend the flatrate carrier model of magento or just open file app/code/core/Mage/Shipping/Model/Carrier/Flatrate.php

class Mage_Shipping_Model_Carrier_Flatrate
    extends Mage_Shipping_Model_Carrier_Abstract
    implements Mage_Shipping_Model_Carrier_Interface
{

    protected $_code = 'flatrate';
    protected $_isFixed = true;

    /**
     * Enter description here...
     *
     * @param Mage_Shipping_Model_Rate_Request $data
     * @return Mage_Shipping_Model_Rate_Result
     */
    public function collectRates(Mage_Shipping_Model_Rate_Request $request)
    {
        if (!$this->getConfigFlag('active')) {
            return false;
        }

        $freeBoxes = 0;
        if ($request->getAllItems()) {
            foreach ($request->getAllItems() as $item) {

                if ($item->getProduct()->isVirtual() || $item->getParentItem()) {
                    continue;
                }

                if ($item->getHasChildren() && $item->isShipSeparately()) {
                    foreach ($item->getChildren() as $child) {
                        if ($child->getFreeShipping() && !$child->getProduct()->isVirtual()) {
                            $freeBoxes += $item->getQty() * $child->getQty();
                        }
                    }
                } elseif ($item->getFreeShipping()) {
                    $freeBoxes += $item->getQty();
                }
            }
        }
        $this->setFreeBoxes($freeBoxes);

        $result = Mage::getModel('shipping/rate_result');
        if ($this->getConfigData('type') == 'O') { // per order
            $shippingPrice = $this->getConfigData('price');
        } elseif ($this->getConfigData('type') == 'I') { // per item
            $shippingPrice = ($request->getPackageQty() * $this->getConfigData('price')) - ($this->getFreeBoxes() * $this->getConfigData('price'));
        } else {
            $shippingPrice = false;
        }
		
        $shippingPrice = $this->getFinalPriceWithHandlingFee($shippingPrice);
		$shippingPrice = $this->get_pro_ship();

        if ($shippingPrice !== false) {
            $method = Mage::getModel('shipping/rate_result_method');

            $method->setCarrier('flatrate');
            $method->setCarrierTitle($this->getConfigData('title'));

            $method->setMethod('flatrate');
            $method->setMethodTitle($this->getConfigData('name'));

            if ($request->getFreeShipping() === true || $request->getPackageQty() == $this->getFreeBoxes()) {
                $shippingPrice = '0.00';
            }


            $method->setPrice($shippingPrice);
            $method->setCost($shippingPrice);

            $result->append($method);
        }

        return $result;
    }

    public function getAllowedMethods()
    {
        return array('flatrate'=>$this->getConfigData('name'));
    }
	
	public function get_pro_ship()
	{
	Mage::getSingleton('core/session', array('name'=>'frontend'));
	$session = Mage::getSingleton('checkout/session');
	$cart_items = $session->getQuote()->getAllItems();
	$_helper = Mage::helper('catalog/output');
 	$custom_ship=0;
	foreach( $cart_items as $items ){
   	
		$cur_fproduct = Mage::getModel('catalog/product')->load($items->getProduct_id());
	$custom_ship +=($items->getQty())*($_helper->productAttribute($cur_fproduct, $cur_fproduct->getShippingWorld(), 'shipping_world'));						
	}
		
		
	return $custom_ship ;	
		
	}// function end

}

The value given in shipping_world attribute of product will be the flat shipping rate of that product.
That’s it. Clear cache and add/edit product where you can input shipping_world value in for each product. value must be numeric without space. then that value will be the shipping flate rate of products. checkingout with multiple product will add all shipping costs per item basis.

  • pepper

    In which file should I paste this code?

    • Anonymous

      You can simply replace the code of flaterate model class located in /app/code/core/Mage/Shipping/Model/Carrier/Flatrate.php with above code.

      • Alessandro

         Dear Sir,

        The flatrate replacement script works perfectly. There is only one problem. During checkout the total final price does not include the shipment price. It just doesn’t get displayed. The total price is calculated as it is shown during payment. It only doesn’t get displayed in the last step in checkout. How can I get the final price displayed correctly during checkout? I’m using Magento 1.6.1.0

        With kind regards,

        Alessandro

        • Brian

          Possibly Make sure your attribute for the flatrate shipping is set to “price”

  • Mike

    can you explain in more details what i would have to do. and just to confirm this would allow me to set per product shipping right?

    • http://blog.aajit.com M. Ashraful Abedien

      Simply add a attribute name it “shipping_world” to ur attribute set (from back-end catelog->attributes then attribute set), this will let you add shipping price when u add/edit a product. then replace all codes of /app/code/core/Mage/Shipping/Model/Carrier/Flatrate.php with above code.

  • http://twitter.com/eCommerceCircle Michael J. Kaye

    Great post! Thanks.

  • Levi

    Dude You are a Life Saver. Thanks For doing this. Well Appreciated

  • Crystal

    I tried doing this and it’s not working for me. I created the attribute, copied over the code and enabled flat rate shipping. But it’s just pulling the flat rate from the system config, even after I add in a shipping amount in the product attribute. Using Mag 1.5. Any help appreciated

  • Yash Shah

    Thanks Buddy…Great Post….You Saved my Day.!!!!

  • Yash Shah

    Hey,I have one question….

    I want to show all multi select attribute products on my home page.?
    How can i do this?

    Please help me…

  • Yash Shah

    One More Question….

    I want to show Dynamic Payment Method on Product View Page MEANS for Every Different Product I want Different Dynamic Payment Method i.e whichever payment method is enabled it should be seen on particular product view page.

    Please help if possible…Thank u again for this post.

  • http://pulse.yahoo.com/_NJVH3VT43GVO4IQL3MQCDARGTY Mr B

    Can someone explain how to set the attribute for an already existing product?

    • http://pulse.yahoo.com/_NJVH3VT43GVO4IQL3MQCDARGTY Mr B

       No problem, I figured it out.

  • Michael Hettwer

    Nice Script!

    But I dont want to add the Shipping Costs. I only need the highest shipping price and use it for shipping. Can you give me a hint?

  • Rinku

    when we use this method there is an error occur in admin session.

    Fatal error: Call to a member function getCode() on a non-object in /opt/lampp/htdocs/newmagento/app/code/core/Mage/Adminhtml/Model/System/Config/Source/Shipping/Tablerate.php on line 34

    • http://blog.aajit.com M. Ashraful Abedien

      This error is in table rate. may be u updated the Tablerate.php , above modification is for flatrate. you can test turning off the table rate and only turn on the flatrate.

  • Lakshmanan M

    Thanks for the code…

    Really simple!!!

    After 32 hours of trying other extensions I found this code is very simple and effective..

    I have changed the below line [for community edition version 1.4.1]

    $cur_fproduct = Mage::getModel(‘catalog/product’)->load($items->getProduct_id());

    to

    $cur_fproduct = Mage::getModel(‘catalog/product’)->load($items->getProductId());

  • Sriman

    Hi
    I exactly place the above code to flatrate.php, I create the attributes etc.. everythings seems to be ok when the user isnt logged in but when I go to the cart I have an internal 500 error..
    Any idea please ?

  • JoelB

    I use 1.7 and I get the following error: Fatal error: Call to a member function setStore() on a non-object in /homepages/46/d423041594/htdocs/site/app/code/core/Mage/Shipping/Model/Shipping.php on line 421

    any help would be appreciated

  • Dave

    I’ve got it working with 1.7 fine and I didn’t do anything special. The problem I’m having is I don’t want it to accumulate the total for shipping. So if Item 1 is $10 shipping and item 2 is $20 shipping, total for shipping would be @20. Or if there were 3 items in the cart each with shipping of $10, total for shipping would be $10 not $30. I have selected flatrate per order in the configuration, instead of per item, but it seems to ignore this.

  • Brian

    Awesome, I went ahead and overwrote the core file, If I wanted to make an extension out of this file what else would be involved.

  • Bhooby

    Nice one. Thanks for the code. Can you tell me how to have both Flat rate and individual shipping cost for the products.

  • Paul
  • dhaval

    very nice really good customized
    Thanks a lots………….!

  • Mary Johnson

    Great job in coding. I know it is useful for those users who have some knowledge of it .If you have not enough knowledge of coding you can try this Magento Plug-in http://bit.ly/1w8CuQi and solves the issue of shipping cost through it.

  • rohit

    when i m creating order from backend it is not working pls provide solution for this

  • Dhaval Dave

    its not work in magento 1.9.* , provide some solution for it