Order items added by Buy X Get Y does not dispatch CART_EMPTY event when removed

Created on 26 September 2023, over 1 year ago
Updated 6 December 2023, about 1 year ago

Problem/Motivation

I made a custom EventSubscriber that subscribes to CartEvents::CART_EMPTY event but I realized it is not triggered when a Buy X Get Y promotion applies on my cart and I remove the last item (because the Y item is removed just after that by the PromotionOrderProcessor).

Steps to reproduce

- Create a custom EventSubscriber on CartEvents::CART_EMPTY and dump something on the event callback.
- Create a Buy X Get Y promotion where the customer gets a specific product variation and check "Automatically add the offer product to the cart if it isn't in it already"
- Add a product to your cart (the specific product variation should also have been added to your cart)
- Remove the first product (which automaticlly remove the other one)
- Nothing was dumped by the custom EventSubscriber even if the cart is empty.

Proposed resolution

Use the cart manager to remove the order item thanks to the removeOrderItem() method.

🐛 Bug report
Status

Needs review

Version

2.0

Component

Promotions

Created by

🇫🇷France solene_ggd

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

Comments & Activities

  • Issue created by @solene_ggd
  • Status changed to Needs review over 1 year ago
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.0 & MySQL 5.7
    last update over 1 year ago
    786 pass
  • 🇫🇷France solene_ggd

    Here is a patch that uses the cart manager in the PromotionOrderProcessor to remove the order item.
    I had to add the commerce_cart module dependency in some tests to not them to fail.

  • Status changed to Closed: won't fix over 1 year ago
  • 🇮🇱Israel jsacksick

    Unfortunately, I think I'm going to mark this as "won't fix" because we can't have the promotion module depend on commerce_cart...

  • Status changed to Active over 1 year ago
  • 🇫🇷France solene_ggd

    Thank you for your reply :)

    I still think we can do something because it really breaks some commerce_cart features.
    Isn't it possible to check if the 'commerce_cart' module exists (with the module handler) in the PromotionOrderProcessor to use removeOrderItem() ? And if we don't use dependency injection to inject the cart manager, it won't break any tests.
    If you say it's a good idea, I'll make another patch.

  • 🇮🇱Israel jsacksick

    I'm not sure this is the right approach as to me this event means "The customer removed an item from its cart" and this is an automatic programmatic removal which has a different meaning.

  • 🇫🇷France solene_ggd

    When you say "this event", do you talk about the CART_EMPTY event or the CART_ORDER_ITEM_REMOVE event also dispatch in removeOrderItem() ? If you talk about CART_ORDER_ITEM_REMOVE event, then I agree it should not be triggered for an order item removed automatically. And in this case, we could call only emptyCart() method instead of all the removeOrderItem() method. But if you talk about the CART_EMPTY event, I don't understand the problem because the cart is litteraly emptied by the user removing the "X" item.

    Moreover, I've just seen that CART_EMPTY is used in commerce_promotion to remove the coupons when the cart is empty as mentionned here : https://www.drupal.org/project/commerce/issues/3065951#comment-13178606
    I have tested it and indeed it doesn't work when the last item removed comes form a Buy X get Y promotion.

  • Status changed to Needs review over 1 year ago
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.0 & MySQL 5.7
    last update over 1 year ago
    786 pass
  • 🇫🇷France solene_ggd

    As I didn't get any answer, I made a new patch removing dependency to commerce_cart and calling only emptyCart() method when it's needed. I did not edit any test then.
    I put the issue in "Needs review" again but if @jsacksick you think it is still not a right approach, you can close it.
    I still post the patch for those who might need it.

  • Status changed to Closed: won't fix about 1 year ago
  • 🇮🇱Israel jsacksick

    I don't think the promotion module should worry about cart events... The "CART_EMPTY" event to me indicates a deliberate action from the customer emptying its cart... You could react to an order item being deleted in your custom code.

  • 🇫🇷France solene_ggd

    Thank's for your answer @jsacksick, I understand the problem in my patch.
    But something is bothering me, as you said :

    The "CART_EMPTY" event to me indicates a deliberate action from the customer emptying its cart

    This is exactly the issue here. When a customer removes the X item from his cart (the deliberate action), the Y item is removed too so the cart is empty but the CART_EMPTY event was not triggered at all. In this case, however, the empty cart comes from a deliberate action from the user. In my mind, it is a breaking issue in commerce_cart.

    If the problem won't be fixed, maybe we should write it somewhere in a documentation ?

    I will keep my patch for now but if anyone got a better idea, I'll be happy to hear it !

  • 🇮🇱Israel jsacksick

    We could maybe then optionally inject the cart manager or... maybe dispatch another event from the promotion module that the cart module reacts to.. none of the solutions are really "elegant". Optionally injecting the cart manager is better than skipping dependency injection though.

  • Status changed to Needs review about 1 year ago
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.0 & MySQL 5.7
    last update about 1 year ago
    773 pass, 2 fail
  • 🇫🇷France solene_ggd

    I think dispatch another event from the promotion module is a better option to avoid requiring commerce_cart.
    Here is a new patch that implements this solution.

  • Status changed to Needs work about 1 year ago
  • 🇫🇷France solene_ggd

    I did not realise that the new patch could failed some tests, I set the issue in Needs work while I fix this.

  • Status changed to Needs review about 1 year ago
  • Open in Jenkins → Open on Drupal.org →
    Core: 9.5.x + Environment: PHP 8.0 & MySQL 5.7
    last update about 1 year ago
    789 pass
  • 🇫🇷France solene_ggd

    Here is a new patch that should fix tests.

Production build 0.71.5 2024