Add custom fee based on total weight in Woocommerce - php

In WooCommerce, I am trying to add a an additional shipping fee based on cart weight.
For the first 1500g the fee is 50$.
Above 1500g we add 10$ to this initial $50 by steps of 1000g
So for example:
if cart weight is 700g we add a fee of $50,
if cart weight is 2600g we add a fee of $70 ($50 + $10 +$10) …
I am stuck on the calculation:
function weight_add_cart_fee() {
$feeaddtocart = get_option('feeaddtocart');
$customweight = get_option('customweight');
global $woocommerce;
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$cart_weight = WC()->cart->get_cart_contents_weight();
if ($cart_weight <= 500 ) {
$get_cart_total = $woocommerce->cart->get_cart_total();
$newtotal = $get_cart_total + 50;
WC()->cart->add_fee( __('Extra charge (weight): ', 'your_theme_slug'), $newtotal, false );
}
}
How can I achieve this? Any help is appreciated.

It can be done very easily with a custom function hooked in woocommerce_cart_calculate_fees action hook…
Updated:
Added conversion of cart weight in grams (instead of kilos by default)
Now for the first 1500g the fee is 50$ (instead of 500g)
Now above 1500g it add $10 by steps of 1000g.
add_action( 'woocommerce_cart_calculate_fees', 'shipping_weight_fee', 30, 1 );
function shipping_weight_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Convert cart weight in grams
$cart_weight = $cart->get_cart_contents_weight() * 1000;
$fee = 50; // Starting Fee below 500g
// Above 500g we add $10 to the initial fee by steps of 1000g
if( $cart_weight > 1500 ){
for( $i = 1500; $i < $cart_weight; $i += 1000 ){
$fee += 10;
}
}
// Setting the calculated fee based on weight
$cart->add_fee( __( 'Weight shipping fee' ), $fee, false );
}
Code goes in function.php file of your active child theme (or active theme).
Tested and works.

Related

Apply a progressive discount based on Woocommerce cart weight

I'm looking for a way to apply a discount (percentage) based on cart total weight.
Example:
10 to 25 kg, set a 5% discount
26 to 50 kg, set a 7,5% discount
51 to 100 kg, set a 10% discount
101 to 150 kg, set a 12,5% discount
more than 150 kg, set a 15% discount
When one of the rules will be applied there should be a message also like this payment discount shown in the picture.
Payment method discount
And if also possible showing a message box like the 'added to cart message box' which shows how much customers have to order to get the first of a second discounted rule like: Order **kg more and get 5% discount.
I have no idea how to achieve this, so I unfortunately did not tried anything.
Thanks in advance.
Regards,
Vasco
You can use a negative fee to make a progressive discount based on cart weight as follow:
add_action( 'woocommerce_cart_calculate_fees', 'shipping_weight_discount', 30, 1 );
function shipping_weight_discount( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$cart_weight = $cart->get_cart_contents_weight();
$cart_subtotal = $cart->get_subtotal(); // Or $cart->subtotal;
$percentage = 0;
if ( $cart_weight >= 10 && $cart_weight <= 25 ) {
$percentage = 5;
} elseif ( $cart_weight > 25 && $cart_weight <= 50 ) {
$percentage = 7.5;
} elseif ( $cart_weight > 50 && $cart_weight <= 100 ) {
$percentage = 10;
} elseif ( $cart_weight > 100 && $cart_weight <= 150 ) {
$percentage = 12.5;
} elseif ( $cart_weight > 150 ) {
$percentage = 15;
}
// Apply a calculated discount based on weight
if( $percentage > 0 ) {
$discount = $cart_subtotal * $percentage / 100;
$cart->add_fee( sprintf( __( 'Weight %s discount', 'woocommerce' ), $percentage.'%'), -$discount );
}
}
Code goes in function.php file of your active child theme (or active theme).
Based on: Add custom fee based on total weight in Woocommerce
Welcome to StackOverflow!
$applied_discount = 0;
add_filter( 'woocommerce_calculated_total', 'add_conditional_discount_by_weight', 10, 2 );
function add_conditional_discount_by_weight( $total, $cart ) {
global $applied_discount;
$total_weight = WC()->cart->get_cart_contents_weight(); // gets cart weight
if($total_weight >= 10 || $total_weight <= 25){
$applied_discount = 5;
return $total*(1-($applied_discount/100));
}
}
add_action( 'woocommerce_cart_totals_after_order_total', 'display_applied_discount' );
function display_applied_discount() {
global $applied_discount;
if($applied_discount > 0){
$discount = WC()->cart->total * ($applied_discount/100);
?>
<tr class="order-total">
<th><?php esc_html_e( "Applied Discount ($applied_discount%)", 'woocommerce' ); ?></th>
<td><?php echo "$".$discount ?></td>
</tr>
<?php
}
}
Here's a code snippet that answers your question. I only added one weight condition. I believe you'll be able to fill in the other conditions yourself.
The snippet can be added to your functions.php (as long as it is a child theme, otherwise your code will be deleted after a theme update!) or as a code snippet using plugins such as Code Snippets

