Repository Forums Support WooCommerce Extended Coupon Features PRO Don’t apply other coupon discounts to a BOGO/Free product

Viewing 9 posts - 1 through 9 (of 9 total)
  • Author
    Posts
  • #15545
    anthonyceo
    Participant

    I want to allow multiple coupons, but don’t want any other coupons to apply further discounts to any products that are buy 1 get 1 free.

    (e.g. I want to use a 20% off coupon with a BOGO coupon. But I don’t want the BOGO item to have this 20% discount)

    How can I accomplish this with the plugin or a filter? I think I need to do this with a filter as it’s too much work selecting all the exclusions for every new coupon.

    #15551
    Soft79
    Keymaster

    I think you could use http://hookr.io/filters/woocommerce_coupon_is_valid_for_product/ for that… return false if the discount shouldn’t apply.

    #15554
    anthonyceo
    Participant

    Hmmm, the $coupon object isn’t in that filter. Just $bool and $product. Scratching my head.

    #15555
    Soft79
    Keymaster

    Yes it is, it’s the 3rd argument.

    #15556
    anthonyceo
    Participant

    Thank you. It seems to work.

    However, I’m determining what products have free products through custom meta data. In this case, the meta data for free products is called hide_sub.

    I don’t want to do it this way. It also won’t work for buy 2 get 1 free, etc. I want to be able to determine programmatically if any product has an auto-applied free product coupon. Is this possible? Thanks.

    add_filter('woocommerce_coupon_is_valid_for_product', 'free_product_discount_coupon', 10, 4);
    
    function free_product_discount_coupon($bool, $product, $coupon, $values) {
    
    	// Get parent product id for variable products.
    	// Required to retrieve custom meta data.
    
    	$parent_id = $product->get_parent_id();
    
    	// Create a parent product from the parent id or 
    	// set $parent_product = $product if the product is the parent product.
    	
    	if ( $parent_id > 0 ) {
    		$parent_product = wc_get_product( $parent_id );
    	} else {
    		$parent_product = $product;
    	}
    
    	// if coupon is a free product coupon, apply it.
    
    	if ($coupon->get_meta('_wjecf_must_select_free_product') === 'yes') {
    		return $bool;
    	} else if ($parent_product->get_meta('hide_sub') == 1) {
    
    		// Don't allow any other coupons to be applied 
    		// to products with free product coupons (hide_sub = 1).
    
    		return false;
    	}
    
    	return $bool;
    	
    }
    #15557
    Soft79
    Keymaster

    if $values['_wjecf_free_product_coupon'] is set, it’s a free product.

    #15560
    anthonyceo
    Participant

    I assume you meant the $coupon object? I don’t see that meta in the $values object.

    The logical problem is that I need to know if the product has a free product coupon associated with it when it’s looping through other (non-free product) coupons. I want all other coupons to apply to everything else but the product with a free product. if I rely on _wjecf_free_product_coupon, no coupons other than the free product coupons will apply.

    I can’t think of a straightforward way to do this except adding custom meta data like above. There must be another way.

    #15561
    Soft79
    Keymaster

    No, it must in the $values array. The value is set for every free cart item that was added by a coupon.

    This works:

    
    add_filter( 'woocommerce_coupon_is_valid_for_product', function( $valid, $product, $coupon, $values ) {
        if ( isset( $values['_wjecf_free_product_coupon'] ) ) error_log ( $product->get_id() . " is a free item" );
        return $valid;
    }, 10, 4 );
    
    #15562
    anthonyceo
    Participant

    Very weird. I’m 100% sure it doesn’t have this on my end. Checked $values many times and doesn’t ever contain _wjecf_free_product_coupon. That code doesn’t work on my end with free products in cart.

    However, I did create code that works. A lot more complex than I anticipated. And not very efficient. It was annoying. But hey, it works.

    add_filter('woocommerce_coupon_is_valid_for_product', 'coupon_is_valid_for_free_product', 10, 4);
    
    function coupon_is_valid_for_free_product($bool, $product, $coupon, $values) {
    
    	// if coupon is a free product coupon, apply it.
    
    	if ($coupon->get_meta('_wjecf_must_select_free_product') === 'yes') {
    		return $bool;
    	}
    
    	// Get parent of product
    
    	$parent_id = $product->get_parent_id();
    	if ( $parent_id > 0 ) {
    		$parent_product = wc_get_product( $parent_id );
    	} else {
    		$parent_product = $product;
    	}
    
    	// Get children ids of product
    
    	$children = $parent_product->get_children();
    	if (empty($children)) {
    		$children[] = $product->id;
    	}
    
    	// get cart coupons
    	
    	$all_coupons = WC()->cart->get_coupons();
    
    	// loop through cart coupons and don't apply non-free product coupons to free products
    	foreach ($all_coupons as $c) {
    		$product_ids = explode(',', $c->get_meta('_wjecf_free_product_ids'));
    		foreach ($children as $id) {
    			// If the current product id is in this free product cart coupon, don't apply coupon
    			if (in_array($id, $product_ids)) {
    				return false;
    			}
    		}
    	}
    
    	return $bool;
    	
    }
Viewing 9 posts - 1 through 9 (of 9 total)
  • You must be logged in to reply to this topic.