How to customize the order invoice?

Note

This cookbook describes customization of a feature available only with Sylius/InvoicingPlugin installed.

The invoicing plugin lets you generate invoice on admin panel and download PDF with it. This plugin also sends an email with this invoice as well as let the administrator to delegate an email resend.

Why would you customize the invoice?

Invoicing Plugin provides a generic solution for generating invoices for orders, it is enough for a basic invoicing functionality but many shops need this feature customized for its needs. For example, one may need to change the look of it, or add some more data.

Getting started

Before you start make sure that you have:

  1. Sylius/InvoicingPlugin installed.
  2. Wkhtmltopdf package installed, because most of pdf generation is done with it.

How to customize the invoice appearance?

There might be need to change how the invoices look like, f.e. shop is using its own logo, there might be some colours changed on the tables, or maybe the order of fields might be changed.

First let’s prepare the HTML’s so we can modify them. This command will copy only the PDF template:

mkdir templates/bundles/SyliusInvoicingPlugin/Invoice/Download
cp vendor/sylius/invoicing-plugin/src/Resources/views/Invoice/Download/pdf.html.twig templates/bundles/SyliusInvoicingPlugin/Download

But you can also copy all of the templates with:

mkdir templates/bundles/SyliusInvoicingPlugin
cp -r vendor/sylius/invoicing-plugin/src/Resources/views/Invoice templates/bundles/SyliusInvoicingPlugin/

In directory templates/bundles/SyliusInvoicingPlugin/Invoice you can find now few files.

Let’s modify the generated PDF. In this case we will modify the file from Download/pdf.html.twig. This is how the default PDF looks like (don’t worry this is not a real address of Myrna, or is it?):

../../_images/pdf_before.png

Now with some magic of HTML and CSS we can modify this template, as an example we can change the color of background to red by changing

<!--...-->
<div class="invoice-box" style="background-color: red">
<!--...-->

and after this change we are graced with this masterpiece:

../../_images/pdf_after.png

Warning

Every PDF that you generate is stored and then extracted so it won’t be created again. If you want to see the changes go to private/invoices and remove the generated PDF. You should see the changes of your file when you generate it again.

Note

You can also modify the view on administrator page by changing code inside show.html.twig and related templates

Note

You can learn more about customizing templates at Customization Guide

How to add additional fields to invoice?

Let’s say that you need (or not) some more fields. In this example we will add the customer phone number. Because we are basing upon the existing field, there should be no problem adding it to document - just place a line into Download/pdf.html.twig file. The Phone Number field is quite nested so you need to add invoice.order.customer.phoneNumber to retrieve it:

<!--...-->
    {{ invoice.billingData.city }}<br/>
    {{ invoice.order.customer.phoneNumber }}<br/>
    {{ invoice.billingData.countryCode}}
<!--...-->

And as a result we can see that phone number has been added just after the city:

../../_images/pdf_phone.png

Note

You can also create some validation (for example if customer has no phone number) so the field won’t be shown. If you want to learn more about twig - visit twig.

How to change the appearance of invoice tables?

By default on lower right corner of invoice we are displaying total of ordered items and shipment. Lets create now a new row where we will show Products total where only price for products will be shown.

First let’s add the new table row between other totals in pdf.html.twig

<!--...-->
    <tr class="totals">
        <!--tr body-->
    </tr>

    <tr class="totals">
        <td colspan="5"></td>
        <td colspan="2" >{{ 'sylius_invoicing_plugin.ui.products_total'|trans([], 'messages', invoice.localeCode) }}:</td>
        <td>{{ '%0.2f'|format(invoice.order.itemsTotal/100) }}</td>
        <td>{{ invoice.currencyCode }}</td>
    </tr>

    <tr class="totals bold">
<!--...-->

And now add the translation by creating file translations/messages.en.yaml and adding:

sylius_invoicing_plugin:
    ui:
        products_total: 'Products total'

after this changes your PDF’s total table should look like this:

../../_images/pdf_total.png

How to extend Invoice with custom logic?

With default behavior and some simple customization it should be quite simple to achieve the Invoice you are looking for. But life is not so straightforward as we all would like, and you are in need to create some custom logic for your needs. Scary process isn’t it? Well not exactly, let’s create some custom logic for your invoice in this step.

First we need a class with our logic that will extend current Invoice:

<?php

declare(strict_types=1);

namespace App\Entity\Invoice;

use Doctrine\ORM\Mapping as ORM;
use Sylius\InvoicingPlugin\Entity\Invoice as BaseInvoice;

/**
 * @ORM\Entity
 * @ORM\Table(name="sylius_invoicing_plugin_invoice")
 */
class Invoice extends BaseInvoice implements InvoiceInterface
{
    public function customFunction(): mixed
    {
        /** your custom logic */
    }
}

And if there is a need you can also create an interface that will extend the base one:

<?php

declare(strict_types=1);

namespace App\Entity\Invoice;

use Sylius\InvoicingPlugin\Entity\InvoiceInterface as BaseInvoiceInterface;

interface InvoiceInterface extends BaseInvoiceInterface
{
    public function customFunction(): mixed;
}

Now let’s add those classes to the configuration:

# config/packages/_sylius.yaml
sylius_invoicing:
resources:
    invoice:
        classes:
            model: App\Entity\Invoice\Invoice
            interface: App\Entity\Invoice\InvoiceInterface

Note

Don’t forget to update your database if you are changing/adding fields.

Now you can show a new invoice table on PDF with some changes just like in chapters before.