Woocommerce - add surcharge in cart based on weight only to some categories (or to all cart except some categories)

A friends ask me to add an extra fee on cart based on weight and only for specific categories (or excluding some categories, it doesn't matters).
The topic is, for summer, he wants to add ice into the packages to keep the products cold (ex. milk, cheese, etc).
He sells also gadgets and guided visits to his factory, etc so he doesn't want to apply the extra fee to those products.
Based on "Add custom fee based on total weight in Woocommerce" answer, my code version below, apply an extra fee to the whole cart, excluding the visit-product from this fee because the weight of the visit is obviously 0.
But I am not an expert with code and I don't know how to insert an array to include categories like 'milk' and 'cheese' (or viceversa to exclude 'visits' and 'gadgets').
In addiction, my code increase the fee by steps of 3kg (due to sizing of the packets by DHL/UPS/GLS etc)
/* Extra Fee based on weight */
add_action( 'woocommerce_cart_calculate_fees', 'shipping_weight_fee', 30, 1 );
function shipping_weight_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Convert in grams
$cart_weight = $cart->get_cart_contents_weight() * 1000;
$fee = 0.00; // initial fee
// if cart is > 0 add €1,20 to initial fee by steps of 3000g
if( $cart_weight > 0 ){
for( $i = 0; $i < $cart_weight; $i += 3000 ){
$fee += 1.20;
}
}
// add the fee / doesn't show extra fee if it's 0
if ( !empty( $fee )) {
$cart->add_fee( __( 'Extra for ice' ), $fee, false );
}
}
Last question is: why the $i variable could be 0...1...1000000 without any change in the results? the code seems working exactly the same...
thanks
The following code is based on:
Predefined categories
Based on product weight (of products belonging to the predefined categories)
Fee increases by steps
(comment with explanation added in the code)
function shipping_weight_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
/* SETTINGS */
// Specific categories
$specific_categories = array( 'categorie-1', 'categorie-2' );
// Initial fee
$fee = 1.20;
// Steps of kg
$steps_of_kg = 3;
/* END SETTINGS */
// Set variable
$total_weight = 0;
// Loop though each cart item
foreach ( $cart->get_cart() as $cart_item ) {
// Get product id
$product_id = $cart_item['product_id'];
// Get weight
$product_weight = $cart_item['data']->get_weight();
// NOT empty & has certain category
if ( ! empty( $product_weight ) && has_term( $specific_categories, 'product_cat', $product_id ) ) {
// Quantity
$product_quantity = $cart_item['quantity'];
// Add to total
$total_weight += $product_weight * $product_quantity;
}
}
if ( $total_weight > 0 ) {
$increase_by_steps = ceil( $total_weight / $steps_of_kg );
// Add fee
$cart->add_fee( __( 'Extra for ice' ), $fee * $increase_by_steps, false );
}
}
add_action( 'woocommerce_cart_calculate_fees', 'shipping_weight_fee', 10, 1 );

WooCommerce add non-taxable fee and discount to cart calculates wrong tax amount

