Pair normal products with subscriptions based on item count in Woocommerce

702 Views Asked by At

In my website I use WooCommerce v3.1+ and Woocommerce Subscriptions. My products that contains items like video cameras and subscription plans. What I would like to do is:

  • when purchasing a camera and subscription plan, at cart page(before checkout), the quantity of the subscription plan must be equal to the quantity of cameras,
  • if another camera is added to the cart an error massage must appear...or something like that.

For example, if I have in my cart 2 specific products like a camera (quantity 2) and a subscription plan (quantity 1), the customer will not be able to checkout, if the subscription plan quantity does not match with cameras quantity.

I believe I have to modify the functions.php in child theme. Any help would be appreciated

See example image


Edit: I have added a piece of code in functions.php, but this will add x2 total items in cart:

add_action('woocommerce_check_cart_items', 'wh_wc_minimum_order_amount'); 
function wh_wc_minimum_order_amount() { 
    $minimum = 2; 
    if (WC()->cart->get_cart_contents_count() % $minimum != 0) { 
        // wc_clear_notices(); 
        wc_add_notice(sprintf('<strong>Error: check product quantity</strong>', $minimum), 'error');
    } 
} 

So this doesn't work.

1

There are 1 best solutions below

0
On BEST ANSWER

Here is a complete solution that will display custom notices when normal products count doesn't match with subscription plans, warning the customer lightly. If products doesn't match your requirements, the customer will be redirected from checkout to shop page (avoiding checkout).

The code (commented):

// Replacing add to cart button link on shop and archives
add_filter( 'woocommerce_loop_add_to_cart_link', 'replacing_add_to_cart_button', 10, 2 );
function replacing_add_to_cart_button( $button, $product ) {
    if( $product->is_type( 'variable-subscription' ) || $product->is_type( 'variable' ) ) return $button;

    $button_text = __( 'View product', 'woocommerce' );
    $button = '<a class="button" href="' . $product->get_permalink() . '">' . $button_text . '</a>';
    return $button;
}

// Counting cart items (utility function)
function counting_cart_items( $subscriptions_count = 0, $products_count = 0, $wc_cart = '' ) {
    $cart_obj = $wc_cart != '' ? $wc_cart :  WC()->cart;
    foreach( $cart_obj->get_cart() as $cart_item ){
        if ( $cart_item['data']->is_type( 'subscription' ) )
            $subscriptions_count += intval( $cart_item['quantity'] );
        else
            $products_count += intval( $cart_item['quantity'] );
    }
    return array( 'subscrip' => $subscriptions_count, 'product' => $products_count );
}

// Displaying Notification messages (utility function)
function conditionally_display_notice( $subscriptions_count, $products_count ) {
    $count = $subscriptions_count - $products_count;
    if( $subscriptions_count < $products_count )
        $txt = sprintf( _n( '%s subscription plan', '%s subscriptions plans', -$count, 'woocommerce' ), -$count );
    elseif( $subscriptions_count > $products_count )
        $txt = sprintf( _n( '%s product', '%s products', $count, 'woocommerce' ), $count );
    if( $subscriptions_count != $products_count )
        wc_add_notice( sprintf( __( "You need to add %s, to be able to checkout", "woocommerce" ), $txt ), "notice" );
}

// Checking and notifying when products are added to cart
add_filter( 'woocommerce_add_to_cart_validation', 'conditionally_check_add_to_cart', 10, 3 );
function conditionally_check_add_to_cart( $passed, $product_id, $quantity ) {
    $items_count = counting_cart_items(); // Counting cart items
    $product = wc_get_product( $product_id ); // Get an instance of the WC_Product object

    // Get the total live count
    if( $product->is_type( 'subscription' ) )
        $items_count['subscrip'] += intval( $quantity );
    else
        $items_count['product'] += intval( $quantity );

    // Notification messages
    conditionally_display_notice( $items_count['subscrip'], $items_count['product'] );
    return $passed;
}

// Conditionally checking and adding your subscription when a product is added to cart
add_action( 'woocommerce_before_main_content', 'display_notice_on_shop_archives' );
function display_notice_on_shop_archives( ) {
    if( is_product() ) return;
    $items_count = counting_cart_items(); // Counting cart items

    // Notification messages
    conditionally_display_notice( $items_count['subscrip'], $items_count['product'] );
    wc_print_notices();
}
/*
// Conditionally checking and adding your subscription when a product is added to cart
add_action( 'woocommerce_add_to_cart', 'conditionally_check_add_to_cart', 10, 6 );
function conditionally_check_add_to_cart( $cart_item_key, $product_id, $quantity, $variation_id, $variation, $cart_item_data ) {
    $items_count = counting_cart_items(); // Counting cart items
    $product = wc_get_product( $product_id ); // Get an instance of the WC_Product object

    // Get the updated count
    if( $product->is_type( 'subscription' ) )
        $items_count['subscrip'] += intval( $quantity );
    else
        $items_count['product'] += intval( $quantity );

    // Notification messages
    conditionally_display_notice( $items_count['subscrip'], $items_count['product'] );
}
*/
// Checking and validating when updating cart item quantities
add_filter( 'woocommerce_update_cart_validation', 'conditionally_check_cart_update', 10, 4 );
function conditionally_check_cart_update( $passed, $cart_item_key, $values, $updated_quantity ) {
    $items_count = counting_cart_items(); // Counting cart items

    // Get the updated count
    if( $values['data']->is_type( 'subscription' ) )
        $items_count['subscrip'] += intval( -$values['quantity'] + $updated_quantity );
    else
        $items_count['product'] += intval( -$values['quantity'] + $updated_quantity );

    // Notification messages
    conditionally_display_notice( $items_count['subscrip'], $items_count['product'] );
    return $passed;
}

// Checking and validating when updating cart item quantities
add_filter( 'woocommerce_cart_item_removed', 'conditionally_check_removed_cart_item', 10, 2 );
function conditionally_check_removed_cart_item( $cart_item_key, $wc_cart ) {
    $items_count = counting_cart_items( 0, 0, $wc_cart ); // Counting cart items

    // Notification messages
    conditionally_display_notice( $items_count['subscrip'], $items_count['product'] );
}

// Checking and conditionally redirecting to shop page
add_action( 'template_redirect', 'conditional_checkout_redirection');
function conditional_checkout_redirection(){
    if ( is_checkout() ) {
        $items_count = counting_cart_items(); // Counting cart items

        if ( $items_count['subscrip'] != $items_count['product']) {
            // redirecting to shop page
            wp_redirect( get_permalink( woocommerce_get_page_id( 'shop' ) ) );
            exit(); // always exit
        }
    }
}

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

This code is tested on Woocommerce 3+ and works