August 22, 2023

Magento 2 : Add Custom Discount Programmatically

How we add custom discount programmatically in Magento 2 ?

Custom Discount in Magento 2

Welcome to our latest Magento 2 tutorial! In the competitive landscape of e-commerce, offering discounts has proven to be a potent strategy for attracting customers and boosting sales. But what if you could take it a step further and create tailored discounts that cater to specific customer segments or behaviors? That’s where the power of custom discounts comes in.

In this comprehensive guide, we will walk you through the process of adding custom discounts to your Magento 2 store. Whether you’re a seasoned e-commerce veteran or just starting out, you’ll discover how to leverage Magento 2’s flexibility to create personalized discount offers that resonate with your customers and drive conversions.

To create a custom discount programatically in Magento 2, you can follow these steps:

Steps 1 : app/code/vendor/module/etc/sales.xml
Steps 2 : app/code/vendor/module/Model/Quote/Address/Total/CustomDiscount.php
Steps 3 : app/code/vendor/module/view/frontend/layout/checkout_cart_index.xml
Steps 4 : app/code/vendor/module/view/frontend/layout/checkout_index_index.xml
Steps 5 : app/code/vendor/module/view/frontend/web/js/view/checkout/cart/totals/custom-discount.js
Steps 6 : app/code/vendor/module/view/frontend/web/js/view/checkout/summary/custom-discount.js
Steps 7 : app/code/vendor/module/view/frontend/web/template/checkout/cart/totals/custom-discount.html
Steps 8 : app/code/vendor/module/view/frontend/web/template/checkout/summary/custom-discount.html

sales.xml
				
					<?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="vendor\module\Model\Quote\Address\Total\CustomDiscount" sort_order="100"/>
        </group>
    </section>
</config>
				
			
CustomDiscount.php
				
					namespace vendor\module\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);

           $baseDiscount = 10;
           $discount =  $this->_priceCurrency->convert($baseDiscount);
           $total->addTotalAmount('customdiscount', -$discount);
           $total->addBaseTotalAmount('customdiscount', -$baseDiscount);
           $total->setBaseGrandTotal($total->getBaseGrandTotal() - $baseDiscount);
           $quote->setCustomDiscount(-$discount);

        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');
    }
}
				
			
checkout_cart_index.xml
				
					<?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">vendor_module/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>
				
			
checkout_index_index.xml
				
					<?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.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">vendor_module/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">vendor_module/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>
</page>
				
			
custom-discount.js
				
					define(
    [
        'vendor_module/js/view/checkout/summary/custom-discount'
    ],
    function (Component) {
        'use strict';

        return Component.extend({

            /**
             * @override
             */
            isDisplayed: function () {
                return true;
            }
        });
    }
);
				
			
custom-discount.js
				
					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: 'vendor_module/checkout/summary/custom-discount'
            },
            totals: quote.getTotals(),
            isDisplayedCustomdiscountTotal : function () {
                return true;
            },
            getCustomdiscountTotal : function () {
                var price = 10;
                return this.getFormattedPrice(price);
            }
         });
    }
);
				
			
custom-discount.html
				
					<!-- ko 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>
<!-- /ko -->
				
			
custom-discount.html
				
					<!-- ko 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>
<!-- /ko -->
				
			

Note*:
– We have used the static discount price for the custom discount. 
– We have use the backward slash(\) for the namespace and forward slash (/) for the directory path.
– If you want to use the dynamic “custom discount price” instead of static, you can create the system configuration file & get their values in the model file to set/calculate the discount and also use this reference to apply config value in js.

 

Author

Share this post:
Facebook
Twitter
LinkedIn
WhatsApp

Discover more articles