It isn't clear to me what I'm doing when I grant a user "Redeem any coupon" permission. That to me sounds like a user can literally come in and use any coupon on the site regardless of any permissions I may have associated with it or its discount. Does this really just mean I can "Redeem coupons of any type"? If so, I'd recommend a change in wording, as "redemption" typically means you're actually using it, not being just having permission to see if you can use it.

This issue was further complicated when I tried to understand the Commerce Coupon User permissions. It isn't clear to me what's going on here - why are there additional permissions for redeeming non-user-specific coupons? Don't the normal Commerce Coupon conditions apply in this case? Additionally, what does a "received" coupon even mean? Is that actually referring to a coupon code that has been specifically assigned to my user account?

As it stands, I want my users to be able to attempt to apply any coupon code to an order and let the conditions of the discount determine whether or not it actually applies. If it applies and I complete checkout, that's when a coupon has technically been "redeemed." I granted anonymous and authenticated users permission to "Redeem any coupon," but I'm not sure I didn't just grant everyone on the site the permission to use any coupon code regardless of discount conditions.

Comments

dpolant’s picture

I am using the word "redeem" to mean add the coupon to the order. Maybe a better wording would be "apply". Either way, discount conditions still get their chance to prevent a discount from taking effect.

Re received/non-user specific:

Received = a coupon assigned to a person's user account
Non-user specific = a coupon that does not specify a user account

These are important because you might want to let people redeem any coupon that either is assigned to them or is assigned to no one.

rszrama’s picture

How do those user specific permissions interact with the core module's permissions? Does one set overrule the other?

dpolant’s picture

The "core" permissions override the received/non-specific ones.

jorditr’s picture

Does this explanation clarifies anything? I still don't understand the goal of the permissions, and being a delicate issue there is not a single line explaining it on the module's documentation...

guypaddock’s picture

I just ran into this debacle myself on a site that just went live. Since the existing comments didn't really seem to clear this up enough, I figured I'd share my findings.

The permissions, as described, are confusing. The name "Redeem any coupon" and "Redeem any XYZ coupon" have the implication that, if granted to a user, that user has the ability to redeem coupons regardless of conditions or restrictions on the coupon. This is not the case.

Looking at the code, the permissions control whether the coupon can be redeemed at all, before any conditionals on the coupon are evaluated. This means that the conditionals get evaluated only if the user has at least permission to redeem the type of coupon they are applying to the order.

I think this could be corrected just by rewording the permissions and removing the word "any". So, that would make the permission names "Redeem coupons of any type" and "Redeem coupons of type XYZ".

Now, another question is how this interacts with permissions exposed by commerce_coupon_user. The answer can be found in commerce_coupon_user_received_coupon_access():

function commerce_coupon_user_received_coupon_access($op, $coupon, $account = NULL) {
  if (user_access($op . ' coupons of type ' . $coupon->type) || user_access('redeem any coupon')) {
    return TRUE;
  }
    
  $coupon_wrapper = entity_metadata_wrapper('commerce_coupon', $coupon);  
  // If the coupon does not specify a recipient and the user is allowed to
  // redeem non-user-specific coupons of this type:
  if (!$coupon_wrapper->commerce_coupon_recipient->value() && user_access($op . ' non user specific coupons of type ' . $coupon->type)) {
    return TRUE;
  }
  // If the user is allowed to redeem coupons they've received:
  else if (user_access($op . ' received coupons of type ' . $coupon->type)) {
    if (!$account) {
      global $user;
    }
    else {
      $user = $account;
    }

    // Evaluate "received coupon" permissions.
    if ($coupon_wrapper->commerce_coupon_recipient->value() && $coupon_wrapper->commerce_coupon_recipient->raw() == $user->uid) {
      return TRUE;
    }
  }
}

To translate:

  • If the coupon is of type XYZ and the user has the permission to redeem coupons of type XYZ or redeem coupons of any type, they can redeem the coupon without having any of the permissions exposed by commerce_coupon_user.
  • If the user does not have the permission to redeem coupons of type XYZ or redeem coupons of any type:
    • If the coupon has no recipient and the user has permission to "redeem non user specific coupons of type XYZ", the user can redeem the coupon.
    • If the coupon has a recipient and the user has permission to "redeem received coupons of type XYZ", the user can redeem the coupon.

If none of the three cases above match, the user cannot redeem the coupon.

I really think that the way these permissions work together should be re-examined. It's not immediately intuitive that permissions at the "Commerce Coupon" level should take precedence over "Commerce Coupon User" level because you have to remove the permissions at the Commerce Coupon level if you want to use permissions defined by Commerce Coupon User. What if you're using other modules that extend Commerce Coupon and that do not expose their own permissions -- how do you allow users to redeem coupons of those type?

Better question -- why does it make sense for Commerce Coupon User to expose any permissions? Is there a reason why a site builder would want to prevent users from redeeming a coupon they've received? It just doesn't seem to make sense, and the current permissions just sow confusion.

guypaddock’s picture

Status: Active » Needs review
StatusFileSize
new842 bytes

Attached is a patch that cleans-up the verbiage in Commerce Coupon.

This doesn't resolve the open question I have in my previous comment about why Commerce Coupon User even defines any permissions at all.

guypaddock’s picture

One other observation: users also need the "View any coupon of any type" permission. Without it, once a coupon is applied to the order, they can't actually see the coupon or remove the coupon.

Unfortunately, because "View any coupon of any type" has a warning about it having security implications, site builders are reticent to grant it. I think that it's inheriting the security warning from commerce_entity_access_permissions(). Correct me if I'm wrong, but, I don't see any security issue with allowing users to view coupons of any type. Thoughts? Can we clear this up in the permissions list so that admins feel safe granting the permission?

egontinno’s picture

+1 #7

Spent hours and hours to figure out, why anonymous user won't see applied coupons on checkout until find #7
That's not nice to mark permission to security warning if it's needed for anonymous user!