Search code examples
phpwordpresswoocommercecategoriescart

Minimum cart amount except and exclusively for a product category


I am trying to set a minimum amount for cart to allow customers to checkout. But I meed to make an exception with a product category, which I will allow the customer to go ahead even if it doesn't meet the 200 minimum required.

My code is working almost fine except for:

  • the cart calculation amount displayed in the notice (is wrong).
  • the exclusive condition for this special category 501 (doesn't work as expected when other categories product items are also in cart in addition of this special category).

Here is my code:

add_action( 'woocommerce_check_cart_items', 'oxynergy_set_min_total' );
    function oxynergy_set_min_total() {
    // Only run in the Cart or Checkout pages
    if( is_cart() || is_checkout() ) {

        global $woocommerce, $product;
        $i=0;
        // Minimum order checking
        $minimumCheck = false;
        // Set minimum cart total
        $minimum_cart_total = 200;
        //loop through all cart products
        foreach ( $woocommerce->cart->cart_contents as $product ) {
            // Total we are going to be using for the Math
            // This is before taxes and shipping charges
            $total = WC()->cart->total;

            // See if any product is from the STOCK category or not
            if ( has_term( '481', 'product_cat', $product['product_id'] ) || has_term( '482', 'product_cat', $product['product_id'] )  || has_term( '495', 'product_cat', $product['product_id'] ) ) {
                $minimumCheck = true;
                //Get price of that product
                $regular_price = get_post_meta($product['product_id'], '_regular_price', true); //change to _sale_price if it is in sale
                //echo $regular_price."<br>";
                $total = $regular_price * $product['quantity']; 
                //echo $total."<br>";
                $subtotal_cat += $total; //get total of 
                //echo $subtotal_cat;
                //$category_price += ( $product['line_subtotal'] + $product['line_subtotal_tax'] );

            }
            if (has_term( '501', 'product_cat', $product['product_id']) ) {
                //Get price of that product
                $regular_price = get_post_meta($product['product_id'], '_regular_price', true); //change to _sale_price if it is in sale
                //echo $regular_price."<br>";
                $total = $regular_price * $product['quantity']; 
                //echo $total."<br>";
                $subtotal_cat += $total; //get total of 
                //echo $subtotal_cat;
                //$category_price += ( $product['line_subtotal'] + $product['line_subtotal_tax'] );
            }

        }


            if ( $minimumCheck && $subtotal_cat <= $minimum_cart_total) {

                // Compare values and add an error is Cart's total
                // happens to be less than the minimum required before checking out.
                // Will display a message along the lines of
                // A Minimum of 200 USD is required before checking out. (Cont. below)
                // Current cart total: 6 USD 
                wc_add_notice( sprintf( '<strong>A Minimum of %s %s excl. TAX is required category before checking out.</strong>'
                        .'<br />Current cart\'s total: %s %s excl. TAX',
                        $minimum_cart_total,
                        get_option( 'woocommerce_currency'),
                        $subtotal_cat,
                        get_option( 'woocommerce_currency') ),
                    'error' );
            }


    }

}

What I am doing wrong?
How can I make this code work to have an exception exclusively for that special product category?

Thanks.


Solution

  • If I have understood, you need to disable the defined "Minimal required total cart amount" only and exclusively for product category, but not if there is other cart items from others product categories with it.

    So you just need to set this product category ID in the code below and you don't need any calculations for cart.

    Also I doesn't use has_term() function to avoid a kind of bug with parent/child product categories. Instead I use wp_get_post_terms() and a foreach loop…

    I have changed consistently your code:

    add_action( 'woocommerce_check_cart_items', 'oxynergy_set_min_total' );
    function oxynergy_set_min_total() {
        // Only run in the Cart or Checkout pages
        if( is_cart() || is_checkout() ) {
    
            // Set HERE your minimum cart total
            $minimum_cart_total = 200;
            // Set HERE your special product category ID
            $special_category = 501; 
    
            //Iterating through each cart items
            foreach ( WC()->cart->get_cart() as $cart_item ) {
    
                // Get the product categories for the current item
                $item_categories = wp_get_post_terms( $cart_item['product_id'], 'product_cat' );
    
                // Iterating through each product categories defined for the item
                foreach($item_categories as $item_category){
                    if( $item_category->term_id == $special_category ) {
                        $minimumCheck = false;
                        break;
                    }
                    else {
                        $minimumCheck = true;
                    }
                }
    
                // The cart total without taxes:
                $cart_total_excl_taxes =  WC()->cart->subtotal_ex_tax;
            }
    
            if ( $minimumCheck == 'true' && $cart_total_excl_taxes <= $minimum_cart_total) {
    
                // Displays the message notice
                wc_add_notice( sprintf( '<strong>A Minimum of %s %s excl. TAX is required category before checking out.</strong>'
                    .'<br />Current cart\'s total: %s %s excl. TAX',
                    $minimum_cart_total,
                    get_option( 'woocommerce_currency'),
                    $cart_total_excl_taxes,
                    get_option( 'woocommerce_currency') ),
                    'error' );
            }
        }
    }
    

    This code is tested and works this time…

    Code goes in any php file of your active child theme (or theme) or also in any plugin php files.