Magento – Add a shipping option with product attributes

I have been playing with Magento for couple days, and trying to understand the code inside it. It looks quite complicate.. probably because I am not really familiar with its frameworks. Basically it is PHP, but since files and functions are breaking up, and I have hard time to read its documentation, I actually still stuck how to start with it… Here is my task: I want to add a shipping option when my item is a small item (so that I don’t have to send it as parcel and save some bucks for customer). I have already defined two shipping option: Hong Kong Post Air Parcel and Hong Kong Speed Post. Here is my solution:

First, I added a new Tablerate table to my database.

CREATE TABLE shipping_tablerate2 (
  `pk` int(10) unsigned NOT NULL auto_increment,
  `website_id` int(11) NOT NULL default '0',
  `dest_country_id` varchar(4) NOT NULL default '0',
  `dest_region_id` int(10) NOT NULL default '0',
  `dest_zip` varchar(10) NOT NULL default '',
  `condition_name` varchar(20) NOT NULL default '',
  `condition_value` decimal(12,4) NOT NULL default '0.0000',
  `price` decimal(12,4) NOT NULL default '0.0000',
  `cost` decimal(12,4) NOT NULL default '0.0000',
  PRIMARY KEY  (`pk`),
  UNIQUE KEY `dest_country` (`website_id`,`dest_country_id`,`dest_region_id`,`dest_zip`,`condition_name`,`condition_value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Because I want to create seperate tablerate for each option, so I must add a new table to the database.

Ok next I need to add module for this tablerate. There are many ways, but I just duplicated from the original tablerate module, and not sure if this is a correcy way.

The original module are located at:
app\code\core\Mage\Shipping\Model\Carrier\Tablerate.php
app\code\core\Mage\Shipping\Model\Mysql4\Carrier\Tablerate.php
app\code\core\Mage\Shipping\Model\Mysql4\Carrier\Tablerate\Collection.php
\app\code\core\Mage\Adminhtml\Model\System\Config\Backend\Shipping\Tablerate.php
\app\code\core\Mage\Adminhtml\Model\System\Config\Source\Shipping\Tablerate.php

and my module files are located at:
\app\code\core\Mage\Shipping\Model\Carrier\Tablerate2.php
\app\code\core\Mage\Shipping\Model\Mysql4\Carrier\Tablerate2.php
\app\code\core\Mage\Shipping\Model\Mysql4\Carrier\Tablerate2\Collection.php
\app\code\core\Mage\Adminhtml\Model\System\Config\Backend\Shipping\Tablerate2.php
\app\code\core\Mage\Adminhtml\Model\System\Config\Source\Shipping\Tablerate2.php

Both module files are basically the same, except I changed all “tablerate” to “tablerate2” inside each files. (so they will access the correct database table)

We also need to edit these files, but I am not going to go through this much:
\app\code\core\Mage\Shipping\etc\config.xml
\app\code\core\Mage\Shipping\etc\system.xml

So now, my products have an attribute which I defined in my admin panel called “small_item”, and it is a YesNo Option. I went through many sites and forum, but couldn’t really find what the value YesNo Attribute is, but I assume it is usually “Yes”, “No” or 1, 0. Furthermore, I am not really sure what is the correct way to retrieve the attribute… Finally I found a function getData(attribute_name), and it seems working for me.

Ok, once again, my task is I want to add a new table rate method for shipping small item that if the product attribute of “small_item” has value “yes”.

The file I edited is:
\app\code\core\Mage\Shipping\Model\Carrier\Tablerate2.php

I added a new function at the end of the file:

protected function checkSmallPacket($request) {
	$items = $request->getAllItems();
	foreach ($items as $item) { //get each item from the shopping cart
		$_product=$item->getProduct(); 
		$_product->load($_product->getId()); // load attribute for the product
		if ($_product->getData('small_item') == "0") // so if I found any attribute is "0"(No), 
			return false; //then return false because there is a item not valid for this shipping method
	}
	return true; // all item valid for this shipping method
}

I also modified the collectRate function:

 public function collectRates(Mage_Shipping_Model_Rate_Request $request)
 {
if (!$this->getConfigFlag('active')) {
      return false;
 }

  if (!$request->getConditionName()) {
            $request->setConditionName($this->getConfigData('condition_name') ? $this->getConfigData('condition_name') : $this->_default_condition_name);
        }
$result = Mage::getModel('shipping/rate_result');
 $rate = $this->getRate($request);
		
$smallShippingOk = $this->checkSmallPacket($request); // Check if all item ok for small packet shipping
		
if (!empty($rate) && $rate['price'] >= 0 && $smallShippingOk) { // Add Condition
      $method = Mage::getModel('shipping/rate_result_method');

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

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

            $shippingPrice = $this->getFinalPriceWithHandlingFee($rate['price']);

            $method->setPrice($shippingPrice);
            $method->setCost($rate['cost']);

            $result->append($method);
        }

        return $result;
    }

$_product->getData(‘small_item’) actually return “0” or “1” (not integer, but string???), but I guess it is good enough for my task. I am sure there is a better way to do this, but can someone tell me? This module actually working well, but I haven’t fully tested it yet.

Post to Twitter Post to Plurk Post to Yahoo Buzz Post to Delicious Post to Digg Post to Facebook Post to MySpace Post to Ping.fm Post to Reddit Post to StumbleUpon

2 thoughts on “Magento – Add a shipping option with product attributes

  1. I am not sure if the Tablerate table structure is still same in the newer version of Magento, but to create a new Tablerate table to your database, usually can be done with any SQL clients, or most likely phpMyAdmin if your server has phpMyAdmin installed.

    Sunny

Leave a Reply