Set Minimum Order Price for Shipping Method in Magento

htmljavascriptPHPshippingshipping-methods

I want to set a minimum order amount for a specific shipping method.
I want a specific shipping method to get enable when subtotal price of order reaches to the specific price which I had set before just like minimum order amount in payment methods.

i added this code to app/code/core/Mage/Shipping/etc/system.xml –> <config><sections><carriers><groups><flatrate><fields>:

<min_order_total translate="label">
        <label>Minimum Order Total</label>
        <frontend_type>text</frontend_type>
        <sort_order>157</sort_order>
        <show_in_default>1</show_in_default>
        <show_in_website>1</show_in_website>
        <show_in_store>0</show_in_store>
</min_order_total>

and i added this code to app/code/core/Mage/Shipping/etc/config.xml–> <config><default><carriers><flatrate>:

<min_order_total>0</min_order_total>

and added this code to app/code/core/Mage/Shipping/Model/Carrier/Flatrate.php

$total = $this->getQuote()->getBaseGrandTotal();
$minTotal = $this->getConfigData('min_order_total');

if(!empty($minTotal) && ($total < $minTotal)) {
    return false;
}

now my Flatrate.php look like this:

<?php
/**
 * Magento
 *
 * NOTICE OF LICENSE
 *
 * This source file is subject to the Open Software License (OSL 3.0)
 * that is bundled with this package in the file LICENSE.txt.
 * It is also available through the world-wide-web at this URL:
 * http://opensource.org/licenses/osl-3.0.php
 * If you did not receive a copy of the license and are unable to
 * obtain it through the world-wide-web, please send an email
 * to license@magento.com so we can send you a copy immediately.
 *
 * DISCLAIMER
 *
 * Do not edit or add to this file if you wish to upgrade Magento to newer
 * versions in the future. If you wish to customize Magento for your
 * needs please refer to http://www.magento.com for more information.
 *
 * @category    Mage
 * @package     Mage_Shipping
 * @copyright  Copyright (c) 2006-2014 X.commerce, Inc. (http://www.magento.com)
 * @license    http://opensource.org/licenses/osl-3.0.php  Open Software License (OSL 3.0)
 */


/**
 * Flat rate shipping model
 *
 * @category   Mage
 * @package    Mage_Shipping
 * @author      Magento Core Team <core@magentocommerce.com>
 */
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)
    {
        $total = $this->getQuote()->getBaseGrandTotal();
        $minTotal = $this->getConfigData('min_order_total');

        if(!empty($minTotal) && ($total < $minTotal)) {
            return false;
        }

        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);

        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'));
    }

}

but i get this error : Fatal error: Call to a member function getBaseGrandTotal() on a non-object in app/code/core/Mage/Shipping/Model/Carrier/Flatrate.php on line 51.
How do I solve this?

Best Answer

In the payment methods is done by this way - in each payment method in etc/system.xml there is this code:

                <min_order_total translate="label">
                    <label>Minimum Order Total</label>
                    <frontend_type>text</frontend_type>
                    <sort_order>98</sort_order>
                    <show_in_default>1</show_in_default>
                    <show_in_website>1</show_in_website>
                    <show_in_store>0</show_in_store>
                </min_order_total>

and then in app/code/core/Mage/Payment/Block/Form/Container.php -> protected function _canUseMethod($method):

/**
 * Checking for min/max order total for assigned payment method
 */
$total = $this->getQuote()->getBaseGrandTotal();
$minTotal = $method->getConfigData('min_order_total');
$maxTotal = $method->getConfigData('max_order_total');

if((!empty($minTotal) && ($total < $minTotal)) || (!empty($maxTotal) && ($total > $maxTotal))) {
    return false;
}
return true;

So you can copy this in each shipping method. For an example for Flat Rate shipping method in app/code/core/Mage/Shipping/etc/system.xml -> <flatrate> -> <fields> add this:

                <min_order_total translate="label">
                    <label>Minimum Order Total</label>
                    <frontend_type>text</frontend_type>
                    <sort_order>98</sort_order>
                    <show_in_default>1</show_in_default>
                    <show_in_website>1</show_in_website>
                    <show_in_store>0</show_in_store>
                </min_order_total>

and in app/code/core/Mage/Shipping/Model/Carrier/Flatrate.php -> public function collectRates add this:

$total = $request->getPackageValue();
$minTotal = $this->getConfigData('min_order_total');

if(!empty($minTotal) && ($total < $minTotal)) {
    return false;
}

If you like it for all shipping methods maybe you can think of altering some way app/code/core/Mage/Shipping/Model/Carrier/Abstract.php (not each method one by one).