Support from Acquia helps fund testing for Drupal Acquia logo

Comments

lodey’s picture

I can help you with the first part, selecting countries to offer the service to, but I'm not sure on the ideal solution for the conditions around size or weight - I've not had to do this yet.

The key is that you need to create your shipping service - then when you create a 'condition' for this service - use the Commerce Order Address Component Comparison option, this will be the set of values you want to check

From here it should be straightforward to select the bits you need.... I used
'Shipping Address'
and
'Country'.

You will then need to specify the country code when specifying the 'value' - this is a 2 letter code (i.e. GB for Great Britain).

You can find the codes if you inspect the html making up the shipping country list on the checkout page, or do a google search and find something similar if you are not comfortable with using firebug or similar.

The next issue you may face is to have multiple countries in that condition :

I just set up a European based version of this and needed to do a condition where I asked if it was any country inside the EU..... this was initially a bit daunting as it looked like I would have to manually repeat that step above for all the countries I wanted to specify - that would be 26 times each time I created a service!! Manual and boring!

My tip here is to go and create a standard (by this I mean not via the shipping module UI pages) rules component set. Here you can build a reusable set of conditions to use later when setting up the shipping service conditions. Rather than build a set there - just reference the one instance. This is great as it is reuseable too.

A time saving tip here to avoid manually using the UI to build all those conditions that are basically the same, but with only the country code changing:

Create the component set > add just one of the countries > then export the Component > looking at the code it is really straight forward to just copy and paste multiple conditions changing just the two letter code each time. When done - import the code and over write the condition - and it will have all those filled in..... much quicker.

I hope that helps you.

At first this seems all a bit complex for regular use --- but this complexity is going to be really useful as Commerce grows..... give it a bit of time and people will create a series of modules to make it easier...... the commerce_conditions module is already heading that way its good to see.

lodey’s picture

Also for those in need - here is the component I created.

This is a list of all EU countries excluding the UK - for me this allowed to work out whether to offer a European delivery service from the UK. It may be of use to you as is - or modify as required.

{ "rules_shipping_europe_countries" : {
"LABEL" : "Shipping Europe Countries",
"PLUGIN" : "or",
"TAGS" : [ "commerce", "countries", "shipping" ],
"REQUIRES" : [ "commerce_order" ],
"USES VARIABLES" : { "commerce_order" : { "label" : "Commerce Order", "type" : "commerce_order" } },
"OR" : [
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "AT"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "BE"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "BG"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "CY"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "CZ"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "DK"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "EE"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "FI"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "FR"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "DE"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "EL"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "HU"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "IE"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "IT"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "LV"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "LT"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "LU"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "MT"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "NL"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "PL"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "PT"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "RO"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "SK"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "SI"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "ES"
}
},
{ "commerce_order_compare_address" : {
"commerce_order" : [ "commerce_order" ],
"address_field" : "commerce_customer_shipping|commerce_customer_address",
"address_component" : "country",
"value" : "SE"
}
}
]
}
}

bmx269’s picture

This ruleset (#2), should be made as a feature, where it allows all countries and states to be added. Say an addon to this module? Ideas?

ardnet’s picture

subscribe

jlhs’s picture

Thankyou very much for sharing Lodey. Sorry I hadn't said thanks earlier.

Thankyou for your clear step by step instructions and the rules to use.

For the ruleset like the European version you have made, would I need to make a module to do this?

If so, I think nodeone.se has rules module creation videos. I have not made a module before.

Thanks from Josh

lodey’s picture

Hi Josh,

No problems - happy to help. You can just use the code above to import a new component.... you don't need to create a module to do it. Head to rules, then you can import new component - paste the code above and you should be away - remember to modify the list of countries to be correct for your needs.

I'm happy to consider putting this into a feature - but to be honest I think that would be too misleading - its only when using from here in the UK that you would want that exact setup of countries - by forcing people to look at the import code, hopefully it is easier to understand how to change to suit your needs.

Out of interest, and if anyone gets a chance to chip in - is there any scope for the actual selection of countries offered by the shipping data selectors to be in a big selectable list..... i.e. the user could just cntrl+click those needed? This would be a big timesaver.....

Hope that helps - good luck.

jlhs’s picture

Oh I see, directly under components and the click the import components link.

Also I had a look at Randy's flat rate shipping video and it looks like I will be able to set up a flatrate for all other countries in the world besides Australia or select countries (Just by the fact that without custom rules put on a flat rate all countries in the world will be hit by the flat rate anyway working hugely in my favor, then Randy had a negating rule, to stop crossover into the targeted countries and vice versa. Randy wasn't setting up world wide shipping, but it should work the same way, all the building blocks are there, now that I understand how shipping flatrate works, I think?) So this will work hugely in my favor (And the favor of others needing similar setup) that I can set a different shipping price for Australia and then different shipping prices for each state if need be within Australia and the rest of the world will get a different flat rate by default the blanket flat rate given by the flat rate shipping module when one makes a flatrate shipping price and saves. Then I should be able to use Commerce extra conditions to target different products of different weights for different flat rates via taxonomy term.

