Magento – Magento 2 – There is an event or method to “plug-in” when the coupon is removed from the cart/quote in the checkout flow

couponevent-observermagento-2.0.4magento2shopping-cart-price-rules

Looking at events.xml of Magento_SalesRule there are two events,

<event name="sales_order_place_after">
    <observer name="salesrule" instance="Magento\SalesRule\Observer\SalesOrderAfterPlaceObserver" />
</event>
<event name="sales_model_service_quote_submit_before">
    <observer name="salesrule" instance="Magento\SalesRule\Observer\AddSalesRuleNameToOrderObserver" />
</event>

but none looks like the one i need. I needed the same for when adding a coupon but i managed to do something if "pluggin in" the canProcessRule method of Magento\SalesRule\Model\Utility but i cant find something similar for when the coupon is removed

Theese operations like add and remove a coupon are made only in JS? There is a controller that process this?

Looking at checkout_index_index.xml layout it pass an item argument Magento_SalesRule/js/view/payment/discount which then loads theese two js

Magento_SalesRule/js/action/set-coupon-code
Magento_SalesRule/js/action/cancel-coupon

That by the name itself looks pretty straightforward, one to add and one to remove the coupon

In the cancel-coupon JS doing a console.log to url return:

rest/default/V1/guest-carts/21229ffad7bf01311b645a4423a4ae22/coupons

This is using rest web services? (Kind of same url for when adding a coupon)

There is a way to know when a coupon is removed from the quote/cart?

Best Answer

Yes there is.

The event you're looking for is controller_action_predispatch_checkout_cart_couponPost

This is generic event that is dispatched before the action class that adds/removes the coupon is called.

As this is the same event for both add and remove you can add the following code at the top of your observer method to check if this is a remove action:

$controller = $observer->getControllerAction();
$remove = $controller->getRequest()->getParam('remove');

if ($remove) {
    // This is a remove action
} else {
    // This is an add action
    $coupon = $controller->getRequest()->getParam('coupon_code');
}

However, when you add a coupon from the checkout flow it won't work as it directly calls the API and there are no events in Magento 2 web APIs

The solution is to use a plugin on Magento\Quote\Model\CouponManagement on the set method:

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
    <type name="Magento\Quote\Model\CouponManagement">
        <plugin name="checkout_coupon_apply"
                type="Vendor\Module\Plugin\CheckoutCouponApply"/>
    </type>
</config>

Then your plugin class:

<?php 

namespace Vendor\Module\Plugin;

use Magento\Quote\Model\CouponManagement;

class CheckoutCouponApply {

    public function beforeSet(CouponManagement $subject, $cartId, $couponCode)
    {
         // Do what you need to do
    }
}
Related Topic