skip to Main Content

I will like to display a message on the checkout page notifying the customers that they have purchased this product in the past (the product they are about to purchase), but this message should only run if these conditions are met.

  1. Customer must be logged in
  2. User role is administrator or customer
  3. previously purchased product should still have order status of ‘processing.’

So far, I have been able to get the first 2 conditions working fine:

function user_logged_in_product_already_bought() {

    global $woocommerce;

    if ( ! is_user_logged_in() ) return;
            

    $items = $woocommerce->cart->get_cart();

    $has_bought = false;

    foreach($items as $item => $values) { 
        if ( wc_customer_bought_product( '', get_current_user_id(), $values['data']->get_id() ) ) {
            $has_bought = true;
            break;
        }
    } 


    
    $user = wp_get_current_user();
$allowed_roles = array( 'administrator', 'customer' );
if ( array_intersect( $allowed_roles, $user->roles ) ) {
    
    if( $has_bought ){
        wc_print_notice( "You purchased this in the past. Buy again?", 'success' );
    }
}
        


}
add_action( 'woocommerce_before_checkout_form', 'user_logged_in_product_already_bought' );

Note: the reason I’m using the foreach is that users only purchase one product at a time (can’t have more than a single appointment product in the cart)

But I don’t know how to go about with the third condition. Any advice?

3

