Create PDF Invoices No Other Magento Store Has

Table of Content

create pdf invoices no other magento store has
Last Updated: March 5, 2026

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:

add pdf invoice to emails

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:

pdf invoice configuration

Choose Sales in the Sales tab:

pdf invoice sales

Open Invoice and Packing Slip Design and browse the image:

upload logo

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:

create new template

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:

load template

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:

customize template

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

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:

pdf invoice example

Thus, buyers will have the ability in Magento to print invoices in PDF and download them from their account:

download and print invoice

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.

Originally published: August 26, 2019
August 29, 2019
August 13, 2019
Comments
Мarie Koval
March 16, 2021
Thank you for the article. All steps are described in detail, so it was easy to understand what's what
Reply
Vladimir Derachits
March 16, 2021
Hi Marie, thanks for your feedback! We are happy to share our experience and try to make the information as clear as possible for our readers.
Leave your comment

Your email address will not be published

This blog was created with Amasty Blog Pro

This blog was created with Amasty Blog Pro

Loading