Now this is a very small issue, but I believe it can have major issues in the inventory and stock checking features which get implemented into Ubercart.
Here's the scenario.
You're a programmer and you've implemented your own hook_add_to_cart, which checks stock against the amount of items which a user is trying to add to his cart.
Lets say you've got 2 Blue Widgets in stock.
Now user comes in and adds 1 Blue Widget to his cart. Your hook_add_to_cart goes and checks $qty = 1, against $stock = 2... we're all good, so we allow this to happen and return TRUE.
Now lets say this user goes back to shopping and he decides, you know what, this is a good deal on Blue Widgets and he goes and purchases another 2 Blue Widgets. Again, your hook_add_to_cart gets fired and this time checks $qty = 2 against $stock = 2 and allow this to happen and returns TRUE.
Problem is, your user now has 3 of these items in his cart! What a JERK! He'll purchase 3 of your existing 2 blue widgets and well...you're screwed.
Now I'll ask the obvious question to your guys and follow up with a more in depth question, which perhaps we should leave for another task/issue. Keep in mind I'm testing this against Ubercart 5-1.7 and I'm not sure what Ubercart 2.x does. I assume the functionality from 1.x was brought into 2.x
So my question: Should hook_add_to_cart, when adding more of the same product into the same customers cart, use the total items he'll end up with in $qty (three in this case) or should we simply pass the current amount he's adding (two in this case).
What I think: Since get's simply "updating" his QTY, I would recommend that we pass 3 into the $qty field, so that other stock modules are properly checking against the proper number he'll end up purchasing.
Question Number 2, something to think about.
I know Ubercart doesn't really deal with out of stock, we let modules figure that out. Think of this scenario for instance. User 1 adds the remaining two Blue Widgets into his cart. User 2 adds two Blue widgets into his cart. User 1 checks out. User 2 checks out.
Ideally a stock module would have to update stock levels for other peoples carts upon hook_order to prevent the purchasing of stock which doesn't exist. Or hook_order $op = submit, will have to double check stock to make sure it still exists before the order goes through. If I was doing this, it would solve my problem above as well. Upon order, a user would be purchasing 3 widgets, when I only have 2....FAIL, warning message.
Solution for issues above
I would recommend that we create a hook_inventory or something, that gets called when someone adds an item to cart and gets called again just before the order submitted. This would allow inventory/out of stock modules to hook into a single function instead of having to deal with the two hooks of hook_add_to_cart and hook_order($op='submit'). I doubt any stock modules are currently dealing with the hook_order case.
Or we can go ahead and make sure all stock modules deal with these two cases and write some documentation about it.
Let me know what you guys think or if this has been solved in Ubercart 2.x.
Comments
Comment #1
j0rd commentedAnother potential solution for carts who care about this stuff, would be to call re-check all the hook_add_to_carts in hook_order($op='submit') to make sure the user can still have all the items in his order before just he purchases them.
If he can't, display an error message and let him know that he was too slow and people already bought his items...or what ever else might have happened (product was deleted?).
The fact that carts can linger around for hours compiles this issue on a busy site with low stock levels.
This might cause other issues I'm un-aware of.
Comment #2
j0rd commentedSeems people know about these discrepancies from the hook_add_to_cart documentation:
But I'm not sure if any improvements or changes are planned or have been made.
Comment #3
j0rd commentedAlso, updating the quantity on the /cart page, does not re-call hook_add_to_cart, so again, inventory checks are ignored.
I assume this is why we mention uc_cart_view_form & hook_form_alter .
Comment #4
cha0s commentedWell, at DrupalCon DC I did some (unfortunately fruitless) work a couple nights trying to get proper stock handling into core. My experience is that we'll need to do SKUs right (that is, unique for each item instead of the way it's handled now) before we can handle it optimally.
I'm not sure I understand why hook_inventory(). Couldn't we just use uc_stock_level to determine the stock on an item at a given time? One question is, do we decrement stock on adding to cart or upon checkout? I suppose we could let the user decide.
Say you're anonymous and you put a widget in the cart. Stock should lower by 1 (if it's set that way). Then, if the cart expires (say, in 5 minutes), that 1 stock should be restocked. So this way of thinking about it, we may benefit from implementing hook_cart_expiration() or something. This 'I have 1 stock of X in my cart' data should be stored in the cart itself. I think there's no need to do another stock check at time of checkout, you just make sure the cart has the right data showing it has reserved the stock for that purchase.**
** Unless the setting was that stock wouldn't be decremented until checkout, then you'd have to do a check, obviously. :)
P.S. Gonna move this out of bug reports and into feature requests.
Comment #5
longwaveIt's too late to do anything with this now Drupal 5 is obsolete. There are other open issues about stock control in newer versions.