WooCommerce: Exclude product from threshold count for free shipping - php

I have set a threshold of 3 items for someone in the UK to get Free Shipping. Every time someone adds a product from a specific category, I automatically add a product to their cart which is a free gift.
My issue is that I am trying to exclude this free gift from the threshold count as currently this is being counted and people are getting free shipping without having 3 actual chargeable items in their cart.
I am unsure to how I can exclude product id 29 from counting, so any help would be greatly appreciated.
add_action( 'woocommerce_before_cart', 'ds_free_shipping_cart_notice' );
function ds_free_shipping_cart_notice() {
$threshold = 3;
$current = WC()->cart->get_cart_contents_count();
$billing_country = WC()->customer->get_billing_country();
if ( $current < $threshold && WC()->customer->get_billing_country() == 'GB' ) {
wc_print_notice( 'Nearly there! Order ' . ( $threshold - $current ) . ' more and shipping is on us', 'notice' );
}
}

I don't have woocommerce set up to be able to test this, but this is the type of logic you need:
$cart_items = WC()->cart->get_cart();
$current = WC()->cart->get_cart_contents_count();
foreach($cart_items as $item => $values) {
if ($values['product_id'] == 29) {
--$current;
}
}
This answer should help as well.
In general, though, this is a pretty fragile approach as you will need to change the hard-coded product ID every time you offer a new gift. It would be better to add a custom field to your products called "Free Gift" or something similar, set that value as needed for the items offered as free gifts, and then set up the code to exclude any of those items from the free shipping.

Related

Display Flat Rate Shipping Cost for Single Product Page on WooCommerce / Wordpress

I am trying to display the flat rate shipping cost for a product on its single product page.
From searching on Stack Overflow, I did find some solutions, but none worked quite as expected.
Currently, the Geo Location is being used, so I want to base the displayed shipping cost off of that location. Each product may have more than one shipping option, but I only want to display the flat rate fee for the individual product. E.g.
In the US - Product X - Shipping Cost $Y
In the UK - Product X - Shipping Cost £Z
Currently I have the following code:
function shipping_cost_display_1() {
$rates = WC()->session->get("shipping_for_package_0")['rates'];
if (! empty($rates) ) {
foreach ( $rates as $rate_key => $rate ) {
$method_id = $rate->method_id;
$instance_id = $rate->instance_id;
$rate_id = $rate_key;
$label = $rate->label;
$cost = $rate->cost;
$taxes_array = $rate->taxes;
$update_cost = ceil($cost *= (1 + display_tax_rate_on_single_product() / 100));
if ($label == 'Shipping cost') {
//'Shipping cost' is the Flat Rate
echo $label;
echo number_format($update_cost, 2);
}
}
}
}
It is displaying on the product page, but there are some issues. It will display the correct price on one page, but then if I go to another page the same price for the previous product will be displayed. If I add something to the cart then the price displayed on all product pages will change to that, so it seems to be related to the cart somehow.
Is there a way to get the direct flat rate for the individual product rather than have it related to the cart? Since Geo Location is already active, it should be possible to simply pull the flat rate for the product based on the current location.
I assume this current issue is happening somehow due to WC()->session , but any input would be appreciated.

Recalculate Taxes in Woocommerce

