Question

I'm working on a mobile application, that is creating an order on Magento programmatically through a custom REST implementation, and everything is working fine, except one thing that i can't find any documentation on: How to set the shipping method for the quote that complies with the available shipping method rules.

So for example, from the Magento backend there are 3 shipping methods enabled:

  1. Free - Only when cart amount is above 80 USD
  2. Fixed Rate - Only if Customer is ordering from USA
  3. Tablerate - If the customer is ordering from outside the USA.

What I was doing was as follows (assuming $quote has the quote built up and the products added to it):

$shippingAddress = $quote->getShippingAddress()->addData($shipping_address);    

$methods = Mage::getSingleton('shipping/config')->getActiveCarriers();
foreach($methods as $_code => $_method){
    // Get the first allowed method of this shipping carrier
    $m = key($_method->getAllowedMethods()); 
    $shipping_method = $_code . '_' . $m;
    break;
}

$quote->collectTotals();
$shippingAddress->setWeight( $weights )
                ->setFreeMethodWeight( $weights )
                ->setShippingMethod( $shipping_method );

Which is kinda retarded, I'm simply getting all ActiveCarriers, and assigning the first one to the quote, which can work in simple scenarios. However, in this example, the first Active Carrier won't work, because i'm not validating the country rules or free shipping rules. So my question is, how can I get the best (and valid) shipping methods for this quote. Is there any built-in function or helper method that I can use?

I'm assuming that I don't want to give the option to the customer to select the shipping method. I want to just assign the complying shipping method to the quote.

Was it helpful?

Solution

To get only applicable shipping methods for a given quote (based on the quote id) you can utilize Mage_Checkout_Model_Cart_Shipping_Api's method getShippingMethodsList.

This method expects two (one) params:

  • $quoteId
  • $store=null

It will return an array of available shipping methods looking like this:

array(1) {
  [0]=>
  array(9) {
    ["carrier"]=>
    string(8) "flatrate"
    ["carrier_title"]=>
    string(9) "Flat Rate"
    ["code"]=>
    string(17) "flatrate_flatrate"
    ["method"]=>
    string(8) "flatrate"
    ["method_description"]=>
    NULL
    ["price"]=>
    string(6) "5.0000"
    ["error_message"]=>
    NULL
    ["method_title"]=>
    string(5) "Fixed"
    ["carrierName"]=>
    string(9) "Flat Rate"
  }

Yet, there are two points that need your attention:

You may not display table rates shipping methods if not applicable (set Show Method if Not Applicable to No as this may bring up some unwanted results [untested - might not even be necessary!]).

According to your description of the existing shipping methods at one point there is more then one shipping method applicable - namely, when the cart amount is above 80 USD. In this case (depending on the shipping country) Free AND either Fixed Rate or Tablerate is (or may be) applicable (since conditions may be fulfilled for both methods). This in return would provide an array count of 2. However, you could address this issue by setting up a sort order where the preferred shipping method would be placed before the second/third possible one (this is possible because the sort order is respected in the output of getShippingMethodsList() already). Hence you would be able to always get the shipping method most relevant to you from array key [0] of the method's output.

Since the setup of your methods (sort orders and so on) may require a tiny bit of testing and/or fine tuning - and to see it in action - I'd like to invite you to try it out directly in your checkout, i.e. by placing something like this in your frontend/{theme}/{theme}/template/checkout/onepage/shipping_method/available.phtml

<?php $quoteId = Mage::getSingleton('checkout/session')->getQuote()->getId(); ?>
<?php $storeId = Mage::app()->getStore()->getStoreId(); ?>
<pre>
<?php var_dump(Mage::getModel('checkout/cart_shipping_api')->getShippingMethodsList($quoteId,$storeId)); ?>
</pre>
Licensed under: CC-BY-SA with attribution
Not affiliated with magento.stackexchange
scroll top