I would like to disable a product as soon as it's stock drops to 0 in Drupal commerce.

I think this might be possible by using rules, but then I don't know what will happen to the product display. I figure that when there are no more active products attached to a product display, the display will still appear in my views but without any product information attached to it. In this case I would also like the product display to be "unpublished".

I can't unpublish the product display immediately after a given product is out of stock because there could be more products added to a single display...

Can some one help me to achieve this through rules or is there some other method that I could use?

I'm using Drupal Commerce and the stock module for it.

  • The last time I asked about this it was not possible and the maintainer of Commerce Stock said that was too fringe a use case to consider. No one else commented on that issue so I'm sure his viewpoint has not changed. – o_O Aug 21 '12 at 1:43

Seems really odd that the maintainer would say that this was impossible and a fringe case.

Seems to me like this is a very normal use case, in fact one that we use on every single Ubercart site we have in production. I actually thought this was a setting in the module config page and was surprised to see that it wasn't.

Anyway, here's what I did. I disabled the included rule because I despise rules and added this code to my module:

/**
 * Implements hook_commerce_checkout_complete().
 */
function MYMODULE_commerce_checkout_complete($order) {
  $order_wrapper = entity_metadata_wrapper('commerce_order', $order);
  $line_items = $order_wrapper->commerce_line_items->value();
  if (is_array($line_items)) {
    foreach ($line_items as $line_item) {
      if (in_array($line_item->type, commerce_product_line_item_types())) {
        $product = commerce_product_load_by_sku($line_item->line_item_label);

        // Subtract the sold amount from the available stock level.
        $qty = (int) $line_item->quantity;
        module_load_include('inc', 'commerce_stock', 'commerce_stock.rules');
        commerce_stock_adjust($product, -$qty);

        // Disable the product if we have no stock left
        $product_wrapper = entity_metadata_wrapper('commerce_product', $product);
        if ($product_wrapper->commerce_stock->value() <= 0) {
          $product_wrapper->status->set(0);
          $result = $product_wrapper->save();

          if ($result) {
            watchdog('commerce_stock', 'Product %sku stock level reached 0, status set to 0.', array('%sku' => $product->sku));
          }
          else {
            watchdog('commerce_stock', 'Failed attempt to disable product %sku', array('%sku' => $product->sku), WATCHDOG_ERROR);
          }
        }
      }   
    }
  }
}

It's just a copy of the default rule that ships with the module with the extra code for disabling the product added in.

I guess you could leave the default rule active and remove the 3 lines that adjust the stock level in my example, but then I'm not sure what would be called first, the rule or my hook so you would have to test that yourself.

  • thanks for the answer, I'll try this as soon as I am able. Upvote for now :) – Mike Sep 24 '12 at 16:18

Here's a pretty basic rule that disables the Product SKU when stock hits 0:

{ "rules_out_of_stock" : {
"LABEL" : "Out of Stock",
"PLUGIN" : "reaction rule",
"REQUIRES" : [ "rules", "entity" ],
"ON" : [ "commerce_product_presave" ],
"IF" : [
  { "entity_is_of_type" : { "entity" : [ "commerce-product" ], "type" : "commerce_product" } },
  { "data_is" : { "data" : [ "commerce-product:commerce-stock" ], "value" : "0" } }
],
"DO" : [
  { "data_set" : { "data" : [ "commerce-product:status" ], "value" : 0 } }
]}}

Your Answer

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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