WooCommerce shipping cost calculated by weight of product - woocommerce

I need to organize a system for calculating shipping on a WooCommerce project. Here's example:
If the product weighs less than 19 kilograms shipping cost: 36$
If the product weighs more than 19 kilograms shipping cost: 300$
Plus, I need to create an additional shipping class (free shipping). So that the administrator of
the store can determine which product to shipping for free.
How I tried to solve this problem:
At first in the WooCommerce -> Settings -> Shipping -> Shipping zones I created new shipping zones (Israel – Shipping by Weight) and in this zone I create three different shipping methods:
Orders Below 19kg (flat_rate:21)
Orders Above 20kg (flat_rate:22)
Free Shipping (flat_rate:24)
Then I placed in the functions.php file this chunk of code:
add_filter( 'woocommerce_package_rates', 'custom_tiered_shipping_rates', 9999, 2 );
function custom_tiered_shipping_rates( $rates, $package ) {
if ( WC()->cart->get_cart_contents_weight() < 19 ) {
if ( isset( $rates['flat_rate:21'] ) ) unset( $rates['flat_rate:22'], $rates['flat_rate:24'] );
} elseif ( WC()->cart->get_cart_contents_weight() > 20 ) {
if ( isset( $rates['flat_rate:21'] ) ) unset( $rates['flat_rate:21'], $rates['flat_rate:24'] );
} else {
if ( isset( $rates['flat_rate:21'] ) ) unset( $rates['flat_rate:21'], $rates['flat_rate:22'] );
}
return $rates;
}
The source of code with the details description I got from here: WooCommerce: Shipping by Weight (Without a Plugin!)
And everything seems to work. Only the free shipping method does not work. When I give a product the free_shipping class. The shipping cost is calculated not by the availability of this class, but by the weight of the product.Please help to fix it. I understand that I have confused something in the conditions. But the more I experiment the more I get confused now.
PS: If there is at least one item with paid shipping in the cart, then even if there is an item with free shipping, the shipping cost should be guided by paid shipping.

Try the following, that will check on cart items if there are only items from "Free shipping" shipping class. If it's the case and if "Free shipping" shipping method is enabled, Free shipping method will be set.
On other cases a Flat rate based on weight will be applied.
Be sure to set the correct shipping class slug, in the code below, for "Free shipping" shipping class.
add_filter( 'woocommerce_package_rates', 'custom_tiered_shipping_rates', 9999, 2 );
function custom_tiered_shipping_rates( $rates, $package ) {
// HERE below set the correct shipping class slug for "Free shipping" items.
$free_shipping_class = 'free-shipping';
$free_shipping_only = true;
$non_free_items_weight = 0;
// Check items shipping class for the current shipping package
foreach( $package['contents'] as $cart_item ) {
// For non "Free shipping items" flag them and get the calculated weight.
if( $cart_item['data']->get_shipping_class() !== $free_shipping_class ) {
$free_shipping_only = false;
$non_free_items_weight += $cart_item['data']->get_weight() * $cart_item['quantity'];
}
}
// Free shipping
if ( $free_shipping_only && isset($rates['flat_rate:24']) ) {
unset($rates['flat_rate:21'], $rates['flat_rate:22']);
}
// Other rates (Flat rates)
else {
if ( $non_free_items_weight < 20 && isset($rates['flat_rate:21']) )
unset( $rates['flat_rate:22'], $rates['flat_rate:24'] );
} elseif ( $non_free_items_weight >= 20 && isset($rates['flat_rate:22']) )
unset( $rates['flat_rate:21'], $rates['flat_rate:24'] );
}
}
return $rates;
}
Code goes in functions.php file of the active child theme (or active theme). Tested and works.
Don't forget to empty your cart to refresh shipping caches.
Now instead of using a "Flat rate" for Free shipping, you should better use WooCommerce "Free shipping" method instead (with no restrictions) and replace flat_rate:24in your code by the correct "Free shipping" method rate ID…

Related

WooCommerce coupon calculate from regular price

