1
votes

I have created some input custom fields in woocommerce single product pages where user can input height and width values respectively… When product is added to cart that custom fields values are displays in cart and checkout page too.

Example: if user input height='15' and width='20' then its display is cart page like height=15 width=20

single product page

single product page

cart page

cart page

Now what Iém trying to achieve is to make a custom price calculation based on that "height" and "width" custom fields values:

total price = (height/3 * width/30 + 3)*1.48

The final calculated price should update cart item price. But I'm unable to achieve this section or I dont know how to achieve it.

Here is my code:

/*
 * Display input on single product page
 * @return html
 */
function kia_satish_option(){
    $value = isset( $_POST['_satish_option'] ) ? sanitize_wp_checkbox( $_POST['_satish_option'] ) : '';
    printf( '<label>%s</label><input name="_satish_option" value="%s" type="number"/>', __( 'Height', 'kia-plugin-textdomain' ), esc_attr( $value ) );
}
add_action( 'woocommerce_before_add_to_cart_button', 'kia_satish_option', 9 );

function kia_satisher_option(){
    $value = isset( $_POST['_satisher_option'] ) ? sanitize_wp_checkbox( $_POST['_satisher_option'] ) : '';
    printf( '<label>%s</label><input name="_satisher_option" value="%s" type="number"/>', __( 'width', 'kia-plugin-textdomain' ), esc_attr( $value ) );
}
add_action( 'woocommerce_before_add_to_cart_button', 'kia_satisher_option', 9 );


function kia_yard_option(){
    $value = isset( $_POST['_yard_option'] ) ? sanitize_wp_checkbox( $_POST['_yard_option'] ) : '';
    printf( '<label>%s</label><input name="_yard_option" value="%s" type="number"/>', __( 'yard', 'kia-plugin-textdomain' ), esc_attr( $value ) );
}
add_action( 'woocommerce_before_add_to_cart_button', 'kia_yard_option', 9 );



/*
 * Add custom data to the cart item
 * @param array $cart_item
 * @param int $product_id
 * @return array
 */
function kia_add_cart_item_data( $cart_item, $product_id ){

    if( isset( $_POST['_satish_option'] ) ) {
        $cart_item['satish_option'] = sanitize_text_field( $_POST['_satish_option'] );
    }

    if( isset( $_POST['_satisher_option'] ) ) {
        $cart_item['satisher_option'] = sanitize_text_field( $_POST['_satisher_option'] );
    }

    if( isset( $_POST['_yard_option'] ) ) {
        $cart_item['yard_option'] = sanitize_text_field( $_POST['_yard_option'] );
    }

    return $cart_item;

}
add_filter( 'woocommerce_add_cart_item_data', 'kia_add_cart_item_data', 10, 2 );


/*
 * Load cart data from session
 * @param array $cart_item
 * @param array $other_data
 * @return array
 */
function kia_get_cart_item_from_session( $cart_item, $values ) {

    if ( isset( $values['satish_option'] ) ){
        $cart_item['satish_option'] = $values['satish_option'];
    }

    if ( isset( $values['satisher_option'] ) ){
        $cart_item['satisher_option'] = $values['satisher_option'];
    }

    if ( isset( $values['yard_option'] ) ){
        $cart_item['yard_option'] = $values['yard_option'];
    }

    return $cart_item;

}
add_filter( 'woocommerce_get_cart_item_from_session', 'kia_get_cart_item_from_session', 20, 2 );





/*
 * Add meta to order item
 * @param int $item_id
 * @param array $values
 * @return void
 */
function kia_add_order_item_meta( $item_id, $values ) {

    if ( ! empty( $values['satish_option'] ) ) {
        woocommerce_add_order_item_meta( $item_id, 'satish_option', $values['satish_option'] );           
    }

    if ( ! empty( $values['satisher_option'] ) ) {
        woocommerce_add_order_item_meta( $item_id, 'satisher_option', $values['satisher_option'] );           
    }
}
add_action( 'woocommerce_add_order_item_meta', 'kia_add_order_item_meta', 10, 2 );




/*
 * Get item data to display in cart
 * @param array $other_data
 * @param array $cart_item
 * @return array
 */
function kia_get_item_data( $other_data, $cart_item ) {

    if ( isset( $cart_item['satish_option'] ) ){

        $other_data[] = array(
            'name' => __( 'height', 'kia-plugin-textdomain' ),
            'value' => sanitize_text_field( $cart_item['satish_option'] )
        );

    }

    if ( isset( $cart_item['satisher_option'] ) ){

        $other_data[] = array(
            'name' => __( 'width', 'kia-plugin-textdomain' ),
            'value' => sanitize_text_field( $cart_item['satisher_option'] )
        );

    }

    if ( isset( $cart_item['yard_option'] ) ){

        $other_data[] = array(
            'name' => __( 'Yard', 'kia-plugin-textdomain' ),
            'value' => sanitize_text_field( $cart_item['yard_option'] )
        );

    }

    return $other_data;

}
add_filter( 'woocommerce_get_item_data', 'kia_get_item_data', 10, 2 );

I tried to achieve formula section by code below:

    function woo_add_custom_general_fields_save($post_id)
{
    $woocommerce_product_height = $_POST['_product_height'];
    $woocommerce_product_width = $_POST['_product_width'];
    $woocommerce_final_price = $_POST['_final_price'];


// calculate and save _product_area_price, _regular_price, price as Height*Width
    if (!empty($woocommerce_product_height) && !empty($woocommerce_product_width)))
        $woocommerce_final_price = $woocommerce_product_height * $woocommerce_product_width ;