I have a WooCommerce site where products may have a non-taxable deposit fee, may have a delivery fee ($7.50), and may have a discount. Without applying the negative fee (discount) the tax is calculated correctly. Once I add the negative fee, the tax includes the non-taxable deposit fee in its calculation. I read somewhere that negative fees are not recommended. I also found this post but don't know if this applies here. Is there another way to accomplish this in the cart and also show in the orders, emails, etc.? FYI the tax rate is 15%. Here's the code I'm using:
function woocommerce_custom_fees( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
$item_data = $cart_item['data'];
$deposit = $item_data->get_attribute('deposit');
$delivery = $cart_item['delivery'];
if ( $deposit ) {
$total_deposit += $cart_item['quantity'] * $deposit;
}
if ( $delivery == 'deliver' ) {
$total_delivery += $cart_item['quantity'] * 7.5;
}
}
if ( $total_deposit > 0 ) {
// non-taxable
$cart->add_fee( 'Deposit', $total_deposit, FALSE );
}
if ( $total_delivery > 0 ) {
// taxable
$cart->add_fee( 'Delivery', $total_delivery, TRUE );
}
// test $10 discount
$cart->add_fee( 'Test discount', -10.00);
}
add_action( 'woocommerce_cart_calculate_fees','woocommerce_custom_fees', 25, 1 );
correct tax amount without negative fee
incorrect tax amount with negative fee
UPDATE: I found this post Apply a discount on the cart content total excluding taxes in WooCommerce which says that using a negative fee will cause the taxes to always get applied. Is there an alternative method to apply discounts in the cart other than to use negative fees or coupons?
function woocommerce_custom_fees( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// non-taxable
$cart->add_fee( 'Deposit', 6, FALSE );
// taxable
$cart->add_fee( 'Delivery', 7, TRUE );
// test $10 discount
//$cart->add_fee( 'Test discount', -10.00 , FALSE);
}
add_action( 'woocommerce_cart_calculate_fees','woocommerce_custom_fees', 25, 1 );
add_filter( 'woocommerce_calculated_total', 'discounted_calculated_total', 10, 2 );
function discounted_calculated_total( $total, $cart ){
$total = $total - 10;
return $total;
}
Tried this way?

Woocommerce Progressive extra cost based on total number of items in the cart

I am looking for some code which can make an extra charge based on the total number of items in the cart like:
If number of items in cart is > 6 ===> extra cost = 5
If number of items in cart is > 12 ==> extra cost = 10
I have tried this code, but I can't get it working for my case.
How can I make an extra cost based on total number of items in the cart?
Based on (this answer) WooCommerce Cart Quantity Base Discount, you can add a progressive fee based on total number of items:
add_action( 'woocommerce_cart_calculate_fees','woocommerce_cart_extra_cost', 10, 1 );
function woocommerce_cart_extra_cost( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
$cart_item_count = $cart->get_cart_contents_count();
// CONDITIONAL ITEMS QUANTITY FEE AMOUNT
if( $cart_item_count < 6 )
$fee = 0;
elseif( $cart_item_count >= 6 && $cart_item_count < 12 )
$fee = 5;
elseif( $cart_item_count >= 12 )
$fee = 10;
if( $fee > 0 )
$cart->add_fee( __( "Extra Cost", "woocommerce" ), $fee, true);
}
Code goes in functions.php file of your active child theme (or theme) or also in any plugin file.
Tested and works.

Progressive percent discount based on cart amount

I am trying to make a simple discount code for WooCommerce that gives you a percent discount before buying. Lets say that if you add products worth $100 you get 2% discount and if you add products worth $250 you get 4%, etc.
The only thing I found was this:
// Hook before calculate fees
add_action('woocommerce_cart_calculate_fees' , 'add_custom_fees');
/**
* Add custom fee if more than three article
* #param WC_Cart $cart
*/
function add_custom_fees( WC_Cart $cart ){
if( $cart->cart_contents_count < 3 ){
return;
}
// Calculate the amount to reduce
$discount = $cart->subtotal * 0.1;
$cart->add_fee( 'You have more than 3 items in your cart, a 10% discount has been added.', -$discount);
}
But could not manage to make it work with the modifying the hooks with those for the price.
How can I achieve this?
Here is the way to do it using conditions based on cart subtotal excl tax amount to add this progressive percentage as a negative fee, so a discount:
add_action( 'woocommerce_cart_calculate_fees','cart_price_progressive_discount' );
function cart_price_progressive_discount() {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
$has_discount = false;
$stotal_ext = WC()->cart->subtotal_ex_tax;
// Discount percent based on cart amount conditions
if( $stotal_ext >= 100 && $stotal_ext < 250 ) {
$percent = -0.02;
$percent_text = ' 2%';
$has_discount =true;
} elseif( $stotal_ext >= 250 ) {
$percent = -0.04;
$percent_text = ' 4%';
$has_discount =true;
}
// Calculation
$discount = $stotal_ext * $percent;
// Displayed text
$discount_text = __('Discount', 'woocommerce') . $percent_text;
if( $has_discount ) {
WC()->cart->add_fee( $discount_text, $discount, false );
}
// Last argument in add fee method enable tax on calculation if "true"
}
This goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works.
Similar: WooCommerce - Conditional Progressive Discount based on number of items in cart
Reference: WooCommerce class - WC_Cart - add_fee() method

Categories