I got a Problem. In Woocommerce I added a custom product type (abo), where the user can choose a area size (in square meters) and there is a price per square meter and a dosage information where it says e.g. "You need 0.165kg per squaremeter" (it´s a fertilizer).
So for example if the user chooses 100 square meters and the price per square meter is 2.30€ and the dosage is 0.165kg/sqm the total price of the abo is 37.95€ and at a tax rate of 10.7% the tax amount should be 4.06€.
My Problem now is, I have normal products in the shop as well, where the standard calculation of the price and tax etc. works perfectly fine and you can buy the abo and a normal product.
So my question is, how can I recalculate the tax amount if I got an abo in cart?
I tried a few things for testing so far:
Adding a custom fee (that isn´t what I´m looking for, cause the tax has to be the same on cart, checkout and receipt):
add_action( 'woocommerce_cart_calculate_fees','custom_tax_surcharge_for_swiss', 10, 1 );
function custom_tax_surcharge_for_swiss( $cart ) {
if(current_user_can('administrator')) :
$percent = 10.7;
// Calculation
$surcharge = ( $cart->cart_contents_total + $cart->shipping_total ) * $percent / 100;
// Add the fee (tax third argument disabled: false)
$cart->add_fee( __( 'TAX', 'woocommerce')." ($percent%)", $surcharge, false );
endif;
}
calc_tax function (I think this one is the one I need) :
/ define the woocommerce_calc_tax callback
function filter_woocommerce_calc_tax( $taxes, $price, $rates, $price_includes_tax, $suppress_rounding ) {
if(current_user_can('administrator')) :
foreach(WC()->cart->cart_contents as $item) :
if($item['data']->get_type() == 'abo') :
$qty = $item['quantity'];
$ppqm = str_replace(',', '.', get_post_meta($item['product_id'], 'abo_product_price_per_kg')[0]);
$kgpqm = str_replace(',', '.', get_post_meta($item['product_id'], 'abo_product_kg_qm')[0]);
$realQty = floatval($kgpqm) * floatval($qty);
$priceCustom = $priceCustom + $realQty * floatval($ppqm);
endif;
endforeach;
return $taxes;
};
// add the filter
add_filter( 'woocommerce_calc_tax', 'filter_woocommerce_calc_tax', 10, 5 );
With the above function I got the problem, that I don´t have the cart contents directly so it could be, that the order of the items isn´t the same as the Tax order which I get from the function.
I would also note, that the woocommerce_calc_tax fires twice. I had for debug reasons an output in the console and if I have 2 items in cart, I got 4 outputs.
Hope my Problem is clear and that anyone could help me with that problem.
Thanks in advance.
I would look into the tax class for WooCommerce. You can specific target a item with a different tax rate. Unless I'm missing something this should actually work how you need it to out of the box.
When checking out it will also separate the taxes.

Can I change the order WooCommerce Coupons are applied programmatically?

I am developing a Woocommerce shop and want to offer all members (users logged in) 20% off their Total.
I have created a coupon called "twentypercent_off" and I am programmatically applying this using a custom function and a hook in my functions.php.
This works well.
In WC settings I have checked "Calculate coupon discounts sequentially" and this works almost as I would expect.
However what I would like is that my "twentypercent_off" is always applied last in cases where there are multiple coupons.
No matter what I have attempted to do (loop through all coupons on current order, remove all coupons, add them back in the order I desire) I find that Woo-commerce seems to always apply them in the order of monetary savings.
For example if the customer orders $100 worth of products and they have a coupon for $25 and also qualified to receive 20% off total.
I would like the total to calculate as (100 -25) * 0.8 = $60
but WC is calculating as such (100 * 0.8) - 25 = $55
I tried the following but it made no difference:
if ( is_user_logged_in() ) {
$Coupon_code = 'twentypercent_off';
$Current_Coupons = WC()->cart->get_coupons();
$Non_Prog_Coupons=array();
// loop through all current coupons
foreach( $Current_Coupons as $code => $coupon ){
if($code==$coupon_code){
WC()->cart->remove_coupon( $code );
} else {
WC()->cart->remove_coupon( $code );
$Non_Prog_Coupons[]=$code; // array of non-programmatically added coupons
}
}
// loop through non-programmatically added coupons
foreach( $Non_Prog_Coupons as $x => $code ){
WC()->cart->add_discount( $code ); // add them again
}
// add programmatically added coupon last !
WC()->cart->add_discount($Coupon_code);
}
return;
The only possible solution I have come across is to apply the 20% discount as a negative fee, which is not suitable for our purposes and would be an absolute last resort
Any ideas on how to achieve this would be greatly appreciated

woocomerce calculate final price based on the quantity of one product

