2

I need to prevent coupons being used if customer have any specific product variations in their cart with following attribute terms:

  • attribute_pa_style => swirly
  • attribute_pa_style => circle

I've looked through the Woocommerce scripts that apply to restricting specific products and specific categories, but can't figure it out with regard to attributes and all coupons.

Any help is appreciated.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • Is "Style" product attribute used for product variations or not? What product types are you targeting? – LoicTheAztec Jan 21 '19 at 21:22
  • Yes, style attribute is used for variations. The product is a variable product with two attributes used for variations "Color" and "Style" . I want to target any products that have the style attribute to be excluded from coupons. – PurpleMonkeyDishwasher Jan 22 '19 at 13:32
  • How do I update this code if I want to reject coupons if only one of the "Style" attributes is selected? I've since changed this to "Style" - yes or no (the terms). I want to reject coupons if the product has the variation "yes" selected for the "style" attribute only. I tried removing the array but couldn't figure it out. Thanks very much for your help. – PurpleMonkeyDishwasher Dec 14 '19 at 17:29

2 Answers2

4

This can be done using woocommerce_coupon_is_valid filter hook this way:

add_filter( 'woocommerce_coupon_is_valid', 'check_if_coupons_are_valid', 10, 3 );
function check_if_coupons_are_valid( $is_valid, $coupon, $discount ){
    // YOUR ATTRIBUTE SETTINGS BELOW:
    $taxonomy   = 'pa_style';
    $term_slugs = array('swirly', 'circle');

    // Loop through cart items and check for backordered items
    foreach ( WC()->cart->get_cart() as $cart_item ) {
        foreach( $cart_item['variation'] as $attribute => $term_slug ) {
            if( $attribute === 'attribute_'.$taxonomy && in_array( $term_slug, $term_slugs ) ) {
                $is_valid = false; // attribute found, coupons are not valid
                break; // Stop and exit from the loop
            }
        }
    }
    return $is_valid;
}

Code goes in function.php file of your active child theme (or active theme). Tested and works.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • I tried this but it makes the coupon invalid for those not in the array. So my taxonomy is `finish` and my array is `'boxed', 'stretched'` but if I add a 3rd product to the cart which is not in this array, the coupon is not applied to that one "valid" product. Please can you help me. @loictheaztec – MitchellK Sep 12 '19 at 14:55
  • 1
    @MitchellK That is normal as it's the purpose of this code: If any product variations that have 'swirly' or 'circle' terms for 'pa_style' attribute is in cart, it makes the coupon invalid, **even if there is other items without**. The coupon can not be applied to other items, as this **is for global coupons types** as cart percentage and cart fixed. – LoicTheAztec Sep 12 '19 at 17:01
  • Is there any way around that issue? I'm trying to achieve the same thing @MitchellK is. Allowing the coupon to be applied to other products in the cart that aren't restricted by this function. These are percentage based coupons, but I need them to either discount 15% off per eligible product in the cart, or the cart total (excluding the ineligible product amount)...Is it possible? I tried this answer here, but it still rejected all - https://stackoverflow.com/a/46728531/7470830 – PurpleMonkeyDishwasher Mar 11 '20 at 16:17
  • I use this all the time. The spelling of your term_slugs must be exactly as they appear in the "Values" section under Attributes. So it applies the current coupon to all items that do NOT match any of the slugs you define. The moment a customers adds another item that is not applicable for the coupon, the coupon is removed from all items. Might not be the best solution and I am sure there could be much smarter and more complex ways of dealing with this. For my needs I found it to do just what I need, – MitchellK Mar 13 '20 at 07:53
  • My term slug for the attribute that I want to be excluded from the discount is simply "yes" . The taxonomy is "pa_customization" and the variations are "yes" or "no". So , spelling isn't the issue. I'm curious to know how you got it working though. Would really love to get these coupons working for the other products in the cart, or cart total excluding the "yes" variable product if in the cart. – PurpleMonkeyDishwasher Mar 14 '20 at 23:52
  • Just realized the above code is rejecting pa_customization = 'no' also. I need it to allow coupons if the product has no selected for that attribute. Any ideas? – PurpleMonkeyDishwasher Mar 18 '20 at 15:00
0

You could also check each product in the cart and restrict it from the coupon with woocommerce_coupon_is_valid_for_product

/**
 * exclude a product from an coupon by attribute value
 */
add_filter('woocommerce_coupon_is_valid_for_product', 'exclude_product_from_coupon_by_attribute', 12, 4);
function exclude_product_from_coupon_by_attribute($valid, $product, $coupon, $values ){
    /**
     * attribute Settings
     */
    $taxonomy = 'pa_saison';
    $term_slugs = array('SS22');

    /**
     * check if the product has the attribute and value 
     * and if yes restrict this product from the coupon
     */
    if(in_array($product->get_attribute($taxonomy), $term_slugs)) {
        $valid = false;

    /**
     * otherwise check if its a variation product
     */
    } elseif($product->parent_id) {
        /**
         * set the parent product
         */
        $parent = wc_get_product($product->parent_id);
        
        /**
         * check if parent has an attribute with this value
         */
        if(in_array($parent->get_attribute($taxonomy), $term_slugs)) {
            $valid = false;
        }

    /**
     * for all other products which does not have the attribute with the value
     * set the coupon to valid
     */
    } else {
        $valid = true;
    }

    return $valid;
}

I have tested it on my site and it works as expected.

cherrycoding
  • 1,855
  • 2
  • 14
  • 19