skip to Main Content

Basically if I have the following issue:

We are selling highly customizable products which vary greatly in weight.
We are setting the weight programmatically upon addition to the cart. That works great so far.

But as soon as the visitor navigates to the checkout and changes his postal code, which triggers a refresh of the shipping calculations, the weight resets again, which results in a wrong shipping price, as we use weight based shipping.

How can we ensure, that the cart_item_data is not refreshed after it gets set once?

We have used this answer, here is my code so far:

// This weight is taken from a custom plugin. The values retrieved are correct.
function changeWeight( $cart_item_data, $product_id, $variation_id ) {
    $arrEzfc       = $cart_item_data['ezfc_edit_values'];
    $productWeight = 0;

    foreach ( $arrEzfc as $key => $value ) {
        //ID of 'Gesamtgewicht' values in calculating forms
        if ( $key === 255 || $key === 280 || $key === 301 || $key === 330 || $key === 366 ) {
            $productWeight            = floatval( str_replace( ',', '.', str_replace( '.', '', $value ) ) );
            $cart_item_data['weight']['new'] = $productWeight;
        }
    }
    return $cart_item_data;
}

add_action( 'woocommerce_before_calculate_totals', 'conditionally_change_tax_class', 10000 );
function conditionally_change_tax_class( $cart ){
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    // Required since Woocommerce version 3.2 for cart items properties changes
    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // Looo through our specific cart item keys
    foreach ( $cart->get_cart() as $cart_item ) {
        // Set the new product weight
        $cart_item['data']->set_weight($cart_item['weight']['new']);
    }
}

2

Answers


  1. Chosen as BEST ANSWER

    The following code solved our problem:

    // Refreshing session shipping methods data (Mandatory)
    add_action( 'woocommerce_checkout_update_order_review', 'refresh_shipping_methods', 10, 1 );
    function refresh_shipping_methods( $post_data){
    
        $cart = WC()->cart;
        // Loop through cart item
        foreach ( $cart->get_cart() as $cart_item ) {
            if (isset($cart_item['new_weight'])) {
                // Set the new product weight
                $cart_item['data']->set_weight($cart_item['new_weight']);
            }
        }
    }
    

    Basically everytime the checkout page updates, the cart-item weight gets set again. That way, the correct weight is set at all times.


  2. Try the following simplified and optimized code version (untested):

    add_filter('woocommerce_add_cart_item_data', 'add_custom_weight_as_cart_item_data', 10, 2);
    function add_custom_weight_as_cart_item_data( $cart_item_data, $product_id ) {
        if ( isset($cart_item_data['ezfc_edit_values']) ) {
            foreach ( $cart_item_data['ezfc_edit_values'] as $key => $value ) {
                //ID of 'Gesamtgewicht' values in calculating forms
                if ( in_array($key, [255, 280, 301, 330, 366]) ) {
                    $cart_item_data['new_weight'] = floatval( str_replace( ',', '.', str_replace( '.', '', $value ) ) );
                }
            }
        }
        return $cart_item_data;
    }
    
    add_action( 'woocommerce_before_calculate_totals', 'conditionally_change_tax_class', 100 );
    function conditionally_change_tax_class( $cart ){
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        // Loop through cart item
        foreach ( $cart->get_cart() as $cart_item ) {
            if (isset($cart_item['new_weight'])) {
                // Set the new product weight
                $cart_item['data']->set_weight($cart_item['new_weight']);
            }
        }
    }
    

    It could work.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search