I am trying to accomplish a thing on WooCommerce that I can not find any information about. It is like the following scenario:

I sell screws and have 1500 in stock. I would like the customer to choose between buying 10, 30, 50 and 100 screws in a drop-down list. The price for each screw is lower when you buy 100 compared to 10, 30 etc.

This works just the way I want by using product attributes and product variations. BUT the stock is not effected the way I want since the system think that it is one package of 100 screws and therefore reduce the stock by 1.

I am thinking of modifying the class-wc-product-variation.php file that contains the following code:

function reduce_stock( $by=1 ) {
    global $woocommerce;
    if ( $this->variation_has_stock ) {
        if ( $this->managing_stock() ) {
            $this->stock        = $this->stock - $by;
            $this->total_stock  = $this->total_stock - $by;
            update_post_meta( $this->variation_id, '_stock', $this->stock );
            $woocommerce->clear_product_transients( $this->id ); // Clear transient
            // Check parents out of stock attribute
            if ( ! $this->is_in_stock() ) {
                // Check parent
                $parent_product = new WC_Product( $this->id );
                // Only continue if the parent has backorders off
                if ( ! $parent_product->backorders_allowed() && $parent_product->get_total_stock() <= 0 ) {
                    update_post_meta( $this->id, '_stock_status', 'outofstock' );
            return $this->stock;
    } else {
        return parent::reduce_stock( $by );

I am trying to set $by to the name of the product variation (10, 30, 50, 100) but I am not that good at PHP. I have tried to collect some relevant code (at least what I think) and putted it together to the following function:

function new_reduce_by () {
    //Get the name of the variation
    $this->variation_data[$name] = $attrvalue[0];
    //Extract only the numbers (some attributes may end with "grams" etc.)
    preg_match_all('!\d+!', $attrvalue[0], $modified_attrvalue);
    //Convert the array to a variable
    $custom_reduce_value = implode(' ', $modified_attrvalue[0]);
    //Return the name (value) of the variation
    return $custom_reduce_value;

I have tried to call this function in different ways but without success, I guess the code above is not correct.

Should the code above work? If so, how do I call the function in the best way? I know that you cant call a function by changing $by=1, you have to pass a value or variable.

Or should I solve this some other way?

Many thanks!

3 Answers 3


You might want to reconsider your approach here, at first glance it seems to me that you could greatly simplify this but using a hook after the order is processed.

If all of your variations are really only quantities then it stands to reason that when an order is completed you'd update the quantities for the parent and each of the variations so that they all reflect the same inventory count.

So when processing the order you have parent ID and the variation IDs within the $product and you can simply update the quantity values for each within the loop.

I don't know the right hook off the top of my head but you can find the WooCommerce docs at http://wcdocs.woothemes.com/apidocs/index.html and http://wcdocs.woothemes.com/codex/extending/hooks/

  • You are right, I totally forgot that I could use hooks for this. The problem now however is how to actually get the variation and modify the stock balance. I can not manage to find the appropriate code and since my PHP knowledge is not that good I can not write my own code from scratch. The code I posted in my question does not work. I guess it is because I have to get the products first. I have tried: $order = new WC_Order( $order_id ); $items = $order_info->get_items(); But I don't know how to proceed.
    – Nicklas
    Nov 20, 2012 at 12:29
  • Take a look at wcdocs.woothemes.com/category/snippets you might find some code there.
    – Steve
    Nov 20, 2012 at 14:28

You can use this plugin: http://wordpress.org/support/plugin/woocommerce-incremental-product-quantities

in conjunction with this plugin: https://wordpress.org/plugins/woocommerce-bulk-discount/

Advanced Product Quantities Plugin will allow you to create minimum quantities as well as define a step value for incremental quantity increases. The only thing is, in your situation, you're going from 10, 30, 50, 100 - this doesn't follow a step value increase rule. So if you can modify your quantity sets to say sets of 10 or 25, then this plugin will do the trick.

The Bulk Discounts plugin will allow you to create % discount rules globally or per product.


Have a look at the Dynamic Pricing add-on for WooCommerce - it might be able to do what you need.

  • 2
    Please provide some details about how exactly referenced product addresses the question and link would be nice (there is usually a lot of similarly named stuff around). Also I am not sure if you are talking about your own product (judging by your details) and if so please disclose affiliation as well.
    – Rarst
    Nov 21, 2012 at 19:03

Not the answer you're looking for? Browse other questions tagged or ask your own question.