I am currently setting up a woocommerce shop. Basically this is what I am trying to achieve.
"this is a fruit shop for whom they want fruits in basket( package), the customer select the fruits he wants (for example 3 items), then he/she select the basket with the desired quantity (1 among 3 different baskets in sites).
the total cost must be calculated like this: {sum(fruit a+fruit b+fruit c+basket price)* (the quantity of selected basket).
for example: apple price 3$, banana price 3$, selected basket price 1$, quantity of basket is: 200. total cost=(3+3+1)*200.
so this is just an example as I would like to setup pricing.
any idea how can that be achieved, I tried multiple plugins recommended by woocommerce but non of them do what I am looking for.
your help is greatly appreciated...
i write the following code for (in this code basket product id is 24).
But the problem is when I set for ex: 10 for basket. the total cost at the end of basket line in cart page exactly at the end of basket row will be like this: basket quantity* basket cost of 1$ so this is here 10 $.
And the total price is (3$ for bababa+3$ for apple+10 $ of basket )* QUANTITY of basket.
The right calculation is (3+3+1)*10.
add_action( 'woocommerce_calculate_totals', 'action_cart_calculate_totals', 10, 1 );
function action_cart_calculate_totals( $cart_object ) {
$targeted_id = 24;
foreach ( WC()->cart->get_cart() as $cart_item ) {
if($cart_item['product_id'] == $targeted_id ){
$qty = $cart_item['quantity'];
break; // stop the loop if product is found
}
}
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( !WC()->cart->is_empty() ):
$cart_object->subtotal *= $qty;
$cart_object->total *= $qty;
$cart_object->cart_contents_total *= $qty;
endif;
}
It seems your problem falls under Custom price calculation category.
There are some wordpress plugins you may get the job done by them like WooPrice Calculator and Booster for WooCommerce.

Custom Fee based on product dimensions and categories

I'm in a unique situation with my Woocommerce site.
I need to add a packaging fee, which will be somewhat similar to a handling fee.
Unfortunately, it's not as simple as adding a $5.00 handling fee to every order.
Since I sell wood products based on their measurements (width x height), the packaging fees are based on the total square footage for items. And they can differ depending on the category of the items, as well.
I've done a ton of research and I can't find a plugin to handle this situation.
To add to the complexity, there's a whole table that would need to be created. For example, if items from one category have a total square footage between 1-10, then the packaging fee will be $10. If total sq ftg is between 11-20, then it'll be $20.
How can I do to achieve that?
Thanks
Updated: Added WooCommerce 3+ compatibility
This is possible and easy with the add_fee() method in the woocommerce_cart_calculate_fees hook. Here is a simple usage example for simple products, with 2 categories and based on the product dimensions measurement calculations for each item of the cart. Its also possible for other product types.
Here is the example code (That you will need to customize for your own case):
add_action( 'woocommerce_cart_calculate_fees','custom_applied_fee', 10, 1 );
function custom_applied_fee( $cart_object ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Set HERE your categories (can be an ID, a slug or the name… or an array of this)
$category1 = 'plain';
$category2 = 'plywood';
// variables initialisation
$fee = 0;
$coef = 1;
// Iterating through each cart item
foreach( $cart_object->get_cart() as $cart_item ){
$product_id = version_compare( WC_VERSION, '3.0', '<' ) ? $cart_item['data']->id : $cart_item['data']->get_id();
$product = $cart_item['data']; // Get the product object
// Get the dimentions of the product
$height = $product->get_height();
$width = $product->get_width();
// $length = $product->get_length();
// Initialising variables (in the loop)
$cat1 = false; $cat2 = false;
// Detecting the product category and defining the category coeficient to change price (for example)
// Set here for each category the modification calculation rules…
if( has_term( $category1, 'product_cat', $cart_item['product_id']) )
$coef = 1.15;
if( has_term( $category2, 'product_cat', $cart_item['product_id']) )
$coef = 1.3;
// ## CALCULATIONS ## (Make here your conditional calculations)
$dimention = $height * $with;
if($dimention <= 10){
$fee += 10 * $coef;
} elseif($dimention > 10 && $dimention <= 20){
$fee += 20 * $coef;
} elseif($dimention > 20){
$fee += 30 * $coef;
}
}
// Set here the displayed fee text
$fee_text = __( 'Packaging fee', 'woocommerce' );
// Adding the fee
if ( $fee > 0 )
WC()->cart->add_fee( $fee_text, $fee, false );
// Note: Last argument in add_fee() method is related to applying the tax or not to the discount (true or false)
}
You will have to set your own categories with the related changes calculations for each category. You will get a non detailed general output fee calculated taking into account each item in the cart.
Code goes in function.php file of your active child theme (or theme). Or also in any plugin php files.
The code is tested and fully functional.
Related Answers:
Discount for Certain Category Based on Total Number of Products
Cart discount for a product category based on quantity calculations

Categories