/** * @param \Magento\Sales\Model\Order\Invoice $invoice * @return $this */ public function collect(\Magento\Sales\Model\Order\Invoice $invoice) { $invoice->setDiscountAmount(0); $invoice->setBaseDiscountAmount(0); $totalDiscountAmount = 0; $baseTotalDiscountAmount = 0; /** * Checking if shipping discount was added in previous invoices. * So basically if we have invoice with positive discount and it * was not canceled we don't add shipping discount to this one. */ $addShippingDiscount = true; foreach ($invoice->getOrder()->getInvoiceCollection() as $previousInvoice) { if ($previousInvoice->getDiscountAmount()) { $addShippingDiscount = false; } } if ($addShippingDiscount) { $totalDiscountAmount = $totalDiscountAmount + $invoice->getOrder()->getShippingDiscountAmount(); $baseTotalDiscountAmount = $baseTotalDiscountAmount + $invoice->getOrder()->getBaseShippingDiscountAmount(); } /** @var $item \Magento\Sales\Model\Order\Invoice\Item */ foreach ($invoice->getAllItems() as $item) { $orderItem = $item->getOrderItem(); if ($orderItem->isDummy()) { continue; } $orderItemDiscount = (double) $orderItem->getDiscountAmount(); $baseOrderItemDiscount = (double) $orderItem->getBaseDiscountAmount(); $orderItemQty = $orderItem->getQtyOrdered(); if ($orderItemDiscount && $orderItemQty) { /** * Resolve rounding problems */ $discount = $orderItemDiscount - $orderItem->getDiscountInvoiced(); $baseDiscount = $baseOrderItemDiscount - $orderItem->getBaseDiscountInvoiced(); if (!$item->isLast()) { $activeQty = $orderItemQty - $orderItem->getQtyInvoiced(); $discount = $invoice->roundPrice($discount / $activeQty * $item->getQty(), 'regular', true); $baseDiscount = $invoice->roundPrice($baseDiscount / $activeQty * $item->getQty(), 'base', true); } $item->setDiscountAmount($discount); $item->setBaseDiscountAmount($baseDiscount); $totalDiscountAmount += $discount; $baseTotalDiscountAmount += $baseDiscount; } } $invoice->setDiscountAmount(-$totalDiscountAmount); $invoice->setBaseDiscountAmount(-$baseTotalDiscountAmount); $invoice->setGrandTotal($invoice->getGrandTotal() - $totalDiscountAmount); $invoice->setBaseGrandTotal($invoice->getBaseGrandTotal() - $baseTotalDiscountAmount); return $this; }