Augusto Gentile
Augusto Gentile

Reputation: 45

Minimum quantity order rules in WooCommerce based on user role and categories

I am trying to build a WooCommerce cart rule functionality. It should work like this:

When the user's role is "Wholesaler", they must add to the cart at least 2 or 3 items (depending on the category) of the same product category. Once that condition is met, they could add any product to the cart no matter the rules set before.

E.g:

Scenarios:


Based on Prevent WooCommerce checkout if minimum quantity for a category is not reached unless another category is added answer code, this is my code attempt:

function action_woocommerce_check_cart_items() {
    // Only run on the cart or checkout pages
    if ( is_cart() || is_checkout() ) {     
        // Minimum
        $minimum = 3;
        
        // Category
        $category1 = 'socks';
        $category2 = 'hats';
        
        // Initialize
        $total_socks = 0;
        $total_hats = 0;
        
        // Loop through cart items        
        foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {        
            // Product id
            $product_id = $cart_item['product_id'];

            // Has certain category
            if ( has_term( $category1, 'product_cat', $product_id ) ) {              
                // Add to total
                $total_socks += $cart_item['quantity'];
            }
            
            elseif ( has_term( $category2, 'product_cat', $product_id ) ) {              
                // Add to total
                $total_hats += $cart_item['quantity'];
            }
        }
        

        // When total is greater than 0 but less than the minimum
        if ( ($total_socks > 0 && $total_socks < $minimum) && ( $total_hats > 0 && $total_hats < $minimum )  ) {
            // Notice
            wc_add_notice( sprintf( __( 'A minimum of %s products are required from the %s category before checking out.', 'woocommerce' ), $minimum, $category1 ), 'error' );
            
            // Optional: remove proceed to checkout button
            remove_action( 'woocommerce_proceed_to_checkout', 'woocommerce_button_proceed_to_checkout', 20 );
        }
        
        
        
    }
}
add_action( 'woocommerce_check_cart_items' , 'action_woocommerce_check_cart_items', 10, 0 );

But I couldn’t add a user role check and mixed with the other categories missing on the script (socks and shirts), any advice?

Upvotes: 1

Views: 655

Answers (1)

7uc1f3r
7uc1f3r

Reputation: 29614

First of all, you can use the wp_get_current_user() function to check if the current user has the specified capability.

Then you better use a $settings array that you will loop through against multiple if/else conditions because this is more effective and much shorter to use.

Via the $settings array you can set the "category" and the "minimun", "total" should not be adjusted!

Generating the error message can be done in different ways, but a loop is used again to automatically create the message.

So you get:

function action_woocommerce_check_cart_items() {
    // Logged in
    if ( is_user_logged_in() ) {
        // Get user role(s)
        $user = wp_get_current_user();
        $roles = ( array ) $user->roles;

        // Compare, set the desired user role(s)
        $compare = array_diff( $roles, array( 'wholesaler', 'wholesale_customer', 'administrator' ) );

        // When empty
        if ( empty ( $compare ) ) {
            // Settings (multiple settings arrays can be added/removed if desired)
            $settings = array(
                array(
                    'category'  => 'socks',
                    'minimum'   => 3,
                    'total'     => 0
                ),
                array(
                    'category'  => 'hats',
                    'minimum'   => 3,
                    'total'     => 0
                ),
                array(
                    'category'  => 'shirts',
                    'minimum'   => 2,
                    'total'     => 0
                )
            );

            // Initialize
            $flag = false;

            // Collect data - loop through cart items        
            foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
                // Get product ID
                $product_id = $cart_item['product_id'];

                // Get quantity
                $product_quantity = $cart_item['quantity'];

                // Loop trough settings array
                foreach ( $settings as $key => $setting ) {
                    // Checks if the current product has any of given terms
                    if ( has_term( $setting['category'], 'product_cat', $product_id ) ) {
                        // Add to the total
                        $settings[$key]['total'] += $product_quantity;
                    }

                    // Checks if the current total is equal to or greater than the minimum
                    if ( $setting['total'] >= $setting['minimum'] ) {
                        // Make true, break loop
                        $flag = true;
                        break;
                    }
                }
            }

            // NOT true
            if ( ! $flag ) {
                // Initialize
                $message = '';
                $first_letter = __( 'A ', 'woocommerce' );

                // Generate error messages - loop trough settings array
                foreach ( $settings as $key => $setting ) {
                    // NOT the first iteration in a foreach loop, convert to capital letter
                    if ( $key !== array_key_first( $settings ) ) {
                        // Make a string lowercase
                        $first_letter = strtolower( $first_letter );
                    }

                    // Generate message, append
                    $message .= sprintf( __( '%s minimum of %s products are required from the "%s" category', 'woocommerce' ), $first_letter, $setting['minimum'], $setting['category'] );

                    // NOT the last iteration in a foreach loop, append 'OR'
                    if ( $key !== array_key_last( $settings ) ) {
                        $message .= '<strong>' . __( ' OR ', 'woocommerce' ) . '</strong>';
                    }
                }

                // Append to message
                $message .= __( ' before checking out.', 'woocommerce' );

                // Notice
                wc_add_notice( $message, 'error' );

                // Removing the proceed button, until the condition is met
                remove_action( 'woocommerce_proceed_to_checkout','woocommerce_button_proceed_to_checkout', 20 );
            }
        }
    }
}
add_action( 'woocommerce_check_cart_items', 'action_woocommerce_check_cart_items', 10 );

Upvotes: 1

Related Questions