How to programmatically create invoice in magento2 – In Magento sometimes we need to generate the invoice of an order automatically when the order is placed or the payment status is successfull for a particular order.
If you want to programmatically create the invoice for a particular order then please follow the below solution.
Here you can learn here how to create a invoice for a particular order or a part of a particular order using item ids.
Create invoice for a new order-
Step 1. Create a Controller CreateInvoice.php in your custom module at app / code / { vendorname } / { modulename } / Controller / { Action } /
Write the below code inside your controller file (CreateInvoice.php) :
<?php /** * Webkul Software. * * @category Webkul * @package Webkul_Grid * @author Webkul * @copyright Copyright (c) 2010-2016 Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ namespace Webkul\TestBlogs\Controller\Blogs; class CreateInvoice extends \Magento\Framework\App\Action\Action { /** * @var \Magento\Sales\Api\OrderRepositoryInterface */ protected $_orderRepository; /** * @var \Magento\Sales\Model\Service\InvoiceService */ protected $_invoiceService; /** * @var \Magento\Framework\DB\Transaction */ protected $_transaction; public function __construct( \Magento\Framework\App\Action\Context $context, \Magento\Sales\Api\OrderRepositoryInterface $orderRepository, \Magento\Sales\Model\Service\InvoiceService $invoiceService, \Magento\Sales\Model\Order\Email\Sender\InvoiceSender $invoiceSender, \Magento\Framework\DB\Transaction $transaction ) { $this->_orderRepository = $orderRepository; $this->_invoiceService = $invoiceService; $this->invoiceSender = $invoiceSender; $this->_transaction = $transaction; parent::__construct($context); } /** * Marketplace order invoice controller. * * @return \Magento\Framework\View\Result\Page */ public function execute() { $orderId = 9; //order id for which want to create invoice $order = $this->_orderRepository->get($orderId); if($order->canInvoice()) { $invoice = $this->_invoiceService->prepareInvoice($order); $invoice->register(); $invoice->save(); $transactionSave = $this->_transaction->addObject( $invoice )->addObject( $invoice->getOrder() ); $transactionSave->save(); $this->invoiceSender->send($invoice); //send notification code $order->addStatusHistoryComment( __('Notified customer about invoice #%1.', $invoice->getId()) ) ->setIsCustomerNotified(true) ->save(); } } }
The above example will let you generate order invoice for the complete order .
Now, If there are multiple items in your order and you want to and you want to generate invoice for a particular item in your order then please follow the below code to be able to do so.
Step 1. Create a Controller CreateInvoice.php in your custom module at app / code / { vendorname } / { modulename } / Controller / { Action } /
Create invoice for a particular item in your order
<?php /** * Webkul Software. * * @category Webkul * @package Webkul_Grid * @author Webkul * @copyright Copyright (c) 2010-2016 Webkul Software Private Limited (https://webkul.com) * @license https://store.webkul.com/license.html */ namespace Webkul\Grid\Controller; class CreateInvoice extends Magento\Framework\App\Action\Action { /** * @var \Magento\Sales\Api\OrderRepositoryInterface */ protected $_orderRepository; /** * @var \Magento\Sales\Model\Service\InvoiceService */ protected $_invoiceService; /** * @var \Magento\Framework\DB\Transaction */ protected $_transaction; public function __construct( \Magento\Framework\App\Action\Context $context, \Magento\Sales\Api\OrderRepositoryInterface $orderRepository, \Magento\Sales\Model\Order\Email\Sender\InvoiceSender $invoiceSender, \Magento\Sales\Model\Service\InvoiceService $invoiceService, \Magento\Framework\DB\Transaction $transaction ) { $this->_orderRepository = $orderRepository; $this->_invoiceService = $invoiceService; $this->invoiceSender = $invoiceSender; $this->_transaction = $transaction; parent::__construct($context); } /** * Marketplace order invoice controller. * * @return \Magento\Framework\View\Result\Page */ public function execute() { $orderId = 1; //order id for which want to create invoice $order = $this->_orderRepository->get($orderId); if($order->canInvoice()) { $itemsArray = ['80'=>2]; //here 80 is order item id and 2 is it's quantity to be invoice $shippingAmount = '10.00'; $subTotal = '110.00'; $baseSubtotal = '110.00'; $grandTotal = '110.00'; $baseGrandTotal = '110.00'; $invoice = $this->_invoiceService->prepareInvoice($order, $itemsArray); $invoice->setShippingAmount($shippingAmount); $invoice->setSubtotal($subTotal); $invoice->setBaseSubtotal($baseSubtotal); $invoice->setGrandTotal($grandTotal); $invoice->setBaseGrandTotal($baseGrandTotal); $invoice->register(); $transactionSave = $this->_transaction->addObject( $invoice )->addObject( $invoice->getOrder() ); $transactionSave->save(); $this->invoiceSender->send($invoice); //send notification code $order->addStatusHistoryComment( __('Notified customer about invoice #%1.', $invoice->getId()) ) ->setIsCustomerNotified(true) ->save(); } } }
How to programmatically create invoice in magento2
In this way you can create invoice for a particular product in a order or for a complete order. After creation of the invoice you can check it in admin panel sales order grid.
You may also check the below links :
- https://webkul.com/blog/how-to-programmatically-create-shipment-in-magento2/
- https://developer.adobe.com/commerce/webapi/rest/tutorials/inventory/create-invoice/
12 comments
This is working fine. I am creating invoice using ajax request.
I am using try catch in my controller.
But I am having problem with this code :
$this->invoiceSender->send($invoice);
When I removed this code ajax response in successful. Please suggest.
Sure we will try to add the blog in future for the topic asked. Thanks
We are working on warehouse management integration for our client.
While we receive order updates from warehouse, we are doing the following activities:
1. invoice creation
2. capture invoice amount that was authorized during order placement
3. create shipment
4. send notification email
5. order cancellation (if applicable)
6. create credit memo (if applicable, while cancelling invoices)
We have to do this process in a loop, for each order updates that we receive.
While doing this process for n number of orders, the script always process the 1st order on the collection.
When it tries to process for the 2nd order, we are getting the below error:
“set order for existing transactions not allowed”
Could you please highlight the cause for this error and solution to fix this error.
I tried the same solution for partial invoice but when i checked from sales_order_item table it shows other products as well. and when i open invoice from admin it does’t shows the invoice items. It shows blank under invoice items
1. Why, in the first example, you save the invoice twice ? first with the $invoice->save() statement, then with the $transactionSave
2. Is there a point to setting the isInProcess flag on the Order before saving it ? $invoice->getOrder()->setIsInProcess(true);
Like you want to create invoice for an order using a controller file (which we used in this post), then you will need to create a controller file CreateInvoice.php (as created in this post) in the path magnetoroot/app/code/VendorDirectory/ModuleName/Controller.
Thanks!
Thanks!