Ad

WooCommerce Checkout Radio Buttons That Set A Percentage Fee Based On The Original Price Of A Specific Product

- 1 answer

I am trying to implement warranty option into woocommerce checkout. The below code works really well for setting a percentage fee based on specific items 'subtotal' amount.

// Custom function to get related cart items subtotal for specific defined product Ids
function get_related_items_subtotal( $cart ) {
    // HERE below define the related targeted products IDs in the array
    $targeted_ids = array(29, 27, 28, 72, 84, 95);
    $custom_subtotal = 0; // Initialize

    // Loop through cart items
    foreach ( $cart->get_cart() as $item ) {
        if ( array_intersect($targeted_ids, array($item['product_id'], $item['variation_id']) ) ) {
            $custom_subtotal += $item['line_subtotal'] + $item['line_subtotal_tax'];
        }
    }
    return $custom_subtotal;
}

// 1 - Display custom checkout radio buttons fields
add_action( 'woocommerce_review_order_before_payment', 'display_custom_checkout_radio_buttons' );
function display_custom_checkout_radio_buttons() {
    $custom_subtotal = get_related_items_subtotal( WC()->cart );

    if ( $custom_subtotal > 0 ) {
        $value = WC()->session->get( 'warranty' );
        $value = empty( $value ) ? WC()->checkout->get_value( 'warranty' ) : $value;
        $value = empty( $value ) ? '0' : $value;

        echo '<div id="checkout-radio">
            <h4>' . __("Choose your Warranty") .'</h4>';

        woocommerce_form_field( 'warranty', array(
            'type' => 'radio',
            'class' => array( 'form-row-wide', 'update_totals_on_change' ),
            'options' => array(
                '0'  => __( '1 Year Repair or Replace Warranty - Included', 'woocommerce' ),
                '10' => __( '2 Years Extended Warranty', 'woocommerce' ) . ' (' . strip_tags( wc_price( 10 * $custom_subtotal / 100 ) ) . ')',
                '15' => __( '3 Years Extended Warranty', 'woocommerce' ) . ' (' . strip_tags( wc_price( 15 * $custom_subtotal / 100 ) ) . ')',
            ),
        ), $value );

        echo '</div>';
    }


}

// 2 - Customizing Woocommerce checkout radio form field
add_filter( 'woocommerce_form_field_radio', 'custom_form_field_radio', 20, 4 );
function custom_form_field_radio( $field, $key, $args, $value ) {
    if ( ! empty( $args['options'] ) && 'warranty' === $key && is_checkout() ) {
        $field = str_replace( '</label><input ', '</label><br><input ', $field );
        $field = str_replace( '<label ', '<label style="display:inline;margin-left:8px;" ', $field );
    }
    return $field;
}

// 3 - Add a percentage Fee based on radio buttons for specific defined product Ids
add_action( 'woocommerce_cart_calculate_fees', 'percentage_fee_based_on_radio_buttons', 20 );
function percentage_fee_based_on_radio_buttons( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    $percentage = (float) WC()->session->get( 'warranty' );

    if ( $percentage ) {
        $custom_subtotal = get_related_items_subtotal( $cart );

        if ( $custom_subtotal > 0 ) {
            $label_text = sprintf( __('Extended Warranty %d years', 'woocommerce'), $percentage == 10 ? 2 : 3 );
            $cart->add_fee( $label_text, $custom_subtotal * $percentage / 100 );
        }
    }
}

// 4 - Set chosen radio button value to a WC Session variable
add_action( 'woocommerce_checkout_update_order_review', 'chosen_input_radio_button_value_to_wc_session' );
function chosen_input_radio_button_value_to_wc_session( $posted_data ) {
    parse_str( $posted_data, $fields );

    if ( isset( $fields['warranty'] ) ){
        WC()->session->set( 'warranty', $fields['warranty'] );
    }
}

Is there a way to output the calculated warranty amount options based on the original price of a specific product and NOT on the 'subtotal' amount? I'm thinking to target a price to be the basis of the calculation whose SKU contains some specific words. Is this possible? Please advise.

Ad

Answer

I added some code to get_related_items_subtotal() to check with SKU. Check the below code.

