I need to create credit memo and online refund programmatically in magento 2. I referred programmatic creation of credit memo in magento 1.x here. Any help for magento 2?
6 Answers
Finally discovered the solution, to create credit memo with online refund from custom code. Use this code in your custom model and call the function where ever you want.
public __construct( \Magento\Sales\Model\Order $order, \Magento\Sales\Model\Order\CreditmemoFactory $creditmemoFactory, \Magento\Sales\Model\Order\Invoice $invoice, \Magento\Sales\Model\Service\CreditmemoService $creditmemoService, array $data = [] ) { parent::__construct($data); $this->order = $order; $this->creditmemoFactory = $creditmemoFactory; $this->creditmemoService = $creditmemoService; $this->invoice = $invoice; } public function refundCode() { $order = $this->order; $order->load(10); $invoices = $order->getInvoiceCollection(); foreach ($invoices as $invoice) { $invoiceincrementid = $invoice->getIncrementId(); } $invoiceobj = $this->invoice->loadByIncrementId($invoiceincrementid); $creditmemo = $this->creditmemoFactory->createByOrder($order); // Don't set invoice if you want to do offline refund $creditmemo->setInvoice($invoiceobj); $this->creditmemoService->refund($creditmemo); } - How to pass here an array of specific items?zhartaunik– zhartaunik2017-03-21 07:52:58 +00:00Commented Mar 21, 2017 at 7:52
- Hi @zhartaunik do we have combination of your code & zhartaunik's answer in Refund it automatically includes Shipping Fee. How to avoid that?Jackson– Jackson2017-04-03 03:23:30 +00:00Commented Apr 3, 2017 at 3:23
- Doesn't work in 2.1.6 and 2.1.7 - throws an error "We don't have enough information to save the parent transaction ID"Fred August– Fred August2017-06-16 19:16:39 +00:00Commented Jun 16, 2017 at 19:16
- How to change order status from closed to cancel when credit memo is created?Slimshadddyyy– Slimshadddyyy2018-10-24 16:11:23 +00:00Commented Oct 24, 2018 at 16:11
- do you know how to return to stock for an item?leo– leo2021-06-29 16:36:18 +00:00Commented Jun 29, 2021 at 16:36
Here some function which can be helpful to you
Create a creditmemo from an order:
\Magento\Sales\Model\Order\CreditmemoFactory::createByOrder Refund a creditmemo:
\Magento\Sales\Model\Service\CreditmemoService::refund Magento 2.1.3
/** * @var \Magento\Sales\Model\Order\CreditmemoFactory */ protected $refundOrder; /** * @var \Magento\Sales\Model\Order\Creditmemo\ItemCreationFactory */ protected $itemCreationFactory; public function __construct( \Magento\Sales\Model\RefundOrder $refundOrder, \Magento\Sales\Model\Order\Creditmemo\ItemCreationFactory $itemCreationFactory ) { $this->refundOrder = $refundOrder; $this->itemCreationFactory = $itemCreationFactory; } public function execute() { $creditmemoItem = $this->itemCreationFactory->create(); $creditmemoItem->setQty(1) ->setOrderItemId(22); $itemIdsToRefund[] = $creditmemoItem; $this->refundOrder->execute( $order->getId(), $itemIdsToRefund ); } Runs as clockwork
- Can i get refund related table fields bz i want to create csv template for data migration.Pramod Kharade– Pramod Kharade2017-07-22 13:50:12 +00:00Commented Jul 22, 2017 at 13:50
- How can I pass invoice id for same?akshay billore– akshay billore2018-10-26 10:32:28 +00:00Commented Oct 26, 2018 at 10:32
- can we refund amout to storecredit ?devhs– devhs2021-03-25 11:05:06 +00:00Commented Mar 25, 2021 at 11:05
- Doesn't seem to be anyway to do an online refund using Magento\Sales\Model\RefundOrder. It will always be offline.Rooster242– Rooster2422021-05-10 22:37:00 +00:00Commented May 10, 2021 at 22:37
To do a partial credit memo against an invoice, you need to do something like this:
/** @var RefundInvoiceInterface $refundInvoice */ $refundInvoice = $objectManager->get("\Magento\Sales\Api\RefundInvoiceInterface"); $items = []; // If items is empty array, the entire invoice will be refunded. /** @var \Magento\Sales\Model\Order\Invoice\Item $item */ foreach ($invoice->getAllItems() as $item) { // Note that the simple and configurable products are returned in getAllItems(). The function getVisibleItems() does not work, so we need this check: if($item->getOrderItem()->getProductType() == \Magento\ConfigurableProduct\Model\Product\Type\Configurable::TYPE_CODE) { continue; } $qtyToReturn = 1; // Select out many you want to refund $creditmemoItemCreation = new \Magento\Sales\Model\Order\Creditmemo\ItemCreation(); $items[] = $creditmemoItemCreation->setQty($qtyToReturn)->setOrderItemId($item->getOrderItemId()); } // If you don't want to refund shipping, or to make adjustment refunds, use the CreationArguments (otherwise, you can leave these next two lines out) $creditMemoCreationArguments = new CreationArguments(); $creditMemoCreationArguments->setShippingAmount(0); $refundInvoice->execute($invoice->getId(), $items, true, true, false, null, $creditMemoCreationArguments); - Seems to possibly be something missing, where does
$invoiceget defined? It also seems like the$itemsarray gets overwritten...joeybab3– joeybab32021-06-21 23:29:19 +00:00Commented Jun 21, 2021 at 23:29
Try below one
$objectManager = \Magento\Framework\App\ObjectManager::getInstance(); /* Instance of object manager */ $incrementId = "100075273"; /*Increment Id */ $collection = $objectManager->create('Magento\Sales\Model\Order'); $order = $collection->loadByIncrementId($incrementId); $invoice = $objectManager->create('Magento\Sales\Model\Order\Invoice'); $creditMemoFacory = $objectManager->create('Magento\Sales\Model\Order\CreditmemoFactory'); $creditmemoService = $objectManager->create('Magento\Sales\Model\Service\CreditmemoService'); try { $invoices = $order->getInvoiceCollection(); foreach ($invoices as $invoice) { $invoiceincrementid = $invoice->getIncrementId(); } if(isset($invoiceincrementid)){ $invoiceobj = $invoice->loadByIncrementId($invoiceincrementid); $creditmemo = $creditMemoFacory->createByOrder($order); // Don't set invoice if you want to do offline refund $creditmemo->setInvoice($invoiceobj); $creditmemoService->refund($creditmemo); echo "CreditMemo Succesfully Created For Order: ".$incrementId; } else { echo "CreditMemo Cannot Be Created For Order: ".$incrementId; /*if order has 0 amount or something wrong happened**/ } } catch (\Exception $e) { echo "Creditmemo Not Created". $e->getMessage(); } - How to do a partial refund ?devhs– devhs2021-03-30 06:37:31 +00:00Commented Mar 30, 2021 at 6:37
That's how I got it working on Magento 2.3. All you need to pass is just the Order object.
<?php namespace Vender\Package\Model\Order\Processor; use Magento\Sales\Api\Data\OrderInterface; use Magento\Sales\Model\Order; use Magento\Sales\Model\Order\CreditmemoFactory; use Magento\Sales\Model\Order\Invoice; use Magento\Sales\Model\Service\CreditmemoService; class CustomClass { protected $creditMemoFactory; protected $creditMemoService; protected $invoice; public function __construct ( CreditmemoFactory $creditMemoFactory, CreditmemoService $creditMemoService, Invoice $invoice ) { $this->creditMemoFactory = $creditMemoFactory; $this->creditMemoService = $creditMemoService; $this->invoice = $invoice; } /** * @param OrderInterface $order * @throws \Magento\Framework\Exception\LocalizedException */ protected function refund(OrderInterface $order): void { $invoices = $order->getInvoiceCollection(); if (count($invoices) == 0) { throw new \Exception(__('No Invoices found for Refund. Magento_ID: %2', $order->getIncrementId())); } foreach ($invoices as $invoice) { $invoice = $this->invoice->loadByIncrementId($invoice->getIncrementId()); $creditMemo = $this->creditMemoFactory->createByOrder($order); // Don't set invoice if you want to do offline refund $creditMemo->setInvoice($invoice); $creditMemo->setCustomerNote(__('Your Order %1 has been Refunded back in your account', $order->getIncrementId())); $creditMemo->setCustomerNoteNotify(false); $creditMemo->addComment(__('Order has been Refunded')); $order->addCommentToStatusHistory(__('Order has been Refunded Successfully')); $this->creditMemoService->refund($creditMemo); } } } I hope it helps.