6

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?

1
12

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); 
}
4
  • How to pass here an array of specific items? – zhartaunik Mar 21 '17 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 Apr 3 '17 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 Orosko Dias Jun 16 '17 at 19:16
  • How to change order status from closed to cancel when credit memo is created? – Slimshadddyyy Oct 24 '18 at 16:11
5

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
0
5

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

2
  • Can i get refund related table fields bz i want to create csv template for data migration. – Pramod Kharade Jul 22 '17 at 13:50
  • How can I pass invoice id for same? – akshay billore Oct 26 '18 at 10:32
0

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();
}
0

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);

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.