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.
Related
i have multiple shipping methods on my page and want to make them cost zero when the order is above 2500 Czech crowns. I only found the code to only show the Free shipping option when the customer hits the minimum for free shipping but that is not what I want.. I want to show all the methods (but with zero price) so customer still can choose which shipping company he wants his order to be delivered with.
Thank you!
Based on Set cart shipping total amount issue after Woocommerce update answer code, here is the way to make it work based on specific cart items subtotal amount:
add_filter('woocommerce_package_rates', 'null_shipping_costs_conditionally', 10, 2 );
function null_shipping_costs_conditionally( $rates, $package ){
$threshold_amount = 2500;
if( $package['contents_cost'] >= $threshold_amount ) {
// Loop through shipping methods rates
foreach ( $rates as $rate_key => $rate ){
// Targeting all shipping methods except "Free shipping"
if ( 'free_shipping' !== $rate->method_id ) {
$has_taxes = false;
$taxes = [];
$rates[$rate_key]->cost = 0; // Set cost to 0 (zero)
// Taxes rate cost (if enabled)
foreach ($rates[$rate_key]->taxes as $key => $tax){
if( $tax > 0 ){
$has_taxes = true;
$taxes[$key] = 0; // Set tax cost to 0 (zero)
}
}
if( $has_taxes )
$rates[$rate_key]->taxes = $taxes;
}
}
}
return $rates;
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
Note: After saving this code, don't forget to empty your cart to refresh shipping cached data.
In Woocommerce, I would like to have a function that I can include within my theme that adds shipping rate based on price and weight.
if price is above 20USD shipping is free, below Shipping cost : 3USD
if weight is above 10kg shipping fee is 2USD extra
Based on "Shipping calculated on the items weight and cart amount" answer thread, I tried something like the beneath code:
//Adding a custom Shipping Fee to cart based conditionally on weight and cart amount
add_action('woocommerce_cart_calculate_fees', 'custom_conditional_shipping_fee', 10, 1);
function custom_conditional_shipping_fee( $cart_object ){
#### SETTINGS ####
// Your targeted "heavy" product weight
$target_weight = 1;
// Your targeted cart amount
$target_cart_amount = 20;
// Price by Kg;
$price_kg = 2;
// Amount set in 'flat rate' shipping method;
$flat_rate_price;
// Initializing variables
$fee = 0;
$calculated_weight = 0;
// For cart SUBTOTAL amount EXCLUDING TAXES
WC()->cart->subtotal_ex_tax >= $target_cart_amount ? $passed = true : $passed = false ;
// For cart SUBTOTAL amount INCLUDING TAXES (replace by this):
// WC()->cart->subtotal >= $target_cart_amount ? $passed = true : $passed = false ;
// Iterating through each cart items
foreach( $cart_object->get_cart() as $cart_item ){
// Item id ($product ID or variation ID)
if( $cart_item['variation_id'] > 0)
$item_id = $cart_item['variation_id'];
else
$item_id = $cart_item['product_id'];
// Getting the product weight
$product_weight = get_post_meta( $item_id , '_weight', true);
// Line item weight
$line_item_weight = $cart_item['quantity'] * $product_weight;
// When cart amount is up to 1kg, Adding weight of heavy items
if($passed && $product_weight < $target_weight)
$calculated_weight += $line_item_weight;
}
#### Making the fee calculation ####
// Cart is up to 250 with heavy items
if ( $passed && $calculated_weight != 0 ) {
// Fee is based on cumulated weight of heavy items
$fee = ($calculated_weight * $price_kg) - $flat_rate_price;
}
// Cart is below 250
elseif ( !$passed ) {
// Fee is based on cart total weight
$fee = ($cart_object->get_cart_contents_weight( ) * $price_kg) - $flat_rate_price;
}
#### APPLYING THE CALCULATED FEE ####
// When cart is below 250 or when there is heavy items
if ($fee > 0){
// Rounding the fee
$fee = round($fee);
// This shipping fee is taxable (You can have it not taxable changing last argument to false)
$cart_object->add_fee( __('Shipping weight fee', 'woocommerce'), $fee, true);
}
}
Edit:
And at the same time I want it to show this immediately on the cart page. Now it is showing "enter address to view shipping options". Basically just look at total of cart and show either a rate or free shipping based on the rules described for weight and price.
woocommerce_package_rates is the right filter to customize the shipping rate.
You can achieve this by following way.
Step-1: Create two shipping method, Free shipping and Flat rate with coast 3$
Step-2: Copy and paste below code snippet into functions.php
Config the flat rate and free shipping properly on the snippet.
add_filter( 'woocommerce_package_rates', 'modify_shipping_rate', 15, 2 );
function modify_shipping_rate( $available_shipping_methods, $package ){
global $woocmmerce;
$total_weight = WC()->cart->cart_contents_weight;
$total_coast = WC()->cart->get_cart_contents_total();
if( $total_coast >= 20 ){
unset($available_shipping_methods['flat_rate:1']); //Remove flat rate for coat abobe 20$
}elseif( $total_weight > 10 ){
unset($available_shipping_methods['free_shipping:1']); // remove free shipping for below 20$
$available_shipping_methods['flat_rate:1']->cost += 2; // add 2$ if weight exceeds 10KG
}else{
unset($available_shipping_methods['free_shipping:1']); // remove free shipping for below 20$
}
return $available_shipping_methods;
}
Use below snippet to change the default cart message.
add_filter( 'woocommerce_cart_no_shipping_available_html', 'change_msg_no_available_shipping_methods', 10, 1 );
add_filter( 'woocommerce_no_shipping_available_html', 'change_msg_no_available_shipping_methods', 10, 1 );
function change_msg_no_available_shipping_methods( $default_msg ) {
$custom_msg = "Enter address to view shipping options";
if( empty( $custom_msg ) ) {
return $default_msg;
}
return $custom_msg;
}
The following code isn't based on a custom fee, but on shipping methods customizations.It requires to set in shipping settings, for each shipping zone:
A "Flat Rate" with a defined cost ($3 for you)
A "Free Shipping" with no requirements (no restrictions).
The code will handle flat rate calculation cost based on the weight and also the tax calculations.
The code will work for any shipping zone without needing to define in the code the shipping method IDs.
Here is the code:
add_filter( 'woocommerce_package_rates', 'filter_package_rates_callback', 10, 2 );
function filter_package_rates_callback( $rates, $package ) {
## -------- Settings -------- ##
$targeted_total = 20; // The targeted cart amount
$weight_threshold = 10; // The cart weight threshold
$extra_for_10kg = 2; // 10 Kg addition extra cost;
$total_weight = WC()->cart->get_cart_contents_weight();
$cart_subtotal = WC()->cart->get_subtotal(); // Excluding taxes
// Set shipping costs based on weight
foreach ( $rates as $rate_key => $rate ){
$has_taxes = false;
if( $cart_subtotal < $targeted_total || $total_weight >= $weight_threshold ){
// Remove Free shipping Method
if( 'free_shipping' === $rate->method_id ) {
unset( $rates[$rate_key] );
}
// Flat rate calculation cost when 10 kg weight is reached
if( 'flat_rate' === $rate->method_id && $total_weight >= $weight_threshold ) {
// The default rate cost (set in the shipping method)
$default_cost = $rate->cost;
// The new calculated cost (up to 10 kg)
$new_cost = $default_cost + $extra_for_10kg;
// Tax rate conversion (for tax calculations)
$tax_rate_converion = $new_cost / $default_cost;
// Set the new cost
$rates[$rate_key]->cost = $new_cost;
// TAXES RATE COST (if enabled)
foreach ($rates[$rate_key]->taxes as $key => $tax){
if( $tax > 0 ){
// New tax calculated cost
$taxes[$key] = $tax * $tax_rate_converion;
$has_taxes = true;
}
}
// Set new taxes cost
if( $has_taxes )
$rates[$rate_key]->taxes = $taxes;
}
} else {
// Remove Flat Rate methods (keeping Free Shipping Method only)
if( 'flat_rate' === $rate->method_id ) {
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)
1) This code is already saved on your function.php file.
2) In a shipping zone settings, disable / save any shipping method, then enable back / save.
You are done and you can test it.
Displaying shipping methods directly (Regarding your question edit)
The provided information in your question is not enough to see how this can be managed.
If you are selling in one country, and you have a unique shipping zone, you can force the country for unlogged customers to get the shipping methods displayed, using the following:
add_action( 'template_redirect', 'allow_display_shipping_methods' );
function allow_display_shipping_methods() {
// HERE define the targeted country code
$country_code = 'GB';
// Set the shipping country if it doesn't exist
if( ! WC()->customer->get_shipping_country() )
WC()->customer->set_shipping_country('GB');
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Now this is another question, in your initial question and should be asked as a new question.
Related answers:
Set a custom shipping rate cost calculated on cart total weight in WooCommerce
Free shipping depending on weight and on minimal cart amount
Shipping cost based on cart total weight in Woocommerce 3
Hide and unhide a specific shipping methods based on shipping class in WooCommerce
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.
I'm trying to specify 2 different Flat rates shipping methods costs without using a plugin:
If there is a product in the cart from only one Vendor, the Flat rate shipping cost needs to be £19.
If there are multiple products in the cart from more than one Vendor, the Flat rate shipping cost needs to be £39.
I have tried various plugins, but they focus on shipping rates based on size, weight, quantity, location, category, but not Attributes or Terms.
I have an Attribute named Vendor with 8 Terms. Each Term is a different Vendor/supplier.
Here's the type of PHP logic I would like to implement:
if product attribute term quantity = 1
then flat rate = £19
else
if product attribute term quantity > 1
then flat rate = £39
How can I change this "Flat rate" shipping method cost when there is more than 1 attribute Vendor terms in cart?
This process needs 2 steps: some code and some settings…
1) CODE - You can use a custom function hooked in woocommerce_package_rates filter hook, targeting the "Flat rate" shipping method when cart items are from more than 1 vendor:
add_filter( 'woocommerce_package_rates', 'custom_flat_rate_cost_calculation', 10, 2 );
function custom_flat_rate_cost_calculation( $rates, $package )
{
// SET BELOW your attribute slug… always begins by "pa_"
$attribute_slug = 'pa_vendor'; // (like for "Color" attribute the slug is "pa_color")
// Iterating through each cart item to get the number of different vendors
foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
// The attribute value for the current cart item
$attr_value = $cart_item[ 'data' ]->get_attribute( $attribute_slug );
// We store the values in an array: Each different value will be stored only one time
$attribute_values[ $attr_value ] = $attr_value;
}
// We count the "different" attribute values stored
$count = count($attribute_values);
// Iterating through each shipping rate
foreach($rates as $rate_key => $rate_values){
$method_id = $rate_values->method_id;
$rate_id = $rate_values->id;
// Targeting "Flat Rate" shipping method
if ( 'flat_rate' === $method_id ) {
// For more than 1 vendor (count)
if( $count > 1 ){
// Get the original rate cost
$orig_cost = $rates[$rate_id]->cost;
// Calculate the new rate cost
$new_cost = $orig_cost + 20; // 19 + 20 = 39
// Set the new rate cost
$rates[$rate_id]->cost = $new_cost;
// Calculate the conversion rate (for below taxes)
$conversion_rate = $new_cost / $orig_cost;
// Taxes rate cost (if enabled)
foreach ($rates[$rate_id]->taxes as $key => $tax){
if( $rates[$rate_id]->taxes[$key] > 0 ){
$new_tax_cost = number_format( $rates[$rate_id]->taxes[$key]*$conversion_rate, 2 );
$rates[$rate_id]->taxes[$key] = $new_tax_cost; // set the cost
}
}
}
}
}
return $rates;
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested with woocommerce version 3+ and works
2) SETTINGS - Once the above code has been saved in the function.php file of your active theme, you will need to set (for all your shipping zones) the "Flat rate" shipping method cost to 19 (£19) (and save).
IMPORTANT: To refresh Shipping method caches you will need to disable "flat rate" then save, and enable back "flat rate" then save.
Now This should work for you as expected.
I want to count shipping cost based on number of products add on cart like,
If I purchase one mobile then it will count shipping cost as 2.5 and after more than two or two mobile I purchased then shipping cost will be 5.0
<?php
$qty(1) * 2.5 = 2.5
$qty(2) * 2.5 = 5.0
$qty(3) * 2.5 = 5.0
?>
So is there any idea or suggestion how to count the shipping cost based on number of products ?
Updated:
As your question is a bit unclear, you could just need to add [qty]*2.5 in the Flat rate shipping method cost (for each shipping zone) in your wooCommerce shipping settings.
But it will not work if you have 2 different items in cart like: item1 (qty 1) + item2 (qty 1)
So this answer will do it in all cases:
1) First you will need to set a "Flat rate" shipping method for each Shipping Zones which cost will be set to 2.5 (in your WooCommerce shipping settings).
2) Adding this code that will calculate for each cart items (based on the total quantity of items) the new updated shipping cost:
add_filter( 'woocommerce_package_rates', 'custom_flat_rate_cost_calculation', 10, 2 );
function custom_flat_rate_cost_calculation( $rates, $package )
{
// The cart count (total items in cart)
$cart_count = WC()->cart->get_cart_contents_count();
$taxes = array();
// If there is more than 1 cart item
if( $cart_count > 1 ){
// Iterating through each shipping rate
foreach($rates as $rate_key => $rate_values){
// Targeting "Flat Rate" shipping method
if ( 'flat_rate' === $rate_values->method_id ) {
// Set the new calculated rate cost
$rates[$rate_id]->cost = number_format($rates[$rate_id]->cost * $cumulated_active_quantity, 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] * $cumulated_active_quantity, 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 theme) or also in any plugin file.
This code is tested on WooCommerce 3+ and works
You will need to refresh shipping zones caches: disabling the Flat rate, then save. And enabling back this rate and save.
You can add a custom fee: Add to theme functions.php or use a plugin
add_action( 'woocommerce_cart_calculate_fees','woocommerce_custom_surcharge' );
function woocommerce_custom_surcharge() {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$price_per_mobile = 2.5;
$shipcharge = ( $woocommerce->cart->cart_contents_total * $price_per_mobile);
$woocommerce->cart->add_fee( 'Total Shipping Cost', $shipcharge, true, '' );
}
Go ahead with Woocommerce filter woocommerce_package_rates. Where you can customize all the shipping rates available in cart page.
Here is the code for adding extra cost to all items for both domestic and international shipement
add_filter('woocommerce_package_rates', 'wf_modify_rate', 10, 3);
function wf_modify_rate( $available_shipping_methods, $package ){
$origin_country = 'US';
$amount_to_add_domestic = 10;
$amount_to_add_inter_national = 20;
$amount_to_add = ($package['destination']['country'] == $origin_country) ?
$amount_to_add_domestic : $amount_to_add_inter_national;
$item_count = 0;
foreach ($package['contents'] as $key => $item) {
$item_count += $item['quantity'];
}
foreach ($available_shipping_methods as $methord_name => $methord) {
$available_shipping_methods[$methord_name]->cost += ($amount_to_add*$item_count);
}
return $available_shipping_methods;
}