Link to home
Start Free TrialLog in
Avatar of Andrew Economedes
Andrew EconomedesFlag for Australia

asked on

Need to change total WooCommerce shopping cart weight.

I have some custom code in my WooCommerce child themes function.php file that calculates the shipping weight based on the products in the cart and the pallet weight used to transport the products via truck.  I need to update or override the actual cart weight with the value of $kilo_rate returned from my function.

add_filter( 'woocommerce_cart_item_name', 'showing_sku_in_cart_items', 99, 3 );
    $item_count  = 0;
	$volume = 0;
	$max_length = 0; 
	$max_width = 0; 
	$max_length_cart = 0; 
	$max_width_cart = 0; 
	$sample_count = 0; 
	$sample_count = 0; 
	$sample_count = "Short"; 

function showing_sku_in_cart_items( $item_name, $cart_item, $cart_item_key  ) {
    global $volume;
    global $max_length;
    global $max_width;
    global $max_length_cart;
    global $max_width_cart;	
	global $item_count ;
	global $pallet_size;
	global $cubic_rate;
	global $kilo_rate;
	global $max_kilo_rate;
	global $cart_less_samples;

	
    // The WC_Product object
    $product = $cart_item['data'];
	
	//Get item Weight
	$weight_item = $product->get_weight();
	
    // Get the  SKU
    $sku = $product->get_sku();
    //IGNORE samples from this list
	$sku_pref = substr($sku,0,2);
	
	
	// When sku doesn't exist
    if(empty($sku)) return $item_name;

    // Add the sku
    $item_name .= '<br><small class="product-sku">' . __( "SKU: ", "woocommerce") . $sku . '</small></br>';

	//if ($sku_pref != 'SM') $sku_num = substr($sku,-3);
	if ($sku_pref != 'SM'){ 
	$sku_num = substr($sku,-3);
	}else{
	 $sample_count = $sample_count + 1;	
	}
	
	//get max pallet vol by product SKU
	if ($sku_num == '001'){ $max_length = 2.6; $max_width = 0.7; $pallet_size = "Long";}
	if ($sku_num == '002'){ $max_length = 2.6; $max_width = 0.8; $pallet_size = "Long";}
	if ($sku_num == '003'){ $max_length = 2.6; $max_width = 1.0; $pallet_size = "Long";}
	if ($sku_num == '004'){ $max_length = 3.2; $max_width = 0.7; $pallet_size = "Long";}
	if ($sku_num == '005'){ $max_length = 3.2; $max_width = 0.9; $pallet_size = "Long";}
	if ($sku_num == '006'){ $max_length = 3.2; $max_width = 1.0; $pallet_size = "Long";}
	if ($sku_num == '007'){ $max_length = 2.6; $max_width = 0.7; $pallet_size = "Long";}
	if ($sku_num == '008'){ $max_length = 3.2; $max_width = 0.7; $pallet_size = "Long";}
	if ($sku_num == '009'){ $max_length = 3.2; $max_width = 1.0; $pallet_size = "Long";}
	
	if ($sku_num == '010'){ $max_length = 1.2; $max_width = 0.7; }
	if ($sku_num == '011'){ $max_length = 1.2; $max_width = 0.9; }
	if ($sku_num == '012'){ $max_length = 1.2; $max_width = 1.0; }

	if ($sku_num == '013'){ $max_length = 2.6; $max_width = 1.0; $pallet_size = "Long";}
	
	if ($pallet_size != "Long") $max_width = 1.2;	
	
	//SET Max Volume to largest pallet based on largest piece selected
	if ($max_length_cart < $max_length) $max_length_cart =  $max_length;
	if ($max_width_cart < $max_width) $max_width_cart =  $max_width;
	
	$pallet_area = ($max_length_cart * $max_width_cart);
	

	global $woocommerce;
	$cart_items = $woocommerce->cart->cart_contents_count;

	$cart_less_samples = $cart_items - $sample_count;
	
	$cubic_rate = ($pallet_area *(($cart_less_samples * 0.06)+ 0.14));	
	
	$kilo_rate = 250 * $cubic_rate;
	
    return $item_name.$weight_item."<strong> Cubic Rate: ".$cubic_rate." - Kilo Rate: ".$kilo_rate."</br>Pallet Size W: ".$max_width_cart."m L: ".$max_length_cart."m</strong>";
   
}

Open in new window

Avatar of Chris Stanyon
Chris Stanyon
Flag of United Kingdom of Great Britain and Northern Ireland image

