Search code examples
phpwordpresswoocommercecart

Custom conditional cart item prices in WooCommerce


I am having a problem here, that I have been trying to solve for weeks now. Tried everything I could find on the internet.

To cut it short it is a system of ordering helpers(for cleaning), I use woocommerce + woocommerce bookings + woocommerce vendors. Basically I need to add cleaning equipment to the cart manually and then I need cart items (helpers) price to be multiplied by service time (except cleaning equipment). But whenever there is cleaning equipment in the cart, the price of other items (helpers) is being multiplied 2x service time.

I don't understand what is wrong, when the cleaning equipment is not in the cart everything is fine. It doesn't matter how many other items(helpers) are in the cart it always multiplies service time by 2.

    // Add equipment to the cart

add_action( 'woocommerce_before_calculate_totals', 'add_equipment_to_cart', 10 );

function add_equipment_to_cart() {
    $product_id = 650; // id=650 - cleaning equipment id

    // check whether radio 'Do you have equipment?' is checked to 'Yes' or 'No'
    if($_POST['equipment'] == 'No') {
        foreach( WC()->cart->get_cart() as $cart_item_key => $values ) {
            $_product = $values['data'];

            // check whether equipment is already in the cart
            if( $values['data']->id == $product_id ) { 
                $equipment = $product_id;
            }
        }
        // add it to cart only if it is not there
        if(empty($equipment)){
            WC()->cart->add_to_cart( $product_id ); 
        }
    } elseif($_POST['equipment'] == 'Yes'){
        foreach( WC()->cart->get_cart() as $cart_item_key2 => $values2 ) {
            $_product2 = $values2['data'];
                if($values2['data']->id == $product_id ){
                   WC()->cart->remove_cart_item($cart_item_key2); 
                }
        }
    }
}


    // Change price of items in the cart

 add_action( 'woocommerce_before_calculate_totals', 'add_custom_item_price', 1 );

function add_custom_item_price( $cart_object ) {

if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    foreach ( WC()->cart->get_cart() as $cart_item_key => $cart_item ) {
        $item_id = $cart_item['data']->get_id();
        if($item_id != 650) { // 650 - cleaning equipment id

                // product original price
                $original_price = $cart_item['data']->get_price(); 

                // comes from an input 
                $servicetime = $_POST['servicetime'];

                $new_price = $original_price * $servicetime;

                // set the new item price in cart
                $cart_item['data']->set_price($new_price); 

        } 

    }

}

Any kind of help would be appreciated!


Solution

  • For price changes in cart, you need to make your price calculation before (Once data has been submitted on add to cart event) and set that custom price calculation in cart item as custom data, to avoid problems and errors:

    // Save custom field value in cart item
    add_filter( 'woocommerce_add_cart_item_data', 'save_custom_field_in_cart_object', 30, 3 );
    function save_custom_field_in_cart_object( $cart_item_data, $product_id, $variation_id ) {
        // Get the correct Id to be used (compatible with product variations)
        $the_id = $variation_id > 0 ? $variation_id : $product_id;
    
        if( isset( $_POST['servicetime'] ) ){
            $product = wc_get_product( $the_id ); // Get the WC_Product object
            $product_price = (float) $product->get_price(); // Get the product price
            $service_time = (float) sanitize_text_field( $_POST['servicetime'] ); // Get service time
            // Set the price calculation as custom data in cart item
            $cart_item_data['custom_price'] = $product_price * $service_time;
        }
        return $cart_item_data;
    }
    
    // Change price of items in the cart
    add_action( 'woocommerce_before_calculate_totals', 'add_custom_item_price', 1 );
    function add_custom_item_price( $cart ) {
        if ( is_admin() && ! defined( 'DOING_AJAX' ) )
            return;
    
        if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
            return;
    
        foreach ( $cart->get_cart() as $cart_item ) {
            // ID 650 is the cleaning equipment id
            if( $cart_item['data']->get_id() != 650 && isset( $cart_item['custom_price'] ) ) { 
                // Get the calculated custom price
                $new_price = (float) $cart_item['custom_price'];
                // set the new item price in cart
                $cart_item['data']->set_price( $new_price );
            }
        }
    }
    

    Code goes in function.php file of your active child theme (or theme). It should work now…