2

I am trying to create a WooCommerce plugin for single product pages. I need to add up regular pricing with custom pricing. I was able to get the sum up of regular price with custom price, but when I click on "Add to Cart" I am not able to set up the new calculated price, in cart.

Any help is appreciated.

// WooCommerce activation
function custom_product_page()
{
    global $wpdb;
    global $product;
    wp_enqueue_style('my-plugin-styles', plugins_url('assets/css/diamond_style.css', __FILE__));

    if (class_exists('WooCommerce') && is_product()) {
        $product = wc_get_product(get_the_ID());

        $product_categories = wp_get_post_terms(get_the_ID(), 'product_cat');
        $is_ring = false;
        foreach ($product_categories as $product_category) {
            if ($product_category->slug === 'rings' || $product_category->slug === 'ring') {
                $is_ring = true;
                break;
            }
        }
        $table_name = $wpdb->prefix . 'diamond_purity';
        $ring_size_table = $wpdb->prefix . 'ring_size';

        // Show Metal Color only if the product category is "ring"
        if ($is_ring) {
            // Retrieve the latest gold rate
            $gold_rate_table = $wpdb->prefix . 'gold_rate';
            $gold_rate = $wpdb->get_var("SELECT final_price FROM $gold_rate_table ORDER BY id DESC LIMIT 1");

            // Get the net weight attribute
            $net_weight = $product->get_attribute('net-weight-g');

            // Get the regular price
            $regular_price = $product->get_regular_price();

            // Calculate the updated price
            $updated_price = ($gold_rate * $net_weight) + $regular_price;

            // Display the updated price
            echo '<p class="productprice">&#8377;' . $updated_price . '</p>';

            $gross_weight = $product->get_attribute('gross-weight');
            echo 'Weight: ' . $gross_weight . ' g';

          

            // Update cart item price with the custom price
            add_filter('woocommerce_add_cart_item', function ($cart_item) use ($updated_price) {
                $cart_item['data']->set_price($updated_price);
                return $cart_item;
            });
        }
    }
}
add_action('woocommerce_single_product_summary', 'custom_product_page', 25);

I tried using add_filter but didn't work me.

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399

1 Answers1

3

I have revisited your code, as there are some mistakes, errors and missing things. Here, what is missing is a hidden input field in product add to cart form, to post your custom price on add to cart action. Then you will be able to use that custom price.

As it seems that you are using your code in a plugin, you should start adding the following to the main plugin file, to check that WooCommerce is active:

defined( 'ABSPATH' ) or exit;

// Make sure WooCommerce is active
if ( ! in_array( 'woocommerce/woocommerce.php', apply_filters( 'active_plugins', get_option( 'active_plugins' ) ) ) ) {
    return;
}

Enqueuing a CSS styles file requires a separated function (you may need to make some CSS changes in your style rules):

add_action( 'wp_enqueue_scripts', 'custom_product_pricing_css' );
function custom_product_pricing_css() {
    // Only on product single pages
    if( ! is_product() ) return;

    wp_enqueue_style('my-plugin-styles', plugins_url('assets/css/diamond_style.css', __FILE__));
}

For your custom database queries, is better to set each in a separated function (reason: code modularity):

function get_the_gold_rate() {
    global $wpdb;

    return $wpdb->get_var( "SELECT final_price FROM {$wpdb->prefix}gold_rate ORDER BY id DESC LIMIT 1");
}

Here is your revisited code function, hooked in a different hook (where I include a mandatory hidden input field inside the product form):

