3
votes

With reference to "Allow specific products to be purchase only if a coupon is applied in Woocommerce" answer code to one of my previous questions, the coupon code is hardcoded in the function and need to match from an existing coupon code in Woocommerce.

But I would like to pick the coupon dynamically from Woocommerce.

How can get the coupon dynamically from woocommerce?

3
Please elaborate, do you mean you want to assign the variable $coupon_code a coupon ID and have it figure out what the coupon name is?Ali_k
i want to make some changes in above code so it will retrieve the coupon code from woocommerce but not like this $coupon_code = 'summer2';Zain Ali
Do you want to retrieve a specific coupon or all of them?Ali_k
all of them, so those coupons which match with the product id will be appliedZain Ali
I understand, will write an answerAli_k

3 Answers

1
votes

The following code extends my previous answer and will add a checkbox in WooCommerce > coupon section enabling any coupon code to be "mandatory" for specific defined items:

enter image description here

So this way you will not have to define any coupon code in a function.

The whole code:

// Add a custom checkbox to Admin coupon settings pages
add_action( 'woocommerce_coupon_options', 'add_coupon_option_checkbox', 10 );
function add_coupon_option_checkbox() {
    woocommerce_wp_checkbox( array(
        'id'            => 'items_mandatory',
        'label'         => __( 'Force specific items', 'woocommerce' ),
        'description'   => __( 'Make this coupon mandatory for specific items.', 'woocommerce' ),
        'desc_tip'      => false,
    ) );
}

// Save the custom checkbox value from Admin coupon settings pages
add_action( 'woocommerce_coupon_options_save', 'save_coupon_option_checkbox', 10, 2 );
function save_coupon_option_checkbox( $post_id, $coupon ) {
    update_post_meta( $post_id, 'items_mandatory', isset( $_POST['items_mandatory'] ) ? 'yes' : 'no' );
}

add_action( 'woocommerce_check_cart_items', 'mandatory_coupon_for_specific_items' );
function mandatory_coupon_for_specific_items() {
    $targeted_ids    = array(37); // The targeted product ids (in this array)
    $applied_coupons = WC()->cart->get_applied_coupons();
    $coupon_applied  = false;

    if( sizeof($applied_coupons) > 0 ) {
        // Loop through applied coupons
        foreach( $applied_coupons as $coupon_code ) {
            $coupon = new WC_Coupon( $coupon_code );
            if( $coupon->get_meta('items_mandatory') === 'yes' ) {
                $coupon_applied = true;
                break;
            }
        }
    }

    // Loop through cart items
    foreach(WC()->cart->get_cart() as $cart_item ) {
        // Check cart item for defined product Ids and applied coupon
        if( in_array( $cart_item['product_id'], $targeted_ids ) && ! $coupon_applied ) {
            wc_clear_notices(); // Clear all other notices

            // Avoid checkout displaying an error notice
            wc_add_notice( sprintf( 'The product"%s" requires a coupon for checkout.', $cart_item['data']->get_name() ), 'error' );
            break; // stop the loop
        }
    }
}

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

enter image description here

And in checkout:

enter image description here

1
votes

Try this, changes are commented:

add_action( 'woocommerce_check_cart_items', 'mandatory_coupon_for_specific_items' );
function mandatory_coupon_for_specific_items() {
    // The targeted product ids (in this array)
    $targeted_ids   = array(37); 
    // Get applied $coupon_names
    $cart_applied_coupons = WC()->cart->get_applied_coupons()
    // Set the variable $coupon_applied to false
    $coupon_applied = false;
    // Create an array to save all coupon names
    $coupon_names = array();
    // Get the available coupons
    $args = array(
        'posts_per_page'   => -1,
        'orderby'          => 'title',
        'order'            => 'asc',
        'post_type'        => 'shop_coupon',
        'post_status'      => 'publish',
    );
    $all_coupons = get_posts( $args );
    if( !empty($all_coupons) ){
      // Loop through the available coupons
      foreach ( $all_coupons as $coupon ) {
          // Get the name for each coupon and add to the previously created array
          $coupon_name = $coupon->post_title;
          array_push( $coupon_names, $coupon_name );
      }
      // If one on the coupons is applied change the value of $coupon_applied to true
      foreach($coupon_names as $coupon_code){
        if( in_array( strtolower($coupon_code), $cart_applied_coupons) ){
          $coupon_applied = true;
          break;
        }
      }
    }


    // Loop through cart items
    foreach(WC()->cart->get_cart() as $cart_item ) {
        // Check cart item for defined product Ids and applied coupon
        if( in_array( $cart_item['product_id'], $targeted_ids ) && ! $coupon_applied ) {
            wc_clear_notices(); // Clear all other notices

            // Avoid checkout displaying an error notice
            wc_add_notice( sprintf( 'The product"%s" requires a coupon for checkout.', $cart_item['data']->get_name() ), 'error' );
            break; // stop the loop
        }
    }
}
0
votes

Thought I'd share my version for categories. Used a combination of the solution posted here and this one.

// Add a custom checkbox to Admin coupon settings pages
add_action( 'woocommerce_coupon_options', 'add_coupon_option_checkbox', 10 );
function add_coupon_option_checkbox() {
    woocommerce_wp_checkbox( array(
        'id'            => 'items_mandatory',
        'label'         => __( 'Force specific items', 'woocommerce' ),
        'description'   => __( 'Make this coupon mandatory for specific items.', 'woocommerce' ),
        'desc_tip'      => false,
    ) );
}


// Save the custom checkbox value from Admin coupon settings pages
add_action( 'woocommerce_coupon_options_save', 'save_coupon_option_checkbox', 10, 2 );
function save_coupon_option_checkbox( $post_id, $coupon ) {
    update_post_meta( $post_id, 'items_mandatory', isset( $_POST['items_mandatory'] ) ? 'yes' : 'no' );
}


// Force Coupon codes for Woocommerce
add_action( 'woocommerce_check_cart_items', 'mandatory_coupon_code' );
function mandatory_coupon_code() {
     // Set your product categories in the array (can be term IDs, slugs or names)
    $product_categories = array( '58');
    $applied_coupons = WC()->cart->get_applied_coupons();
    $found = false;
    
    if( sizeof($applied_coupons) > 0 ) {
        // Loop through applied coupons
        foreach( $applied_coupons as $coupon_code ) {
            $coupon = new WC_Coupon( $coupon_code );
            if( $coupon->get_meta('items_mandatory') === 'yes' ) {
                $coupon_applied = true;
                break;
            }
        }
    }
    // Loop through cart items to check for the product categories
    foreach ( WC()->cart->get_cart() as $cart_item ){
        if( has_term( $product_categories, 'product_cat', $cart_item['product_id'] ) ){
            $found = true; // cart item from the product category is found
            break; // We can stop the loop
        }
    }

    // If not found we exit
    if( ! $found ) return; // exit
    
    // Coupon not applied and product category found
    
    if( ! $coupon_applied) {
        // Display an error notice preventing checkout
        $message = __( 'The product "%s" requires a coupon for checkout.' );
        wc_add_notice( sprintf($message, $cart_item['data']->get_name() ), 'error' );
    }
}