Simone Conti
Simone Conti

Reputation: 379

WooCommerce - Modified cart weight does not affect shipping costs

Good evening. I wrote some code to alter the total weight of some specific articles in my cart (due to a specific request of the courier). Before you ask... no, I cannot modify the single article weight, because I have to calculate a special weight for packaging. Yes, it's a long story,

My code looks like that (simplified version):

function set_my_weight($weight) {
  global $woocommerce;
  $cart_items = $woocommerce->cart->get_cart(); 
  $addedWeight = 0;

  echo "prev: ". $weight;
  foreach($cart_items as $prod => $values):
     if(conditions):
       $addedWeight += 1.5;
     endif;
  endforeach;

  $weight += $addedWeight;
  echo "final: ". $weight;

  return $weight;
}
add_filter('woocommerce_cart_contents_weight', 'set_my_weight',10,1);

When I echo the value calling echo WC()->cart->cart_contents_weight; all seems working fine, but for some reason the shipping costs do not change. I'm using "WooCommerce Weight Based Shipping" plugin to manage my shipping costs.

Why the new weight is ignored by the plugin?

Thanks

Upvotes: 4

Views: 893

Answers (4)

Evock
Evock

Reputation: 1

If you are using the "WooCommerce Weight Based Shipping" plugin, you will need to add two hooks.

woocommerce_before_calculate_totals and woocommerce_cart_loaded_from_session

add_action('woocommerce_before_calculate_totals', 'logic_in_cart');
add_action('woocommerce_cart_loaded_from_session', 'logic_in_cart');

function logic_in_cart($cart){
    $cart_items = $cart->get_cart();

    foreach($cart_items as $cart_item_key => $cart_item){
        $cart_item['data']->set_weight(0);     
    }
}

This is the only way you won't have any problems.

Upvotes: 0

Catherine Colin
Catherine Colin

Reputation: 1

The filter woocommerce_cart_contents_weight is not usable since get_cart_contents_weigh is not used to set the shipping fee. A solution is to modify the weight of each product of the cart.

Upvotes: 0

Zaim
Zaim

Reputation: 476

If you are using this WooCommerce Weight Based Shipping plugin,

@LoicTheAztec answer's could work if you change the cart data early before WC()->cart->calculate_shipping() which is using the hook woocommerce_checkout_update_order_review.

add_action( 'woocommerce_checkout_update_order_review', 'conditionally_change_tax_class', 10000 );

Source: woocommerce/includes/class-wc-ajax.php

Upvotes: 1

LoicTheAztec
LoicTheAztec

Reputation: 254373

As WooCommerce Weight Based Shipping is a third party plugin, there is different ways to calculate cost changes based on cart weight.

Here below are 2 ways to alter the cart weight.

1) Alter cart contents total weight:

add_filter( 'woocommerce_cart_contents_weight', 'filter_wc_cart_contents_weight', 10000 );
function filter_wc_cart_contents_weight( $weight ) {
    $condition    = true; // Only for testing
    $extra_weight = 1.5;

    // Loop through cart items
    foreach(WC()->cart->get_cart() as $cart_item ) {
        $quantity = $cart_item['quantity']; // If needed

        if( $condition ) {
            $weight += $extra_weight;
        }
    }
    return $weight;
}

// For testing: display the total weight after order total in cart page (Ajax updated)
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
}

Code goes in functions.php file of your active child theme (or active theme). Tested and works.


2) Alter cart items weight:

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;

    $condition    = true; // Only for testing
    $extra_weight = 1.5;

    // Looo through our specific cart item keys
    foreach ( $cart->get_cart() as $cart_item ) {
        // get product weight
        $weight = (float) $cart_item['data']->get_weight();

        // Set the new product weight
        $cart_item['data']->set_weight( $weight + ( $extra_weight / $cart_item['quantity'] ) );
    }
}

// For testing display the total weight after order total
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
}

Code goes in functions.php file of your active child theme (or active theme). Tested and works.


Now if WooCommerce Weight Based Shipping plugin get the weight from each product, you will be not able to alter cart weight, so shipping costs.

Upvotes: 3

Related Questions