Automatically remove one-off products that have been sold?

Posts: 19
Joined: 10/24/2008

G'day all,
I'm a new user of Ubercart and I'm installing it on Drupal 6 for a website that will sell Birdhouses. The birdhouses are all one-off art pieces so when one gets sold it will have to be removed from ubercart.

Firstly I need a way to display just the images of all of the birdhouses on a single page (there will be about 16 or so) but the images need to sync with the Ubercart so that when a birdhouse is sold it is removed from the gallery. Any ideas on this? I installed the catalog module but it lists the text too and is too long, I just need a single image per birdhouse on one page.

I have played around with the inventory setting and stock reports but when I view the catalog I still see a product in it that has a stock value of 1 and a quantity of 0. Anyone know why this feature is not working or perhaps I don't understand its functionality.

Thanks for all the work done Ubercart devs and an affiliate fee will be coming your way via a new Pay Pal account signup.

Cheers
Richard
www.MyLittlePortal.com
www.Jacana.net

Posts: 10
Joined: 10/23/2008

I encountered also this. After sale catalog shows items which have stock quantity zero. I havent foudn any option to disable it.

Posts: 19
Joined: 10/24/2008

Ok, seems like no one is reading this post or knows how to solve the problem. On the good news front I did figure out how to create a gallery of products using our old friend the View module. After some tweaks of the style sheets it looks great. The latest version of views is a beast but just play around with it and you'll be up and riding in no time.

For now the client will have to un-publish the product node once it's sold, makes sense really cos all are one-off art pieces but it would be nice to have this done automagically.

Posts: 5625
Joined: 08/07/2007
AdministratorHead Code Monkey - I eat bugs.

Just a quick bit of brainstorming... if you know PHP, you can create a custom Workflow-ng action that includes PHP to look at the products on an order and unpublish their nodes if need be. Something like...

<?php
  $nids
= array();

  foreach (
$order->products as $product) {
   
$nids[] = $product->nid;
  }

 
node_operations_unpublish($nids);
?>

Obviously, you might need to tweak that to make sure only those unique products are being unpublished. Good luck!

Posts: 19
Joined: 10/24/2008

Ryan, I have been known to dabble in a little PHP so I'll give this a try, thanks!

Posts: 1
Joined: 11/08/2008

That looks wonderful for global policy.

Could there be a mechanism to make physical products unavailable with inventory of 0 while automata need not be replenished? Having to reconfigure the workflow for each added product seems a bit tedious.

Posts: 116
Joined: 04/23/2008

If you don't want to unpublish the node, you can also use the uc_stockstub module. It shows "out of stock" greyed out button instead of "add to cart" when inventory is 0. If you use this, you will need inventory_api, and hence mange your stock.

See these links:

http://www.ubercart.org/contrib/4792

http://www.ubercart.org/docs/user/5181/out_stock_solutions

This is useful until inventory is replenished.

Posts: 4
Joined: 11/07/2008

Ryan wrote:
Just a quick bit of brainstorming... if you know PHP, you can create a custom Workflow-ng action that includes PHP to look at the products on an order and unpublish their nodes if need be. Something like...

<?php
  $nids
= array();

  foreach (
$order->products as $product) {
   
$nids[] = $product->nid;
  }

 
node_operations_unpublish($nids);
?>

Obviously, you might need to tweak that to make sure only those unique products are being unpublished. Good luck!

Hi Ryan,

I'm trying to use your code, but it appears that it unpublishes all the products that a user ordered, not just the ones that have stock level = 0 after they complete their order.

Is there a way to go through all the $order->products and check stock levels?

Thanks!

Posts: 5625
Joined: 08/07/2007
AdministratorHead Code Monkey - I eat bugs.

Right, that's what the line below the code example was pointing to... you'll need to wrap it in whatever if statement you need to accomplish that behavior. I don't have time to dig it up right now, but I believe there's a function you can pass $product->model to to find its stock level.

Posts: 4
Joined: 11/07/2008

UPDATE: I found the solution. This code will check the stock of each product when completing an order, then unpublish any products that have a stock or zero or negative. I left the echo's in to help debug, but as it is nothing gets sent to the screen. Any bugs please let me know!

<?php
$nids
= array();

foreach (
$order->products as $product) {
 
//echo '<br />Checking the stock level of model:' . $product->model;
  //echo '<br />The stock level is ' . uc_stock_level($product->model) . ' which we check against zero';
 
if ((uc_stock_level($product->model) - 1) <= 0) {
   
   
//echo '<br />The stock level is zero or negative, unpublish nid:' . $product->nid;
    // if the stock WILL be 0 or negative after this order, then add to the list to unpublish
   
$nids[] = $product->nid;
  }
}
/*
echo '<pre><b>The nids that will be unpublished are:</b><hr>';
print_r($nids);
echo '</pre>';
*/
node_operations_unpublish($nids);
?>

