19

Is there an event or place I can plugin for when a shopping cart price rule is no longer valid (such as when it expires or if you change the quantity of other products where it no longer applies)? I know that it is automatically removed from the cart, but I can't seem to find the place this is happening in the code.

I am writing a module that adds a free product to the cart for a coupon where the subtotal is more than X amount. It is all working except for when reducing the quantity of items in the cart where the subtotal goes below X. The coupon is getting removed, but my product is staying in the cart.

So far I've tapped into the following events to do what I need so far...

salesrule_validator_process
checkout_cart_update_items_after
sales_quote_collect_totals_before

I did find Magento\Quote\Model\CouponManagement which seemed promising since it has set() and remove() methods, but they don't appear to be getting called when the cart is updated.

In the checkout_cart_update_items_after it also seems like a logical place I can check, but it appears the rule is still set according to $cart->getQuote()->getAppliedRuleIds()


UPDATE: I ended up adding an observer for the checkout_cart_save_after event which runs after collectTotals() so knows if the rule is still on the cart or not. Then I basically compare $quote->getAppliedRuleIds() with $quote->getOrigData('applied_rule_ids') to see if the rule has been removed. I feel like there is a better way to do this, but it works for the moment. I still have the issue with coupons that expire though...

1
  • can you please explain in short, its very complex Jul 5, 2019 at 7:03

4 Answers 4

1

I would try to write an around plugin on the function \Magento\SalesRule\Model\Quote\Discount::collect

When the coupon is already set and the total in the cart do show discount amount and the coupon code, it is the totals that drive the content of the cart sidebar.

In this function, the discount description is reset (line 92) and then the discount total is evaluated after this.

We can see clearly the total eventually are update with a discountAmount and a discountDescription.. These 2 are perfect contender for you to trigger you logic that remove your product?

1

I would do it with an around plugin for

\Magento\SalesRule\Model\RulesApplier::applyRules

There you have $rules parameter which would be an array containing old applied rule ids, and result of $proceed() call will be an array of applied ids. Maybe a better place could be found if you disclose what you intend to do with it.

1

The first event you might want to try is salesrule_validator_process. This event is dispatched by the process() method of the Magento\SalesRule\Model\Validator class, which is responsible for applying shopping cart price rules to a quote. The event is dispatched each time a shopping cart price rule is validated, so you could use it to check whether the current rule is still valid for the quote, and remove your free product if it is not.

Another event you might want to try is checkout_cart_save_after. This event is dispatched each time a quote is saved, which can happen whenever the cart is updated. You could use this event to check whether the quote still meets the requirements for your free product, and remove it if it does not.

In terms of the code you're currently working with, it's possible that the sales_quote_collect_totals_before event is firing too early in the quote calculation process to accurately reflect whether the shopping cart price rule is still valid. Similarly, the checkout_cart_update_items_after event might be firing too late to remove your free product when the cart no longer meets the requirements for it. The Magento\Quote\Model\CouponManagement class is not directly involved in the calculation of shopping cart price rules, so it's unlikely to be helpful in this case.

I hope that helps!

1

The salesrule_validator_process event that you mentioned is a good start. You can observe this event and check if the applied rule is still valid. You may need to inspect the coupon code and its associated rule to determine if it has expired. If it has expired, you can take appropriate actions, such as removing the associated free product

Implement custom validation logic to check the expiration of coupons. You can create an observer for the salesrule_validator_process event and add your logic to validate the coupon code. If the coupon has expired, you can remove the associated product.

class CustomModule implements ObserverInterface
{
    public function execute(Observer $observer)
    {
        $quote = $observer->getEvent()->getQuote();
        $couponCode = $quote->getCouponCode();

        // Implement your custom logic to check if the coupon has expired
        if ($this->isCouponExpired($couponCode)) {
            // Perform actions like removing associated products
            // $this->removeAssociatedProducts($quote);
        }
    }

    private function isCouponExpired($couponCode)
    {
        // Your logic to check coupon expiration
    }
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.