Magento 2 How To Set Custom Discount Or Fee At Cart

If you want to set custom discount or fee at cart level in Magento 2, you can use the following code. It is common if you set a discount, you have to subtract the discount amount from the cart price and if you want to set custom fee on cart price, then you can add it.

Step 1 :

First you have to create a sales.xml file on app/code/Magemeta/Cartfee/etc

<?xml version="1.0"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Sales:etc/sales.xsd">
    <section name="quote">
        <group name="totals">
            <item name="customdiscount" instance="Magemeta\Cartfee\Model\Quote\Address\Total\CustomDiscount" sort_order="400"/>
        </group>
    </section>
</config>

Step 2 :

Create the file CustomDiscount.php on this path app\code\Magemeta\Cartfee\Model\Quote\Address\Total

namespace Magemeta\Cartfee\Model\Quote\Address\Total;
 
class CustomDiscount extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal
{
 
    /**
    * @var \Magento\Framework\Pricing\PriceCurrencyInterface
    */
    protected $priceCurrency;
 
    /**
     * @param \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency [description]
     */
    public function __construct(
        \Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency
    ) {
        $this->priceCurrency = $priceCurrency;
    }
 
    public function collect(
        \Magento\Quote\Model\Quote $quote,
        \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment,
        \Magento\Quote\Model\Quote\Address\Total $total
    ) {
         parent::collect($quote, $shippingAssignment, $total);
 
         $customDiscount = -10; 
         $total->addTotalAmount('customdiscount', $customDiscount);
         $total->addBaseTotalAmount('customdiscount', $customDiscount);
         $quote->setCustomDiscount($customDiscount);
         return $this;
    }
 
    /**
     * Assign subtotal amount and label to address object
     *
     * @param \Magento\Quote\Model\Quote $quote
     * @param Address\Total $total
     * @return array
     * @SuppressWarnings(PHPMD.UnusedFormalParameter)
     */
    public function fetch(\Magento\Quote\Model\Quote $quote, \Magento\Quote\Model\Quote\Address\Total $total)
    {
        return [
            'code' => 'Custom_Discount',
            'title' => $this->getLabel(),
            'value' => 10
        ];
    }
 
    /**
     * get label
     * @return string
     */
    public function getLabel()
    {
        return __('Custom Discount');
    }
}

Step 3 :

Create file checkout_cart_index.xml on path app\code\Magemeta\Cartfee\view\frontend\layout

<?xml version="1.0"?>
<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" 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="customdiscount" xsi:type="array">
		         <item name="component" xsi:type="string">Magemeta_Cartfee/js/view/checkout/summary/custom-discount</item>
		             <item name="sortOrder" xsi:type="string">20</item>
		                 <item name="config" xsi:type="array"
		                   <item name="customdiscount" xsi:type="string" translate="true">Custom Discount</item>
		                         </item>
		                      </item>
		                  </item>
		             </item>
		        </item>
		  </argument>
	    </arguments>
	</referenceBlock>
    </body>
</page>

Step 4 :

Create another file on same location.

<page xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" layout="1column" 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="customdiscount" xsi:type="array">
                                                            <item name="component"  xsi:type="string">Magemeta_Cartfee/js/view/checkout/cart/totals/custom-discount</item>
                                                            <item name="sortOrder" xsi:type="string">20</item>
                                                            <item name="config" xsi:type="array">
                                                                 <item name="template" xsi:type="string">Magemeta_Cartfee/checkout/cart/totals/custom-discount</item>
                                                                <item name="title" xsi:type="string" translate="true">Custom Discount</item>
                                                            </item>
                                                        </item>
                                                    </item>
                                                </item>
                                                <item name="cart_items" xsi:type="array">
                                                    <item name="children" xsi:type="array">
                                                        <item name="details" xsi:type="array">
                                                            <item name="children" xsi:type="array">
                                                                <item name="subtotal" xsi:type="array">
                                                                    <item name="component" xsi:type="string">Magento_Tax/js/view/checkout/summary/item/details/subtotal</item>
                                                                </item>
                                                            </item>
                                                        </item>
                                                    </item>
                                                </item>
                                            </item>
                                        </item>
                                    </item>
                                </item>
                            </item>
                        </item>
                    </item>
                </argument>
            </arguments>
        </referenceBlock>
    </body

Step 5 :

Create a file custom-discount.js on path app/code/Magemeta/Cartfee/view/frontend/web/js/view/checkout/cart/totals

define(
    [
        'Magemeta_Cartfee/js/view/checkout/summary/custom-discount'
    ],
    function (Component) {
        'use strict';
 
        return Component.extend({
 
            /**
             * @override
             */
            isDisplayed: function () {
                return true;
            }
        });
    }
);

Step 6 :

Create a file on this path custom-discount.js app/code/Magemeta/Cartfee/view/frontend/web/js/view/checkout/summary

define(
    [
       'jquery',
       'Magento_Checkout/js/view/summary/abstract-total',
       'Magento_Checkout/js/model/quote',
       'Magento_Checkout/js/model/totals',
       'Magento_Catalog/js/price-utils'
    ],
    function ($,Component,quote,totals,priceUtils) {
        "use strict";
        return Component.extend({
            defaults: {
                template: 'Magemeta_Cartfee/checkout/summary/custom-discount'
            },
            totals: quote.getTotals(),
            isDisplayedCustomdiscountTotal : function () {
                return true;
            },
            getCustomdiscountTotal : function () {
                var price = 10;
                return this.getFormattedPrice(price);
            }
         });
    }
)

Step 7 :

Create a file custom-discount.html on path app/code/Magemeta/Cartfee/view/frontend/web/template/checkout/cart/totals

<!-- if: isDisplayedCustomdiscountTotal() -->
<tr class="totals customdiscount excl">
    <th class="mark" colspan="1" scope="row" data-bind="text: title"></th>
    <td class="amount">
        <span class="price" data-bind="text: getCustomdiscountTotal()"></span>
    </td>
</tr>
<!-- /if -->

Step 8 :

Create a file custom-discount.html on path app/code/Magemeta/Cartfee/view/frontend/web/template/checkout/summary

<!-- if: isDisplayedCustomdiscountTotal() -->
<tr class="totals coupon-discount excl">
   <th class="mark" colspan="1" scope="row" data-bind="text: customdiscount"></th>
   <td class="amount">
       <span class="price" data-bind="text: getCustomdiscountTotal(), attr: {'data-th': customdiscount}"></span>
   </td>
</tr>
<!-- /if -->

Now you can see the custom discount amount on your cart and checkout page.

Leave a Reply