Jump to content

<SOLVED> Selling unique items: how to enforce quantity check during ordering?


Recommended Posts

Hello!

I'm helping a friend set up a webshop for unique items she is selling, so our main requirement is that people cannot order an item more than once. When I order an item as one user, then after my order is finished the item is properly displayed as out-of-stock on the web page, so that is fine, we can live with that. When two people are logged in simultaneously, and proceed with the order, both can click on the final "order" button in the last step without a problem -- just when the one who did it second looks at their order, it has a notice that it's on back order.

I've tried that last step with osCommerce and Magento, and they both do a quantity check at that point, so that the person who presses the final order button just a wee bit later gets an error that the product is out of stock. Can this be done with PrestaShop -- because I really like it otherwise, just this feature is critical. Ideally I would like to set this in the back office, but if anyone knows where this is in the code, any pointers would be appreciated! For what it's worth, I'm using Bank Wire as payment.

Thanks!

PS: I've tried searching for order, or quantity, but can't easily find a topic that covers this exactly.

  • Like 1
Link to comment
Share on other sites

I guess this is an little bit complicated issue, because PrestaShop does not create an order in database until the payment is done. I know some other software like osCommerce they create an order in database when customer start checkout and confirmed the order.

In your case, you must first decide at what timing you think the customer own the product?

At timing of confirmed order before payment?
At timing of payment finished?

At my knowledge, PrestaShop is not checking this (sorry if I am wrong), so you may have to do some coding to implement it yourself.

Link to comment
Share on other sites

Hi Shokinro!

Thanks for your explanation, that makes somewhat sense. However, there must be different mechanisms, or different "order states" I guess, because if I order an item like this, even without the admin setting anything, the item then shows up as "out of stock" on the front end afterwards. So the front end does do this check and it has the right definition of order state. I just want that check to be applied right before the customer presses "order". I can code it up if it's not there, I would just appreciate any pointers to where that would be before I spend a few hours getting accustomed to the codebase.

Link to comment
Share on other sites

I assume your click "Order" means at choose shipping and click "Next" to go payment. The problem is that at this moment the order is not created yet.

So you have to check both shopping cart(ps_cart_product) and order (ps_order_detail) table in database.
But even if there is something is shopping cart, it doesn't mean that it will become an order.

So here is what I can suggest(just guidance for your reference)

1. Add new filed in cart to indicate the user start order
2. When user choose carrier and click "Next" goes to payment, check if there is any existing other cart has the same product and has the flag set on, also check if there is existing order in the ps_order_detail table
3. If yes, then show error
If no, set the flag
4. when user cancel payment from payment process comes back to your site, you need to set the flag off

I think that's pretty much you have to do.

Link to comment
Share on other sites

No, I mean if two people with the same item are at the step where they have the payment module info (so right after they have chosen their payment), and then press "order". so I don't care what's in the cart, but if person A has finished his order and gotten to the order confirmation page, then person B should get an error when he presses the final order button after having chosen his payment. I don't care what's in the cart, but as soon as one person orders something and has it confirmed, it should block anybody else.

What I see in order.php sounds promising:

if (!$cart->checkQuantities())
{
       $step = 0;
       $errors[] = Tools::displayError('An item in your cart is no longer available, you cannot proceed with your order');
}


but the trouble is that only gets checked during the order phase (whatever order.php handles) -- the problem is that for the payment, it gets redirected to a module, and the final confirmation is there. I just need to look at the code some more to figure out where that last step is happening, haven't had much time yet. I guess I was just hoping that someone who knows the basic code base would know right away where this execution path is.

Link to comment
Share on other sites

The order data is generated when payment is finished. Different payment module will have different timing. For example, Paypal, even user has finished payment, the order still not generated. It will take a few seconds for Paypal server calling PrestaShop Paypal module to validation order, then the order is created in database.

But no matter what payment method it is used, it will call PaymentModule->validateOrder(), the order is created in this method of class PaymentModule. so I think you need to check at that code. But if you detected that someone has an order at that timing, it is too late to tell customer that the product is sold out. Because the customer has already paid for his/her order.

Link to comment
Share on other sites

Ok, thanks, that makes sense. Then I will check out bankwire's validateOrder call and I've taken a quick look at PaymentModule (which does detect out of stock, but not sure what it does with it). Since we are planning on using bank wire only, the order creation should be immediate (and I've checked the DB as soon as I pressed the order button). I'll keep you posted if I find anything (now that the kids are asleep ;-) )

Link to comment
Share on other sites

if you ate using only one payment method and it is bank wire, then the it make things much easier.
I think you can handle that because there is almost no time gap between click "confirm order" and payment finish.
you should be able to handle it 99.99% correctly.

Link to comment
Share on other sites

Ok, I've sifted through the code a bit, and I guess you are right in that the whole notion of being able to order out of stock items is kind of woven into the code. I agree that I can very easily add a code snippet like

if (!$cart->checkQuantities())
{
       Tools::displayError('An item in your cart is no longer available, you cannot proceed with your order');
       Tools::redirectLink(__PS_BASE_URI__.'order.php?step=0');
}



right in the beginning of modules/bankwire/validation.php as a one-off solution. It would be a much larger effort to make a default check of out-of-stock before the final order confirmation for any payment, including the seconds-delayed PayPal that you mentioned.

Just makes me wonder what the design decision was here and why it's handled differently in other eCommerce solutions.

  • Like 1
Link to comment
Share on other sites

  • 11 months later...

Woww! this is what I've been looking for, since I got a couple times that my product's stock is "-1" even I have disabled "allow order on out of stock product".

 

I made a test with 2 customers with a product which has the last qty ( 1 ), and then at the same time doing the checkout, and select the same bank wire payment, and no problem, and after I click on "Confirm my order" button, both of the users got the order-confirmation.

 

So you're very right, sling_addict, adding the validation of cart quantity in the validation.php is very important , in case for the very high traffic store, so there won't be any big problem.

 

Thank you for sharing this :D

Link to comment
Share on other sites

  • 5 months later...

Oh my word, I have been searching and searching for a solution to this as I also sell unique items.

 

Did you get it to work for paypal? Where can I add this extra check?

 

I'm using paypal payment only and I am so desperate for a fix for this. I keep getting orders for items which sold out seconds before :(

 

Many Many Thanks

Sarah

Edited by atwitz3nd (see edit history)
Link to comment
Share on other sites

if you ate using only one payment method and it is bank wire, then the it make things much easier.

I think you can handle that because there is almost no time gap between click "confirm order" and payment finish.

you should be able to handle it 99.99% correctly.

 

Hi there

Can you advise where to add this for my PayPal module?

I'm suffering this issue daily on my handmade website, as I sell unique items.

 

Thanks you so much

Edited by atwitz3nd (see edit history)
Link to comment
Share on other sites

SOLVED:

 

I think I got it to work!! yay :)

 

I added it to the top of the Modules/paypal/submit.php page and it seems to do the trick. I only tested it manually, turning the stock on and off, during the various steps and the further paypal screens and it seems to block the order at every chance when it's out of stock, and bounces back to order step 0!! I'm so delighted.

 

Of course only a true shopping senario with test the balls of it in terms of speeds, so only time will tell, but for now it seems to have solved my issue. Thank you Thank you!

Link to comment
Share on other sites

  • 2 months later...

Wow, took a long time to find this post.

 

I'm looking at using Prestashop and this unique item order issue is very critical as there is no way to provide a second item of something. Is the code sling_addict noted the only code that needs to be added to provide the functionality with Paypal that atwitz3nd successfully implemented?

 

Do any of the new releases provide this functionality. I'm thinking not as my review of the manuals don't show anything but I may have missed something.

 

Thanks all!

  • Like 1
Link to comment
Share on other sites

  • 9 months later...

Did any of you guys update that check for the newer paypal version in 1.5.4?

 

I am tried quite a bunch of options but I cant bring it to work... (I was able though to integrate it in the wire transfer and my other credit card processor).

 

Thanks!

Link to comment
Share on other sites

  • 1 year later...

I just found this old topic - problem with missing check for quantities during payment validation is still present even in current PrestaShop version 1.6.0.14.

Better approach as editing each one module is changing function validateOrder in abstract class PaymentModule.

 

1. Create file /override/classes/PaymentModule.php

2. Copy and paste there this:

 

<?php
abstract class PaymentModule extends PaymentModuleCore
{
	public function validateOrder($id_cart, $id_order_state, $amount_paid, $payment_method = 'Unknown',
		$message = null, $extra_vars = array(), $currency_special = null, $dont_touch_amount = false,
		$secure_key = false, Shop $shop = null)
	{

		if (!isset($this->context))
			$this->context = Context::getContext();
		$this->context->cart = new Cart($id_cart);

		if (!$this->context->cart->checkQuantities()){
			Tools::redirect(__PS_BASE_URI__.'order.php?step=0');
		}
		return parent::validateOrder($id_cart, $id_order_state, $amount_paid, $payment_method, $message, 
			$extra_vars, $currency_special, $dont_touch_amount, $secure_key, $shop);
	}
}
 

3. Delete file /cache/class_index.php (it will be regenerated with reference on this new overridden class)

4. Make sure you have enabled overridden classes in your /admin interface/advanced parameters/performance - second section "Debug mode", option Disable all overrides

Edited by zulien (see edit history)
Link to comment
Share on other sites

  • 2 months later...

I just found this old topic - problem with missing check for quantities during payment validation is still present even in current PrestaShop version 1.6.0.14.

Better approach as editing each one module is changing function validateOrder in abstract class PaymentModule.

 

1. Create file /override/classes/PaymentModule.php

2. Copy and paste there this:

 

<?php
abstract class PaymentModule extends PaymentModuleCore
{
	public function validateOrder($id_cart, $id_order_state, $amount_paid, $payment_method = 'Unknown',
		$message = null, $extra_vars = array(), $currency_special = null, $dont_touch_amount = false,
		$secure_key = false, Shop $shop = null)
	{

		if (!isset($this->context))
			$this->context = Context::getContext();
		$this->context->cart = new Cart($id_cart);

		if (!$this->context->cart->checkQuantities()){
			Tools::redirect(__PS_BASE_URI__.'order.php?step=0');
		}
		return parent::validateOrder($id_cart, $id_order_state, $amount_paid, $payment_method, $message, 
			$extra_vars, $currency_special, $dont_touch_amount, $secure_key, $shop);
	}
}
 

3. Delete file /cache/class_index.php (it will be regenerated with reference on this new overridden class)

4. Make sure you have enabled overridden classes in your /admin interface/advanced parameters/performance - second section "Debug mode", option Disable all overrides

 

 

 

 

Hello Zulien

 

It seems that this solution fixes the problem in their own modules prestashop. COD, transfer. I've tried it and it works in 1.6.0.14.

But some users say that modules card payment or Paypal are not working. https://www.prestashop.com/forums/topic/444788-caso-curioso-deja-vender-sin-stock-¿es-un-fallo/

Redsys official module, payment cards

https://www.prestashop.com/forums/topic/266480-modulo-redsys-tpv-virtual-gratis-en-su-web/

http://www.redsys.es/wps/wcm/connect/redsys/3e852424-9f3b-4a7d-910f-26d45bf3144d/redsys_prestashop_V2.4.3.zip?MOD=AJPERES

 

Thanks.

Link to comment
Share on other sites

  • 1 year later...
  • 3 weeks later...

/override/classes/PaymentModule.php - This method works perfectly! I spend a lot of time to searching solution for this... Thank you all very much :)

It doesn't work as mentioned above for some payment modules. Using the eWay payment module for example - it takes the cash, then returns you to basket saying you can't order the out of stock product.

Edited by pbscreative (see edit history)
Link to comment
Share on other sites

  • 3 months later...
  • 1 year later...

In PS 1.7.3.0 you need to change:

\classes\checkout\CheckoutPaymentStep.php

Line 46:

public function handleRequest(array $requestParams = array())
{
if (isset($requestParams['select_payment_option'])) {
$this->selected_payment_option = $requestParams['select_payment_option'];
}
.......
 
TO THIS:
 
public function handleRequest(array $requestParams = array())
{
$allProductsInStock = $this->getCheckoutSession()->getCart()->isAllProductsInStock();
 
if ($allProductsInStock !== true) {
$cartShowUrl = $this->context->link->getPageLink(
'cart',
null,
$this->context->language->id,
array(
'action' => 'show'
),
false,
null,
false
);
Tools::redirect($cartShowUrl);
}
if (isset($requestParams['select_payment_option'])) {
$this->selected_payment_option = $requestParams['select_payment_option'];
}
.......
Edited by juanzapatac (see edit history)
Link to comment
Share on other sites

  • 1 year later...

Hello

This seems to be a problem.
I have ps version 1.7.6.3 installed and I have this problem.

When 2 customers have the same product in the cart at same time but we only have one product in stock, the ps let them finish the order 😞 .

One order is correct and the second order shows it as "Pending order due to Stock"

Checking the product shows stock -1

have any solution for this ?

I check the comment by @juanzapatac and the line 46 in ps 1.7.6.3

\classes\checkout\CheckoutPaymentStep.php

$allProductsInStock = $this->getCheckoutSession()->getCart()->isAllProductsInStock();

Link to comment
Share on other sites

  • 1 year later...

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...