简体   繁体   中英

Cart total Weight and Shipping Recalculation on WooCommerce

I'm trying to use a snippet to add my custom boxes weight to the total order weight and it is currently working fine. However, the shipping methods are not recalculated based on the recalculated weight of the snippet. Any ideas how to force the shipping recalculation?

 add_filter( 'woocommerce_cart_contents_weight', 'filter_wc_cart_contents_weight', 10000 );
function filter_wc_cart_contents_weight( $weight ) {
    //box testing sizes (kg)
    $Envelope = 2;
    $Small_parcel = 10;
    $Medium_parcel = 50;

    // Loop through cart items
    foreach(WC()->cart->get_cart() as $cart_item ) {
        $total_height += $cart_item['data']->get_height() * $cart_item['quantity'];
        }
    if( $total_height <= 8)  {
            $weight += $Envelope;
    }
    if( $total_height >= 8 && $total_height <=61)  {
            $weight += $Small_parcel;
    }
    return $weight;
}


//show calculated weight at checkout

add_action( 'woocommerce_cart_totals_after_order_total', 'display_wc_cart_total_weight_after_order_total' );
function display_wc_cart_total_weight_after_order_total() {
    ?>
    <tr class="order-total">
        <th><?php esc_html_e( 'Total weight', 'woocommerce' ); ?></th>
        <td data-title="<?php esc_attr_e( 'Total weight', 'woocommerce' ); ?>"><?php echo wc_format_weight( WC()->cart->get_cart_contents_weight() ); ?></td>
    </tr>
    <?php
}

The following method allows adding the weight of the package at the checkout by dividing the weight of the package that will be used, by the cart items. In this way, the total cart weight includes the box weight also and the shipping options can reflect the correct prices for the total actual order weight.

    add_action( 'woocommerce_before_calculate_totals', 'add_custom_weight', 10, 1 );
    
    function add_custom_weight( $cart ) {
        
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return;
        
        //box sizes (kg)
        $Small_envelope = 0.095;
        $Medium_envelope = 0.11;
        $Large_envelope = 0.2;
        $Small_box = 0.4;
        $Medium_box = 0.6;
        
// 

Loop through cart items and get total height and max-width of item in the order, for additional checks to apply the appropriate box (if needed)

        foreach(WC()->cart->get_cart() as $cart_item ) {
                $total_height += $cart_item['data']->get_height() * $cart_item['quantity'];
                $temp_width = $cart_item['data']->get_width();
                if ($temp_width > $max_width){
                    $max_width = $temp_width;                   }
            $cart_items_qty += $cart_item['quantity'];
        }
        
    //Check which box should be used based on total order height
        if( $total_height <= 2.7 && $max_width < 19)  {
                $extra_weight = $Small_envelope; 
            } 
        if( $total_height > 2.7 && $total_height <=8 && $max_width < 19)  {
                $extra_weight = $Medium_envelope;
            }
        if( $total_height > 8 && $total_height <=16 && $max_width < 19)  {
                $extra_weight = $Large_envelope;
            }
        if( $total_height > 16 && $total_height <=22)  {
                $extra_weight = $Small_box;
            }
        if( $total_height > 22 && $total_height <=38)  {
                $extra_weight = $Medium_box;
            }
        
        
    //

Divide the $extra_weight (box weight), by the number of cart items. Then loop through cart items again to add the divided weight to each item.

$xtr_weight_per_item = $extra_weight / $cart_items_qty;
            foreach ( $cart->get_cart() as $cart_item ) {
                $cart_item['data']->set_weight( $cart_item['data']->get_weight()+$xtr_weight_per_item);
            }
        }
    //

show calculated weight at checkout for testing

    add_action( 'woocommerce_cart_totals_after_order_total', 'display_wc_cart_total_weight_after_order_total' );
    function display_wc_cart_total_weight_after_order_total() {
        ?>
        <tr class="order-total">
            <th><?php esc_html_e( 'Total weight', 'woocommerce' ); ?></th>
            <td data-title="<?php esc_attr_e( 'Total weight', 'woocommerce' ); ?>"><?php echo wc_format_weight( WC()->cart->get_cart_contents_weight() ); ?></td>
        </tr>
        <?php
    }

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