Magento 2: How to add custom discount in cart programmatically?

Refer to how Magento2 applies sales-rule discounts. I applied similar approach to apply custom discount, by creating following files in my module:

Namespace_Module\etc\sales.xml
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Sales:etc/sales.xsd">
<!--
/**
* @author Reena Parekh <reena1.parekh@gmail.com>
*/
-->
<section name="quote">
<group name="totals">
<item name="testdiscount" instance="Namespace\Module\Model\Quote\Discount" sort_order="500"/>
</group>
</section>
</config>
view raw sales.xml hosted with ❤ by GitHub


Namespace_Module\Model\Quote\Discount.php

<?php
/**
* @author Reena Parekh <reena1.parekh@gmail.com>
*/
namespace Namespace\Module\Model\Quote;
/**
* Discount totals calculation model.
*/
class Discount
{
/**
* @param \Magento\Quote\Model\Quote $quote
* @param \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment
* @param \Magento\Quote\Model\Quote\Address\Total $total
*
* @return $this
*/
public function collect(
\Magento\Quote\Model\Quote $quote,
\Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment,
\Magento\Quote\Model\Quote\Address\Total $total
) {
//Fix for discount applied twice
$items = $shippingAssignment->getItems();
if (!count($items)) {
return $this;
}
parent::collect($quote, $shippingAssignment, $total);
$label = __('My Custom Discount');
$discountAmount = -10; //You can change your amount here
$appliedCartDiscount = 0;
if($total->getDiscountDescription()) {
// If a discount exists in cart and another discount is applied, the add both discounts.
$appliedCartDiscount = $total->getDiscountAmount();
$discountAmount = $total->getDiscountAmount()+$discountAmount;
$label = $total->getDiscountDescription().', '.$label;
}
$total->setDiscountDescription($label);
$total->setDiscountAmount($discountAmount);
$total->setBaseDiscountAmount($discountAmount);
$total->setSubtotalWithDiscount($total->getSubtotal() + $discountAmount);
$total->setBaseSubtotalWithDiscount($total->getBaseSubtotal() + $discountAmount);
if(isset($appliedCartDiscount)) {
$total->addTotalAmount($this->getCode(), $discountAmount - $appliedCartDiscount);
$total->addBaseTotalAmount($this->getCode(), $discountAmount - $appliedCartDiscount);
} else {
$total->addTotalAmount($this->getCode(), $discountAmount);
$total->addBaseTotalAmount($this->getCode(), $discountAmount);
}
return $this;
}
}
view raw Discount.php hosted with ❤ by GitHub


Namespace_Module\view\frontend\layout\checkout_cart_index.xml

<?xml version="1.0"?>
<!--
/**
* @author Reena Parekh <reena1.parekh@gmail.com>
*/
-->
<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="before_grandtotal" xsi:type="array">
<item name="children" xsi:type="array">
<item name="testdiscount" xsi:type="array">
<item name="config" xsi:type="array">
<item name="title" xsi:type="string" translate="true">My Discount</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>


Namespace_Module\view\frontend\layout\checkout_index_index.xml

<?xml version="1.0"?>
<!--
/**
* @author Reena Parekh <reena1.parekh@gmail.com>
*/
-->
<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="testdiscount" xsi:type="array">
<item name="config" xsi:type="array">
<item name="title" xsi:type="string" translate="true">My Discount</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</item>
</argument>
</arguments>
</referenceBlock>
</body>
</page>


If Fetch is not showing the custom discount description, it was a core magento bug, see this ticket for patch details: https://github.com/magento/magento2/issues/3594

Comments

Popular posts from this blog

SEO for your Press Releases [Updated 2025 list]

XDebug - PHPStorm - Mac: How to configure Xdebug with PHPStorm on Mac OS and PHP 7.3