Randy's Video on flat rate shipping
http://www.commerceguys.com/resources/articles/246

The rest of Randy's videos, are here
http://vimeo.com/user5912539/videos/sort:date

lodey’s picture

Randy's videos are really good at showing the basics - they also really show how much of commerce requires a basic understanding of setting up rules.

By the sounds of it - you don't need to import that component set. You basically only need to have a single country - AU - then you can negate it for rest of the world.

jlhs’s picture

No,

I will not need to import the component set for my use case, I will just need to have AU.

I think however you ruleset will come in very handy for others.

I wonder if Africa would also need a ruleset like the one you made for the EU. If making a blanket price for a country?

As for rules, one must have a basic understanding of rules. Thankfully nodeone.se have just release a massive collection of Drupal 7 videos and a HUGE series of Rules videos, which should come in handy http://vimeo.com/nodeone

rszrama’s picture

Status: Active » Fixed

For different rates for different sized products, the problem is that you typically select one shipping service for the whole order. One thing you can do is use a base rate and then use rate calculation rules (from the Calculation rules tab of the Shipping admin interface) to increase a base rate by X amount based on the products on the order. This will get you into advanced Rules territory pretty quickly, tbh, so it's not for the faint of heart. The gist of it is that it's just the same as product pricing, so you'll use the "Add an amount to the unit price" action to increment your shipping line item's unit price based on objects on the order.

Typically, if you have development staff, it will be easier to write custom conditions / actions for more precise tasks.

jlhs’s picture

Thankyou Ryan, for bringing this up, of course, you are absolutely right, I didn't think of it at all. People will have a combination of all different sized products in their cart. Thanks for pointing us in the right direction and for encouraging us to take it to the next level with rules : )

rszrama’s picture

hehe Good luck. I'm glad you're learning so much, and I expect you'll like Node One's videos as you work through them. : )

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.

lpalgarvio’s picture

updated European Union set with latest list, 2007 (EL=GR, UK=GB)
http://en.wikipedia.org/wiki/Member_state_of_the_European_Union

{ "rules_european_union_countries" : {
    "LABEL" : "European Union Countries",
    "PLUGIN" : "or",
    "TAGS" : [ "billing", "commerce", "countries", "shipping" ],
    "REQUIRES" : [ "commerce_order" ],
    "USES VARIABLES" : { "commerce_order" : { "label" : "Commerce Order", "type" : "commerce_order" } },
    "OR" : [
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "AT"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "BE"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "BG"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "CY"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "CZ"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "DK"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "EE"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "FI"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "FR"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "DE"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "GR"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "HU"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "IE"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "IT"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "LV"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "LT"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "LU"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "MT"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "NL"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "PL"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "PT"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "RO"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "SK"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "SI"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "ES"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "SE"
        }
      },
      { "commerce_order_compare_address" : {
          "commerce_order" : [ "commerce_order" ],
          "address_field" : "commerce_customer_shipping|commerce_customer_address",
          "address_component" : "country",
          "value" : "GB"
        }
      }
    ]
  }
}
lpalgarvio’s picture

added a feature

Devline’s picture

An easier way would be to check the current country against a list of countries by adding a new condition, selecting 'Execute custom PHP code' and use the following code which retrieves the commerce customer profile of the shipping address, set a list of countries, and checks if our country belongs to the list.

$profile_wrapper = entity_metadata_wrapper('commerce_customer_profile', [commerce-order:commerce-customer-shipping:profile-id])->value();
$cee = array('BE', 'DE', 'GB', 'LU', 'NL', 'AT', 'ES', 'IT', 'DK', 'FI', 'PT', 'SE', 'CZ', 'EE', 'HU', 'IE', 'LT', 'LV', 'PL', 'RO', 'SI', 'SK', 'BG', 'CY', 'GR', 'MT');
if ( in_array( $profile_wrapper->commerce_customer_address['und'][0]['country'], $cee))  {
  return true;
}
return false ;
josephcvh’s picture

Hi guys,

Any way to set shipping rates for each states at Malaysia? The charges to different states are vary.

Thanks,
Joseph

lanquarem’s picture

Thanks a lot, you saved my day !

stevieb’s picture