// Custom function to get related cart items subtotal for specific defined product Ids
function get_related_items_subtotal( $cart ) {
    // HERE below define the related targeted products IDs in the array
    $targeted_skus = array('BCA', 'ABC', 'MPN', 'A4545A', '5656FGDF', 'FDF4FD');
    $custom_subtotal = 0; // Initialize

    // Loop through cart items
    foreach ( $cart->get_cart() as $item ) {

        // Retrieve WC_Product object from the product-id:
        $product = wc_get_product( $item["variation_id"] ? $item["variation_id"] : $item["product_id"] );

        $sku = $product->get_sku();

        if( is_string_contain_word( $sku, $targeted_skus ) ){
            $custom_subtotal += $item['line_subtotal'] + $item['line_subtotal_tax'];
        }

    }
    return $custom_subtotal;
}

// 1 - Display custom checkout radio buttons fields
add_action( 'woocommerce_review_order_before_payment', 'display_custom_checkout_radio_buttons' );
function display_custom_checkout_radio_buttons() {
    $custom_subtotal = get_related_items_subtotal( WC()->cart );

    if ( $custom_subtotal > 0 ) {
        $value = WC()->session->get( 'warranty' );
        $value = empty( $value ) ? WC()->checkout->get_value( 'warranty' ) : $value;
        $value = empty( $value ) ? '0' : $value;

        echo '<div id="checkout-radio">
            <h4>' . __("Choose your Warranty") .'</h4>';

        woocommerce_form_field( 'warranty', array(
            'type' => 'radio',
            'class' => array( 'form-row-wide', 'update_totals_on_change' ),
            'options' => array(
                '0'  => __( '1 Year Repair or Replace Warranty - Included', 'woocommerce' ),
                '10' => __( '2 Years Extended Warranty', 'woocommerce' ) . ' (' . strip_tags( wc_price( 10 * $custom_subtotal / 100 ) ) . ')',
                '15' => __( '3 Years Extended Warranty', 'woocommerce' ) . ' (' . strip_tags( wc_price( 15 * $custom_subtotal / 100 ) ) . ')',
            ),
        ), $value );

        echo '</div>';
    }


}

// 2 - Customizing Woocommerce checkout radio form field
add_filter( 'woocommerce_form_field_radio', 'custom_form_field_radio', 20, 4 );
function custom_form_field_radio( $field, $key, $args, $value ) {
    if ( ! empty( $args['options'] ) && 'warranty' === $key && is_checkout() ) {
        $field = str_replace( '</label><input ', '</label><br><input ', $field );
        $field = str_replace( '<label ', '<label style="display:inline;margin-left:8px;" ', $field );
    }
    return $field;
}

// 3 - Add a percentage Fee based on radio buttons for specific defined product Ids
add_action( 'woocommerce_cart_calculate_fees', 'percentage_fee_based_on_radio_buttons', 20 );
function percentage_fee_based_on_radio_buttons( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    $percentage = (float) WC()->session->get( 'warranty' );

    if ( $percentage ) {
        $custom_subtotal = get_related_items_subtotal( $cart );

        if ( $custom_subtotal > 0 ) {
            $label_text = sprintf( __('Extended Warranty %d years', 'woocommerce'), $percentage == 10 ? 2 : 3 );
            $cart->add_fee( $label_text, $custom_subtotal * $percentage / 100 );
        }
    }
}

// 4 - Set chosen radio button value to a WC Session variable
add_action( 'woocommerce_checkout_update_order_review', 'chosen_input_radio_button_value_to_wc_session' );
function chosen_input_radio_button_value_to_wc_session( $posted_data ) {
    parse_str( $posted_data, $fields );

    if ( isset( $fields['warranty'] ) ){
        WC()->session->set( 'warranty', $fields['warranty'] );
    }
}

function is_string_contain_word( $find, $string, $exact = false ){
    if( is_array( $string ) ){
        foreach ( $string as $key => $str ) {
            if( !$exact ){
                $find = strtolower( $find );
                $str  = strtolower( $str );
            }   
            if ( preg_match( '/\b'.$find.'\b/', $str ) ) {
                return true;
            }
        }
        return false;
    }else{
        if( !$exact ){
            $find   = strtolower( $find );
            $string = strtolower( $string );
        }
        if ( preg_match( '/\b'.$find.'\b/', $string ) ) {
            return true;
        }
        return false;
    }
}
Ad
source: stackoverflow.com
Ad