I need functionality for "friend" customers, who can get products with better price. User role based solution is not what I'm looking for and customer wants it to work with coupons. They give coupon code to their customers and they get for example 8€ off from REGULAR price on certain products. The problem is, by default WooCommerce coupons calculate it from smallest price. If sale price is set, then this calculation is wrong and the customer gets it too cheap. Basically, I want coupon to give certain products fixed "friend" price.
I've been googling around and can't find a ready solution for it. Any suggestions how to solve this problem are welcome.
I have checked multiple plugins, but none of them has filled my requirements.
Add to functions.php. Based off of this code https://brilliantinfo.net/apply-coupon-discount-on-regular-price-in-woocommerce/
Modified for coupon type of fixed_product. If you need this to only work for a specific coupon then I can modify for that. (As it stands this will apply to any fixed_product coupons that are used)
add_action( 'woocommerce_before_calculate_totals', 'adjust_cart_coupon', 10, 1);
function adjust_cart_coupon( $cart_object) {
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) ){
return;
}
$coupon = False;
if ($coupons = WC()->cart->get_applied_coupons() == False ) {
$coupon = False;
} else {
foreach ( WC()->cart->get_applied_coupons() as $code ) {
$coupons1 = new WC_Coupon( $code );
if ($coupons1->type == 'fixed_product'){
$coupon = True;
}
}
}
if ($coupon == True){
foreach ( $cart_object->get_cart() as $cart_item ){
$price = $cart_item['data']->regular_price;
//sets cart item to use regular price and not sale price
$cart_item['data']->set_price( $price );
}
}
}
The Discount Rules for WooCommerce plugin might fit your requirements.
With it you can apply a coupon, or any discount rule, to specific customers.
Also there is a setting to Apply discount based on Sale price or Regular price.

Add a Woocommerce fee based on shipping class and item quantity