add_action('woocommerce_before_add_to_cart_button', 'add_to_cart_product_pricing', );
function add_to_cart_product_pricing() {
    global $woocommerce, $product;

    if ( is_a($woocommerce, 'WooCommerce') && is_product() ) {

        // Targeting "ring" or "rings" product category
        if ( has_term( array('ring', 'rings'), 'product_cat' ) ) {
            // Load the latest gold rate
            $gold_rate = (float) get_the_gold_rate();

            // Get net weight product attribute
            $net_weight = $product->get_attribute('net-weight-g');

            // Get product regular price
            $regular_price = $product->get_regular_price();

            // Calculate product updated price
            $updated_price = ($gold_rate * $net_weight) + $regular_price;

            // Get the displayed price 
            $args = array( 'price' => floatval( $updated_price ) );

            if ( 'incl' === get_option('woocommerce_tax_display_shop') ) {
                $displayed_price = wc_get_price_including_tax( $product, $args );
            } else {
                $displayed_price = wc_get_price_excluding_tax( $product, $args );
            }

            // Display product updated price
            printf( '<p class="productprice">%s</p>', wc_price( $displayed_price ) );

            // Display a hidden input field with the "updated_price" as value
            printf( '<input type="hidden" name="updated_price" value="%s" />', $updated_price );
            
            // Get gross weight product attribute 
            $gross_weight = $product->get_attribute('gross-weight');

            // Display the Gross Weight
            printf( '<p class="grossweight">' . __('Weight: %s g') . '</p>', $gross_weight );
        }
    }
}

Now to include the updated price as custom cart item data, we use the following:

add_filter( 'woocommerce_add_cart_item_data', 'save_custom_cart_item_data', 10, 2 );
function save_custom_cart_item_data( $cart_item_data, $product_id ) {

    if( isset($_POST['updated_price']) && ! empty($_POST['updated_price'])  ) {
        // Set the custom data in the cart item
        $cart_item_data['updated_price'] = (float) wc_clean($_POST['updated_price']);

        // Make each item as a unique separated cart item
        $cart_item_data['unique_key'] = md5( microtime().rand() );
    }
    return $cart_item_data;
}

So we can now show in Minicart, items with this custom updated price:

add_action( 'woocommerce_cart_item_price', 'filter_cart_displayed_price', 10, 2 );
function filter_cart_displayed_price( $price, $cart_item ) {
    if ( isset($cart_item['updated_price']) ) {
        $args = array( 'price' => floatval( $cart_item['updated_price'] ) );

        if ( 'incl' === get_option('woocommerce_tax_display_cart') ) {
            $product_price = wc_get_price_including_tax( $cart_item['data'], $args );
        } else {
            $product_price = wc_get_price_excluding_tax( $cart_item['data'], $args );
        }
        return wc_price( $product_price );
    }
    return $price;
}

And finally, we set the cart item price with the custom updated price:

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

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

    // Loop through cart items and set the updated price
    foreach ( $cart->get_cart() as $cart_item ) {
        // Set the new price
        if( isset($cart_item['updated_price']) ){
            $cart_item['data']->set_price($cart_item['updated_price']);
        }
    }
}

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

Related: Custom cart item price set from product hidden input field in Woocommerce 3

LoicTheAztec
  • 229,944
  • 23
  • 356
  • 399
  • 1
    Thank you so much for your help. The answer put me through. It is an excellent opportunity to learn from you. – Nilima Bose Jun 23 '23 at 04:40
  • 1
    Just a question Why can't I add the function in my plugin itself rather than putting it in theme function.php? I am creating this plugin to use on multiple websites for pricing – Nilima Bose Jun 23 '23 at 05:03
  • I tried adding it to my plugin but certainly, it s not working. Am I doing something wrong? – Nilima Bose Jun 23 '23 at 05:30
  • I enabled the wp dubbing but in the error log, there is no error related to my plugin. I am attaching a video for reference of my frontend - https://www.loom.com/share/cc3c7ad0ce674aa2897042faaf4e45ba?sid=decc2fca-80cb-483f-930e-71e7f71fd265 – Nilima Bose Jun 23 '23 at 05:56
  • 1
    I have just retested my code *(bypassing 'rings'/'ring' product categories, simulating fakes "gold rate" and a "net weight" to get an updated calculated price)*… For me, it works perfectly: on add to cart, the cart item price is set and displayed with the updated price. – LoicTheAztec Jun 23 '23 at 07:03