Hi Andrew,

I'm having a look through your question to see if I can understand what you need. If I've got this right, you want to set the total cart weight to the value you've previously stored in the global $kilo_rate variable.

Reading through your code, and it looks like you may have some problems doing this. The code you've posted above fires for each item in your cart (if you have 5 items, then the code will fire 5 times). The $kilo_rate is calculated in that function based on various product attributes, so that value will be re-calculated each time the function runs. Whatever value is calculated for the last product in your cart, is what the rate will be set to.

Maybe I'm missing something, but that seems a little odd, and probably won't give you an accurate $kilo_rate.

You also mention about the $kilo_rate that's returned from your function, but your function doesn't return the $kilo_rate - it only returns a string, so I'm unsure what you mean.

Once you've clarified those points and you know exactly what weight you want to set, you would set it with the woocommerce_cart_contents_weight filter:

function cs_update_cart_weight( $weight ) { 
    // set your weight to whatever you like
    $weight = 1234; 

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

Open in new window

Avatar of Andrew Economedes

ASKER

Thanks for your feedback, very much appreciated.

Yes, I am looping through all products in cart to determine which Pallet size that will fit the largest item ( kitchen bench tops) .
Then shipping weight is calculated by volume not the actual product weight.
We add the pallet volume and then increase its height for every product’s that stacks onto the pallet.

So the $kilo_rate on the last loop is what I want to pass to another function which updates the cart weight.
Hey Andrew,

Sorry for the delay in coming back to you. Busy, busy, busy !!

I've had a chance to have a quick look at Woo, and as I Mentioned in my previous comment, to alter the weight of the cart, you would need to hook into the woocommerce_cart_contents_weight filter.

The problem you're going to have though is that the filter is called BEFORE your woocommerce_cart_item_name filter. What this means is that given the code you've provided, the weight for the cart has already been grabbed before you filter the item names, so you won't be able to do the calculation in there.

I think you'll have to do the calculation directly in the woocommerce_cart_contents_weight  filter. Might need tweaking, but something along these lines:

add_filter( 'woocommerce_cart_contents_weight', 'cs_update_cart_weight', 1, 1 );
function cs_update_cart_weight( $weight ) { 

    $palletSizes = [
        '001' => [ 'length' => 2.6, 'width' => 0.7 ],
        '002' => [ 'length' => 2.6, 'width' => 0.8 ],
        '003' => [ 'length' => 2.6, 'width' => 1.0 ],
        '004' => [ 'length' => 3.2, 'width' => 0.7 ],
        '005' => [ 'length' => 3.2, 'width' => 0.9 ],
        '006' => [ 'length' => 3.2, 'width' => 1.7 ],
        '007' => [ 'length' => 2.6, 'width' => 0.7 ],
        '008' => [ 'length' => 3.2, 'width' => 0.7 ],
        '009' => [ 'length' => 3.2, 'width' => 1.0 ],
        '010' => [ 'length' => 1.2, 'width' => 0.7 ],
        '011' => [ 'length' => 1.2, 'width' => 0.9 ],
        '012' => [ 'length' => 1.2, 'width' => 1.0 ],
        '013' => [ 'length' => 2.6, 'width' => 1.0 ],
    ];

    $sampleCount = 0;
    $usedPallets = [];

    foreach ( WC()->cart->get_cart() as $cartItem ) {
        if (empty($cartItem['data']->get_sku())) continue;

        $skuPrefix = substr($cartItem['data']->get_sku(), 0, 2);
        $palletCode = substr($cartItem['data']->get_sku(), -3);

        if ($skuPrefix == 'SM') $sampleCount++;

        if (isset($palletSizes[$palletCode])) {
            $usedPallets[] = $palletSizes[$palletCode];
        }
    }

    $maxLength = max(array_column($usedPallets, 'length'));
    $maxWidth = max(array_column($usedPallets, 'width'));
    $palletArea = $maxLength * $maxWidth;

    $cartItems = WC()->cart->get_cart_contents_count() - $sampleCount;

    $cubicRate = $palletArea * (($cartItems * 0.06) + 0.14);
    $weight = 250 * $cubicRate;

    return $weight;
};

Open in new window

This question needs an answer!
Become an EE member today
7 DAY FREE TRIAL
Members can start a 7-Day Free trial then enjoy unlimited access to the platform.
View membership options
or
Learn why we charge membership fees
We get it - no one likes a content blocker. Take one extra minute and find out why we block content.