Regression: Limit promotion (via coupon) to only apply once per order

Created on 12 January 2024, over 1 year ago

In 🐛 Limit promotion to only apply once per order Fixed , the ability to apply the same promotion multiple times using unique coupons was removed.

https://git.drupalcode.org/project/commerce/-/commit/4a8e073085981f3a0d6...

      // The promotion might already be applied, make sure we don't apply the
      // same promotion more than once.
      if ($referenced_coupon->getPromotionId() == $coupon->getPromotionId()) {
        $form_state->setErrorByName($coupon_code_path, $this->t('The provided coupon code cannot be applied to your order.'));
        return;
      }

The introduction of this block of code has broken functionality - I do want users to be able to apply multiple single use unique coupon codes to an order. In our case, each single use code gives up to $20 off the order. If a user uses 2 of them, they get $40 off etc. Trying to use the exact same coupon twice still rejects which is desired.

I can just remove this code for now, but it would be ideal if this was configurable like the other usage limits, say Usage limits: Total allowed uses per order.

I thought it was working just fine as it was. I'm sure others are using it similarly as it seems like an obvious use case.

🐛 Bug report
Status

Active

Version

2.0

Component

Promotions

Created by

🇦🇺Australia elc

Live updates comments and jobs are added and updated live.
Sign in to follow issues

Merge Requests

