phpwordpresswoocommerceproductcoupon

Exclude product from all coupons in WooCommerce


I have searched all over the internet, but it doesn't seem to be any answer anywhere in spite of countless people asking the question.

Is there any way to exclude a specific product from ALL coupons?

I understand that you can do it on coupon level, but this is rather messy especially as a lot of people have automatic coupons, several people creating coupons etc…

TLDR: Any way to make a product excluded from all coupons at Product level.


Solution

  • Here is a nice way to automate this process.

    1) We add a custom checkbox in product general settings metabox to disable the coupon functionality for the current product. So you will get this in Backend Edit Product pages:

    custom checkbox in product general settings metabox

    All selected products will be saved in an array and will be used in the following…

    2) This selected products will be excluded from coupon discount at product level and the product discount amount will be set to zero.


    The code:

    // Create and display the custom field in product general setting tab
    add_action( 'woocommerce_product_options_general_product_data', 'add_custom_field_general_product_fields' );
    function add_custom_field_general_product_fields(){
        global $post;
    
        echo '<div class="product_custom_field">';
    
        // Custom Product Checkbox Field
        woocommerce_wp_checkbox( array(
            'id'        => '_disabled_for_coupons',
            'label'     => __('Disabled for coupons', 'woocommerce'),
            'description' => __('Disable this products from coupon discounts', 'woocommerce'),
            'desc_tip'  => 'true',
        ) );
    
        echo '</div>';;
    }
    
    // Save the custom field and update all excluded product Ids in option WP settings
    add_action( 'woocommerce_process_product_meta', 'save_custom_field_general_product_fields', 10, 1 );
    function save_custom_field_general_product_fields( $post_id ){
    
        $current_disabled = isset( $_POST['_disabled_for_coupons'] ) ? 'yes' : 'no';
    
        $disabled_products = get_option( '_products_disabled_for_coupons' );
        if( empty($disabled_products) ) {
            if( $current_disabled == 'yes' )
                $disabled_products = array( $post_id );
        } else {
            if( $current_disabled == 'yes' ) {
                $disabled_products[] = $post_id;
                $disabled_products = array_unique( $disabled_products );
            } else {
                if ( ( $key = array_search( $post_id, $disabled_products ) ) !== false )
                    unset( $disabled_products[$key] );
            }
        }
    
        update_post_meta( $post_id, '_disabled_for_coupons', $current_disabled );
        update_option( '_products_disabled_for_coupons', $disabled_products );
    }
    
    // Make coupons invalid at product level
    add_filter('woocommerce_coupon_is_valid_for_product', 'set_coupon_validity_for_excluded_products', 12, 4);
    function set_coupon_validity_for_excluded_products($valid, $product, $coupon, $values ){
        if( ! count(get_option( '_products_disabled_for_coupons' )) > 0 ) return $valid;
    
        $disabled_products = get_option( '_products_disabled_for_coupons' );
        if( in_array( $product->get_id(), $disabled_products ) )
            $valid = false;
    
        return $valid;
    }
    
    // Set the product discount amount to zero
    add_filter( 'woocommerce_coupon_get_discount_amount', 'zero_discount_for_excluded_products', 12, 5 );
    function zero_discount_for_excluded_products($discount, $discounting_amount, $cart_item, $single, $coupon ){
        if( ! count(get_option( '_products_disabled_for_coupons' )) > 0 ) return $discount;
    
        $disabled_products = get_option( '_products_disabled_for_coupons' );
        if( in_array( $cart_item['product_id'], $disabled_products ) )
            $discount = 0;
    
        return $discount;
    }
    

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

    Tested and perfectly works