Eric
Eric

Reputation: 5215

Create a Woocommerce product sold in units of gram

I would like to create a product in WooCommerce that is sold in units of gram.

The customer would enter the number of grams they want (in an input field) on the product page, and the price would be computed on the fly and added to the cart.

My question is: is this possible, and if so, can someone give me just a "big picture" idea of how I would implement it?

I don't need line-by-line code, just hoping someone with more knowledge of the structure of Woo can guide me on how to best attack the problem.

I already have parts of it worked out:

But... I think every discrete product in Woo needs to have its own price.. So for example, if a customer wants 123g of a product, it seems like I might have to create a variation on the fly for that specific price/amount, and then add that to the cart. Which (judging by this) looks non-trivial and a little hacky. Is there a better way to do this?

Upvotes: 3

Views: 14801

Answers (4)

LoicTheAztec
LoicTheAztec

Reputation: 254271

It's easier and quicker to give you that real example, than explain step by step… You will see which hooks are used for all steps or tasks.

You dont need variable products or generate a variation on the fly.

You just need to set on each simple product the price for one gram (or any other base). Now in this code, you can target those products with:

  • an array of product Ids
  • or by product categories (or even product tags).

Your concern is about the way to pass the data in the cart, to update the final price for each product and display the chosen grams amount in cart, checkout and in the order.

So in each product you will only set the price by gram… (or you can also make changes in the code and set the product price for 100 grs or even any other base).

The code:

// Add a product custom field "grams_quantity" that will update the displayed price
add_action('woocommerce_before_add_to_cart_button', 'special_product_by_grams', 25);
function special_product_by_grams(){
    global $product;

    // HERE Define the special product IDs sold by grams
    $targeted_product_ids = array(37);

    // or HERE Define a product categories (ids, slugs or names)
    $categories = array('sold-by-gram');

    // Only for products sold by gram
    $product_id = $product->get_id();
    if ( ! ( in_array( $product_id, $targeted_product_ids ) || has_term( $categories, 'product_cat', $product_id ) ) ) return;
    ?>
        <div class="grams-field">
            <label for="grams_quantity"><?php _e('Grams: ','woocoomerce'); ?><span></span><br>
                <input type="number" step="1" name="grams_quantity" class="grams_quantity" id="grams_quantity" value="1">
            </label>
        </div><br>

        <script type="text/javascript">
            (function($){
                // variables initialization
                var priceByGram = <?php echo wc_get_price_to_display( $product ); ?>,
                    currencySymbol = $(".woocommerce-Price-currencySymbol").html(),
                    updatedPrice;

                // On live event: imput number fields
                $('input#grams_quantity').on( "click blur", function(){
                    updatedPrice = ($(this).val() * priceByGram).toFixed(2);
                    $(".woocommerce-Price-amount.amount").html('<span class="woocommerce-Price-amount amount">'+updatedPrice+'&nbsp;'+currencySymbol+'</span>');
                    console.log("event"); // <== To be removed
                });
            })(jQuery);
        </script>
    <?php
}

// Save the "grams_quantity" custom product field data in Cart item
add_filter( 'woocommerce_add_cart_item_data', 'save_in_cart_the_custom_product_field', 10, 2 );
function save_in_cart_the_custom_product_field( $cart_item_data, $product_id ) {
    if( isset( $_POST['grams_quantity'] ) ) {
        $cart_item_data[ 'grams_quantity' ] = $_POST['grams_quantity'];

        // When add to cart action make an unique line item
        $cart_item_data['unique_key'] = md5( microtime().rand() );
        WC()->session->set( 'custom_data', $_POST['grams_quantity'] );
    }
    return $cart_item_data;
}

// Update product price by grams in cart and checkout
add_filter( 'woocommerce_before_calculate_totals', 'update_prices_by_gram', 10, 1 );
function update_prices_by_gram( $cart_object ) {

    // HERE Define the special product IDs sold by grams
    $targeted_product_ids = array(37);

    // or HERE Define a product categories (ids, slugs or names)
    $categories = array('sold-by-gram');

    foreach ( $cart_object->get_cart() as $cart_item ) {

        // Only for products sold by gram
        $product_id = $cart_item['product_id'];
        if ( in_array( $product_id, $targeted_product_ids ) || has_term( $categories, 'product_cat', $product_id ) ){

            // Get an instance of the WC_Product object and the
            $product = $cart_item['data'];

            $grams = $cart_item['grams_quantity'];

            // Method is_on_sale() manage everything (dates…)
            $product->set_price( $product->get_price() * $grams);
        }
    }
}

// Render "grams_quantity" the custom product field in cart and checkout
add_filter( 'woocommerce_get_item_data', 'render_product_custom_field_meta_on_cart_and_checkout', 10, 2 );
function render_product_custom_field_meta_on_cart_and_checkout( $cart_data, $cart_item ) {
    $custom_items = array();

    if( !empty( $cart_data ) )
        $custom_items = $cart_data;

    if( isset( $cart_item['grams_quantity'] ) )
        $custom_items[] = array(
            'name'      => __( 'Grams', 'woocommerce' ),
            'value'     => sanitize_text_field( $cart_item['grams_quantity'] ),
            'display'   => sanitize_text_field( $cart_item['grams_quantity'] ),
        );

    return $custom_items;
}

// Save "grams_quantity" to the order items meta data
add_action('woocommerce_add_order_item_meta','add_product_custom_fiel_to_order_item_meta', 1, 3 );
function add_product_custom_fiel_to_order_item_meta( $item_id, $item_values, $item_key ) {

    if( isset( $item_values['grams_quantity'] ) )
        wc_update_order_item_meta( $item_id, 'Grams', sanitize_text_field( $item_values['grams_quantity'] ) );
}

Code goes in function.php file of your active child theme (or active theme) or in any plugin file.

Tested and works.

Upvotes: 0

Michael Yaeger
Michael Yaeger

Reputation: 824

There is a free plugin for WooCommerce that allows you to input a unit of measure (UOM) for each product:

https://wordpress.org/plugins/woocommerce-unit-of-measure/

Upvotes: 1

Eric
Eric

Reputation: 5215

I found this plugin that does pretty much exactly what I need-- https://woocommerce.com/products/measurement-price-calculator/

Upvotes: 0

Vikas Yadav
Vikas Yadav

Reputation: 3354

WooCommerce has an option to show the weights as grams.

enter image description here

The following code will display the KG weights as grams on the WooCommerce templates :



    // Convert the product weight
       function ag_woocommerce_product_get_weight( $weight ) {

       // Only convert if we have a weight
    if ($weight) {

    // The weight is in KGS, and we want grams, to multiple by 1000
    $weight = $weight * 1000;
    }

    return $weight;
    };
    // add the filter
    add_filter( 'woocommerce_product_get_weight', 'ag_woocommerce_product_get_weight', 10, 1 );

Hope this might help. Cheers!

Upvotes: 1

Related Questions