neppers
neppers

Reputation: 97

Show cash on delivery (COD) based on applied coupons in WooCommerce

I am trying to have cash on delivery (COD) enabled only for customers that use certain type off coupons.

I have an existing code that, when coupons of a certain type are entered, converts the product sales price to the regular product price.

Now I would like to add that cash on delivery (COD) only is available for valid coupons within the same function.

The part that I have tried to add is this:

if ($coupons = WC()->cart->get_applied_coupons()  == False )
    unset( $available_gateways['cod'] );

Resulting in:

add_action( 'woocommerce_before_calculate_totals', 'add_custom_price', 10, 1);
function add_custom_price( $cart_object) {

    global $woocommerce;

    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    $coupon = False;

    if ($coupons = WC()->cart->get_applied_coupons()  == False )
        unset( $available_gateways['cod'] );

    if ($coupons = WC()->cart->get_applied_coupons()  == False ) 
      $coupon = False;
    else {
        foreach ( WC()->cart->get_applied_coupons() as $code ) {
          $coupons1 = new WC_Coupon( $code );
          if ($coupons1->type == 'percent_product' || $coupons1->type == 'percent')
            $coupon = True;
        }
    }

    if ($coupon == True)
        foreach ( $cart_object->get_cart() as $cart_item ) 
        {
            $price = $cart_item['data']->regular_price;
            $cart_item['data']->set_price( $price );
        }
}

This does not give real error messages, but certainly not the desired result either. Any advice?

Upvotes: 1

Views: 570

Answers (1)

7uc1f3r
7uc1f3r

Reputation: 29614

First of all I have rewritten your existing code, the part that converts sale prices to regular prices when a certain type of coupon is applied. This because your current code contains outdated methods:

function action_woocommerce_before_calculate_totals( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) ) return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 ) return;
    
    // Initialize
    $flag = false;
    
    // Applied coupons only
    if (  sizeof( $cart->get_applied_coupons() ) >= 1 ) {
        // Loop trough
        foreach ( $cart->get_applied_coupons() as $coupon_code ) {
            // Get an instance of the WC_Coupon Object
            $coupon = new WC_Coupon( $coupon_code );
            
            // Only for certain types, several can be added, separated by a comma
            if ( in_array( $coupon->get_discount_type(), array( 'percent', 'fixed_product', 'percent_product' ) ) ) {
                $flag = true;
                break;
            }
        }
    }
    
    // True
    if ( $flag ) {
        // Loop through cart items
        foreach ( $cart->get_cart() as $cart_item ) {
            // Get regular price
            $regular_price = $cart_item['data']->get_regular_price();
            
            // Set new price
            $cart_item['data']->set_price( $regular_price );
        }
    }
}
add_action( 'woocommerce_before_calculate_totals', 'action_woocommerce_before_calculate_totals', 10, 1 );

Then to only make COD active, if coupons of a certain type are applied you can use the woocommerce_available_payment_gateways hook

By default COD will not be available:

// Payment gateways
function filter_woocommerce_available_payment_gateways( $payment_gateways ) {
    // Not on admin
    if ( is_admin() ) return $payment_gateways;
    
    // Initialize
    $flag = false;
    
    // WC Cart
    if ( WC()->cart ) {     
        // Get cart
        $cart = WC()->cart;
    
        // Applied coupons only
        if (  sizeof( $cart->get_applied_coupons() ) >= 1 ) {
            // Loop trough
            foreach ( $cart->get_applied_coupons() as $coupon_code ) {
                // Get an instance of the WC_Coupon Object
                $coupon = new WC_Coupon( $coupon_code );
                
                // Only for certain types, several can be added, separated by a comma
                if ( in_array( $coupon->get_discount_type(), array( 'percent', 'fixed_product', 'percent_product' ) ) ) {
                    $flag = true;
                    break;
                }
            }
        }
    }
    
    // NOT true, so false
    if ( ! $flag ) {
        // Cod
        if ( isset( $payment_gateways['cod'] ) ) {
            unset( $payment_gateways['cod'] );
        }  
    }
    
    return $payment_gateways;
}
add_filter( 'woocommerce_available_payment_gateways', 'filter_woocommerce_available_payment_gateways', 10, 1 );

Both codes go goes in functions.php file of the active child theme (or active theme).

Tested in WordPress 5.8.1 and WooCommerce 5.8.0

Upvotes: 3

Related Questions