Apply discount from checkout second page/tab
-
02-10-2020 - |
Question
I am using Magento 2 enterprise edition (2.0.6)
I want to apply discount on sub total, Discount is applied from cart page (added a button on cart which applies the discount) and then if I go to checkout discount is visible there.
Now I am trying to add button on checkout second page to apply discount. The discount is applied but the order summary is not updated. If I click on button (checkout page) and goto payment express, it shows the discounted amount.
even if i goto cart page after applying discount on checkout it is visible on cart and then visible on checkout also.
I took reference from how to add fee to order totals in magento2 to apply discount
Below is my code
[Namespace]/[ModuleName]/etc/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="custom" instance="[Namespace]\[ModuleName]\Model\Total\Quote\Custom" sort_order="420">
</item>
</group>
</section>
</config>
I created Model under [Namespace]/[ModuleName]/Model/Total/Quote/Custom.php
namespace [Namespace]\[ModuleName]\Model\Total\Quote;
class Custom extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal
{
protected $_priceCurrency;
public function __construct(
\Magento\Framework\Pricing\PriceCurrencyInterface $priceCurrency,
\Magento\Checkout\Model\Session $checkoutSession,
\[Namespace]/[ModuleName]\Helper\Data $helper
){
$this->_priceCurrency = $priceCurrency;
$this->checkoutSession = $checkoutSession;
$this->helper = $helper;
}
public function getDiscountAmount()
{
return $this->helper->getDiscountAmount();
}
/**
* @param \Magento\Quote\Model\Quote $quote
* @param \Magento\Quote\Api\Data\ShippingAssignmentInterface $shippingAssignment
* @param \Magento\Quote\Model\Quote\Address\Total $total
* @return $this|bool
*/
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);
$address = $shippingAssignment->getShipping()->getAddress();
$label = 'My Custom Discount';
$discountAmount = -self::getDiscountAmount();
$appliedCartDiscount = 0;
if ($address->getAddressType() == 'shipping')
{
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;
}
}
Solution
I got the solution,
below is the explanation of process to approach the result. Please modify accordingly.
Actually the methodology that i followed works perfect for cart page Model file [Namespace]/[ModuleName]/Model/Total/Quote/Custom.php
is not called on checkout process, On checkout need to follow the default Magento mechanism using webapi.xml
I followed the process of reward module in enterprise edition
[Namespace]/[ModuleName]/etc/webapi.xml
<?xml version="1.0"?>
<routes xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Webapi:etc/webapi.xsd">
<route url="/V1/rewardpoints/mine/use-reward" method="POST">
<service class="[Namespace]\[ModuleName]\Api\RewardManagementInterface" method="set"/>
<resources>
<resource ref="self" />
</resources>
<data>
<parameter name="cartId" force="true">%cart_id%</parameter>
</data>
</route>
</routes>
[Namespace]/[ModuleName]/Api/RewardManagementInterface.php
<?php
namespace Namespace]\[ModuleName]\Api;
interface RewardManagementInterface
{
public function set($cartId);
}
create model to extend this interface and have the functionality in the function set($cartId)
as below
public function __construct(
\Magento\Quote\Api\CartRepositoryInterface $quoteRepository,
\[Namespace]\[ModuleName]\Helper\Data $helper,
\[Namespace]\[ModuleName]\Model\PaymentDataImporter $importer
) {
$this->quoteRepository = $quoteRepository;
$this->helper = $helper;
$this->importer = $importer;
}
/**
* {@inheritdoc}
*/
public function set($cartId)
{
if ($this->helper->getEnabled())
{
/* @var $quote \Magento\Quote\Model\Quote */
$quote = $this->quoteRepository->getActive($cartId);
$this->importer->import($quote, $quote->getPayment(), true);
$quote->collectTotals();
$this->quoteRepository->save($quote);
return true;
}
return false;
}
create another model PaymentDataImporter which will actually apply discount on checkout process
public function __construct(
\[Namespace]\[ModuleName]\Helper\Data $helper,
\Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
) {
$this->_scopeConfig = $scopeConfig;
$this->helper = $helper;
}
public function import($quote, $payment, $useRewardPoints)
{
$discount = $this->helper->getDiscountAmount();
$quote->getBaseGrandTotal()-$discount;
return $this;
}
most important your js action should give call to this webapi stuff
storage.post(
urlBuilder.createUrl('/modulename/mine/use-reward', {}), {}
)