I'm trying to setup no tax for orders under $110.
I bumped into this thread Set different Tax rates conditionally based on cart item prices in Woocommerce and tried it but doesn't seems to work when i add it on functions.php - Maybe because some of the codes are outdated?
Here's the revised code:
add_action( 'woocommerce_before_calculate_totals', 'change_cart_items_prices', 10, 1 );
function change_cart_items_prices( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
foreach ( $cart->get_cart() as $cart_item ) {
// get product price
$price = $cart_item['data']->get_price();
// Set conditionaly based on price the tax class
if ( $price < 111 )
$cart_item['data']->set_tax_class( 'zero-rate' ); // below 111
if ( $price >= 111 )
$cart_item['data']->set_tax_class( 'standard' ); // Equal above 110
}
}
I believe Standard & Zero rates tax options in Woo commerce > Settings > Tax are setup correctly.
Got it working using this code:
add_action( 'woocommerce_before_calculate_totals', 'apply_conditionally_zero_tax_rate', 10, 1 );
function apply_conditionally_zero_tax_rate( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$defined_amount = 110;
$subtotal = 0;
// Loop through cart items (1st loop - get cart subtotal)
foreach ( $cart->get_cart() as $cart_item ) {
$subtotal += $cart_item['line_total'];
}
// Targeting cart subtotal up to the "defined amount"
if ( $subtotal > $defined_amount )
return;
// Loop through cart items (2nd loop - Change tax rate)
foreach ( $cart->get_cart() as $cart_item ) {
$cart_item['data']->set_tax_class( 'zero-rate' );
}
}
Related
I'm trying to add a 10% discount to all products that fall into category B when a product from category A is in the cart, this is what i've tried so far and from what I see there's not an obvious reason but the discount is not applied in the cart. It can be a total discount fee or a separate discount for each item.
add_action( 'woocommerce_before_calculate_totals', 'apply_category_discount_in_cart', 10, 1 );
function apply_category_discount_in_cart( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$discount_amount = 0;
$category_A_in_cart = false;
// Loop through each item in the cart
foreach ( $cart->get_cart() as $cart_item ) {
$product = $cart_item['data'];
// Check if the product has category A
if ( has_term( 'categorya', 'product_cat', $product->get_id() ) ) {
$category_A_in_cart = true;
break;
}
}
// If a product with category A is found in the cart
if ( $category_A_in_cart ) {
// Loop through each item in the cart again
foreach ( $cart->get_cart() as $cart_item ) {
$product = $cart_item['data'];
// Check if the product has category B
if ( has_term( 'categoryb', 'product_cat', $product->get_id() ) ) {
$discount_amount += $cart_item['line_total'] * 0.1;
$cart_item['data']->set_price( $cart_item['data']->get_price() * 0.9 );
}
}
// Add the discount amount as a fee
$cart->add_fee( 'Discount', -$discount_amount, true );
}
}
Hello this code creates two discount classes, and then with a filter on the cart page it shows the regular price and the discounted price, how can I do to have the same visual result also on the mini cart??
this is what i am trying to achieve in the minicart
add_action( 'woocommerce_before_calculate_totals', 'bbloomer_quantity_based_pricing', 9999 );
function bbloomer_quantity_based_pricing( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// Define discount rules and thresholds
$threshold1 = 2; // Change price if items > 100
$discount1 = 0.05; // Reduce unit price by 5%
$threshold2 = 3; // Change price if items > 1000
$discount2 = 0.1; // Reduce unit price by 10%
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item_key => $cart_item )
{
if( has_term( array('cartucce-inkjet'), 'product_cat', $cart_item['product_id'] ) ){
if ( $cart_item['quantity'] >= $threshold1 && $cart_item['quantity'] < $threshold2 )
{
$price = round( $cart_item['data']->get_price() * ( 1 - $discount1 ), 2 );
$cart_item['data']->set_price( $price );
}
elseif ( $cart_item['quantity'] >= $threshold2 )
{
$price = round( $cart_item['data']->get_price() * ( 1 - $discount2 ), 2 );
$cart_item['data']->set_price( $price );
}
}
}
}
function filter_woocommerce_cart_item_price( $price_html, $cart_item, $cart_item_key ) {
// Get the product object
$product = $cart_item['data'];
// Is a WC product
if ( is_a( $product, 'WC_Product' ) ) {
// Get reqular price
$regular_price = $product->get_regular_price();
// New price
$new_price = $cart_item['data']->get_price();
// NOT empty and NOT equal
if ( ! empty ( $regular_price ) && $regular_price != $new_price ) {
// Output
$price_html = '<del>' . wc_price( $regular_price ) . '</del> <ins>' . wc_price( $new_price ) . '</ins>';
}
}
return $price_html;
}
add_filter( 'woocommerce_cart_item_price', 'filter_woocommerce_cart_item_price', 10, 3 );
When a coupon is applied (belonging to a certain type) I change the product discount price to the regular price via:
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 10, 1);
function add_custom_price( $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 == 'percent_product' || $coupons1->type == 'percent')
$coupon = True;
}
}
if ($coupon == True)
foreach ( $cart_object->get_cart() as $cart_item )
{
$price = $cart_item['data']->regular_price;
$cart_item['data']->set_price( $price );
}
}
But if I have a category excluded, the code freaks out because it changes the price from sale to regular in the cart and does not add a discount.
How to work around this so that the excluded category does not change to the regular price?
To exclude certain categories you can use has_term() when loop through the cart items
So you get:
function action_woocommerce_before_calculate_totals( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
// Specific categories: the term name/term_id/slug. Several could be added, separated by a comma
$excluded_categories = array( 63, 15, 'categorie-1' );
// Initialize
$coupon_flag = false;
// Loop through applied coupons
foreach ( $cart->get_applied_coupons() as $coupon_code ) {
// Get an instance of the WC_Coupon Object
$coupon = new WC_Coupon( $coupon_code );
// Only for certain types, several can be added, separated by a comma
if ( in_array( $coupon->get_discount_type(), array( 'percent', 'percent_product' ) ) ) {
$coupon_flag = true;
break;
}
}
// True
if ( $coupon_flag ) {
// Loop through cart items
foreach ( $cart->get_cart() as $cart_item ) {
// Get product ID in
$product_id = $cart_item['product_id'];
// NOT contains the definite term
if ( ! has_term( $excluded_categories, 'product_cat', $product_id ) ) {
// Get regular price
$regular_price = $cart_item['data']->get_regular_price();
// Set new price
$cart_item['data']->set_price( $regular_price );
}
}
}
}
add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );
The discount I currently have essentially says
If 6 products within a specific category are in the cart --- discount the total price of $10
This piece of the code works fine. My issue is, this does not work
If there are 7 products, the 7th product being from a different category.
My goal is to give the discount no matter how many products are in the cart so long as there are 6 products within "Category A".
The following code works so long as there is 6 products in the "discounted category" or there is 1 product with a quantity of 6 etc. It falls apart when I add a product from another category. Feel free to rip it apart.
add_action( 'woocommerce_before_calculate_totals', 'this_item_free' );
function this_item_free() {
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$valid_product_category_id = array('soup-mix');
$has_category = false;
$count = WC()->cart->get_cart_contents_count();
foreach ( WC()->cart->get_cart() as $product ) {
$quantity = $product['quantity'];
$price = $product['data']->get_price();
}
if ( has_term( $valid_product_category_id, 'product_cat', $product['product_id'],
$product['quantity'] ) ) {
$has_category = true;
$cart_total = floatval( preg_replace( '#[^\d.]#', '', WC()->cart->get_cart_total() ) );
if($count == 6 && $has_category = true){
add_action( 'woocommerce_cart_calculate_fees', 'discount_based_on_total', 25, 1 );
function discount_based_on_total( $cart ) {
$total = $cart->cart_contents_total;
$discount = 9.95;
$cart->add_fee( __('discount', 'woocommerce'), -$discount );
wc_add_notice( apply_filters( 'discount_applied', 'You just got a free soup!') );
}
}
}
}
Your code contains some unnecessary steps and what you want to achieve can be obtained with just the woocommerce_cart_calculate_fees action hook
My answer contains:
Give a discount no matter how many products are in the cart so long as there are 6 products or there is 1 product with a quantity of 6, etc.. within "Category A".
function action_woocommerce_cart_calculate_fees( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
/* SETTINGS */
// Specific categories
$specific_categories = array( 'Categorie-A' );
// Discount
$discount = 10;
// Min quantity
$minimun_quantity = 6;
/* END SETTINGS */
// Counter
$current_quantity = 0;
// Loop though each cart item
foreach ( $cart->get_cart() as $cart_item ) {
// Get product id
$product_id = $cart_item['product_id'];
// Has certain category
if ( has_term( $specific_categories, 'product_cat', $product_id ) ) {
// Quantity
$product_quantity = $cart_item['quantity'];
// Add to total
$current_quantity += $product_quantity;
}
}
// Greater than or equal to
if ( $current_quantity >= $minimun_quantity ) {
// Add fee
$cart->add_fee( __( 'Discount_applied', 'woocommerce' ), -$discount, false );
}
}
add_action( 'woocommerce_cart_calculate_fees', 'action_woocommerce_cart_calculate_fees', 10, 1 );
To apply the discount per 6 products (6 = $10, 12 = $20, 18 = $30, etc..)
Replace
// Greater than or equal to
if ( $current_quantity >= $minimun_quantity ) {
// Add fee
$cart->add_fee( __( 'Discount_applied', 'woocommerce' ), -$discount, false );
}
With
// Greater than or equal to
if ( $current_quantity >= $minimun_quantity ) {
// Modulo
$mod = $current_quantity % $minimun_quantity;
// Times it fit
$times = ( $current_quantity - $mod ) / $minimun_quantity;
// Discount * times
$discount = $discount * $times;
// Add fee
$cart->add_fee( __( 'Discount_applied', 'woocommerce' ), -$discount, false );
}
I wish to set up a specific discount on a particular variable products but for certain selected variations not for all variation:
eg : my varible id - 1571
variation id - 1572
variation id - 1573
So if customer buys one product they get the another (the same) on 50% discount (Buy one get another for 50% off).
I've tried many discount plugins and the closest that I have found are:
Pricing Deals for WooCommerce,
Conditional Discounts for WooCommerce
WooCommerce Extended Coupon Features FREE
With some of them, I was able to setup discount on subtotal or discount on a each product but not exactly what I am looking for (Buy 1 get 1 off). There are other pro plugins I don't want to go for it.
The nearest code that I found is WooCommerce discount: buy one get one 50% off with a notice.
Is it possible to make a discount on the 2nd item for specific product variations of a variable product (only for each product variation)?
mak
To get a 50% Off on the 2nd item for some specific product variations of a variable product, you will use the following instead:
add_action('woocommerce_cart_calculate_fees', 'add_custom_discount_2nd_at_50', 10, 1 );
function add_custom_discount_2nd_at_50( $cart ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// YOUR SETTINGS:
$product_variations_ids = array(1572, 1573); // <== HERE your targeted product variations
// Initializing variables
$discount = 0;
$product_names = array();
// Loop through cart items
foreach ( $cart->get_cart() as $key => $cart_item ) {
if ( in_array( $cart_item['variation_id'], $product_variations_ids ) ) {
$qty = (int) $cart_item['quantity'];
$price = (float) $cart_item['data']->get_price();
$name = (string) $cart_item['data']->get_name();
if ( $qty > 1 ) {
$discount -= number_format( $price / 2, 2 );
}
elseif( $qty = 1 ) {
$product_names[] = $name;
}
}
}
// Applying the discount
if( $discount != 0 ){
$cart->add_fee('Buy one get one 50% off', $discount );
}
// Display a custom reminder notice on cart page (otional)
if( ! empty($product_names) ){
wc_clear_notices(); // clear other notices on checkout page.
if( ! is_checkout() ){
wc_add_notice( sprintf(
__( "Add one more to get 50%% off on the 2nd item for %s" ),
'"<strong>' . implode(', ', $product_names) . '</strong>"'
), 'notice' );
}
}
}
Code goes in functions.php file of your active child theme (or active theme) Tested and works.
To get 1 item at 50% OFF for each item purchased, instead of 50% OFF on the 2nd item, replace:
$discount -= number_format( $price / 2, 2 );
by:
$multiplier = ( $qty % 2 ) === 0 ? $qty / 2 : ( $qty - 1 ) / 2;
$discount -= number_format( $price / 2 * $multiplier, 2 );
To get the 2nd one Free instead of 50% OFF on the 2nd item, replace the code line:
$discount -= number_format( $price / 2, 2 );
by:
$discount -= $price;
To get 1 item free for each item purchased, instead of 50% OFF on the 2nd item, replace:
$discount -= number_format( $price / 2, 2 );
by:
$multiplier = ( $qty % 2 ) === 0 ? $qty / 2 : ( $qty - 1 ) / 2;
$discount -= $price * $multiplier;
You were really close!
The discount amount calculation were wrong
add_action('woocommerce_cart_calculate_fees', 'add_custom_discount_2nd_at_50', 10, 1 );
function add_custom_discount_2nd_at_50( $wc_cart ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;
$discount = 0;
$items_prices = array();
$qty_notice = 0; // <== Added HERE
// Set HERE your targeted variable product ID
$targeted_product_id = 1571 ;
foreach ( $wc_cart->get_cart() as $key => $cart_item ) {
if( $cart_item['product_id'] == $targeted_product_id ){
$qty = intval( $cart_item['quantity'] );
$qty_notice += intval( $cart_item['quantity'] ); // <== Added HERE
for( $i = 0; $i < $qty; $i++ )
$items_prices[] = floatval( $cart_item['data']->get_price());
}
}
$count_items_prices = count($items_prices);
//to get the discount of lowest price sorting in descending order
rsort($items_prices);
if( $count_items_prices > 1 ) foreach( $items_prices as $key => $price )
if( $key % 2 == 1 ) $discount -= number_format($price / 2, 2 );
if( $discount != 0 ){
// The discount
# Note: Last argument in add_fee() method is related to applying the tax or not to the discount (true or false)
$wc_cart->add_fee('50% off de segunda almohada' , (($price/2)*($discount))^⁻1, true ); //EDITED
// Displaying a custom notice (optional)
wc_clear_notices();
if(!is_checkout()){
wc_add_notice( __("Hurrah!! You got 50% off discount on the 2nd item"), 'notice');
}}
// Display a custom notice on cart page when quantity is equal to 1.
elseif( $qty_notice == 1){
wc_clear_notices();
if(!is_checkout()){
wc_add_notice( __( "Add one more to get 50% off on 2nd item" ), 'notice');
}}
}