7

I am trying to understand the working of discount coupon codes on the checkout page.

When we apply any coupon code, then the discount is added to cart without reloading the page.

I have checked and found some below points:

  • "discount" totals segment is added by Magento_SalesRule module.

When we apply any coupon code then, using vendor\magento\module-sales-rule\view\frontend\web\js\action\set-coupon-code.js, an ajax request is send to rest/default/V1/carts/mine/coupons/:coupon.

Code from vendor\magento\module-sales-rule\view\frontend\web\js\action\set-coupon-code.js :

 return storage.put(
            url,
            {},
            false
        ).done(function (response) {
            var deferred;

            if (response) {
                deferred = $.Deferred();

                isApplied(true);
                totals.isLoading(true);
                getPaymentInformationAction(deferred);
                $.when(deferred).done(function () 
                {
                    fullScreenLoader.stopLoader();
                    totals.isLoading(false);
                });
                messageContainer.addSuccessMessage({
                    'message': message
                });
            }
        }).fail(function (response) {
            fullScreenLoader.stopLoader();
            totals.isLoading(false);
            errorProcessor.process(response, messageContainer);
        });
  • After the above ajax call, Summary total section gets refresh and Discount appears in it below image.

apply coupon

  • When we click on the cancel coupon button then code from vendor\magento\module-sales-rule\view\frontend\web\js\action\cancel-coupon.js runs and "Discount" disappears from the summary total section.

enter image description here

How does the total_segments add or remove "discount"?

2
  • What is your requirement? Commented Apr 19, 2018 at 12:57
  • Hi @SureshChikani, I wanted to add custom fee to total_segments like a discount.
    – vedu
    Commented Apr 20, 2018 at 4:20

1 Answer 1

6
+50

1) For customer account: /V1/carts/mine/coupons/:couponCode

I just explain how sale rules work for customer logged

a) Set coupon:

vendor/magento/module-quote/etc/webapi.xml

<route url="/V1/carts/mine/coupons/:couponCode" method="PUT">
    <service class="Magento\Quote\Api\CouponManagementInterface" method="set"/>
    <resources>
        <resource ref="Magento_Cart::manage" />
    </resources>
</route>

So, the service class interface class Magento\Quote\Api\CouponManagementInterface::set() will be used and Magento\Quote\Model\CouponManagement::set will be called.

$quote->setCouponCode($couponCode);
$this->quoteRepository->save($quote->collectTotals());

When quote collects totals: $quote->collectTotals()

\Magento\SalesRule\Model\Quote\Discount::collect() will be called. It will calculate the coupon logic here.

b) Remove coupon:

vendor/magento/module-quote/etc/webapi.xml

<route url="/V1/carts/mine/coupons" method="DELETE">
    <service class="Magento\Quote\Api\CouponManagementInterface" method="remove"/>
    <resources>
        <resource ref="self" />
    </resources>
    <data>
        <parameter name="cartId" force="true">%cart_id%</parameter>
    </data>
</route>

Magento\Quote\Model\CouponManagement::remove() will be called.

c) Total Segment: V1/carts/mine/payment-information

vendor/magento/module-checkout/etc/webapi.xml

<route url="/V1/carts/mine/payment-information" method="GET">
    <service class="Magento\Checkout\Api\PaymentInformationManagementInterface" method="getPaymentInformation"/>
    <resources>
        <resource ref="self" />
    </resources>
    <data>
        <parameter name="cartId" force="true">%cart_id%</parameter>
    </data>
</route>

vendor/magento/module-checkout/Model/PaymentInformationManagement.php

/**
 * {@inheritDoc}
 */
public function getPaymentInformation($cartId)
{
    ...
    $paymentDetails->setTotals($this->cartTotalsRepository->get($cartId));
    ...
}

\Magento\Quote\Model\Cart\CartTotalRepository::get()

 if ($quote->isVirtual()) {
        $addressTotalsData = $quote->getBillingAddress()->getData();
        $addressTotals = $quote->getBillingAddress()->getTotals();
    } else {
        $addressTotalsData = $quote->getShippingAddress()->getData();
        $addressTotals = $quote->getShippingAddress()->getTotals();
    }
......

$calculatedTotals = $this->totalsConverter->process($addressTotals);
$quoteTotals->setTotalSegments($calculatedTotals);

This will get the totals data and set the total segments.

\Magento\Quote\Model\Quote\TotalsReader::fetch()

foreach ($this->collectorList->getCollectors($quote->getStoreId()) as $reader) {
        $data = $reader->fetch($quote, $total);

2) For guest account, we can see the apis:

vendor/magento/module-quote/etc/webapi.xml

<!-- Managing Guest Cart Coupons -->
<route url="/V1/guest-carts/:cartId/coupons" method="GET">
    <service class="Magento\Quote\Api\GuestCouponManagementInterface" method="get"/>
    <resources>
        <resource ref="anonymous" />
    </resources>
</route>
<route url="/V1/guest-carts/:cartId/coupons/:couponCode" method="PUT">
    <service class="Magento\Quote\Api\GuestCouponManagementInterface" method="set"/>
    <resources>
        <resource ref="anonymous" />
    </resources>
</route>
<route url="/V1/guest-carts/:cartId/coupons" method="DELETE">
    <service class="Magento\Quote\Api\GuestCouponManagementInterface" method="remove"/>
    <resources>
        <resource ref="anonymous" />
    </resources>
</route>
3
  • 1
    Thank you for the answer. I wanted to add a custom fee to total_segments like discount, \Magento\Quote\Model\Quote\TotalsReader::fetch() this line helped me.
    – vedu
    Commented Apr 20, 2018 at 5:19
  • @Khoa TruongDinh, can you please help here magento.stackexchange.com/questions/296379/… Commented Nov 21, 2019 at 7:20
  • How is error message shown when the coupon code is invalid?
    – Toji
    Commented Sep 8, 2020 at 14:51

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.