Combine discounted shipping cost with discounted cart items prices in WooCommerce

久未见 提交于 2021-01-29 00:39:00

问题


I need some help to combine custom shipping cost with discounted cart item prices in WooCommerce.

In the below code, the first function is responsible for adding a 50% discount depending on the selected delivery option and the 2nd one is responsible for calculating a 50% discount for each item in the basket, except for specific category (and its subcategories).

I would like to make sure when a customer chooses "Pickup" delivery to display "-50%" of discount that is added only for goods not included in specific category and its subcategories (for main category ID 37).

First function:

add_filter('woocommerce_package_rates', 'local_pickup_percentage_discount', 12, 2);
function local_pickup_percentage_discount( $rates, $package ){
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return $rates;
    // HERE define the discount percentage
    $percentage = 50; // 50%
    $subtotal = WC()->cart->get_subtotal();
    // Loop through the shipping taxes array
    foreach ( $rates as $rate_key => $rate ){
        $has_taxes = false;
        // Targeting "Local pickup"
        if( 'local_pickup' === $rate->method_id ){
            // Add the Percentage to the label name (optional
            $rates[$rate_key]->label .= ' ( - ' . $percentage . '% )';
            // Get the initial cost
            $initial_cost = $new_cost = $rates[$rate_key]->cost;
            // Calculate new cost
            $new_cost = -$subtotal * $percentage / 100;
            // Set the new cost
            $rates[$rate_key]->cost = $new_cost;

            // Taxes rate cost (if enabled)
            $taxes = [];
            // Loop through the shipping taxes array (as they can be many)
            foreach ($rates[$rate_key]->taxes as $key => $tax){
                if( $rates[$rate_key]->taxes[$key] > 0 ){
                    // Get the initial tax cost
                    $initial_tax_cost = $new_tax_cost = $rates[$rate_key]->taxes[$key];
                    // Get the tax rate conversion
                    $tax_rate    = $initial_tax_cost / $initial_cost;
                    // Set the new tax cost
                    $taxes[$key] = $new_cost * $tax_rate;
                    $has_taxes   = true; // Enabling tax
                }
            }
            if( $has_taxes )
                $rates[$rate_key]->taxes = $taxes;
        }
    }
    return $rates;
}

And the second one:

add_action( 'woocommerce_before_calculate_totals', 'custom_cart_item_price', 10, 1 );
function custom_cart_item_price( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;
    
    $parent_id = 37; // premium-rolls id
    $taxonomy  = 'product_cat';
    
    foreach ( $cart->get_cart() as $cart_item ){
        $product_id = $cart_item['product_id'];
        $terms_ids  = get_term_children( $parent_id, $taxonomy, $product_id ); // get children terms ids array
        array_unshift( $terms_ids, $parent_id );  // insert parent term id to children terms ids array
        
        if ( ! has_term( $terms_ids, $taxonomy, $product_id ) ){
            $new_price = $cart_item['data']->get_price() / 2; // Get 50% of the initial product price
            $cart_item['data']->set_price( $new_price ); // Set the new price
        }
    }
}

回答1:


Here is the way to make it work for cart items and specific shipping method excluding a product category and its subcategories (code is commented):

// Custom conditional function that check cart items for specific category and its children terms ids
function has_targeted_terms( $cart_item ){
    $parent_id  = 37; // <= Targeted main product category
    $taxonomy   = 'product_cat';
    $terms_ids  = get_term_children( $parent_id, $taxonomy, $cart_item['product_id'] ); // get children terms ids array
    array_unshift( $terms_ids, $parent_id );  // insert parent term id to children terms ids array

    return has_term( $terms_ids, $taxonomy, $cart_item['product_id'] );
}

// For shipping rate costs (discount)
add_filter('woocommerce_package_rates', 'local_pickup_percentage_discount', 12, 2);
function local_pickup_percentage_discount( $rates, $package ){
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return $rates;

    $percentage      = 50; // <= The percentage discount
    $shipping_method = 'local_pickup'; // <= Targeted shipping method id
    $subtotal        = WC()->cart->get_subtotal();
    $others_found  = false; // Initializing

    // Loop through cart items for the current package
    foreach( $package['contents'] as $cart_item ) {
        if ( ! has_targeted_terms( $cart_item ) ) {
            $others_found  = true;
            break; // stop the loop
        }
    }

    // Loop through the shipping methods
    foreach ( $rates as $rate_key => $rate ){
        $has_taxes = false; // Initializing

        // Targeting "Local pickup"
        if( $shipping_method === $rate->method_id && $others_found ){
            // Add the Percentage to the label name (optional
            $rates[$rate_key]->label .= ' ( - ' . $percentage . '% )';
            // Get the initial cost
            $initial_cost = $new_cost = $rates[$rate_key]->cost;
            // Calculate new cost
            $new_cost = -$subtotal * $percentage / 100;
            // Set the new cost
            $rates[$rate_key]->cost = $new_cost;

            // Taxes rate cost (if enabled)
            $taxes = [];
            // Loop through the shipping taxes array (as they can be many)
            foreach ($rates[$rate_key]->taxes as $key => $tax){
                if( $rates[$rate_key]->taxes[$key] > 0 ){
                    // Get the initial tax cost
                    $initial_tax_cost = $new_tax_cost = $rates[$rate_key]->taxes[$key];
                    // Get the tax rate conversion
                    $tax_rate    = $initial_tax_cost / $initial_cost;
                    // Set the new tax cost
                    $taxes[$key] = $new_cost * $tax_rate;
                    $has_taxes   = true; // Enabling tax
                }
            }
            if( $has_taxes )
                $rates[$rate_key]->taxes = $taxes;
        }
    }
    return $rates;
}

// For cart items price discount
add_action( 'woocommerce_before_calculate_totals', 'custom_cart_item_price', 10, 1 );
function custom_cart_item_price( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    $shipping_method = 'local_pickup'; // <= Targeted shipping method id
    $is_local_pickup = false;

    // Loop through chosen shipping methods
    foreach ( WC()->session->get('chosen_shipping_methods') as $chosen_shipping_method ){
        if( strpos( $chosen_shipping_method, $shipping_method ) !== false ) {
            $is_local_pickup = true;
            break;
        }
    }

    // If "Local pickup" is not the chosen shipping method, we exit
    if( ! $is_local_pickup ) {
        return;
    }


    foreach ( $cart->get_cart() as $cart_item ){
        if ( ! has_targeted_terms( $cart_item ) ) {
            $new_price = $cart_item['data']->get_price() / 2; // Get 50% of the initial product price
            $cart_item['data']->set_price( $new_price ); // Set the new price
        }
    }
}

// Cart page: Refreshing cart items on shipping method change
add_action( 'wp_footer', 'custom_cart_jquery_script' );
function custom_cart_jquery_script() {
    // Only on cart page
    if( is_cart() ):
    ?>
    <script type="text/javascript">
    (function($){
        var a = 'input[name^="shipping_method"]';

        $(document.body).on('change', a, function() {
            setTimeout(function(){
               $(document.body).trigger('added_to_cart');
            }, 300);
            console.log('change');
        });
    })(jQuery);
    </script>
    <?php
    endif;
}

Code goes in functions.php file of the active child theme (or active theme). It should works.

Note: Some jQuery code is required to refresh cart items on shipping method change (on cart page).



来源:https://stackoverflow.com/questions/64849601/combine-discounted-shipping-cost-with-discounted-cart-items-prices-in-woocommerc

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!