Comments & Activities

  • Issue created by @elc
  • 🇮🇱Israel jsacksick

    The "obvious" usecase to me is supporting coupon codes belonging to different promotions. Supporting applying coupon codes belonging to the same promotion sounds like a bug to me...

  • 🇦🇺Australia elc

    Use case:

    I have 2x promotions: "Fixed amount off the order subtotal"
    - $50 off
    - $20 off

    Both require coupons. Unlimited uses per user, unlimited available.

    I have 1000 unique codes on each which are given out. They each have single use set.

    If a user has 4x $20 codes, they get $80 off their order.

    If a user has 1x $50 code and 2x $20 codes, they get $90 off their order.

  • 🇮🇱Israel jsacksick

    I think this issue should be changed to a feature request, and we might need a new setting. Describing what it does might be a bit challenging as I doubt your usecase is a frequent one... I'm pretty sure in most cases the expectation is to NOT allow applying the same promotion multiple times.

  • 🇦🇺Australia elc

    I've updated the the issue description into a FR.

    For now I've just commented out the code with a patch to get the previous function working for users who have been complaining.

    I have since had a request that it be possible to limit it to a number per order, so a similar setup as the other usage limits would be ideal. Setting to allow unlimited applications, or N applications per order.

  • +1

    Would be nice to be able to use multiple coupons from a promotion on one order with the possibility to limit the amount of coupons per order.

  • 🇮🇱Israel jsacksick

    Reasonable proposal I guess.
    The current fields we have for limiting usage are named like "usage" and "usage_limit_customer". If we keep the same pattern, I guess we could go with "usage_limit_coupon" with a method getCouponUsageLimit()

    The only problem is if we now introduce this, the default value for these fields is "0" which actually means unlimited, and the current behavior is 1. But perhaps it is fine to limit to 1 by default?

  • 🇮🇱Israel jsacksick

    Perhaps "usage_limit_order" makes more sense, though you can't apply the same promotion multiple times if not using multiple coupons, but it does sound more explicit.

  • First commit to issue fork.
  • 🇩🇪Germany onfire84

    +1

    i just run into the same issue when implementing the promotion feature for a customer. it wolud be great if we could get a configurable solution for that setting.

  • 🇮🇳India sorabh.v6 Indore

    I am interested in working on this issue. Just to confirm, we are going with "usage_limit_order"? I was thinking this name might be little bit confusing.

    IMO if we put a checkbox in the usage limit details container that says "allow applying multiple coupons per promotion". If this is not checked then we can compare promotion id of the applied coupons else we compare the coupons id and promotion id.

    Let me know how this sounds to you @jsacksick.

    Thanks

  • 🇮🇱Israel jsacksick

    Ok, this isn't really a "usage" setting, so I'm thinking we could go with:

    • Field name: allow_multiple_coupons
    • Method: isMultipleCouponsAllowed()
  • Pipeline finished with Failed
    4 months ago
    Total: 145s
    #416669
  • ivnish Kazakhstan

    Looks like MR is broken

  • Pipeline finished with Failed
    4 months ago
    Total: 156s
    #416910
  • 🇮🇳India sorabh.v6 Indore

    I think its better that we add this into the 3.0.x-dev.

    @jsacksick Let me know you opinion.

  • 🇮🇱Israel jsacksick

    Definitely, didn't pay attention to that, 3.0.x is the recommended version.

  • Pipeline finished with Success
    4 months ago
    Total: 580s
    #417684
  • 🇮🇱Israel jsacksick

    Code looks ok at first glance, not sure why the MR was closed. Any chance we could get tests coverage for this extra setting?

  • 🇮🇱Israel jsacksick

    Also we might need a description explaining what the setting does. Setting to needs work for the tests.

  • 🇮🇳India sorabh.v6 Indore

    Sure, I will add test coverage for this extra setting. I will add description/help text for the field as well.

  • Pipeline finished with Canceled
    3 months ago
    Total: 502s
    #433262
  • Pipeline finished with Failed
    3 months ago
    Total: 4374s
    #433269
  • Pipeline finished with Failed
    3 months ago
    Total: 516s
    #433489
  • 🇮🇳India sorabh.v6 Indore

    @jsacksick There's some issue with the phpunit pipeline. Its giving me failed tests for the files which I did not changed.

    Other than that, MR has the updated code that has -

    • need a description explaining what the setting does
    • PhpUnit tests for the change

    Let me know if I understood it wrong and those failing tests are related to my code.

    Thanks

  • 🇮🇱Israel jsacksick

    The code added looks wrong... The order module shouldn't have promotion related code? The coupons field is not necessarily present and is added by the promotion module for example.

  • 🇮🇳India sorabh.v6 Indore

    Actually, when multiple coupons are not allow and we apply coupons from UI then we get validation error. But when we apply the coupons programmatically then we do not get error and multiple coupons are applied.

    I thought to prevent this I need to update the code in order presave.

    If you do not want me to update the code in the order module, then I can add that validation in the hook_entity_presave.

    Let me know if that works.

    Thanks

  • Pipeline finished with Canceled
    3 months ago
    Total: 79s
    #438629
  • Pipeline finished with Failed
    3 months ago
    Total: 563s
    #438634
  • Pipeline finished with Success
    3 months ago
    Total: 521s
    #438711
  • 🇮🇳India sorabh.v6 Indore

    As per the conversation in the slack -> https://drupal.slack.com/archives/C1TLCCF9B/p1740661087476619

    Updated the MR and needs review now.

    Thanks

  • Status changed to Needs review 3 months ago
  • 🇮🇱Israel jsacksick

    I just don't understand why the existing code in CouponTest was touched. Would have been better to add new code rather than modifying the existing logic which makes this more complicated to review.

  • 🇮🇳India sorabh.v6 Indore

    Hey @jsacksick, I will move my changes to a new method in the CouponTest. I hope that would make it better to review.

  • 🇮🇳India sorabh.v6 Indore

    Hey @jsacksick, I have made the changes. Let me know if you think anymore changes are needed.

  • Pipeline finished with Success
    3 months ago
    Total: 761s
    #452219
  • 🇮🇱Israel jsacksick

    Ok almost there, let's change the description to:
    "Allow multiple coupons to apply to a single order."

    Also, let's add setSetting('display_description', TRUE) to the field definition. Thanks to this no form alteration would be needed.

    Also, let's update the promotion order processor test to test the case where multiple coupons are allowed using the new setting (we're missing that).

  • 🇮🇳India sorabh.v6 Indore

    @jsacksick

    Also, let's update the promotion order processor test to test the case where multiple coupons are allowed using the new setting (we're missing that).

    Do you mean this code -
    https://git.drupalcode.org/project/commerce/-/merge_requests/407/diffs#d...

  • Pipeline finished with Success
    3 months ago
    Total: 513s
    #454051
  • 🇮🇱Israel jsacksick

    Referring to PromotionOrderProcessorTest:: testMultipleCouponRedemption().

    Also, the kernel promotion test doesn't need an extra method, but I can refactor that myself prior to commit, I can also make the final changes myself prior to commit when I get some time to finally wrap this up.

  • 🇮🇳India sorabh.v6 Indore

    This isn't needed with "display_description", correct?

    Yes, but we can show the description.

  • 🇮🇱Israel jsacksick

    I don't understand? The setting is there so the description is correctly added, so no need for injecting it from the PromotionForm?

  • 🇮🇱Israel jsacksick

    I tweaked the setting description, moved the setting under "Usage limits", and manual testing works as expected... Let's see if the tests are still green but I believe this is good to go.

  • Pipeline finished with Skipped
    about 2 months ago
    #471363
  • 🇮🇱Israel jsacksick

    @sorabh.v6: Thank you for your work on this, committed!

  • Automatically closed - issue fixed for 2 weeks with no activity.

Production build 0.71.5 2024