In Woocommerce I am trying to add a shipping fee if a cart item has a specific shipping class assigned to the related product. I would like this shipping fee to be multiplied by the cart item quantity…
I have this working when a product is added to the cart and the quantity is increased and the additional shipping fee is increased also. However if I add another product with the same shipping class and increase the quantity the additional fee does not increase.
This is my code:
// Add additional fees based on shipping class
function woocommerce_fee_based_on_shipping_class( $cart_object ) {
global $woocommerce;
// Setup an array of shipping classes which correspond to those created in Woocommerce
$shippingclass_dry_ice_array = array( 'dry-ice-shipping' );
$dry_ice_shipping_fee = 70;
// then we loop through the cart, checking the shipping classes
foreach ( $cart_object->cart_contents as $key => $value ) {
$shipping_class = get_the_terms( $value['product_id'], 'product_shipping_class' );
$quantity = $value['quantity'];
if ( isset( $shipping_class[0]->slug ) && in_array( $shipping_class[0]->slug, $shippingclass_dry_ice_array ) ) {
$woocommerce->cart->add_fee( __('Dry Ice Shipping Fee', 'woocommerce'), $quantity * $dry_ice_shipping_fee ); // each of these adds the appropriate fee
}
}
}
add_action( 'woocommerce_cart_calculate_fees', 'woocommerce_fee_based_on_shipping_class' ); // make it all happen when Woocommerce tallies up the fees
How can I make it work for additional cart items too?
Your code is a bit outdated and there is some mistakes. To add a fee based on product shipping class and cart item quantity use the following:
// Add a fee based on shipping class and cart item quantity
add_action( 'woocommerce_cart_calculate_fees', 'shipping_class_and_item_quantity_fee', 10, 1 );
function shipping_class_and_item_quantity_fee( $cart ) {
## -------------- YOUR SETTINGS BELOW ------------ ##
$shipping_class = 'dry-ice-shipping'; // Targeted Shipping class slug
$base_fee_rate = 70; // Base rate for the fee
## ----------------------------------------------- ##
$total_quantity = 0; // Initializing
// Loop through cart items
foreach( $cart->get_cart() as $cart_item ) {
// Get the instance of the WC_Product Object
$product = $cart_item['data'];
// Check for product shipping class
if( $product->get_shipping_class() == $shipping_class ) {
$total_quantity += $cart_item['quantity']; // Add item quantity
}
}
if ( $total_quantity > 0 ) {
$fee_text = __('Dry Ice Shipping Fee', 'woocommerce');
$fee_amount = $base_fee_rate * $total_quantity; // Calculate fee amount
// Add the fee
$cart->add_fee( $fee_text, $fee_amount );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
If there is one shipping class in cart there should be no fees, but if there is more than one shipping class, then should be additional 1 Eur handling fee and increase for every another shipping class.
Situation 1: Product with shipping class (Warehouse 1) added to cart = No extra fees
Situation 2: Product with shipping class (Warehouse 1) added to cart, Product with another shipping class (Warehouse 2) added to cart = 1x Handling fee added to cart
Subtotals:
Products 2x - 10 Eur
Shipping - Free
Handling fee 1x - 1Eur
Total - 11 Eur
Situation 3: Product with shipping class (Warehouse 1) added to cart, Product with shipping class (Warehouse 2) added to cart, Product with shipping class (Warehouse 3) added to cart = 2x Handling fee added to cart
Subtotals:
Products 3x - 15 Eur
Shipping - Free
Handling fee 2x - 1Eur
Total - 12 Eur

How do I disable shipping in some of my woocommerce products

I have a WooCommerce online shop that offers shipping to most products. Some of the products are for local pickup. I've tried setting a class on shipping zones with cost equal to zero and assigning the class on the products. But so far, the checkout still displays the shipping cost. Is there any way where some products will not have a shipping cost?
If you are searching for plugin solution, try WooCommerce Conditional Shipping and Payments. By using this plugin, you could add restrictions on certain product or product categories.
You've might want to look into the woocommerce_package_rates filter, which allows you to filter the set of shipping options that are available to the customer. An example would be something like this:
<?php
// add this snippet to functions.php:
add_filter( 'woocommerce_package_rates', function ( $rates, $package ) {
// examine $package for products. this could be a whitelist of specific
// products that you wish to be treated in a special manner...
$special_ids = array( 1, 2, 3, 4, 5 );
$special_product_present = false;
foreach ( $package['contents'] as $line_item ) {
if ( in_array( $line_item['product_id'], $special_ids ) ) {
$special_product_present = true;
}
}
$rates = array_filter( $rates, function ( $r ) use ( $special_product_present ) {
// do some logic here to return true (for rates that you wish to be displayed), or false.
// example: only allow shipping methods that start with "local"
if ( $special_product_present ) {
return preg_match( '/^local/', strtolower( $r->label ) );
} else {
return true;
}
} );
return $rates;
}, 10, 2 );
This blog post here shows some variations on that idea using this hook, including how to customize the available rates based on shopping cart value, customer's country, number of items in the cart, etc. And here's the source code: https://github.com/woocommerce/woocommerce/blob/v2.2.3/includes/class-wc-shipping.php#L366

Woocommerce : how to Disable "Free shipping" if Coupon applied?

I'm using woocommerce plugin for online shop.
I set free shipping option after certain amount of order.
how to disable "free shipping" option if coupon applied?
Based on a quick google lookup.
add_filter( 'woocommerce_shipping_packages', function( $packages ) {
$applied_coupons = WC()->session->get( 'applied_coupons', array() );
if ( ! empty( $applied_coupons ) ) {
$free_shipping_id = 'free_shipping:2';
unset($packages[0]['rates'][ $free_shipping_id ]);
}
return $packages;
} );
Where $free_shipping_id is set to the id of your free shipping method.

woocommerce exclude state free shipping (australian states)

I'm trying to implement woocommerces exclude states from free shipping (Australian Site) snippet but am running into this error:
'Fatal error: Call to a member function get_shipping_state() on a non-object in
/home/bpcsport/public_html/wp-content/plugins/wa-exclude/wa-exclude.php
on line 30'
My client needs to exclude Western Australia from the free-shipping deal they offer through woocommerce. I get the error either way if I put it in my themes function.php or via plug-in format.
I've also tried the following method to no avail.
How can I disable free shipping for particular states?
This is the snippet from woocommerce that is in the plug-in
/**
* Hide ALL shipping options when free shipping is available and customer is NOT in certain states
* Hide Free Shipping if customer IS in those states
*
* Change $excluded_states = array( 'AK','HI','GU','PR' ); to include all the states that DO NOT have free shipping
*/
add_filter( 'woocommerce_available_shipping_methods', 'hide_all_shipping_when_free_is_available' , 10, 1 );
/**
* Hide ALL Shipping option when free shipping is available
*
* #param array $available_methods
*/
function hide_all_shipping_when_free_is_available( $available_methods ) {
$excluded_states = array( 'WA' );
if( isset( $available_methods['free_shipping'] ) AND !in_array( $woocommerce->customer->get_shipping_state(), $excluded_states ) ) :
// Get Free Shipping array into a new array
$freeshipping = array();
$freeshipping = $available_methods['free_shipping'];
// Empty the $available_methods array
unset( $available_methods );
// Add Free Shipping back into $avaialble_methods
$available_methods = array();
$available_methods[] = $freeshipping;
endif;
if( isset( $available_methods['free_shipping'] ) AND in_array( $woocommerce->customer->get_shipping_state(), $excluded_states ) ) {
// remove free shipping option
unset( $available_methods['free_shipping'] );
}
return $available_methods;
}
?>
I've made an plugin which allow advanced user configurations. Altough it includes only US states, you can configure country and postal code conditions.
I don't know if this meets you requirements, but might worth checking out: http://wordpress.org/plugins/woocommerce-advanced-free-shipping/

Resources