PDF Invoices
Generate and send PDF invoices to your customers for placed orders. Includes sensible defaults, but fully customizable when needed.
npm install @pinelab/pinelab-invoice-plugin
Official documentation here
A plugin for generating customizable PDF invoices for orders. Supports incremental invoice numbering, credit invoices, and customizable Handlebars templates.
This is a paid plugin. For production use, please purchase a license at https://vendure.io/marketplace.
Migration from V3.x to V4.0.0
In v4 the field invoice.isCreditInvoice
was changed from a getter to a physical database column. To populate the column you need to:
- Back up your database!
- Install the invoices plugin v4.x and generate + run a database migration. This introduced the new database field
isCreditInvoice
where all values are 'false'. - Run the query
UPDATE invoice SET isCreditInvoice = 1 WHERE orderTotals LIKE '%total":-%';
to set the value to 'true' for invoices that have a negative total. - :warning: The plugin now uses Puppeteer, so your Docker image might need additional dependencies installed. See Getting Started below!
Getting started
- Install the plugin with
yarn add @vendure-hub/pinelab-invoice-plugin
- Add the following config to your
vendure-config.ts
:
- Run a migration, to add the Invoice and InvoiceConfig entities to the database.
- Start Vendure and login to the admin dashboard
- Make sure you have the permission
AllowInvoicesPermission
- Go to
Sales > Invoices
. - Unfold the
Settings
accordion. - Check the checkbox to
Enable invoice generation
for the current channel on order placement. - A default HTML template is set for you. Click the
Preview
button to view a sample PDF invoice.
Docker
To make Puppeteer work on Docker, you need some additional steps in your Dockerfile. This is the Dockerfile we use ourselves:
Adding invoices to your order-confirmation email
Add the following link to your email template:
https://<your server>/invoices/e2e-default-channel/C7YH7WME4LTQNFRZ?email=hayden.zieme12@hotmail.com
.
When the customer clicks the link, the server will check if the ordercode
, channelCode
and customer emailaddress
match with the requested order. If so, it will return the invoice.
This link will always return the first invoice generated for an order. If invoices were recreated via the Admin UI, you can specify the invoice number in the url: ``
Recreating invoices and credit invoices
On the order detail page you can click the button recreate invoice
to generate a new invoice based on the current state of the order.
By default, this will first create a credit invoice, then a new invoice. A credit invoice basically voids the previous invoice before generating a new one.
To send emails when new invoices are created, you can listen for InvoiceCreatedEvents
:
Credit invoices use the same template as regular invoices, so make sure to handle credit invoice data. Checkout the default template for an example on how to use it for credit invoices.
Credit invoices will receive additional data with the default loadDataFn()
. This data is needed to create valid credit invoices:
To disable the credit invoice behaviour:
Increase invoice template DB storage
By default, the plugin uses TypeOrm's text
to store the invoice template in the DB. This might not be enough, for example when you'd like to add base64 encoded images to your invoices. This will result in the error ER_DATA_TOO_LONG: Data too long for column 'templateString'
. You can specify your DB engine with an env variable, and the plugin will resolve the correct column type:
Don't forget to run a DB migration: This will delete any data in the templateString
column!
Checkout https://orkhan.gitbook.io/typeorm/docs/entities for available databases and column types.
Google Storage strategy
This plugin also includes a strategy for storing invoices in Google Storage:
yarn add @google-cloud/storage
- Enable the service account IAM in Google Cloud Console
- Add role 'Service account token creator' to the Cloud Run service account
The strategy will use the projectId and credentials in from your environment, which is useful for Google Cloud Run or Cloud Functions.
However, if you want to run it locally or on a custom environment, you need to pass a keyFile to the plugin. This is needed to generate signedUrls, which are used to give customers temporary access to a file on Storage. More info about locally using signedUrls: https://github.com/googleapis/nodejs-storage/issues/360
Amazon S3 Storage strategy
This plugin also includes a strategy for storing invoices on Amazon S3.
yarn add aws-sdk
Custom file storage
Implement your own strategy for storing invoices by implementing one of these interfaces:
Remote storage strategy
RemoteStorageStrategy
for storing PDF files on an external platform like Google Cloud or S3. It redirects the user to
a public/authorized URL for the user to download the invoice PDF.
Local file storage
LocalFileStrategy
streams the invoice through the Vendure service to the user.
Custom invoice numbering and custom template data
Implement a custom loadDataFn
to pass custom data into your template or generate custom invoice numbers:
Make sure to return the data needed for credit invoices when shouldGenerateCreditInvoice
is defined.
You can access this data in your HTML template using Handlebars.js:
Exporting to external accounting platforms
You can automatically export each created invoice to an accounting platform by including an accounting strategy in the plugin. See one of the examples below for more details.
Xero UK
This strategy exports each invoice to Xero (UK only). To get started:
- Create an OAuth app by clicking 'New app' here: https://developer.xero.com/app/manage
- This integration uses 'Custom connection', because we are syncing data from machine to machine. See this page for more details on app types.
- Select the scopes
accounting.transactions
,accounting.contacts
andaccounting.settings.read
. - Get your client ID and client secret, and pass them into the plugin like so:
npm install xero-node
to install the Xero NodeJS client.
If you are getting { error: 'invalid_client' }
during startup, you might have to recreate your Xero app on https://developer.xero.com/app/manage.
Custom accounting strategy
You can implement your own export strategy to export invoices to your custom accounting platform. Take a look at the included XeroUKExportStrategy
as an example.
Migrating from V1 to V2 of this plugin
- Always create a backup of your database
- Install the plugin and generate a migration
- In your migration file, add the function
migrateInvoices(queryRunner)
to the bottom of theup
function in your migration file, like so
- Run the migration.