Answers


  1. according to this article:

    you can implement such a login as below :

    $customer_orders = get_posts( array(
        'numberposts' => -1,
        'meta_key'    => '_customer_user',
        'meta_value'  =>  $user->ID,
        'post_type'   => wc_get_order_types(),
        'post_status' => array_keys( wc_get_is_paid_statuses() ),
    ) );
    
    // LOOP THROUGH ORDERS AND GET PRODUCT IDS
    if ( ! $customer_orders ) return;
    
    $product_ids = array();
    foreach($items as $item) { 
       foreach ( $customer_orders as $customer_order ) {
           $order = wc_get_order( $customer_order->ID );
           $orderItems = $order->get_items();
           foreach ( $orderItems as $orderItem ) {
              if ($orderItem->get_product_id() == $item->get_product_id() )
                 $has_bought = true;
                 break;
           }
       }
    } 
    
    Login or Signup to reply.
  2. Your first 2 steps indeed work, for the 3rd step you will have to use a custom function which only checks for the order status ‘processing’.

    The advantage of this custom function is that it is much faster and lighter compared to going through all existing orders.

    So you get:

    function has_bought_items( $user_id = 0, $product_ids = 0 ) {
        // When empty, return false
        if ( empty ( $product_ids ) ) return false;
    
        global $wpdb;
        
        $product_ids = is_array( $product_ids ) ? implode( ',', $product_ids ) : $product_ids;
    
        $line_meta_value = $product_ids != 0 ? 'AND woim.meta_value IN (' . $product_ids . ')' : 'AND woim.meta_value != 0';
    
        // Count the number of products
        $count = $wpdb->get_var( "
            SELECT COUNT(p.ID) FROM {$wpdb->prefix}posts AS p
            INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
            INNER JOIN {$wpdb->prefix}woocommerce_order_items AS woi ON p.ID = woi.order_id
            INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS woim ON woi.order_item_id = woim.order_item_id
            WHERE p.post_status IN ( 'wc-processing' )
            AND pm.meta_key = '_customer_user'
            AND pm.meta_value = '$user_id'
            AND woim.meta_key IN ( '_product_id', '_variation_id' ) $line_meta_value 
        " );
    
        // Return true if count is higher than 0 (or false)
        return $count > 0 ? true : false;
    }
     
    function action_woocommerce_before_checkout_form() {
        // Customer must be logged in
        if ( ! is_user_logged_in() ) return;
        
        // Get current user
        $user = wp_get_current_user();
        
        // Allowed user roles
        $allowed_roles = array( 'administrator', 'customer' );
        
        // Compare
        if ( array_intersect( $allowed_roles, $user->roles ) ) {
            // WC Cart NOT null
            if ( ! is_null( WC()->cart ) ) {
                // Initialize
                $product_ids = array();
                
                // Loop through cart contents
                foreach ( WC()->cart->get_cart_contents() as $cart_item ) {
                    // Get product ID and push to array
                    $product_ids[] = $cart_item['variation_id'] > 0 ? $cart_item['variation_id'] : $cart_item['product_id'];
                }
                
                // Call function, and if true
                if ( has_bought_items( $user->ID, $product_ids ) ) {
                    // Notice
                    wc_print_notice( __( 'You purchased this in the past. Buy again?', 'woocommerce' ), 'success' );
                }
            }
        }
    }
    add_action( 'woocommerce_before_checkout_form', 'action_woocommerce_before_checkout_form' );
    

    Result: a general message

    enter image description here


    Optional: Instead of displaying a general message, but showing this separately per product, you can use the woocommerce_checkout_cart_item_quantity hook

    So you would get:

    function has_bought_items( $user_id = 0, $product_ids = 0 ) {
        // When empty, return false
        if ( empty ( $product_ids ) ) return false;
    
        global $wpdb;
        
        $product_ids = is_array( $product_ids ) ? implode( ',', $product_ids ) : $product_ids;
    
        $line_meta_value = $product_ids != 0 ? 'AND woim.meta_value IN (' . $product_ids . ')' : 'AND woim.meta_value != 0';
    
        // Count the number of products
        $count = $wpdb->get_var( "
            SELECT COUNT(p.ID) FROM {$wpdb->prefix}posts AS p
            INNER JOIN {$wpdb->prefix}postmeta AS pm ON p.ID = pm.post_id
            INNER JOIN {$wpdb->prefix}woocommerce_order_items AS woi ON p.ID = woi.order_id
            INNER JOIN {$wpdb->prefix}woocommerce_order_itemmeta AS woim ON woi.order_item_id = woim.order_item_id
            WHERE p.post_status IN ( 'wc-processing' )
            AND pm.meta_key = '_customer_user'
            AND pm.meta_value = '$user_id'
            AND woim.meta_key IN ( '_product_id', '_variation_id' ) $line_meta_value 
        " );
    
        // Return true if count is higher than 0 (or false)
        return $count > 0 ? true : false;
    }
     
    function filter_woocommerce_checkout_cart_item_quantity( $item_qty, $cart_item, $cart_item_key ) {
        // Customer must be logged in
        if ( ! is_user_logged_in() ) return;
        
        // Get current user
        $user = wp_get_current_user();
        
        // Allowed user roles
        $allowed_roles = array( 'administrator', 'customer' );
        
        // Initialize
        $message = '';
        
        // Compare
        if ( array_intersect( $allowed_roles, $user->roles ) ) {
            // Get product id
            $product_id = $cart_item['variation_id'] > 0 ? $cart_item['variation_id'] : $cart_item['product_id'];
            
            // Call function, and if true
            if ( has_bought_items( $user->ID, $product_id ) ) {
                $message = '<p>' . __( 'You purchased this in the past. Buy again?', 'woocommerce' ) . '</p>';
            }
        }
    
        // Return
        return $item_qty . $message;
    }
    add_filter( 'woocommerce_checkout_cart_item_quantity', 'filter_woocommerce_checkout_cart_item_quantity', 10, 3 );
    

    Result: show separately by product

    enter image description here


    Note: the has_bought_items() function is based on Check if a user has purchased specific products in WooCommerce answer code

    Related: Display message below product name on WooCommerce cart page if user has bought product before

    Login or Signup to reply.
  3. Regarding 3rd point you can get the customer processing orders easily using wc_get_orders()

    $user              = wp_get_current_user();
    $processing_orders = wc_get_orders(
        array(
           'customer' => $user->ID,
           'status'   => 'wc-processing',
        )
    );
    

    You can check if the processing orders are empty or not.
    and you can loop over the orders products to get details about each product.

    foreach ( $processing_orders as $p_order ) {
       $order_products = $p_order->get_items();
       foreach ( $order_products as $product_item ) {
          $product_id = $product_item->get_id();
       }
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search