Invoice is an obligatory commercial document used by you and millions of other online stores.
How to stand out in such a competitive environment?
How to make the document clear, unique without high costs?
Today we will talk about how to make it without any dev skills. We will consider how to create invoices programmatically, automatically, attach a PDF invoice to email, and create a custom PDF version.
Let’s start!
How to create automatically sent invoices in Magento 2 programmatically
All Magento 2 merchants seek to customize the invoice PDF to reduce the time spent on the process and stand out against competitors. However, to make it automatically, you need to develop a custom module.
If you don’t want to waste money on custom extension development or have no time to develop extensions by yourself, then you can try our Mass Order Actions. This module allows you to create invoices programmatically in bulk on the order grid. You don’t need to open every order one by one in Magento 2 to create an order invoice. Save your time for more important deals!
Say, you are sure in your development skills, and you want to create a custom module. So, take a look at the following tips that we have prepared for you to create an invoice programmatically in Magento 2.
Step 1. Go to app/code/<Vendor>/<Module>/etc, create module.xml, and insert the following code:
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd"> <module name="<Vendor>_<Module>" setup_version="1.0.0"> </module> </config>
Step 2. Add registration.php to app/code/<Vendor>/<Module> and register the mod by entering the code:
<?php \Magento\Framework\Component\ComponentRegistrar::register( \Magento\Framework\Component\ComponentRegistrar::MODULE, '<Vendor>_<Module>', __DIR__ );
Step 3. Then go to <Vendor>/<Module>/etc and create events.xml. Please use this code:
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:framework:Event/etc/events.xsd"> <event name="checkout_submit_all_after"> <observer name="Vendor>_<Module>::auto_invoice_shipment_checkout_submit_all_after"
instance="<Vendor>\<Module>\Observer\CheckoutAllSubmitAfterObserver"/> </event> </config>
Step 4. For this step, you need to create an observer class. Go to <Vendor>/<Module>/Observer and add file CheckoutAllSubmitAfterObserver.php, then enter the code:
<?php
namespace <Vendor>\<Module>\Observer;
use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;
use <Vendor>\<Module>\Helper\Data;
class CheckoutAllSubmitAfterObserver implements ObserverInterface
{
/**
*
* @var Data
*/
protected $helper;
/**
* @param Data $helper
*/
public function __construct(
Data $helper
) {
$this->helper = $helper;
}
/**
*
* @param Observer $observer
* @return $this
*/
public function execute(Observer $observer)
{
if(!$this->helper->isEnabled()) {
return $this;
}
$order = $observer->getEvent()->getOrder();
if(!$order->getId()) {
return $this;
}
$invoice = $this->helper->createInvoice($order);
if($invoice) {
$this->helper->createShipment($order, $invoice);
}
return $this;
}
}Step 5. The last what you need to do is create a file Data.php in <Vendor>/<Module>/Helper and paste this code:
<?php
namespace <Vendor>\<Module>\Helper;
use Magento\Framework\App\Helper\AbstractHelper;
use Magento\Framework\App\Config\ScopeConfigInterface;
use Magento\Sales\Model\ResourceModel\Order\Invoice\CollectionFactory;
use Magento\Sales\Model\Service\InvoiceService;
use Magento\Sales\Model\Order\ShipmentFactory;
use Magento\Framework\DB\TransactionFactory;
use Magento\Framework\App\Helper\Context;
class Data extends AbstractHelper
{
const MODULE_ENABLED = '<Vendor>_<Module>_auto_invoice_shipment/settings/enabled';
/**
* @var ScopeConfigInterface
*/
protected $scopeConfig;
/**
*
* @var CollectionFactory
*/
protected $invoiceCollectionFactory;
/**
*
* @var InvoiceService
*/
protected $invoiceService;
/**
*
* @var ShipmentFactory
*/
protected $shipmentFactory;
/**
*
* @var TransactionFactory
*/
protected $transactionFactory;
public function __construct(
Context $context,
ScopeConfigInterface $scopeConfig,
CollectionFactory $invoiceCollectionFactory,
InvoiceService $invoiceService,
ShipmentFactory $shipmentFactory,
TransactionFactory $transactionFactory
)
{
parent::__construct($context);
$this->scopeConfig = $scopeConfig;
$this->invoiceCollectionFactory = $invoiceCollectionFactory;
$this->invoiceService = $invoiceService;
$this->shipmentFactory = $shipmentFactory;
$this->transactionFactory = $transactionFactory;
}
public function createInvoice($order)
{
try {
$invoices = $this->invoiceCollectionFactory->create()
->addAttributeToFilter('order_id', array('eq' => $order->getId()));
$invoices->getSelect()->limit(1);
if ((int)$invoices->count() !== 0 || !$order->canInvoice()) {
return null;
}
$invoice = $this->invoiceService->prepareInvoice($order);
$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();
} catch (\Exception $e) {
$order->addStatusHistoryComment('Exception message: ' . $e->getMessage(),
false);
$order->save();
return null;
}
return $invoice;
}
public function createShipment($order, $invoice)
{
try {
$shipment = $this->prepareShipment($invoice);
if ($shipment) {
$order->setIsInProcess(true);
$order->addStatusHistoryComment('Automatically SHIPPED', false);
$this->transactionFactory->create()->addObject($shipment)->
addObject($shipment->getOrder())->save();
}
} catch (\Exception $e) {
$order->addStatusHistoryComment('Exception message: ' . $e->getMessage(),
false);
$order->save();
}
}
public function prepareShipment($invoice)
{
$shipment = $this->shipmentFactory->create(
$invoice->getOrder(),
[]
);
return $shipment->getTotalQty() ? $shipment->register() : false;
}
/**
* Is the module enabled in configuration.
*
* @return bool
*/
public function isEnabled()
{
return $this->scopeConfig->getValue(self::MODULE_ENABLED);
}
}Step 6. The last what we will create now is the file that allows to turn on and off this module in admin panel. Create <Vendor>/<Module>/etc/adminhtml/system.xml and use the following code:
<?xml version="1.0"?> <config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="urn:magento:module:Magento_Config:etc/system_file.xsd"> <system> <section id="<Vendor>_<Module>_auto_invoice_shipment" translate="label" type="text"
sortOrder="1300" showInDefault="1" showInWebsite="1" showInStore="1"> <label>Auto Invoice Shipment</label> <tab>sales</tab> <resource><Vendor>_<Module>::auto_invoice_shipment</resource> <group id="settings" translate="label" sortOrder="1000" showInDefault="1" showInWebsite="1"
showInStore="1"> <label>Extension Settings</label> <field id="enabled" translate="label" type="select" sortOrder="10" showInDefault="1"
showInWebsite="1" showInStore="1" canRestore="1"> <label>Enabled</label> <source_model>Magento\Config\Model\Config\Source\Yesno</source_model> </field> </group> </section> </system> </config>
And that’s all.
Run the following commands after installing this module:
php bin/magento cache:flush
php bin/magento setup:upgrade
php bin/magento setup:di:compile
php bin/magento setup:static-content:deploy
php bin/magento setup:upgrade
Now invoices will be created automatically.
How to attach a PDF invoice to an email in Magento 2
Adding a PDF invoice to a confirmation email is another common challenge. And we have two solutions for you.
Solution 1
If you have good technical skills, you can try to create a custom module for this option. Below you will find instructions that will help you with this.
Solution 2
Or you can create a custom invoice with Magento 2 PDF Customizer. This plugin allows you to design a custom Magento PDF invoice template right in the admin panel by using an HTML/CSS tool and attach it to your invoice emails. You can set this in a few clicks. Let’s consider a fast example. Go to Stores>Configuration>Amasty Extensions>PDF Customizer>Invoice, choose a template from the list and select Yes in the Add PDF Attachment to Emails to Clients Automatically drop-down:

