Our customer currently sells artificial grass and has 3 different shipping zones set up depending on where in the UK the order is being shipped.
They’ve now decided to also sell accessories, but they want the shipping to work the following way:
A flat delivery cost on any purchase of these accessories nationwide
will be £10 if the customer is purchasing accessories only (no grass
sale). If the customer is purchasing a grass sale and accessories at
the same time then there will only be the grass delivery charge to be
added as they will be delivered at the same time.
Is this possible?
I have found a solution, I added the following code to my functions.php file in my child theme:
add_filter('woocommerce_package_rates', 'specific_products_shipping_methods', 10, 2);
function specific_products_shipping_methods($rates, $package) {
$terms = array('grass');
$taxonomy = 'product_cat';
$method_instances_ids = array('flat_rate:9', 'flat_rate:10', 'flat_rate:11');
$found = false;
foreach($package['contents'] as $cart_item) {
if (has_term($terms, $taxonomy, $cart_item['product_id'])) {
$found = true;
break;
}
}
if (! $found) return $rates;
foreach($rates as $rate_id => $rate) {
if (in_array($rate_id, $method_instances_ids)) {
unset($rates[$rate_id]);
}
}
return $rates;
}
This hides the accessories shipping options if there is a grass product in the cart.
Related
i have a small problem. In my project a few months ago i used add_filter to filtering payments methods based on shipping. I have shipping methods for cash on delivery packages so I hide online payments methods if customer select one of this methods. My code:
add_filter('woocommerce_available_payment_gateways','gateway_disable_for_shipping_rate', 10);
function gateway_disable_for_shipping_rate($available_gateways)
{
if (!is_admin()) {
$chosen_methods = WC()->session->get('chosen_shipping_methods');
$chosen_shipping = $chosen_methods[0];
// some conditionals...
}
return $available_gateways;
}
Today i must add fees based on payment method. I realize that with this code:
add_action('woocommerce_cart_calculate_fees', 'add_checkout_fee_for_gateway', 10);
function add_checkout_fee_for_gateway()
{
if (is_admin() && !defined('DOING_AJAX')) {
return;
}
$cart = WC()->cart;
// RESET
$cart->fees_api()->set_fees([]);
// END RESET
$chosen_gateway = WC()->session->get('chosen_payment_method');
if ($chosen_gateway === 'paypal') {
$tax = $cart->subtotal * 0.05;
$cart->add_fee('PayPal', $tax);
} else if ($chosen_gateway === 'eh_stripe_pay') {
$tax = $cart->subtotal * 0.02;
$cart->add_fee('Stripe', $tax);
} else if ($chosen_gateway === 'cod') {
$tax = $cart->subtotal * 0.02;
$cart->add_fee('COD', $tax);
}
}
add_action('wp_footer', 'refresh_checkout_on_payment_methods_change');
function refresh_checkout_on_payment_methods_change()
{
if ( ! ( is_checkout() && ! is_wc_endpoint_url() ) )
return;
?>
<script type="text/javascript">
(function($){
$('form.checkout').on('change', 'input[name^=\'payment_method\']', function(){
$(document.body).trigger('update_checkout');
});
$('form.checkout').on('change', 'input[name^=\'shipping_method\']', function(){
$(document.body).trigger('update_checkout');
});
})(jQuery);
</script>
<?php
}
And problem is with fee. Scenario:
I change shipping method. Shipping method has payment via paypal. I check this and fee is added to total price -> good.
Now i change shipping method. Now shipping method has only payment via cod. My fee is not update.
My fee updates only if i can click to payment method, if i cant click - not update.
I log this and i think actions to calculate fee run first, before run filtering.
So i have 'checked method' and calculate fee, but after run filter this method is disabled but calculates for fee are already saved. If i change methods many times always calculate fee based on previous method, not current checked.
Small example:
https://vimeo.com/720301741
I would like to create a plugin to add 2 shortcodes to my woocommerce shop so I can add the shipping cost as shortcode in text like this example:
Our shipping costs to Amsterdam is [shipping_cost_1] Euro
So on front end the text will be like this: Our shipping costs to Amsterdam is 6,95 Euro
These are the rates and shortcodes I want to use:
[shipping_cost_1] = flat rate woocommerce shipping cost including VAT for shipping zone 1 (shipping inside Amsterdam)
[shipping_cost_2] = flat rate woocommerce shipping cost including VAT for shipping zone 2 (shipping outside Amsterdam)
For reference, this is where the shipping costs for Amsterdam are displayed on the checkout page:
I would like to add the code in the following structure:
// The shortcode function
function shipping_cost_display_1() {
// Get shipping cost from woocommerce
???
// Ad code returned
???
// Register shortcode
add_shortcode('shipping_cost_1', 'shipping_cost_display_1');
just wondering if you checked this article already: WooCommerce: Show Shipping Rates # Single Product Page?
Basically you can get the shipping zones with a simple command:
WC_Shipping_Zones::get_zones();
Once you have them, you can loop over the array and find rates inside ($instance['cost']).
The following should do the trick for you - of course change "amsterdam" to your desired zone name:
function shipping_cost_display_1() {
$zones = WC_Shipping_Zones::get_zones();
foreach ( $zones as $zone_id => $zone ) {
if ( "amsterdam" !== $zone['zone_name'] ) continue;
$zone_shipping_methods = $zone['shipping_methods'];
foreach ( $zone_shipping_methods as $index => $method ) {
$instance = $method->instance_settings;
return $instance['cost'];
}
}
}
add_shortcode( 'shipping_cost_1', 'shipping_cost_display_1' );
There is also to say that the same shortcode could be used to return the two rates, by using a shortcode parameter.
What's the best way to set up a flat rate shipping fee up to a certain dollar amount, and then free shipping over that dollar amount? I'd like to set it up like this: $15 shipping for all items in their cart if cart is less than $50, free shipping on orders over $50. Thanks!
You can achieve this with following way
Config the flat rate in WooCommerce zone
Config the Free shipping with minimum order amount $50
Use below code snippet to hide Flate rate if the cart total is above $50
add_filter('woocommerce_package_rates', 'hide_flat_rate_based_on_cart_total', 10, 3);
function hide_flat_rate_based_on_cart_total( $available_shipping_methods, $package ){
$price_limit = 50;
if( WC()->cart->get_total() > $price_limit ){
foreach($available_shipping_methods as $method_key => $method){
if ( strpos($method->method_id, 'flat_rate' ) !== false) {
unset($available_shipping_methods[$method_key]);
}
}
}
return $available_shipping_methods;
}
How to make woocommerce always show price including tax based on shop location and only in checkout would woocommerce show price depends on user country.
It is possible?
Thank you
A lot later, just in case someone else still needs it.
I don't know if you can show prices based on the shop location only before the checkout, but you can surely assign a default country to the user if they have never bought before.
If they are returning customers, it's right they see the taxes according to their country, if not so it's not a so bad idea to assign them as a default country the shop country.
Translated in code:
add_filter( 'default_checkout_billing_country',function( $country ){
if ( WC()->customer->get_is_paying_customer() ) {
return $country;
}
return wc_get_base_location()['country'];
} );
add_action('woocommerce_add_to_cart' ,function(){
if( !WC()->customer->get_is_paying_customer() ) {
$country = wc_get_base_location()['country'];
WC()->customer->set_billing_country( $country );
}
} );
It's easy to find how to hide other shipping methods when free shipping is available. But I would like to hide other shipping methods when flat rate is available (I have custom other methods).
Can you help please ?
regards
The code below is modified from this article :
add_filter('woocommerce_package_rates', 'xa_hide_shipping_rates_when_flat_rate_is_available', 10, 2);
function xa_hide_shipping_rates_when_flat_rate_is_available($rates, $package) {
global $woocommerce;
$version = "2.6";
if (version_compare($woocommerce->version, $version, ">=")) {
foreach($rates as $key => $value) {
$key_part = explode(":", $key);
$method_title = $key_part[0];
if ('flat_rate' == $method_title) {
$flat_rate_shipping = $rates[$key];
// Unset all rates.
$rates = array();
// Restore flat rate shipping rate.
$rates[$key] = $flat_rate_shipping;
return $rates;
}
}
}
else {
if (isset($rates['flat_rate'])) {
// Below code is for unsetting single shipping method/option.
$flat_rate = $rates['flat_rate'];
// Unset all rates.
$rates = array();
// Restore flat rate shipping rate.
$rates['flat_rate'] = $flat_rate;
}
}
return $rates;
}
I am not sure which WooCommerce version you are using but I have tested for version 2.6 but not the versions before it.