Welcome to our Magento blog!

In order to help store owner easily ship products to customers after they purchase in Shopping cart site, Magento offers Shipping caculation platform to add more shipping methods. Thus, to complete the checkout process on a store, I think it is also necessary to understand Magento calculate shipping well. Let’s read my artilce today for more details!

Related post: Top 10 best Magento shipping extensions 2018

1. Magento calculate shipping rates

Magento calculates Shipping rate throught the Insance Model of each shipping method. So, shipping method is checked whether to be active or not. It will be estimated the fee by collectRates() of Instance model. You could follow one typicle example with module Mage_Shipping_Model_Carrier_Tablerate. You can see the collectRates() method:

/**
* 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;
}

// exclude Virtual products price from Package value if pre-configured
if (!$this->getConfigFlag('include_virtual_price') && $request->getAllItems()) {
foreach ($request->getAllItems() as $item) {
if ($item->getParentItem()) {
continue;
}
if ($item->getHasChildren() && $item->isShipSeparately()) {
foreach ($item->getChildren() as $child) {
if ($child->getProduct()->isVirtual()) {
$request->setPackageValue($request->getPackageValue() - $child->getBaseRowTotal());
}
}
} elseif ($item->getProduct()->isVirtual()) {
$request->setPackageValue($request->getPackageValue() - $item->getBaseRowTotal());
}
}
}

// Free shipping by qty
$freeQty = 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()) {
$freeQty += $item->getQty() * ($child->getQty() - (is_numeric($child->getFreeShipping()) ? $child->getFreeShipping() : 0));
}
}
} elseif ($item->getFreeShipping()) {
$freeQty += ($item->getQty() - (is_numeric($item->getFreeShipping()) ? $item->getFreeShipping() : 0));
}
}
}

if (!$request->getConditionName()) {
$request->setConditionName($this->getConfigData('condition_name') ? $this->getConfigData('condition_name') : $this->_default_condition_name);
}

// Package weight and qty free shipping
$oldWeight = $request->getPackageWeight();
$oldQty = $request->getPackageQty();

$request->setPackageWeight($request->getFreeMethodWeight());
$request->setPackageQty($oldQty - $freeQty);

$result = Mage::getModel('shipping/rate_result');
$rate = $this->getRate($request);

$request->setPackageWeight($oldWeight);
$request->setPackageQty($oldQty);

if (!empty($rate) && $rate['price'] >= 0) {
$method = Mage::getModel('shipping/rate_result_method');

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

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

if ($request->getFreeShipping() === true || ($request->getPackageQty() == $freeQty)) {
$shippingPrice = 0;
} else {
$shippingPrice = $this->getFinalPriceWithHandlingFee($rate['price']);
}

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

$result->append($method);
}

return $result;
}

The table rate method calculates shipping rates based on the combination of several conditions. The rate is upon Weight vs. Destination, Price vs. Destination, or # of Items vs. Destination (site admin can configurate for that). The method above gets configuration and rate data from database to calculate.

2. Add custom shipping method rates

To add new shipping method to Magento system, you need to follow 2 steps. At first, you need to add configuration for your method (config.xml):

...

<[CUSTOM_SHIPPING_CODE]>
1

[CUSTOM_MODULE]/carrier_[SHIPPING_MODEL]
100
250
[CUSTOM_SHIPPING_CODE]
0
US
1
Sorry! We don't support in this country.
<!--&#91;CUSTOM_SHIPPING_CODE&#93;-->

And if you want to show configuration for admin to edit, add the file system.xml:


&lt;[CUSTOM_SHIPPING_CODE] translate="label" module="shipping"&gt;
<label>New Shipping Method!</label>
text
13
1
1
1

<label>Enabled</label>
select
adminhtml/system_config_source_yesno
1
1
1
1

&lt;br /&gt; &lt;label&gt;Title&lt;/label&gt;&lt;br /&gt; &lt;frontend_type&gt;text&lt;/frontend_type&gt;&lt;br /&gt; &lt;sort_order&gt;2&lt;/sort_order&gt;&lt;br /&gt; &lt;show_in_default&gt;1&lt;/show_in_default&gt;&lt;br /&gt; &lt;show_in_website&gt;1&lt;/show_in_website&gt;&lt;br /&gt; &lt;show_in_store&gt;1&lt;/show_in_store&gt;&lt;br /&gt;
...

<label>Shipping title</label>
text
5
1
1
1

<label>Shipping code</label>
text
6
1
1
1

<label>Ship to applicable countries</label>
select
adminhtml/system_config_source_shipping_allspecificcountries
90
1
1
1

<label>Ship to Specific countries</label>
multiselect
adminhtml/system_config_source_country
91
1
1
1

<label>Show method if not applicable</label>
select
adminhtml/system_config_source_yesno
92
1
1
1

<label>Show method if not applicable</label>
textarea
99
1
1
1

<!--&#91;CUSTOM_SHIPPING_CODE&#93;-->

Secondly, you need to write the model carrier for your shipping method. In this model please write two methods (collectRates and getAllowedMethods):

class [FULL_CUSTOM_MODULE]_Model_Carrier_[SHIPPING_MODEL]
extends Mage_Shipping_Model_Carrier_Abstract
implements Mage_Shipping_Model_Carrier_Interface
{
protected $_code = '[CUSTOM_SHIPPING_CODE]';

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

$result = Mage::getModel('shipping/rate_result');

$method = Mage::getModel('shipping/rate_result_method');

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

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

/** Custom shipping method rate calculation and set for method */
$method->setPrice('1.00');
$method->setCost('1.00');

$result->append($method);
return $result;
}

public function getAllowedMethods() {
return array('[CUSTOM_SHIPPING_CODE]'=>$this->getConfigData('name'));
}
}

Thanks much for your reading! If you want to read more articles on Magento developer exam, visit our Magento blog.

Author

Why Magestore? We believe in building a meaningful & long-term relationship with you.

10 Comments

  1. i regularly read your tutorial and i am planning to give certification exam after completion of your 10 topics if you think i have to read anything extra or if you can recommend me any extra thing for reading regarding certification please do need full.

    thanks

    • Hello Jimin,
      To be well-prepared for Magento certificate exam, I think you’d better read other books about Mangento (you can search them on the Internet). Besides, it’s great if you can read more about the code of specific areas that exam covers according to Magento guide.
      Hope you succeed and good luck to you!

  2. Hi David.

    Good post. Waiting for next chapter 🙂

    Thank you 🙂

  3. Great article! Please consider using some code formatter or highlighter, it seems to be messed out and difficult to read.

    Thanks

  4. hi david after upgrading your site in this post i think syntax highlighter destroy your code for specific xml file please edit this to code=xml so it gives exact code in this post

  5. hi david,
    check this post carefully,in this post some XML code not showing properly because of that reason i told you syntax highlighter spoil your some code and your post is valuable for readers.

    1

    [CUSTOM_MODULE]/carrier_[SHIPPING_MODEL]
    100
    250
    [CUSTOM_SHIPPING_CODE]
    0
    US
    1
    Sorry! We don’t support in this country.

    and below section of this part.

    • Hello Jaimin,

      Sorry for the inconvenience. We’ve updated our blog interface and it’s a little different from the old one. I’ve edited all code paragraphs in the post. Thanks for your following!

  6. Hi David, the Mage_Shipping_Model_Carrier_Interface seams to have two methods:

    public function isTrackingAvailable();
    and
    public function getAllowedMethods();

    Your class have only two methods:
    public function collectRates and public function getAllowedMethods
    Isn’t that a mistake?

    Thanks for the tuts!!

    • Hi,
      Thanks for your comment. The class Mage_Shipping_Model_Carrier_Interface has two methods that need to be implemented. They are isTrackingAvailable() and getAllowedMethods(). But my custom carrier extends from class Mage_Shipping_Model_Carrier_Abstract and it defined method isTrackingAvailable(). Thus you can choose to rewrite this method or not.

Write A Comment