But it doesn't work…

How can I change the cart item price with a custom calculation based on custom cart data?

2

2 Answers

2
votes

I have revisited completely your code, removed some little things, renamed others and added missing parts…

Yours calculation looks very strange:

$total_price = ($height/3 * $width/30 + 3)*1.48;

As everything works, you will be able to make easily changes in your calculation if needed…

The code:

// Display custom input fields in single product page
add_action( 'woocommerce_before_add_to_cart_button', 'add_product_custom_fields', 20 );
function add_product_custom_fields(){
    $domain =  'woocommerce';
    $value = isset( $_POST['height_option'] ) ? sanitize_key( $_POST['height_option'] ) : '';
    printf( '<label>%s</label><input name="height_option" value="%s" type="number"/><br>', __( 'Height', $domain ), esc_attr( $value ) );

    $value = isset( $_POST['width_option'] ) ? sanitize_key( $_POST['width_option'] ) : '';
    printf( '<label>%s</label><input name="width_option" value="%s" type="number"/><br>', __( 'Width', $domain ), esc_attr( $value ) );
}

// Add custom fields data to cart items and make calculation price
add_filter( 'woocommerce_add_cart_item_data', 'custom_add_cart_item_data', 20, 2 );
function custom_add_cart_item_data( $cart_item, $product_id ){

    if( isset( $_POST['height_option'] ) )
        $cart_item['custom_data']['height'] = sanitize_key( $_POST['height_option'] );

    if( isset( $_POST['width_option'] ) )
        $cart_item['custom_data']['width'] = sanitize_key( $_POST['width_option'] );

    // Make calculation and save calculated  price
    if( isset( $_POST['height_option'] ) && isset( $_POST['width_option'] ) ){
        $height      = (int) sanitize_key( $_POST['height_option'] );
        $width       = (int) sanitize_key( $_POST['width_option'] );

        if( $width > 0 && $height > 0 ){
            $total_price = ( ( $height / 3 ) * ( $width / 30 ) + 3 ) * 1.48; // <== The calculation
            $cart_item['custom_data']['price'] = round($total_price, 2); // Save the price in the custom data
        }
    }

    return $cart_item;
}

// Display custom data in cart and checkout pages
add_filter( 'woocommerce_get_item_data', 'display_custom_cart_item_data', 10, 2 );
function display_custom_cart_item_data( $cart_data, $cart_item ) {
    $domain = 'woocommerce';

    if ( isset( $cart_item['custom_data']['height'] ) ){
        $cart_data[] = array(
            'name' => __( 'Height', $domain ),
            'value' => $cart_item['custom_data']['height']
        );
    }
    if ( isset( $cart_item['custom_data']['width'] ) ){
        $cart_data[] = array(
            'name' => __( 'Width', $domain ),
            'value' => $cart_item['custom_data']['width']
        );
    }
    return $cart_data;
}

// Set the new calculated price replacing cart item price
add_action( 'woocommerce_before_calculate_totals', 'set_cart_item_calculated_price', 20, 1 );
function set_cart_item_calculated_price( $cart ) {
    if ( is_admin() && ! defined( 'DOING_AJAX' ) )
        return;

    if ( did_action( 'woocommerce_before_calculate_totals' ) >= 2 )
        return;

    // Loop through cart items
    foreach ( $cart->get_cart() as $cart_item ){
        if( ! isset( $cart_item['custom_data']['price'] ) ){
            continue;
        }
        if( $cart_item['custom_data']['price'] > 0 ){
            // Set the calculated item price (if there is one)
            $cart_item['data']->set_price( (float) $cart_item['custom_data']['price'] );
        }
    }
}


// Get cart item custom data and update order item meta and display in orders and emails
add_action( 'woocommerce_checkout_create_order_line_item', 'save_order_item_custom_meta_data', 10, 2 );
function custom_add_order_item_meta( $item_id, $values ) {
    $domain = 'woocommerce';

    if( isset( $cart_item['custom_data']['height'] ) )
        $item->update_meta_data( __( 'Height', $domain ), $values['custom_data']['height'] );

    if( isset( $cart_item['custom_data']['width'] ) )
        $item->update_meta_data( __( 'Width', $domain ), $values['custom_data']['width'] );
}

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

0
votes

Sorry to knock your door again but its throw error when i add above line

Parse error: syntax error, unexpected 'return' (T_RETURN)

    // Display custom input fields in single product page
add_action( 'woocommerce_before_add_to_cart_button', 'add_product_custom_fields', 20 );
function add_product_custom_fields(){
    global $product;

    if( ! has_term( "fitness", 'product_cat', $product->get_id() ) return;

    $domain =  'woocommerce';
    $value = isset( $_POST['height_option'] ) ? sanitize_key( $_POST['height_option'] ) : '';
    printf( '<label>%s</label><input name="height_option" value="%s" type="number"/><br>', __( 'Height', $domain ), esc_attr( $value ) );

    $value = isset( $_POST['width_option'] ) ? sanitize_key( $_POST['width_option'] ) : '';
    printf( '<label>%s</label><input name="width_option" value="%s" type="number"/><br>', __( 'Width', $domain ), esc_attr( $value ) );

}