Magento2 How to Discount Description add on Checkout order summary
-
15-03-2021 - |
Question
I Want to add Coupon Description in Order Summary
I have to Find the file here
app/design/frontend/[VendorName]/[theme]/Magento_SalesRule/web/template/cart/totals/discount.html
<!-- ko if: isDisplayed() -->
<tr class="totals discount">
<th class="mark" scope="row">
<span class="title" data-bind="text: getTitle()"></span>
<span class="discount coupon" data-bind="text: getCouponCode()"></span>
</th>
<td class="amount">
<span class="price" data-bind="text: getValue(), attr: {'data-th': name}"></span>
</td>
</tr>
<!-- /ko -->
Here Hoe can I get Coupon Description
Note: I have added coupon description in Backend.
Solution
Take a look at Magento default:
vendor/magento/module-sales-rule/Plugin/CartTotalRepository.php
As we can see, coupon_label
is an extension attribute.
So, we can follow this rule. Create our coupon description extension attribute.
app/code/Vendor/Quote/etc/extension_attributes.xml
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Quote\Api\Data\TotalsInterface">
<attribute code="coupon_description" type="string" />
</extension_attributes>
</config>
app/code/Vendor/Quote/etc/di.xml
<?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\Cart\CartTotalRepository">
<plugin name="coupon_description_plugin" type="Vendor\Quote\Plugin\CartTotalRepository" />
</type>
</config>
app/code/Vendor/Quote/Plugin/CartTotalRepository.php
<?php declare(strict_types=1);
namespace Vendor\Quote\Plugin;
use Magento\Quote\Api\Data\TotalsExtensionFactory;
use Magento\Quote\Api\Data\TotalsInterface;
use Magento\SalesRule\Api\RuleRepositoryInterface;
use Magento\SalesRule\Model\Coupon;
/**
* Class CartTotalRepository
* @package Magento\SalesRule\Plugin
*/
class CartTotalRepository
{
/**
* @var TotalsExtensionFactory
*/
private $extensionFactory;
/**
* @var RuleRepositoryInterface
*/
private $ruleRepository;
/**
* @var Coupon
*/
private $coupon;
/**
* CartTotalRepository constructor.
* @param TotalsExtensionFactory $extensionFactory
* @param RuleRepositoryInterface $ruleRepository
* @param Coupon $coupon
*/
public function __construct(
TotalsExtensionFactory $extensionFactory,
RuleRepositoryInterface $ruleRepository,
Coupon $coupon
) {
$this->extensionFactory = $extensionFactory;
$this->ruleRepository = $ruleRepository;
$this->coupon = $coupon;
}
/**
* @param \Magento\Quote\Model\Cart\CartTotalRepository $subject
* @param TotalsInterface $result
* @return TotalsInterface
*
* @throws \Magento\Framework\Exception\LocalizedException
* @throws \Magento\Framework\Exception\NoSuchEntityException
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
*/
public function afterGet(
\Magento\Quote\Model\Cart\CartTotalRepository $subject,
TotalsInterface $result
) {
if ($result->getExtensionAttributes() === null) {
$extensionAttributes = $this->extensionFactory->create();
$result->setExtensionAttributes($extensionAttributes);
}
$extensionAttributes = $result->getExtensionAttributes();
$couponCode = $result->getCouponCode();
if (empty($couponCode)) {
return $result;
}
$this->coupon->loadByCode($couponCode);
$ruleId = $this->coupon->getRuleId();
if (empty($ruleId)) {
return $result;
}
$rule = $this->ruleRepository->getById($ruleId);
$extensionAttributes->setCouponDescription($rule->getDescription());
$result->setExtensionAttributes($extensionAttributes);
return $result;
}
}
Check window.checkoutConfig.totalsData
in browser console:
Frontend Part:
We will use our custom js component and templates
app/code/Vendor/Quote/view/frontend/layout/checkout_cart_index.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="checkout.cart.totals">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="block-totals" xsi:type="array">
<item name="children" xsi:type="array">
<item name="discount" xsi:type="array">
<item name="component" xsi:type="string">Vendor_Quote/js/view/cart/totals/discount</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>
app/code/Vendor/Quote/view/frontend/layout/checkout_index_index.xml
<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:View/Layout/etc/page_configuration.xsd">
<body>
<referenceBlock name="checkout.root">
<arguments>
<argument name="jsLayout" xsi:type="array">
<item name="components" xsi:type="array">
<item name="checkout" xsi:type="array">
<item name="children" xsi:type="array">
<item name="sidebar" xsi:type="array">
<item name="children" xsi:type="array">
<item name="summary" xsi:type="array">
<item name="children" xsi:type="array">
<item name="totals" xsi:type="array">
<item name="children" xsi:type="array">
<item name="discount" xsi:type="array">
<item name="component" xsi:type="string">Vendor_Quote/js/view/summary/discount</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>
app/code/Vendor/Quote/view/frontend/web/js/view/cart/totals/discount.js
define([
'Magento_SalesRule/js/view/summary/discount'
], function (Component) {
'use strict';
return Component.extend({
defaults: {
template: 'Vendor_Quote/cart/totals/discount'
},
getDescription: function() {
if (!this.totals()) {
return null;
}
if (typeof this.totals()['extension_attributes'] === 'undefined') return null;
return this.totals()['extension_attributes']['coupon_description'];
}
});
});
app/code/Vendor/Quote/view/frontend/web/js/view/summary/discount.js
define([
'Magento_SalesRule/js/view/summary/discount'
], function (Component) {
'use strict';
return Component.extend({
defaults: {
template: 'Vendor_Quote/cart/totals/discount'
},
getDescription: function() {
if (!this.totals()) {
return null;
}
if (typeof this.totals()['extension_attributes'] === 'undefined') return null;
return this.totals()['extension_attributes']['coupon_description'];
},
/**
* @override
*
* @returns {Boolean}
*/
isDisplayed: function () {
return this.getPureValue() != 0; //eslint-disable-line eqeqeq
}
});
});
app/code/Vendor/Quote/view/frontend/web/template/cart/totals/discount.html
<!-- ko if: isDisplayed() -->
<tr class="totals">
<th colspan="1" style="" class="mark" scope="row">
<span class="title" data-bind="text: getTitle()"></span>
<span class="discount coupon" data-bind="text: getCouponLabel()"></span>
<span class="discount description" data-bind="text: getDescription()"></span>
</th>
<td class="amount" data-bind="attr: {'data-th': title}">
<span><span class="price" data-bind="text: getValue()"></span></span>
</td>
</tr>
<!-- /ko -->
app/code/Vendor/Quote/view/frontend/web/template/summary/discount.html
<!-- ko if: isDisplayed() -->
<tr class="totals discount">
<th class="mark" scope="row">
<span class="title" data-bind="text: getTitle()"></span>
<span class="discount coupon" data-bind="text: getCouponCode()"></span>
<span class="discount description" data-bind="text: getDescription()"></span>
</th>
<td class="amount">
<span class="price" data-bind="text: getValue(), attr: {'data-th': name}"></span>
</td>
</tr>
<!-- /ko -->
Result:
OTHER TIPS
You can override
app/design/frontend/[VendorName]/[theme]/Magento_SalesRule/web/template/cart/totals/discount.html and add below code
<span class="description" data-bind="text: getCouponDescription()"></span>
in your theme and also override below js as well
app/design/frontend/[VendorName]/[theme]/Magento_SalesRule/js/view/summary/discount.js
add function like getCouponDescription and add below code
getCouponCode: function () { if (!this.totals()) { return null; }
return this.totals()['coupon_description'];
},
add extension attribute in your quote api for coupon_description
<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Api/etc/extension_attributes.xsd">
<extension_attributes for="Magento\Quote\Api\Data\CartInterface">
<attribute code="coupon_description" type="string" />
</extension_attributes>
</config>
and create plugin
$extensionAttributes = $cart->getExtensionAttributes();
$quoteId = $cart->getId();
$couponDescription = "Your coupon descriptin code"
$extensionAttributes->setCouponDescription($couponDescription);
$cart->setExtensionAttributes($extensionAttributes);
Hope it should works
The quickest way is to override the SalesRule module's template and JS.
This is how I did it on several of my shops:
In you theme folder create
Magento_SalesRule/web/template/cart/totals/discount.html
<!-- ko if: isDisplayed() -->
<tr class="totals">
<th colspan="1" style="" class="mark" scope="row">
<span class="title" data-bind="text: getDiscountLabel()"></span>
<span class="discount coupon" data-bind="text: getCouponLabel()"></span>
</th>
<td class="amount" data-bind="attr: {'data-th': title}">
<span><span class="price" data-bind="text: getValue()"></span></span>
</td>
</tr>
<!-- /ko -->
Magento_SalesRule/web/js/view/summary/discount.js
define([
'Magento_Checkout/js/view/summary/abstract-total',
'Magento_Checkout/js/model/quote'
], function (Component, quote) {
'use strict';
return Component.extend({
defaults: {
template: 'Magento_SalesRule/summary/discount'
},
totals: quote.getTotals(),
/**
* @return {*|Boolean}
*/
isDisplayed: function () {
return this.isFullMode() && this.getPureValue() != 0; //eslint-disable-line eqeqeq
},
/**
* @return {*}
*/
getCouponCode: function () {
if (!this.totals()) {
return null;
}
return this.totals()['coupon_code'];
},
/**
* @return {*}
*/
getCouponLabel: function () {
if (!this.totals()) {
return null;
}
return this.totals()['coupon_label'];
},
/**
* @return {*}
*/
getDiscountLabel: function () {
if (!this.totals()) {
return null;
}
return this.totals()['total_segments'][2]['title'];
},
/**
* @return {Number}
*/
getPureValue: function () {
var price = 0;
if (this.totals() && this.totals()['discount_amount']) {
price = parseFloat(this.totals()['discount_amount']);
}
return price;
},
/**
* @return {*|String}
*/
getValue: function () {
return this.getFormattedPrice(this.getPureValue());
}
});
});
Make sure to flush the static files cache and Magento's cache afterwards.
You should then be able to see the label (description) of the discount.