And that’s all, so simple.
If you still feel like coding is what you need, follow the instructions below.
Step 1. Create and register a new programmatically order invoice module as shown at the beginning of the article. The module.xml, registration.php files should be in every new module.
Step 2. Next, you need to override InvoiceOrder in Magento/Sales/Model and add this comment:
Step 3. Now you need to create events.xml in <Vendor>/<Module>/etc with code:
Step 4. Add observer sales_order_shipment_save_after in <Vendor>/<Module>/Observer then enter the code:
Customize your PDF invoice
Add your logo to PDF invoice using vanilla admin panel settings
You can customize PDF invoice only with your logo and address in default Magento. To do it go to Stores>Configuration:

Choose Sales in the Sales tab:

Open Invoice and Packing Slip Design and browse the image:

Then click the Save Config button.
Advanced customization options with the Amasty PDF invoice module
If you want to get more customization options, try our PDF Customizer for Magento 2. It has an HTML/CSS editor where you customize the Magento invoice template: change the text of your file, add variables, change fonts, colors, add a logo, etc. To do this, go to Marketing>Amasty PDF Templates. Click the Add New Template button:
Choose the needed pattern from the drop-down and load it. There is not only an Invoice template, but also Credit Memo, Order, and Shipment:

Then you will see where this template is already used. You need to give a title to the Magento invoice template, can change the content, and styles:

What’s even more convenient, now you can preview the changes before saving the form by clicking on Preview Template:

When you are ready, save the changes to use this template in your emails.
This way, you can customize invoice PDFs in Magento 2, add an unlimited number of invoice templates and perform the Magento 2 change of an existing invoice PDF template. Here is just one of PDF invoice examples:

Thus, buyers will have the ability in Magento to print invoices in PDF and download them from their account:
What are the benefits? This module provides you with an option to generate invoices automatically in Magento 2 without any coding knowledge.
Add an unlimited number of invoice templates!
That’s all for today!
Feel free to ask your questions in the comment section below, we will be glad to help you out.







