3

I want to apply a discount coupon automatically to everyone who has made at least one purchase on my website. This is the code that I tried but I get a fatal error on the page ...

function has_bought( $customer_email ){
    $orders = get_posts(array(
        'numberposts' => -1,
        'post_type' => 'shop_order',
        'post_status' => array('wc-completed'),
    )  );

    $email_array = array();

    foreach($orders as $order) {
        $order_obj = wc_get_order($order->ID);
        $order_obj_data = $order_obj->get_data();

        array_push($email_array, $order_obj_data['billing']['email']);
    }


    if (in_array($customer_email, $email_array)) {
        return true;
    } else {
        return false;
    }
}

add_action( 'woocommerce_before_cart', 'apply_matched_coupons' );
function apply_matched_coupons() {
    global $woocommerce;

    $coupon_code = '10fidelity'; // coupon code

    if ( $woocommerce->cart->has_discount( $coupon_code ) ) return;

    if ( has bought() {
        $woocommerce->cart->add_discount( $coupon_code );
        $woocommerce->show_messages();
    }
}
LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399

1 Answers1

2

Your actual code is heavy and outdated… Instead try the following much more lighter and efficient way, that use the WC_Customer is_paying_customer property:

add_action( 'woocommerce_before_calculate_totals', 'enable_customer_fidelity_discount', 10, 1 );
function enable_customer_fidelity_discount( $cart ) {
    if ( ! ( is_cart() || is_checkout() ) )
        return;

    if ( ( is_admin() && ! defined( 'DOING_AJAX' ) ) || ! is_user_logged_in() )
        return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // The discount coupon code below
    $coupon_code = '10fidelity';

    if( ! in_array( $coupon_code, $cart->get_applied_coupons() ) && WC()->customer->get_is_paying_customer() ) {
        $cart->apply_coupon( $coupon_code );
    } elseif( in_array( $coupon_code, $cart->get_applied_coupons() ) && ! WC()->customer->get_is_paying_customer() ) {
        $cart->remove_coupon( $coupon_code );
    }
}

Code goes in functions.php file of your active child theme (or active theme). Tested and works


Or using this improved and light function that checks if customer has already made an order:

function has_bought( $user_id = 0 ) {
    global $wpdb;
    $customer_id = $user_id == 0 ? get_current_user_id() : $user_id;
    $paid_order_statuses = array_map( 'esc_sql', wc_get_is_paid_statuses() );

    $results = $wpdb->get_col( "
        SELECT p.ID FROM {$wpdb->prefix}posts AS p
        INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
        WHERE p.post_status IN ( 'wc-" . implode( "','wc-", $paid_order_statuses ) . "' )
        AND p.post_type LIKE 'shop_order'
        AND pm.meta_key = '_customer_user'
        AND pm.meta_value = $customer_id
    " );

    // Count number of orders and return a boolean value depending if higher than 0
    return count( $results ) > 0 ? true : false;
}

add_action( 'woocommerce_before_calculate_totals', 'enable_customer_fidelity_discount', 10, 1 );
function enable_customer_fidelity_discount( $cart ) {
    if ( ! ( is_cart() || is_checkout() ) )
        return;

    if ( ( is_admin() && ! defined( 'DOING_AJAX' ) ) || ! is_user_logged_in() )
        return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // The discount coupon code below
    $coupon_code = 'summer';

    if( ! in_array( $coupon_code, $cart->get_applied_coupons() ) && has_bought() ) {
        $cart->apply_coupon( $coupon_code );
    } elseif( in_array( $coupon_code, $cart->get_applied_coupons() ) && ! has_bought() ) {
        $cart->remove_coupon( $coupon_code );
    }
}

Code goes in functions.php file of your active child theme (or active theme). Tested and works.


Related:

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • I have also tried the code that you put in this post https://stackoverflow.com/questions/55821613/auto-apply-coupon-only-one-time-per-user-based-on-total-spent-in-woocommerce/ 55822058 # 55822058 and I get syntax error from this line // If the coupon has already been used by the customer, we exit – Carlos Gomez May 26 '19 at 07:14
  • Thank you very much for your answer @LoicTheAztec! I have tried both codes and none of them works, the coupon does not apply. I discovered that if I delete this line from your code it works (although I get many coupon messages added and try to end the purchase automatically) "if (! (Is_cart () || is_checkout ())) return; " – Carlos Gomez May 27 '19 at 20:20