简体   繁体   中英

Shipping calculated on cart items weight and cart amount

In a client WooCommerce web site, free shipping method is enabled for orders amount up to 250. I use the code below (from this answer ) , to hide other shipping rates when the order amount is over 250, except when there is heavy items in cart.

add_filter( 'woocommerce_package_rates', 'conditionally_hide_other_shipping_based_on_items_weight', 100, 1 );
function conditionally_hide_other_shipping_based_on_items_weight( $rates ) {
    // targeted weight
    $target_product_weight = 12;
    $target_cart_amount = 250;

    WC()->cart->subtotal_ex_tax >= $target_cart_amount ? $passed = true : $passed = false ;

    // Iterating trough cart items to get the weight for each item
    foreach(WC()->cart->get_cart() as $cart_item){
        if( $cart_item['variation_id'] > 0)
            $item_id = $cart_item['variation_id'];
        else
            $item_id = $cart_item['product_id'];

        // Getting the product weight
        $product_weight = get_post_meta( $item_id , '_weight', true);

        if( !empty($product_weight) && $product_weight >= $target_cart_amount ){
            $light_products_only = false;
            break;
        }
        else $light_products_only = true;
    }

    // If 'free_shipping' method is available and if products are not heavy
    // and cart amout up to the target limit, we hide other methods
    $free = array();
    foreach ( $rates as $rate_id => $rate ) {
        if ( 'free_shipping' === $rate->method_id && $passed && $light_products_only ) {
            $free[ $rate_id ] = $rate;
            break;
        }
    }

    return ! empty( $free ) ? $free : $rates;
}

But now, I would like to set a variable shipping amount that will be calculated in 2 ways:

  • When order amount is below 250, the calculation will be 1 euro by kilo on the total order items weight.
  • When order amount is up to 250, the calculation will be made on heavy items weight only (1 euro by kilo). If there is not heavy items, the free shipping rate is available.

How can I achieve this, as it's a bit complicated?
Any track to follow?

I have tried some existing related plugins, but they aren't convenient for this case.

Thanks.

Code improved (on March 2019) :

Yes this is possible without a plugin with a custom SHIPPING FEE , calculated on cart items weight and cart amount… But you will need to have a 'Flat rate' shipping method set with a minimal amount . This normally should work with the code you are using.

Here is that code (commented) :

//Adding a custom Shipping Fee to cart based conditionaly on weight and cart amount
add_action('woocommerce_cart_calculate_fees', 'custom_conditional_shipping_fee', 10, 1);
function custom_conditional_shipping_fee( $cart ){

    ## --- YOUR SETTINGS --- ##
    $targeted_weight      = 20;  // Your targeted "heavy" product weight
    $targeted_cart_amount = 250; // Your targeted cart amount
    $price_per_kg         = 1;   // Price by Kg;
    $flat_rate_price      = 10;  // Set the cost like in 'flat rate' shipping method

    // Initializing variables
    $fee = $calculated_weight = 0;

    // For cart SUBTOTAL amount EXCLUDING TAXES
    $passed = $cart->subtotal_ex_tax >= $targeted_cart_amount ? true : false ;

    // For cart SUBTOTAL amount INCLUDING TAXES (replace by this):
    // $passed = $cart->subtotal >= $targeted_cart_amount ? true : false ;

    // Iterating through each cart items
    foreach( $cart->get_cart() as $cart_item ){
        // The Product weight
        $product_weight = $cart_item['data']->get_weight();

        // cart item weight
        $cart_item_weight = $cart_item['quantity'] * $cart_item['data']->get_weight();

        // When cart amount is up to 250, Adding weight of heavy items
        if($passed && $product_weight > $targeted_weight)
            $calculated_weight += $cart_item_weight;
    }

    #### Making the fee calculation ####

    // Cart is up to 250 with heavy items
    if ( $passed && $calculated_weight != 0 ) {
        // Fee is based on cumulated weight of heavy items
        $fee = ( $calculated_weight * $price_per_kg ) - $flat_rate_price;
    }
    // Cart is below 250
    elseif ( ! $passed ) {
        // Fee is based on cart total weight
        $fee = ( $cart->get_cart_contents_weight( ) * $price_per_kg ) - $flat_rate_price;
    }

    #### APPLYING THE CALCULATED FEE ####

    // When cart is below 250 or when there is heavy items
    if ($fee > 0){
        // Rounding the fee
        $fee = round( $fee );
        // This shipping fee is taxable (You can have it not taxable changing last argument to false)
        $cart->add_fee( __('Shipping weight fee', 'woocommerce'), $fee, true);
    }
}

Code goes in function.php file of your active child theme (or theme) or also in any plugin file.

This code is tested and it works

The minimal 'Flat rate' amount is subtracted from the fee calculation, this way the customer pay the right price .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM