If set param
Maximum number of redemptions (per user): 1
and store can anonymous user buy products, you fill email but coupon module before checkout not check email (exists user) and this param not work.
Users buy products unlimited use this action.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

tharrison’s picture

Title: Coupons not work in buyer amonumous user » Coupons maximum number of redemptions per user does not work why buyer is anonymous user

If I understand the issue correctly, I would think this is not really a solvable issue, and not really a bug.

My company has a store where anonymous users can make a purchase. We recognize that there's no effective way to limit the number of times the coupon is used by a given anonymous user. There are perhaps some things you could do to try to prevent multiple uses, for example: set a cookie indicating their coupon has been redeemed, record their IP address and a time and prevent redemption from the same IP for a given time period. Both are flawed -- a user could delete any cookie or just use a different browser; in many cases, many users share a single IP address (e.g. everyone in a company), so any solution could end up either not working, or disappointing customers. It might be a nice feature to allow in the module, though.

I would propose two alternatives for your case:

  1. Limit the total number of coupon redemptions
  2. Require your users to authenticate first (create an account) before using a coupon -- perhaps this alone is the value of the coupon discount!

I hope this is helpful.

Tom

longwave’s picture

Status: Active » Closed (won't fix)

As tharrison explains, this cannot really be fixed, as anonymous users that are allowed to use a coupon could just create a new Hotmail account and use that to make their purchase, IP address checks are not reliable - users can always find a way around this if they are determined enough. Marking won't fix, but feel free to reopen if anyone has a good idea on how to solve this properly.

rickmanelius’s picture

Status: Closed (won't fix) » Active

My need/use is slightly different. I don't care if an anonymous user creates a new account to get a coupon because they won't have access to all the purchases made in their old account. So for me, I like allowing them to check out without logging in and still putting in their email address. But at that point, the order still gets attributed to that account.

So how about this...

When running uc_coupon_validate($code, $order = NULL), we currently only grab global $user. What about if $user->uid =0, we run an additional check on $order->primary_email to see if a valid user account does exist. If it does, we load $user2 and then run all validation checks off of $user2. And one can set $user2 = $user if it that's not the case.

The reason we'd want to use $user2 is that assigning a non-logged in user object to $user would essentially log them in (security risk!). But it looks like this could be done fairly simply...

I could provide a patch if I knew it would make it in the code...

longwave’s picture

Title: Coupons maximum number of redemptions per user does not work why buyer is anonymous user » Maximum number of redemptions per user does not work when buyer is anonymous
Assigned: wowik73 » Unassigned
Category: bug » feature
Priority: Critical » Normal

$order->primary_email is not always available. Users can apply coupons on the cart page or via a block, where we don't have any details of the anonymous user. Even at checkout, if the coupon is applied using the "Apply" button, this is done via an Ajax request which doesn't (currently) send the email address either from what I remember. So this would need to be taken into consideration in the code - but I'd be happy to review a patch if you supply one.

rickmanelius’s picture

Hey Longwave.

Thanks for the speedy reply.

You are correct that the order object has no primary_email at the cart pane and thus it would apply. However, it would be available by the time we are at the review page as you'd need an email by then.

The hole I'm trying to plug is allow anonymous checkout but still apply a per user cap. Right now, we have a product coupon for 100% off an 1 use only. But someone checking out anonymous and giving the email address for that membership skirts around the cap. So currently we switched back to not allowing 'anonymous' checkout.

But, that may be a better option. Let me talk to my client and if they require anonymous checkout to be reinstated, I'll definitely test on my end and submit a patch. For now, it's not needed with anonymous checkout turned off (my short term solution).

hanoii’s picture

Just faced this issue. I guess the only way to make a redemption limit for anonymous purchase are, indeed, associating them to email address. Thus, instead of applying the validation to an account that has the email, we might rather just limit the coupon by email address (like when sent in a mailing).

I see the fact that this will be needed on all the entry points for coupons and to do that, an email address field might have to be added to the coupon form (when it's not available on order or a logged in user) elsewhere rather than in the checkout, and we have to have that email address on every part of the code to be validated.

If I am asked to quote and work for this, I might be submitting a patch, otherwise just leaving here the approach I think might be the best one.

rickmanelius’s picture

This one has reared its ugly head again. But now I'm more interested in Drupal 7 which has ajax included within the form API... so it might be possible to grab the email this time.

Pinging this with my comment so it jumps back up to the top of my issue queue.

wodenx’s picture

Version: 6.x-1.3 » 6.x-1.x-dev

I'd definitely consider a patch for this - but how would we handle coupon validation before an e-mail address has been entered (i.e. on the cart page or the coupon block, or even on the checkout page before the customer has entered an email address)? Also, I think I'd want this to be a configurable behavior (a "Validate coupons for anonymous users based on email address" setting).

wodenx’s picture

Version: 6.x-1.x-dev » 7.x-2.x-dev
rickmanelius’s picture

Hi @wodenx,

I definitely agree about the configuration.

As for the checkout process, I know that (for example) taxes will be triggered to update by one of several events (shipping address, subtotal updating, shipping changing, etc). So I think the coupon's validity could also change on that. If someone puts in their email, goes through the rest of the process, adds a coupon, and THEN updates their email address again... that is when the coupon gets removed.

Off the top of my head, I believe there is a way to checkout anonymously without putting in an email address. If that's true, this functionality would be null and void in that situation. So any configuration would have to toggle off if anonymous checkout without email was specified.

Thoughts? I'm not asking for someone to write it, but is there anything else to consider if I were to create said patch?

wodenx’s picture

There are some issues pending in ubercart core which might have an impact here - particularly #1373236: Allow multiple modules to react on checkout Ajax events, which will affect responding via ajax to user entering an e-mail address, and #1351104: Need to clear line items as well as products for cart orders, which may change the way the cart contents are connected to the order contents during checkout. May just want to keep those in mind. Also, if a previously applied coupon is invalidated by entering an e-mail address on the cart page, we need to make sure this is made clear to the user - status messages generated during ajax calls can get lost. Finally, I think if the site is configured to use e-mail addy to validate coupons, then i think it makes sense to invalidate all coupons if customer manages to advance to review without entering an email address.

If you do start working on this, please set the "assigned" field to yourself. Thanks.

rickmanelius’s picture

One of the issues in #11 has been resolved and the other is close to release. I'm adding this as a patch/placeholder as solution. I understand (as per #2), there are situations where a user can simply create a new account. But my situation is for users that just forgot to login and the order ultimately gets associated to their account. This has the additional benefit of a role restriction now working because a person can be a 'member' but not logged in... and yet if their email indicates that they are indeed a member, standard validation would apply.

I know there is more to this than this... but again, this is a start.

rickmanelius’s picture

Status: Active » Needs work
rickmanelius’s picture

Status: Needs work » Needs review
FileSize
1.06 KB

This is now much better space... I was running into a snag because uc_coupon_validate() from uc_coupon_session_validate() were not sending in the full order object, but rather a shell of one with the products and data within it. Therefore it was not possible to snag $order->primary_email.

I wrapped the lines of code in #12 with an additional function to load the full order object (but only in this edge case scenario) and then do a user lookup and determine if we should load the full $account based on the email address inserted.

YES, people can still get around this. I'm banking on the fact that 98% of our users are not sophisticated enough to know how to do that... so it's not meant to be a cure all. And there might be a better way to do this (e.g. load the actual full $order object in uc_coupon_session_validate()). But this little bit of code solves my problem because it will remove the coupon from the order the second they go to the review page... therefore no matter what order they put in the code + email, it takes care of the validation limits.

Any feedback/reviews would be appreciated. I considered writing a simpletest, but the module doesn't use that type of functionality yet, so I didn't want to go hog wild (yet!).

rickmanelius’s picture

I hate to be that guy... but I have feature release scheduled for November 15th and could really use a quick review on this. I know it's an edge case and I'll probably end up keeping this as a local patch if it doesn't get committed to the module, but any feedback on something I might be missing would be most appreciated!

rickmanelius’s picture

WARNING. Do not use the patch in #14. By using loading a new order object and setting to $order, it breaks the functionality of the coupon system for anonymous users. I've temporarily adjusted the $order to $order2, but I'm open to it being changed to something more meaningful ($order_temp).

Here is a new version...

wodenx’s picture

Status: Needs review » Needs work

You'll have the same problem with the $account object -- esp. bc uc_coupon_session_validate() passes in the global $user object.
Also, you should probably check to be sure the $order object doesn't already have an associated user, in case someone else is calling uc_coupon_validate directly, we don't want to break their code. Only use $_SESSION['cart_order'] if the info isn't available elsewhere. Finally, I'd much prefer that you make this feature optional -- add a setting that enables the added degree of security.

rickmanelius’s picture

Hi @Wodenx. Would that still be a problem? In this scenario, the global $user variable would still validate the session and $account would be passed in to validate the coupon. And in #16, I'm loading the order up as $order2 so nothing else in that function would mix up that variable name.

I'll run some more tests to see if I can cause it to fail, and thanks for the heads up!

wodenx’s picture

Status: Needs work » Needs review
FileSize
2.21 KB

I've reworked the patch to address my concerns. I moved the logic into uc_coupon_session_validate(), since uc_coupon_validate shouldn't be tied to the session in any way. I've also made it an optional feature.

Please test this thoroughly.

wodenx’s picture

Here's the same patch for 7.x-3.x