Thank you Thank you Thank you

#14 is perfect for me ... I was building each country individually and you saved me headaches

I'll prepare a rest of the world using the same code and post it later

stevie

stevieb’s picture

ahh it's easier just to "Negate" the "European Union Countries" condition than make a rest of the world condition

zorax’s picture

Hi DevLine,
Thank's for your code !It seems the best solution for me
I just wonder, what is the desatvantage to use php filter module in general, because I only need it for adding in rules "Execute custom PHP code".
regards,

Joni Haeck’s picture

When i try to do this, it won't validate and still show the shipping service for a country that is not equal to the one i selected... anybody has the same problem?

1kubik’s picture

#16 works very well!
thanks al lot!!

here a list of all country codes
http://userpage.chemie.fu-berlin.de/diverse/doc/ISO_3166.html

and in addition for #16
the codes for

ZONE 2 (Europe but NOT EU)

 $cee = array('FI','AD','AL','BY','BA','EA','GE','GI','GL','AX','IS','GL','GIR','IC','HR','LI','MK','MD','ME','NO','CH','RU','SM','RS','TR','UK','VA','CY');
 

ZONE 3 (others)

 $cee = array('EG','DZ','AM','AZ','IL','JO','CV','LE','LY','MA','SY','US');
aeremeev’s picture

#16 Worked very well.
It took me a while ot figure it out because I couldn't see the 'Execute custom PHP code' condition in the condition list. I had to enable the PHP Filter module and that did the trick.

Thanks for the solution!

ketan404’s picture

We recently wrote a custom module that uses a CSV file as database to retrieve shipping costs based on shipping country. The module however, does not have an interface to update the csv file.

We find that the csv-matrix file is a faster way of setting the shipping costs.

stesind’s picture

I wrote a module to choose the countries from a list. You can install it from my sandbox: https://drupal.org/sandbox/stesind/2208841

andyg8’s picture

We're using the above code in #16 to great effect for Royal Mail's very difficult shipping rates.

Our developer has suggested one tiny readability improvement to the code, to address the issue addressed here about language support: http://stackoverflow.com/questions/8071525/trying-to-get-value-from-arra...

The code in #16 uses 'und' as an array key. You can access your field's value either using und as an array key or (preferably) use the LANGUAGE_NONE constant (if you're not expecting the site to use languages) as follows:

$profile_wrapper = entity_metadata_wrapper('commerce_customer_profile', [commerce-order:commerce-customer-shipping:profile-id])->value();
$cee = array('BE', 'DE', 'LU', 'NL', 'AT', 'ES', 'IT', 'DK', 'FI', 'PT', 'SE', 'CZ', 'EE', 'HU', 'IE', 'LT', 'LV', 'PL', 'RO', 'SI', 'SK', 'BG', 'CY', 'GR', 'MT');
if ( in_array( $profile_wrapper->commerce_customer_address[LANGUAGE_NONE][0]['country'], $cee)) {
return true;
}
return false ;

This code is for the EU outside the UK.

Hope that might be helpful.

fiable.biz worker’s picture

FileSize
155.97 KB

Subscriping

hosais’s picture

Issue summary: View changes

Thank you Devline, #16 worked great for me.

Just some feedback about the Zip code. Sometimes, in Some country, you may have different price for special area. If you need to check ZIP code for that here is my code that In Spain we do not accept Cueta, Melilla, and Canarias:

$profile_wrapper = entity_metadata_wrapper('commerce_customer_profile', [commerce-order:commerce-customer-shipping:profile-id])->value();
$pattern =  '/51\d{0,3}|52\d{0,3}|35\d{0,3}/';/*zip code of , Ceuta, Melilla, and Canarias */
if (preg_match($pattern, $profile_wrapper->commerce_customer_address[LANGUAGE_NONE][0]['postal_code']) ) {
     return false;
}
return true;

Hope this will help some people.

subetha_de’s picture

#16 was very helpful as inspiration! However the token-replacement did not work in custom PHP code, I could not find the reason.

This is what worked for me, maybe it helps others as well:

$list = array('AD','AL','AM','AX','AZ','BA','BY','CH');
$return = false;
$profile_wrapper = entity_metadata_wrapper('commerce_customer_profile', $commerce_order->commerce_customer_shipping[LANGUAGE_NONE][0]['profile_id'])->value();
$country = ( ! empty($profile_wrapper->commerce_customer_address[LANGUAGE_NONE][0]['country'])) ? $profile_wrapper->commerce_customer_address[LANGUAGE_NONE][0]['country'] : false;
if ( ! empty($country) && in_array($country , $list) == true) $return = true;
return ($return);