Generate invoice and shipment automatically when a new order is placed in Magento 2

Many merchants wants to create invoice / shipment and complete the order all at once when place order. So today I will discuss about how achieve their need. Although it’s custom needs/requirement so we need to create a custom module for that.

In that case, you need to do is to observe the checkout_submit_all_after event. So lets start.

Here Vendor is ‘SR’ and Module name ‘AutoInvoiceShipment’.

So create a module you can follow this post

Create events.xml [SR/AutoInvoiceShipment/etc/events.xml]

<?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="sr_auto_invoice_shipment_checkout_submit_all_after" instance="SR\AutoInvoiceShipment\Observer\CheckoutAllSubmitAfterObserver"/>
    </event>
</config>

Create observer class for that [SR/AutoInvoiceShipment/Observer/CheckoutAllSubmitAfterObserver.php]

namespace SR\AutoInvoiceShipment\Observer;

use Magento\Framework\Event\Observer;
use Magento\Framework\Event\ObserverInterface;

class CheckoutAllSubmitAfterObserver implements ObserverInterface
{
    /**
     *
     * @var \SR\AutoInvoiceShipment\Helper\Data
     */
    protected $helper;

    /**
     * @param \SR\AutoInvoiceShipment\Helper\Data $helper
     */
    public function __construct(
        \SR\AutoInvoiceShipment\Helper\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;
    }
}

Create a helper[SR/AutoInvoiceShipment/Helper/Data.php]

namespace SR\AutoInvoiceShipment\Helper;

use Magento\Framework\App\Helper\AbstractHelper;

class Data extends AbstractHelper
{
    const MODULE_ENABLED = 'sr_auto_invoice_shipment/settings/enabled';

    /**
     * @var \Magento\Framework\App\Config\ScopeConfigInterface
     */
    protected $scopeConfig;

    /**
     *
     * @var \Magento\Sales\Model\ResourceModel\Order\Invoice\CollectionFactory
     */
    protected $invoiceCollectionFactory;

    /**
     *
     * @var \Magento\Sales\Model\Service\InvoiceService
     */
    protected $invoiceService;

    /**
     *
     * @var \Magento\Sales\Model\Order\ShipmentFactory
     */
    protected $shipmentFactory;

    /**
     *
     * @var \Magento\Framework\DB\TransactionFactory
     */
    protected $transactionFactory;

    /**
     * @param \Magento\Framework\App\Helper\Context $context
     * @param \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig
     * @param \Magento\Sales\Model\ResourceModel\Order\Invoice\CollectionFactory $invoiceCollectionFactory
     * @param \Magento\Sales\Model\Service\InvoiceService $invoiceService
     * @param \Magento\Sales\Model\Order\ShipmentFactory $shipmentFactory
     * @param \Magento\Framework\DB\TransactionFactory $transactionFactory
     */
    public function __construct(
        \Magento\Framework\App\Helper\Context $context,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        \Magento\Sales\Model\ResourceModel\Order\Invoice\CollectionFactory $invoiceCollectionFactory,
        \Magento\Sales\Model\Service\InvoiceService $invoiceService,
        \Magento\Sales\Model\Order\ShipmentFactory $shipmentFactory,
        \Magento\Framework\DB\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) {
                return null;
            }

            if(!$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);
    }
}

That’s it.

If you want an option that you can handle this module on/off. So create a configuration
[SR/AutoInvoiceShipment/etc/adminhtml/system.xml]

<?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="sr_auto_invoice_shipment" translate="label" type="text" sortOrder="1300" showInDefault="1" showInWebsite="1" showInStore="1">
            <label>Auto Invoice Shipment</label>
            <tab>sales</tab>
            <resource>SR_AutoInvoiceShipment::sr_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>

Download Full Module From Here

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s