Posts: 5625
Joined: 08/07/2007
AdministratorHead Code Monkey - I eat bugs.

If I were you, instead of - 1 you might use - $product->qty in case the customer buys 2, for example.

Posts: 4
Joined: 11/07/2008

Good catch, here's the updated code:

<?php
$nids
= array();

foreach (
$order->products as $product) {
 
//echo '<br />Checking the stock level of model:' . $product->model;
  //echo '<br />The stock level is ' . uc_stock_level($product->model) . ' which we check against zero';
 
if ((uc_stock_level($product->model) - $product->qty) <= 0) {
   
   
//echo '<br />The stock level is zero or negative, unpublish nid:' . $product->nid;
    // if the stock WILL be 0 or negative after this order, then add to the list to unpublish
   
$nids[] = $product->nid;
  }
}
/*
echo '<pre><b>The nids that will be unpublished are:</b><hr>';
print_r($nids);
echo '</pre>';
*/
node_operations_unpublish($nids);
?>

Posts: 19
Joined: 10/24/2008

Can you hand hold me here a little, where does this code go, create a Workflow-ng action? If so can you show me how to do this, I've played around with some actions but not sure where / how this one will work.

Posts: 19
Joined: 10/24/2008

Just realized that I'm out here in Drupal 6.5 land, so no workflow-ng for me and the conditional actions CAs don't work properly either. Seems like Cha0s may have a solution with a revised module http://www.ubercart.org/contrib/7359 . Will keep you posted.

Posts: 1
Joined: 12/29/2008

This has been the one thing that has really kept me from moving from ZenCart to Ubercart, the lack of ability to hide products with 0 inventory. This code snippet has worked perfectly for me.

This is how this is implimented:

1. Go to WORKFLOW-NG.
2. Select ADD A NEW RULE CONFIGURATION.
3. Select CUSTOMER COMPLETES CHECKOUT for the EVENT.
4. Give it a nice label (anything).
5. Select SUBMIT.
6. Select ADD AN ACTION under ACTIONS.
7. Select EXECUTE CUSTOM PHP CODE then select ADD.
8. Paste the code snippet (but without the <?PHP ?> tags, as these can not be in the PHP dialog)!

$nids = array();

foreach ($order->products as $product) {
  // echo '<br />Checking the stock level of model:' . $product->model;
  // echo '<br />The stock level is ' . uc_stock_level($product->model) . ' which we check against zero';
  if ((uc_stock_level($product->model) - $product->qty) <= 0) {
   
  // echo '<br />The stock level is zero or negative, unpublish nid:' . $product->nid;
    // if the stock WILL be 0 or negative after this order, then add to the list to unpublish
    $nids[] = $product->nid;
    node_operations_unpublish($nids);
   
    // echo '<pre><b>The nids that will be unpublished are:</b><hr>';
// print_r($nids);
// echo '</pre>';

  }
}

// echo '<pre><b>Nothing to un-publish!</b><hr>';
// echo '</pre>';

9. Select SUBMIT.

I tested this and it seems to work very well. When I purchased a product with a stock value of 1 the stock was correctly decremented to 0 and the product was unpublished! Now my customers will not see products with 0 qty, which is what I think makes the most sense for a lot of ecommerce sites.

I hope this can be included in a future version of Ubercart?

Now, just need to find a way to create a worklow-ng for setting products back to published if the stock changes from 0 to 1!

Posts: 405
Joined: 10/16/2007

Is this code for Uber 1.6 or Uber 2? Or will it work for both?

Posts: 974
Joined: 11/05/2007
Bug FinderFAQ ModeratorGetting busy with the Ubercode.

Be aware that the fix described above will only work reliably when exactly one person is browsing your site at a time. If multiple people are making purchase at the same time, this fix can (and at some point will) fail in its goal to restrict the quantity sold.

A proper solution requires applying concurrent programming techniques and DB transactions to ensure thread-safe limitation of purchase quantities to stock available, and it won't be as simple as a few lines of code.

Concurrency becomes an issue when you are reading/modifying/writing information in the DB from multiple processes simultaneously. Any separation in the code between the reading and the writing opens the possibility that two independent processes can step on each other. (This situation also exists in software development, which is why we use CVS/Bazaar to manage teams of developers working with the same code). Most of Drupal/Ubercart never has to deal with concurrency, because most modules either simply display the current content of the DB (a read-only operation), or modify user- or process-specific information (i.e., operate on data not shared between processes). Stock control is an exception, hence the need for a more sophisticated solution.

--

<tr>.

Posts: 405
Joined: 10/16/2007

TR:

Thanks for the great explanation. Looks like I will just stay with the present "sold out" message on the site. Thought that this would be a nice substitute, but will not chance it.