/** * Refund payment online or offline, depending on whether there is invoice set in the creditmemo instance * Updates transactions hierarchy, if required * Updates payment totals, updates order status and adds proper comments * * @param Creditmemo $creditmemo * @return $this * @throws \Exception * @throws \Magento\Framework\Exception\LocalizedException * @SuppressWarnings(PHPMD.CyclomaticComplexity) * @SuppressWarnings(PHPMD.NPathComplexity) */ public function refund($creditmemo) { $baseAmountToRefund = $this->_formatAmount($creditmemo->getBaseGrandTotal()); $this->_generateTransactionId(Transaction::TYPE_REFUND); // call refund from gateway if required $isOnline = false; $gateway = $this->getMethodInstance(); $invoice = null; if ($gateway->canRefund() && $creditmemo->getDoTransaction()) { $this->setCreditmemo($creditmemo); $invoice = $creditmemo->getInvoice(); if ($invoice) { $isOnline = true; $captureTxn = $this->_lookupTransaction($invoice->getTransactionId()); if ($captureTxn) { $this->setParentTransactionId($captureTxn->getTxnId()); } $this->setShouldCloseParentTransaction(true); // TODO: implement multiple refunds per capture try { $gateway->setStore($this->getOrder()->getStoreId()); $this->setRefundTransactionId($invoice->getTransactionId()); $gateway->refund($this, $baseAmountToRefund); $creditmemo->setTransactionId($this->getLastTransId()); } catch (\Magento\Framework\Exception\LocalizedException $e) { if (!$captureTxn) { throw new \Magento\Framework\Exception\LocalizedException(__('If the invoice was created offline, try creating an offline credit memo.'), $e); } throw $e; } } } // update self totals from creditmemo $this->_updateTotals(['amount_refunded' => $creditmemo->getGrandTotal(), 'base_amount_refunded' => $baseAmountToRefund, 'base_amount_refunded_online' => $isOnline ? $baseAmountToRefund : null, 'shipping_refunded' => $creditmemo->getShippingAmount(), 'base_shipping_refunded' => $creditmemo->getBaseShippingAmount()]); // update transactions and order state $transaction = $this->_addTransaction(Transaction::TYPE_REFUND, $creditmemo, $isOnline); if ($invoice) { $message = __('We refunded %1 online.', $this->_formatPrice($baseAmountToRefund)); } else { $message = $this->hasMessage() ? $this->getMessage() : __('We refunded %1 offline.', $this->_formatPrice($baseAmountToRefund)); } $message = $message = $this->_prependMessage($message); $message = $this->_appendTransactionToMessage($transaction, $message); $this->setOrderStateProcessing($message); $this->_eventManager->dispatch('sales_order_payment_refund', ['payment' => $this, 'creditmemo' => $creditmemo]); return $this; }
/** * Prepare order data for refund * * @param \Magento\Sales\Model\Order\Creditmemo $creditmemo * @return void */ protected function prepareOrder(\Magento\Sales\Model\Order\Creditmemo $creditmemo) { $order = $creditmemo->getOrder(); $baseOrderRefund = $this->priceCurrency->round($order->getBaseTotalRefunded() + $creditmemo->getBaseGrandTotal()); $orderRefund = $this->priceCurrency->round($order->getTotalRefunded() + $creditmemo->getGrandTotal()); $order->setBaseTotalRefunded($baseOrderRefund); $order->setTotalRefunded($orderRefund); $order->setBaseSubtotalRefunded($order->getBaseSubtotalRefunded() + $creditmemo->getBaseSubtotal()); $order->setSubtotalRefunded($order->getSubtotalRefunded() + $creditmemo->getSubtotal()); $order->setBaseTaxRefunded($order->getBaseTaxRefunded() + $creditmemo->getBaseTaxAmount()); $order->setTaxRefunded($order->getTaxRefunded() + $creditmemo->getTaxAmount()); $order->setBaseDiscountTaxCompensationRefunded($order->getBaseDiscountTaxCompensationRefunded() + $creditmemo->getBaseDiscountTaxCompensationAmount()); $order->setDiscountTaxCompensationRefunded($order->getDiscountTaxCompensationRefunded() + $creditmemo->getDiscountTaxCompensationAmount()); $order->setBaseShippingRefunded($order->getBaseShippingRefunded() + $creditmemo->getBaseShippingAmount()); $order->setShippingRefunded($order->getShippingRefunded() + $creditmemo->getShippingAmount()); $order->setBaseShippingTaxRefunded($order->getBaseShippingTaxRefunded() + $creditmemo->getBaseShippingTaxAmount()); $order->setShippingTaxRefunded($order->getShippingTaxRefunded() + $creditmemo->getShippingTaxAmount()); $order->setAdjustmentPositive($order->getAdjustmentPositive() + $creditmemo->getAdjustmentPositive()); $order->setBaseAdjustmentPositive($order->getBaseAdjustmentPositive() + $creditmemo->getBaseAdjustmentPositive()); $order->setAdjustmentNegative($order->getAdjustmentNegative() + $creditmemo->getAdjustmentNegative()); $order->setBaseAdjustmentNegative($order->getBaseAdjustmentNegative() + $creditmemo->getBaseAdjustmentNegative()); $order->setDiscountRefunded($order->getDiscountRefunded() + $creditmemo->getDiscountAmount()); $order->setBaseDiscountRefunded($order->getBaseDiscountRefunded() + $creditmemo->getBaseDiscountAmount()); if ($creditmemo->getDoTransaction()) { $order->setTotalOnlineRefunded($order->getTotalOnlineRefunded() + $creditmemo->getGrandTotal()); $order->setBaseTotalOnlineRefunded($order->getBaseTotalOnlineRefunded() + $creditmemo->getBaseGrandTotal()); } else { $order->setTotalOfflineRefunded($order->getTotalOfflineRefunded() + $creditmemo->getGrandTotal()); $order->setBaseTotalOfflineRefunded($order->getBaseTotalOfflineRefunded() + $creditmemo->getBaseGrandTotal()); } $order->setBaseTotalInvoicedCost($order->getBaseTotalInvoicedCost() - $creditmemo->getBaseCost()); }