I'm trying to add custom discount amount on quote to specific product line, I saw event sales_quote_address_discount_item, when I use it like that :

    $item = $observer->getData('item');

In database (quote_item) I can see that column 'discount_amount' and 'base_discount_amount' contains my amount, but nothing on quote table and on quote_address.

How can I apply from code a custom discount on one specific product in quote ?

  • What event are you hooking onto? I've had success using sales_quote_item_set_product May 30 '18 at 10:16
  • hi @dharth, have you got the correct answer for this? Aug 1 '19 at 12:43

We are saving custom discount on line item level i.e in quote_item table

Please follow the below steps:

  1. Create sales.xml file in your custom module inside etc directory

    <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="[VendorName]\[Namespace]\Model\Quote\Address\Total\Discount" sort_order="500"/>
  2. create discount.php in [VendorName]/[Namespace]/Model/Quote/Address/Total

Note : This is not the complete code but it will help you to save the custom discount on item level.

    namespace [VendorName]\[Namespace]\Model\Quote\Address\Total;

    use Magento\Catalog\Model\ProductRepository;

    class Discount extends \Magento\Quote\Model\Quote\Address\Total\AbstractTotal

/** @var $_productRepository */
protected $_productRepository;

 * Discount constructor.
 * @param ProductRepository $productRepository
public function __construct(
    ProductRepository $productRepository

) {
    $this->_productRepository = $productRepository;


 * Collect address discount amount
 * @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
) {
    $data = $quote->getItems();
    if (!count($data)) {
        return $this;
    parent::collect($quote, $shippingAssignment, $total);

        /** Custom Discount is saved in line item level (i.e in quote_item) */
        foreach ($data as $item) {
            if ($item['has_children']) {
                $product = $this->_productRepository->get($item['sku']);
            } else {
                $product = $this->_productRepository->getById($item['product_id']);


  • I tried but problem is still the same, values are ok on item but not on total. On table quote the grand_total, subtotal_with_discount doesn't take discount
    – dharth
    May 30 '18 at 14:20
  • Maybe I need to add my values to the total like that : $total->addTotalAmount() ?
    – dharth
    May 30 '18 at 14:23
  • @dharth yes you have to set the values in $total. Here is an example : $discountAmount = [customDiscountTotal]; $total->setDiscountAmount([customDiscountTotal]); $total->setBaseDiscountAmount([customDiscountTotal]); $total->setTaxAmount([customTaxTotal]); $total->setBaseTaxAmount([customTaxTotal]); $total->addTotalAmount($this->getCode(), $discountAmount); $total->addBaseTotalAmount($this->getCode(), $discountAmount); Note : customDiscountTotal is sum of custom discount amount applied to each product in cart . Jun 5 '18 at 13:35
  • @RenuMishra can we use $quote->collectTotals() method to get total?
    – Umar
    Jul 4 '18 at 8:56
  • @umar yes, It is possible to get Grand Total Sub Total : $quote->collectTotals()->getSubtotal(); Grand Total :$quote->collectTotals()->getGrandTotal(); Jul 6 '18 at 10:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.