We recently discovered a bug with Magento on a client's site. For a short while, they've been having problems with their checkout process whereby the payment gateway would take payment for an order, but no order would appear in Magento. This was obviously very frustrating for customers, and indeed the client.
After getting in touch with some customers, we were finally able to re-produce the error.
To replicate it on your system, follow the below instructions (we're currently running version 1.6 on their store):
- Add a product to your cart
- Add another product to your cart
- Go into the admin side, and change first product quantity to 0 and set it as out of stock
- Go back to the shopping cart page
- You should now be able to checkout
So, you can checkout. Why?
On first glance, it looks like Magento is only checking the last item in your basket. This is likely to cause problems in any system where access to stock is essential (i.e. non-drop shipping stores).
However, having stepped through the code (specifically looking at what the checkQuoteItemQty
function of app/code/core/Mage/CatalogInventory/Model/Stock/Item.php
returns), it appears that Magento does actually go through each product to check its status before deciding whether to display the checkout button to a customer.
So, if it's returning an error on the first item, why isn't it remembering this error and therefore stopping the customer completing the order?
The actual bug
The actual bug is located in the Observer which calls the above mentioned function. The Observer in question is Mage_CatalogInventory_Model_Observer
and the line that causes the issue is this one:
So what's going on here?
This line calls a function which removes items which were causing errors however, no quote / item association seems to be kept, so it clears all of the errors for the cart, instead of just the ones for the specific item.
A true bug?
The bug had actually recently been lodged with Magento Issue #27561 and at the time of writing is assigned.
So, the jury is out on whether this is perhaps functionality that we don't really understand, or that it's genuinely a bug. It seems strange that no-one has ever noticed this before, but equally strange that multiple folk have now recognised it.
A fix?
It was obvious that we could probably override the Observer and write our own handler for this, but it wasn't immediately obvious what angle to come at it from. Luckily, the same bug report also suggested a solution.
The solution
So, the solution is to put together a module which will work without any core hacks. In it, we attach the Observer to the sales_quote_item_qty_set_after event using the function reinitQuoteErrorState
.
Coding-wise, we need to step through each error'd item and check if it's an error based on qty.
The helper we use to raise the error means that we can override it using a Locale CSV, but we could quite as easily update this Observer to give custom error messages at the same time like so:
The complete package
Rather than offer half the solution, we've created a module for you to download. Take a look here:
No hay comentarios:
Publicar un comentario