I wanted to apply a coupon code to cart if cart have minimum 2 items. if not have then the coupon not will apply and show alter message and if have apply then will show a success message here is my code I have tried not working like I want
add_action( 'woocommerce_before_calculate_totals','conditionally_auto_add_coupon', 30, 1 );
function conditionally_auto_add_coupon( $cart ) {
if ( is_admin() && !defined('DOING_AJAX') ) return; // Exit
// HERE set the coupon code (in lowercase)
$coupon_code = 'mycode';
$total_item = 0;
if (WC()->cart->has_discount('mycode')) {
foreach( $cart->get_cart() as $cart_item ){
$total_item++;
}
if($total_item < 2){
$cart->remove_coupon( $coupon_code );
wc_add_notice( __('you have only 1 item in cart'), 'alert');
}
else{
$cart->add_discount( $coupon_code );
wc_add_notice( __('coupon added'), 'notice');
}
}
}
Any help is welcome.
Try the following:
add_action( 'woocommerce_before_calculate_totals', 'auto_apply_coupon_conditionally', 10, 1 );
function auto_apply_coupon_conditionally( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
$coupon_code = 'summer'; // HERE set the coupon code (in lowercase)
$applied = in_array( $coupon_code, $cart->get_applied_coupons() ) ? true : false;
$item_count = sizeof( $cart->get_cart() );
$total_item = 0;
// Remove coupon
if ( $item_count < 2 && $applied ) {
$cart->remove_coupon( $coupon_code );
wc_clear_notices();
wc_add_notice( __('You have only 1 item in cart'), 'error');
}
// Add coupon
elseif ( $item_count >= 2 && ! $applied ) {
$cart->apply_coupon( $coupon_code );
wc_clear_notices();
wc_add_notice( __('A coupon has been added'), 'notice' );
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works
Please use "Smart Coupon For Woocommerce" plugin implementing the auto coupon functionality,
Please refer this code in svn repo.
Related
I need to apply a previously created coupon in woocommerce cart based on total spent in shop by logged in users. Example, If user already spent $300 or more in previous orders, in the next order, automatically apply "xxx" coupon.
based on "Apply automatically a coupon based on specific cart items count in Woocommerce" answer thread, that is what I have so far:
add_action( 'woocommerce_before_calculate_totals', 'auto_add_coupon_based_on_cart_items_count', 25, 1 );
function auto_add_coupon_based_on_cart_items_count( $user_id, $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Setting and initialising variables
$coupon = 'descuentolealtad'; // <=== Coupon code
$matched = false;
$customer = new WC_Customer( $user_id );
if( $customer->get_total_spent >= 60 ){
$matched = true; // Set to true
}
// If conditions are matched add coupon is not applied
if( $matched && ! $cart->has_discount( $coupon )){
// Apply the coupon code
$cart->add_discount( $coupon );
// Optionally display a message
wc_add_notice( __('Descuento de Lealtad aplicado'), 'notice');
}
// If conditions are not matched and coupon has been appied
elseif( ! $matched && $cart->has_discount( $coupon )){
// Remove the coupon code
$cart->remove_coupon( $coupon );
// Optionally display a message
//wc_add_notice( __('Descuento de Lealtad removido'), 'error');
}
}
I'm trying to use the dedicated get_total_spent() function from woocommerce but is giving me a blank screen.
Any help is appreciated.
Edit
That is my working code very different as I am using a negative fee:
add_action('woocommerce_cart_calculate_fees' , 'discount_based_on_customer_orders', 10, 1);
function discount_based_on_customer_orders( $cart_object ){
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Getting "completed" customer orders
$customer_orders = get_posts( array(
'numberposts' => -1,
'meta_key' => '_customer_user',
'meta_value' => get_current_user_id(),
'post_type' => 'shop_order', // WC orders post type
'post_status' => 'wc-completed' // Only orders with status "completed"
) );
// Orders count
$customer_orders_count = count($customer_orders);
// The cart total
$cart_total = WC()->cart->get_total(); // or WC()->cart->get_total_ex_tax()
// First customer order discount
if( empty($customer_orders) || $customer_orders_count == 0 ){
$discount_text = __('Loyalty Discount', 'woocommerce');
$discount = -7;
}
}
Updated - There is many mistakes in your code like:
For this hook there is only one variable argument: $cart… and not $user_id and $cart
Since Woocommerce 3, use the method get_total_spent() and not the property get_total_spent.
You should first check that user is logged in too.
Use the following revisited code instead:
add_action( 'woocommerce_before_calculate_totals', 'auto_add_coupon_based_on_total_spent', 10, 1 );
function auto_add_coupon_based_on_total_spent( $cart ) {
if ( ( is_admin() && ! defined( 'DOING_AJAX' ) ) || ! is_user_logged_in() )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Setting and initialising variables
$coupon = 'summer'; // <=== Coupon code
$spent_amount = 60;
$customer = new WC_Customer(get_current_user_id());
// If conditions are matched add coupon is not applied
if( $customer->get_total_spent() >= $spent_amount && ! $cart->has_discount( $coupon )){
// Apply the coupon code
$cart->add_discount( $coupon );
// Optionally display a message
wc_add_notice( __('Descuento de Lealtad aplicado'), 'notice');
}
// If conditions are not matched and coupon has been appied
elseif($customer->get_total_spent() < $spent_amount && $cart->has_discount( $coupon )){
// Remove the coupon code
$cart->remove_coupon( $coupon );
}
}
Code goes in function.php file of your active child theme (or active theme). It should better works.
I am trying to automatically trigger a coupon to be applied in the cart specifically for when there are 4 items in the cart.
The coupon is pre-created in the Woocommerce back-end of the site "tasterbox"
I am using an amended version from this answer code:
Add WooCommerce coupon code automatically based on product categories
Here is my code version:
add_action( 'woocommerce_before_calculate_totals', 'wc_auto_add_coupons', 10, 1 );
function wc_auto_add_coupons( $cart_object ) {
// Coupon code
$coupon = 'tasterbox';
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Initialising variables
$is_match = false;
$taster_item_count = 4;
// Iterating through each cart item
foreach ( WC()->cart->get_cart() as $cart_item ) {
// If cart items match 4
if( $cart->cart_contents_count == $taster_item_count ){
$is_match = true; // Set to true
break; // stop the loop
}
}
// If conditions are matched add the coupon discount
if( $is_match && ! $cart_object->has_discount( $coupon )){
// Apply the coupon code
$cart_object->add_discount( $coupon );
// Optionally display a message
wc_add_notice( __('TASTER BOX ADDED'), 'notice');
}
// If conditions are not matched and coupon has been appied
elseif( ! $has_category && $cart_object->has_discount( $coupon )){
// Remove the coupon code
$cart_object->remove_coupon( $coupon );
// Optionally display a message
wc_add_notice( __('SORRY, TASTERBOX NOT VALID'), 'alert');
}
}
However I can not get it to auto apply the coupon when there are 4 items in the cart. It seems like something simple to do, but I'm stuck.
Any help appreciated.
There is some little mistakes and errors in your code. Try the following instead:
add_action( 'woocommerce_before_calculate_totals', 'auto_add_coupon_based_on_cart_items_count', 25, 1 );
function auto_add_coupon_based_on_cart_items_count( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// Setting and initialising variables
$coupon = 'tasterbox'; // <=== Coupon code
$item_count = 4; // <=== <=== Number of items
$matched = false;
if( $cart->cart_contents_count >= $item_count ){
$matched = true; // Set to true
}
// If conditions are matched add coupon is not applied
if( $matched && ! $cart->has_discount( $coupon )){
// Apply the coupon code
$cart->add_discount( $coupon );
// Optionally display a message
wc_add_notice( __('TASTER BOX ADDED'), 'notice');
}
// If conditions are not matched and coupon has been appied
elseif( ! $matched && $cart->has_discount( $coupon )){
// Remove the coupon code
$cart->remove_coupon( $coupon );
// Optionally display a message
wc_add_notice( __('SORRY, TASTERBOX NOT VALID'), 'error');
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
We have some products in shop , and we are giving some coupons to customer .
product -> ABC price 10
coupon code is 'newcp' discount 20%;
so when people add the product to cart price will be 10 .
Then they apply coupon then original product price shown as 10 and calculate 20% from that and at the end the total will be 8
But now we need to change this as per specific condition
When people apply product coupon newbc
1)if coupon is newcp , then change order_item_price as order_item_price +3[ only if category is Fruit] , and this price should be shown in cart page, checkout page , order email
2)Calculate discount from the new price calculate discouunt from 13
3)If people remove coupon then price will again return to 10
I made 2 solutions , but not working.
Solution 1
add_action('woocommerce_before_calculate_totals', 'add_custom_price', 10, 1);
function add_custom_price($cart_obj)
{
if (is_admin() && !defined('DOING_AJAX')) return;
foreach($cart_obj->get_cart() as $key => $value)
{
$product_id = $value['product_id'];
$coupon_code = $value['coupon_code'];
if ($coupon_code != '' && $coupon_code == "newcp")
{
global $woocommerce;
if (WC()->cart->has_discount($coupon_code)) return;
else
{
if (has_term('fruits', 'product_cat', $product_id))
{
$value['data']->set_price(CURRENT_CART_PRICE + 3);
}
}
}
}
}
Solution 2
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 ) {
$coupon = $code;
}
}
if ($coupon == "newcp"){
foreach ( $cart_object->get_cart() as $cart_item )
{
$price = $cart_item['data']->price+3;
$cart_item['data']->set_price( $price );
}
}
}
Please help .
Here is a possible way to achieve that:
// Add custom calculated price conditionally as custom data to cart items
add_filter( 'woocommerce_add_cart_item_data', 'custom_add_cart_item_data', 20, 2 );
function custom_add_cart_item_data( $cart_item_data, $product_id ){
// Your settings below
$product_categories = array('fruits');
$addition = 3;
$product = wc_get_product($product_id);
$the_id = $product->is_type('variation') ? $product->get_parent_id() : $product_id;
if ( has_term( $product_categories, 'product_cat', $the_id ) )
$cart_item['custom_price'] = $product->get_price() + $addition;
return $cart_item;
}
// Set conditionally a custom item price
add_action('woocommerce_before_calculate_totals', 'add_custom_price', 20, 1);
function add_custom_price( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Only for a DEFINED coupon code ( to be set below )
$coupon_code = 'newcp';
if ( ! $cart->has_discount( $coupon_code ) ) return;
foreach( $cart->get_cart() as $cart_item ) {
if ( isset($cart_item['custom_price']) ) {
$cart_item['data']->set_price( (float) $cart_item['custom_price'] );
}
}
}
Code goes in function.php file of the active child theme (or active theme). Tested and works.
First post here so be gentle. I have done my usual searching and testing but I am stumped.
Anyways here is my code that I am trying to use. I need to apply a coupon code that takes 2% off all orders if the user belongs to a certain buying group which is in their profile.
The coupon also does an exclude on one category at the moment so I don't know exactly how that factors in when automatically applying a code.
Does it just follow the restrictions for the coupon?
add_action( 'woocommerce_before_cart', 'anla_apply_buying_group_discount_coupon' );
function anla_apply_buying_group_discount_coupon() {
global $woocommerce;
global $current_user;
$user_id = get_current_user_id();
$maybe_has_buying_group_discount = get_user_meta( $user_id, 'has_buying_group_discount', true );
if ( '1' === $maybe_has_buying_group_discount ) {
return true;
}
elseif ( '0' === $maybe_has_buying_group_discount ) {
return false;
}
if ($maybe_has_buying_group_discount == true ) {
$woocommerce->cart->add_discount( 'buying group discount (2%)' );
}
elseif ($maybe_has_buying_group_discount == false ) {
$woocommerce->cart->remove_discount( 'buying group discount (2%)' );
$woocommerce->cart->calculate_totals();
}
}
Any help is appreciated.
There are some errors and deprecated methods in your code. The hook that you are using is not the right one. Instead try the following with additional notice messages:
add_action( 'woocommerce_before_calculate_totals', 'apply_group_discount_coupon', 20, 1 );
function apply_group_discount_coupon( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// HERE set your coupon code
$coupon_name = "buying group discount (2%)";
$user_id = get_current_user_id();
$discount_enabled = get_user_meta( $user_id, 'has_buying_group_discount', true );
$coupon_code = sanitize_title( $coupon_name );
if ( $discount_enabled && ! $cart->has_discount( $coupon_code ) ){
$cart->apply_coupon( $coupon_code );
$message = __("You have 2% of discount as Premium user group", 'woocommerce');
} elseif ( ! $discount_enabled && $cart->has_discount( $coupon_code ) ) {
$cart->remove_coupon( $coupon_code );
$message = __("You can't get a discount as Premium user group", 'woocommerce');
} else
return;
// Display a custom notice
if( isset($message) ){
wc_clear_notices();
wc_add_notice( $message, 'notice');
}
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
The version without message:
add_action( 'woocommerce_before_calculate_totals', 'apply_group_discount_coupon', 20, 1 );
function apply_group_discount_coupon( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
// HERE set your coupon code
$coupon_name = "buying group discount (2%)";
$user_id = get_current_user_id();
$discount_enabled = get_user_meta( $user_id, 'has_buying_group_discount', true );
$coupon_code = sanitize_title( $coupon_name );
if ( $discount_enabled && ! $cart->has_discount( $coupon_code ) )
$cart->apply_coupon( $coupon_code );
elseif ( ! $discount_enabled && $cart->has_discount( $coupon_code ) ) {
$cart->remove_coupon( $coupon_code );
else
return;
}
I am unable to override price on second time purchase.
The use case would be: If a user has already bought product "944" then the price would be 0 for next time orders.
Meaning, the customer would pay only for first order of that specific product and it would be free for next orders.
Here my code:
// Enter the ID of the product that shouldn't be purchased again
$no_repeats_id = 944;
$no_repeats_product = wc_get_product( $no_repeats_id );
// Get the current product to check if purchasing should be disabled
global $product;
if ( $no_repeats_product->is_type( 'variation' ) ) {
// Bail if we're not looking at the product page for the non-purchasable product
if ( ! $no_repeats_product->parent->id === $product->id ) {
return;
}
// Render the purchase restricted message if we are
if ( wc_customer_bought_product( wp_get_current_user()->user_email, get_current_user_id(), $no_repeats_id ) ) {
sv_render_variation_non_purchasable_message( $product, $no_repeats_id );
}
} elseif ( $no_repeats_id === $product->id ) {
if ( wc_customer_bought_product( wp_get_current_user()->user_email, get_current_user_id(), $no_repeats_id ) ) {
// Create your message for the customer here
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price' );
add_action( 'woocommerce_before_calculate_totals', 'add_custom_price' );
function add_custom_price( $cart_object ) {
$custom_price = 10; // This will be your custome price
$target_product_id = 944;
foreach ( $cart_object->cart_contents as $value ) {
if ( $value['product_id'] == $target_product_id ) {
$value['data']->price = $custom_price;
}
/*
// If your target product is a variation
if ( $value['variation_id'] == $target_product_id ) {
$value['data']->price = $custom_price;
}
*/
}
}
}
}
}
add_action( 'woocommerce_single_product_summary', 'sv_purchase_disabled_message', 31 );
Here is the way to make it work in woocommerce 3+ too:
add_action( 'woocommerce_before_calculate_totals', 'conditionally_change_cart_items_price', 10, 1 );
function conditionally_change_cart_items_price( $cart_object ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
return;
// Set Here your targeted product ID
$targeted_product_id = 944;
// Set Here your custom price (1st purshase)
$custom_price = 10; // First purshase for product ID 944
// Detecting if customer has already bought The targeted product (944)
if( is_user_logged_in() ){
$customer = wp_get_current_user();
$customer_id = $customer->ID; // customer ID
$customer_email = $customer->email; // customer email
if( wc_customer_bought_product( $customer_email, $customer_id, $targeted_product_id) )
$custom_price = 0; // Set to 0 for other purchases (product ID 944)
}
foreach ( $cart_object->get_cart() as $cart_item ) {
// When targeted product is in cart we change the price
if ( $cart_item['product_id'] == $targeted_product_id ) {
// Woocommerce 3+ compatibility
if ( version_compare( WC_VERSION, '3.0', '<' ) )
$cart_item['data']->price = $custom_price;
else
$cart_item['data']->set_price( $custom_price );
}
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
This code is tested and works even in WooCommerce 3+