Generate an Auto Invoice Programmatically from Magento 2 required an order id. Based on the Order Id, You can fetch Order Object.
Given code, a snippet is used to generate an Invoice in Magento, After generating an invoice automatically sends the invoice mail to a customer who has placed the order.
I have just given a demo to create an invoice with the specified order id,
<?php declare(strict_types=1); namespace Rbj\Invoice\Block; class Invoice extends \Magento\Framework\View\Element\Template { public function __construct( \Magento\Framework\View\Element\Template\Context $context, \Magento\Sales\Api\OrderRepositoryInterface $orderRepository, \Magento\Sales\Model\Service\InvoiceService $invoiceService, \Magento\Framework\DB\TransactionFactory $transactionFactory, \Magento\Framework\Message\ManagerInterface $messageManager, \Magento\Sales\Model\Order\Email\Sender\InvoiceSender $invoiceSender, array $data = [] ) { $this->orderRepository = $orderRepository; $this->invoiceService = $invoiceService; $this->transactionFactory = $transactionFactory; $this->messageManager = $messageManager; $this->invoiceSender = $invoiceSender; parent::__construct($context, $data); } /** * Create Invoice Based on Order Object * @param \Magento\Sales\Model\Order $order * @return $this */ public function generateInvoice($orderId) { try { $order = $this->orderRepository->get($orderId); if (!$order->getId()) { throw new \Magento\Framework\Exception\LocalizedException(__('The order no longer exists.')); } if (!$order->canInvoice()) { throw new \Magento\Framework\Exception\LocalizedException( __('The order does not allow an invoice to be created.') ); } $invoice = $this->invoiceService->prepareInvoice($order); if (!$invoice) { throw new \Magento\Framework\Exception\LocalizedException(__('We can\'t save the invoice right now.')); } if (!$invoice->getTotalQty()) { throw new \Magento\Framework\Exception\LocalizedException( __('You can\'t create an invoice without products.') ); } $invoice->setRequestedCaptureCase(\Magento\Sales\Model\Order\Invoice::CAPTURE_OFFLINE); $invoice->register(); $invoice->getOrder()->setCustomerNoteNotify(false); $invoice->getOrder()->setIsInProcess(true); $order->addStatusHistoryComment('Automatically INVOICED', false); $transactionSave = $this->transactionFactory->create()->addObject($invoice)->addObject($invoice->getOrder()); $transactionSave->save(); // send invoice emails, If you want to stop mail disable below try/catch code try { $this->invoiceSender->send($invoice); } catch (\Exception $e) { $this->messageManager->addError(__('We can\'t send the invoice email right now.')); } } catch (\Exception $e) { $this->messageManager->addError($e->getMessage()); } return $invoice; } }
We just need to pass the order id in the generateInvoice($orderId) function in the given code snippet.
Code is checking the Order by order id, validating it, and checking for the invoice applicable to the order.
Preparing the Invoice, setting qty for the invoice record, set offline capture mode, and finally creating a transaction object for the Invoice.
Call function from the specific class,
$orderId = 1;
$this->generateInvoice($orderId);
This is the correct way to check all the possible validation before generating an invoice.