I am trying to update the shipping cost after the address is entered. When the client starts typing the address, and autocomplete function helps the client find the street name, building, floor, and side.
Once the address is entered JavaScript calculates the distance and the price.
Then the price is via AJAX send to shipment.php
It is my goal to have shipment update the shipping cost accordingly.
I have tried:
include '../../../../wp-load.php';
add_action( 'woocommerce_flat_rate_shipping_add_rate','add_another_custom_flat_rate', 10, 2 );
function add_another_custom_flat_rate( $method, $rate ) {
$new_rate = $rate;
$new_rate['cost'] = 50; // Update the cost to 50
$method->add_rate( $new_rate );
}
But without luck.
I have also following this guide and added another shipping method: Tuts
https://code.tutsplus.com/tutorials/create-a-custom-shipping-method-for-woocommerce--cms-26098
But once again, I cannot update the price once the address is entered.
I think that You don't need Query ajax to update the price directly for this calculated shipping cost and you don't need a custom shipping method as in your code or linked tutorial.
THERE IS THREE STEPS:
1) In your existing Ajax driven PHP function, you will set the calculated price in a custom WC_Session attribute where $shipping_cost variable will be the collected value of the calculated shipping cost passed via JS Ajax:
WC()->session->set( 'shipping_calculated_cost', $shipping_cost );
Then in jQuery Ajax "on success" event you will update checkout with the following:
$('body').trigger('update_checkout');
That will refresh checkout data…
2) In the custom function hooked in woocommerce_package_rates filer hook, you will get the session value of the calculated shipping cost…
IMPORTANT: In WooCommerce settings > shipping, you will set the "flat rate" cost to 1…
In The function code you will set the default price for this flat rate (that will be used when the shipping cost calculation doesn't exist yet):
add_filter('woocommerce_package_rates', 'update_shipping_costs_based_on_cart_session_custom_data', 10, 2);
function update_shipping_costs_based_on_cart_session_custom_data( $rates, $package ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return $rates;
// SET HERE the default cost (when "calculated cost" is not yet defined)
$cost = '50';
// Get Shipping rate calculated cost (if it exists)
$calculated_cost = WC()->session->get( 'shipping_calculated_cost');
// Iterating though Shipping Methods
foreach ( $rates as $rate_key => $rate_values ) {
$method_id = $rate_values->method_id;
$rate_id = $rate_values->id;
// For "Flat rate" Shipping" Method only
if ( 'flat_rate' === $method_id ) {
if( ! empty( $calculated_cost ) ) {
$cost = $calculated_cost;
}
// Set the rate cost
$rates[$rate_id]->cost = number_format($rates[$rate_id]->cost * $cost, 2);
// Taxes rate cost (if enabled)
foreach ($rates[$rate_id]->taxes as $key => $tax){
if( $rates[$rate_id]->taxes[$key] > 0 ){ // set the new tax cost
$taxes[$key] = number_format( $rates[$rate_id]->taxes[$key] * $cost, 2 );
$has_taxes = true;
} else {
$has_taxes = false;
}
}
if( $has_taxes )
$rates[$rate_id]->taxes = $taxes;
}
}
return $rates;
}
Code goes in function.php file of your active child theme (or active theme) or in any plugin file.
3) Refresh the shipping caches (needed sometimes):
First empty your cart.
This code is already saved on your function.php file.
Go in a shipping zone settings and disable one "flat rate" (for example) and "save". Then re-enable that "flat rate" and "save". You are done and you can test it.
This should work for you,
If you have many different "flat rates" by shipping zones, you will need to make some changes in my code, if the default cost is different for each…
Related
There is the built in option for woocommerce shipping to set a fee for quantity of products in cart. There is also option for fee per shipping class. But I have thousands of products and need to charge a fee for each product(each product not qty of products).
For example 2 product "apples", and 23 product "oranges" in cart. I need to charge flat fee of $10 for any amount of apples and $10 for any amount of oranges. I dont seem to find solution to this in any of the available plugins. They all do fee per quantity but not this.
To get a cost by line item in cart, it requires the following:
1) In WooCommerce Settings > Shipping: set a cost of 10 for your "Flat rate" shipping methods (and save).
2) Add to functions.php file of your active child theme (or active theme), this code:
add_filter( 'woocommerce_package_rates', 'shipping_cost_based_on_number_of_items', 10, 2 );
function shipping_cost_based_on_number_of_items( $rates, $package ) {
$numer_of_items = (int) sizeof($package['contents']);
// Loop through shipping rates
foreach ( $rates as $rate_key => $rate ){
// Targetting "Flat rate" shipping method
if( 'flat_rate' === $rate->method_id ) {
$has_taxes = false;
// Set the new cost
$rates[$rate_key]->cost = $rate->cost * $numer_of_items;
// Taxes rate cost (if enabled)
foreach ($rates[$rate_key]->taxes as $key => $tax){
if( $tax > 0 ){
// New tax calculated cost
$taxes[$key] = $tax * $numer_of_items;
$has_taxes = true;
}
}
// Set new taxes cost
if( $has_taxes )
$rates[$rate_key]->taxes = $taxes;
}
}
return $rates;
}
Refresh the shipping caches: (required)
This code is already saved on your active theme's function.php file.
The cart is empty
In a shipping zone settings, disable / save any shipping method, then enable back / save.
Tested and work.
I'm setting up a website with shipping but i have items that are collection on for all shipping zone and item that can be sent in all shipping zone.
So I have set up shipping classes for all the zones.
I am using "Hide shipping method for specific shipping classes in woocommerce" answer code and it is what I need.
But instead of putting in each flat_rate id is there a way I can target all the Flat Rate shipping methods, so when I add an other flat rate shipping setting, it will work for it, without having me making changes into the code.
I hope you understand what I am after. Any help is appreciated.
To use it for all "flat rate" Shipping methods and some other defined shipping methods, you will use the following instead:
add_filter( 'woocommerce_package_rates', 'hide_shipping_method_based_on_shipping_class', 10, 2 );
function hide_shipping_method_based_on_shipping_class( $rates, $package )
{
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// HERE define your shipping class to find
$class = 92;
// HERE define the shipping methods you want to hide (others than "flat rate")
$method_key_ids = array('local_pickup:3');
$found = false;
// Checking in cart items
foreach( $package['contents'] as $cart_item ){
// If we find the shipping class
if( $cart_item['data']->get_shipping_class_id() == $class ){
$found = true;
break; // Stop the loop
}
}
if( ! $found )
return $rates;
// Loop through shipping methods
foreach( $rates as $rate_key => $rate ) {
// Targetting "Flat rate" and other defined shipping mehods
if( 'flat_rate' === $rate->method_id || in_array($rate->id, $method_key_ids) ) {
unset($rates[$rate_key]);
}
}
return $rates;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Refresh the shipping caches: (required)
This code is already saved on your active theme's function.php file.
The cart is empty
In a shipping zone settings, disable / save any shipping method, then enable back / save.
I am using Hide specifics Flat Rates when Free Shipping is available in WooCommerce 3 lightly changed answer code to hide all shipping methods except one. The only method I want showing is a rate from the "Woocommerce Advanced Shipping" plugin.
I am using the correct rate ID etc...
Everything works fine except when a customer tries to click that shipping method, it won't stay selected. It just jumps back to free shipping.
I have tried debugging and also tried the code with a native woocommerce flat rate ID and it showed up/able to select it just fine.
add_filter( 'woocommerce_package_rates', 'conditionally_hide_shipping_methods', 100, 2 );
function conditionally_hide_shipping_methods( $rates, $package ) {
$flat_rates_express = array( '2588' );
$free = $flat2 = array();
foreach ( $rates as $rate_key => $rate ) {
// Updated Here To
if ( in_array( $rate->id, $flat_rates_express ) )
$flat2[ $rate_key ] = $rate;
if ( 'free_shipping:12' === $rate->id )
$free[ $rate_key ] = $rate;
}
return ! empty( $free ) ? array_merge( $free, $flat2 ) : $rates;
}
ID I want to Keep Shown: "2588" (Custom Shipping Rate From Plugin)
How can I disable the Flat rate shipping method when free shipping is available o and keep a custom shipping rate (from a plugin)?
As you have 3 shipping methods, 1 free shipping, 1 flat rate and 1 custom '2588', it's possible to hide the flat rate shipping method when free shipping is available instead:
add_filter( 'woocommerce_package_rates', 'free_shipping_disable_flat_rate', 1000, 2 );
function free_shipping_disable_flat_rate( $rates, $package ) {
// Here your free shipping rate Id
$free_shipping_rate_id = 'free_shipping:12';
// When your Free shipping method is available
if ( array_key_exists( $free_shipping_rate_id, $rates ) ) {
// Loop through shipping methods rates
foreach ( $rates as $rate_key => $rate ) {
// Removing "Flat rate" shipping method
if ( 'flat_rate' === $rate->method_id ){
unset($rates[$rate_key]);
}
}
}
return $rates;
}
Code goes in functions.php file of your active child theme (or active theme). Tested and works.
Refresh the shipping caches:
This code is already saved on your function.php file.
In a shipping zone settings, disable / save any shipping method, then enable back / save.
You are done and you can test it.
I have 3 shipping methods in my cart that should become zero prices as soon as your customer enters Free Shipping coupon.
I know how to add a filter in functions.php to detect the coupon but is someone know a snippet to set shipping methods visibles in cart (radio button) to ZERO for this order?
My deliveries methods are companies like UPS, FedEx...
I activated the free shipping option in order it can be managed with coupon.
The list of choice of deliveries methods for the customers is calculated according to my products shipping class and order total weight.
Shipping class are not calculated but set by product and i use TABLE RATE PLUGIN to calculate the weight.
First free shipping method has to be enabled with option "A valid free shipping coupon"…
Then you need to set the desired coupon codes with option "Allow free shipping" enabled.
The following code will set all shipping methods costs to zero when a valid coupon code (with option "Allow free shipping" enabled) will be applied.
Update: Hide "Free shipping" method and append shipping label titles with "(free)"
add_filter( 'woocommerce_package_rates', 'coupon_free_shipping_customization', 20, 2 );
function coupon_free_shipping_customization( $rates, $package ) {
$has_free_shipping = false;
$applied_coupons = WC()->cart->get_applied_coupons();
foreach( $applied_coupons as $coupon_code ){
$coupon = new WC_Coupon($coupon_code);
if($coupon->get_free_shipping()){
$has_free_shipping = true;
break;
}
}
foreach( $rates as $rate_key => $rate ){
if( $has_free_shipping ){
// For "free shipping" method (enabled), remove it
if( $rate->method_id == 'free_shipping'){
unset($rates[$rate_key]);
}
// For other shipping methods
else {
// Append rate label titles (free)
$rates[$rate_key]->label .= ' ' . __('(free)', 'woocommerce');
// Set rate cost
$rates[$rate_key]->cost = 0;
// Set taxes rate cost (if enabled)
$taxes = array();
foreach ($rates[$rate_key]->taxes as $key => $tax){
if( $rates[$rate_key]->taxes[$key] > 0 )
$taxes[$key] = 0;
}
$rates[$rate_key]->taxes = $taxes;
}
}
}
return $rates;
}
Code goes in function.php file of your active child theme (or active theme).
Tested and works. It should works also for you.
Sometimes, you should may be need to refresh shipping methods:
1) Empty cart first.
2) Go to shipping Zones settings, then disable/save and re-enable/save the related shipping methods.
If you want to achieve the same but whenever there is a free shipping method available (not only applied coupon, but also cart total is above certain price), you can use this:
add_filter( 'woocommerce_package_rates', 'wc_apply_free_shipping_to_all_methods', 10, 2 );
function wc_apply_free_shipping_to_all_methods( $rates, $package ) {
if( isset( $rates['free_shipping:11'] ) ) {
unset( $rates['free_shipping:11'] );
foreach( $rates as $rate_key => $rate ) {
// Append rate label titles (free)
$rates[$rate_key]->label .= ' ' . __('(free)', 'woocommerce');
// Set rate cost
$rates[$rate_key]->cost = 0;
// Set taxes rate cost (if enabled)
$taxes = array();
foreach ($rates[$rate_key]->taxes as $key => $tax){
if( $rates[$rate_key]->taxes[$key] > 0 )
$taxes[$key] = 0;
}
$rates[$rate_key]->taxes = $taxes;
}
}
return $rates;
}
Notice, that after free_shipping there is a :11. Prior to WooCommerce 2.6, the details of shipping method "Free Shipping" were stored under array element $rates['free_shipping']. Now, however, it is stored as $rates['free_shipping:shipping_zone_instance_id'] where shipping_zone_instance_id is the shipping zone instance id of the shipping method. You can check the instance id of the shipping method by inspecting the "Free Shipping" in admin panel, or opening it in new tab and looking at the url http://prntscr.com/jd2zjy.
In WooCommerce 3, I have these shipping options (settings):
Free Shipping: free_shipping:1 - Minimum order amount is set at $50.
Normal Shipping flat_rate:3 - Amount $5.
Express Shipping flat_rate:5 - Amount $10.
I would like Express Shipping option to be always available (shown).
But when Free shipping is available (meaning that the customer has more than $50 in the cart) I would like to hide Normal Shipping only.
So when Free shipping is NOT available (and hidden), the available shipping rates will be Normal Shipping and Express Shipping.
Is that possible? How can I get this on WooCommerce 3?
Based on the official WooCommerce snippet code, making some light changes, you will be able to hide only your first flat rate when free shippings is available:
add_filter( 'woocommerce_package_rates', 'conditionally_hide_shipping_methods', 100, 2 );
function conditionally_hide_shipping_methods( $rates, $package ) {
// HERE yours 2nd flat rate "Express Shipping" (that you never hide) in the array:
$flat_rates_express = array( 'flat_rate:5', 'flat_rate:12', 'flat_rate:14' );
$free = $flat2 = array();
foreach ( $rates as $rate_key => $rate ) {
// Updated Here To
if ( in_array( $rate->id, $flat_rates_express ) )
$flat2[ $rate_key ] = $rate;
if ( 'free_shipping' === $rate->method_id )
$free[ $rate_key ] = $rate;
}
return ! empty( $free ) ? array_merge( $free, $flat2 ) : $rates;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Tested on WooCommerce 3 and works.
Refresh the shipping caches:
1) First empty your cart.
2) This code is already saved on your function.php file.
3) Go in a shipping zone settings and disable one "flat rate" (for example) and "save". Then re-enable that "flat rate" and "save". You are done and you can test it.