Support for Drupal 7 is ending on 5 January 2025—it’s time to migrate to Drupal 10! Learn about the many benefits of Drupal 10 and find migration tools in our resource center.
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.
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.
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.....
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 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.
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
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.
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 : )
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.
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,
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?
#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.
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.
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:
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;
Comments
Comment #1
lodey CreditAttribution: lodey commentedI 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.
Comment #2
lodey CreditAttribution: lodey commentedAlso 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"
}
}
]
}
}
Comment #3
bmx269 CreditAttribution: bmx269 commentedThis 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?
Comment #4
ardnet CreditAttribution: ardnet commentedsubscribe
Comment #5
jlhs CreditAttribution: jlhs commentedThankyou 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
Comment #6
lodey CreditAttribution: lodey commentedHi 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.
Comment #7
jlhs CreditAttribution: jlhs commentedOh 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
Comment #8
lodey CreditAttribution: lodey commentedRandy'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.
Comment #9
jlhs CreditAttribution: jlhs commentedNo,
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
Comment #10
rszrama CreditAttribution: rszrama commentedFor 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.
Comment #11
jlhs CreditAttribution: jlhs commentedThankyou 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 : )
Comment #12
rszrama CreditAttribution: rszrama commentedhehe 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. : )
Comment #14
lpalgarvio CreditAttribution: lpalgarvio commentedupdated European Union set with latest list, 2007 (EL=GR, UK=GB)
http://en.wikipedia.org/wiki/Member_state_of_the_European_Union
Comment #15
lpalgarvio CreditAttribution: lpalgarvio commentedadded a feature
Comment #16
Devline CreditAttribution: Devline commentedAn 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.
Comment #17
josephcvh CreditAttribution: josephcvh commentedHi guys,
Any way to set shipping rates for each states at Malaysia? The charges to different states are vary.
Thanks,
Joseph
Comment #18
lanquarem CreditAttribution: lanquarem commentedThanks a lot, you saved my day !
Comment #19
stevieb CreditAttribution: stevieb commentedThank 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
Comment #20
stevieb CreditAttribution: stevieb commentedahh it's easier just to "Negate" the "European Union Countries" condition than make a rest of the world condition
Comment #21
zoraxHi 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,
Comment #22
Joni Haeck CreditAttribution: Joni Haeck commentedWhen 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?
Comment #23
1kubik CreditAttribution: 1kubik commented#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)
ZONE 3 (others)
Comment #24
aeremeev CreditAttribution: aeremeev commented#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!
Comment #25
ketan404 CreditAttribution: ketan404 commentedWe 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.
Comment #26
stesind CreditAttribution: stesind commentedI wrote a module to choose the countries from a list. You can install it from my sandbox: https://drupal.org/sandbox/stesind/2208841
Comment #27
andyg8 CreditAttribution: andyg8 commentedWe'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.
Comment #28
fiable.biz worker CreditAttribution: fiable.biz worker commentedSubscriping
Comment #29
hosais CreditAttribution: hosais commentedThank 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:
Hope this will help some people.
Comment #30
subetha_de CreditAttribution: subetha_de as a volunteer commented#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: