How to print orders in Commerce

Commerce Order page with button

In this tutorial or guide, I will share the best solutions I found for two basic Drupal Commerce use-cases and delve into their respective setup.

Commerce Kickstart 2 (CK2) is a great distribution for setting up an online store; it packs a lot of goodies out-of-the-box. But it can't have them all. Printing an order to PDF is not included. So one has to do some R&D for that.

Print to PDF in the Commerce admin UI

It is common practice to include a printed version of the customer's order - also known as a packing slip - when shipping purchased goods. In this use case, our objective is to allow admins to easily print an oder to PDF.

If you google "Drupal 7 commerce print" you will quickly find two modules: Entity Print and Commerce Packing Slip. I'll come back to Entity Print later.

For our first use-case, Commerce Packing Slip offers a lightweight solution in a customized order view to be used as a printable packing slip. It takes 2 minutes to install and configure and, best of all, it has no dependencies other than Commerce and Views i.e. no PDF library to install and configure. Very nice!

Installation Guide

  • Install and enable Commerce Packing Slip (need help ?)

That's it!

Now go to Orders (/admin/commerce/orders) and simply select the Packing Slip menu item from the Quick Edit dropdown for the order you wish to print. From the Packing Slip page (a customizable view by the way), simply print like you would print any document (ctrl + P, cmd + P, etc.) and print to your printer or save as PDF.

Beautiful! Gotta love it when it's that simple.

The flip side of simplicity is often a reduced scope of action. As it turns out, the Packing Slip functionality is only available in the admin UI i.e. not available to customers who might like to print or download a PDF of their order. Nevertheless, Commerce Packing Slip is one great module.

Print to PDF in a customer's account

As a store owner, you may not need or want to print packing slips at all and instead simply let customers download a PDF version of their order should they need one.

In this use case, our objective is to allow logged in customers to easily download a PDF copy of their orders.

It think it would be great if Commerce Packing Slip offered this functionality. Why install two modules if you can cover all bases with one. So I posted a feature request in the issue queue. If you feel this is a worthwhile functionality, add your support to this request.

In the mean time, we will have to look elsewhere. After spending quite some time R&D-ing I have narrowed down the field to two modules: Print and Entity Print.

Print has been around for ever it seems (2004) while Entity Print, as its name suggests, is the new kid on the block (2015).

Both modules require the installation of a PDF library. Print supports dompdf, mPDF, TCPDF, Wkhtmltopdf and DocRaptor* PDF Libraries while Entity Print only supports Wkhtmltopdf. Print's versatility comes as a price though, it weighs in at 600 KB versus 119 KB for Entity Print.

As far as installation is concerned, I found it easier or more Drupal-like to install Print because I can add support for the various PDF libraries (except DocRaptor) simply by downloading and installing them in /sites/all/libraries.

In comparison, the Wkhtmltopdf library that Entity Print requires is a os-specific package that can only be installed on the web server, outside Drupal. Entity Print assumes, by default, that the path to this library on the web server is: /usr/local/bin/wkhtmltopdf. But you can change this at /admin/config/content/entityprint.

So ease of installation may or may not be an issue depending on the type of hosting that you have. Pantheon.io, for one, makes this library accessible to all its customers.

So taking all of the above into consideration and wanting to keep it as simple as possible, I chose Print.

Installation Guide: part-1

  • Download the Print module
  • Download one of the libraries e.g. mpdf to /sites/all/libraries
  • Enable the following modules: PDF version (print_pdf) and mPDF library handler (print_pdf_mpdf). We don't need Printer-friendly pages since this is for nodes entities and what we're dealing with is order entities.
  • To be sure the library is properly installed, go to /admin/reports/status and look for Printer, email and PDF versions - PDF generation library and make sure it's green.
  • Enable Access the PDF version permission for authenticated users @ /admin/people/permissions.
  • Configure Print @ /admin/config/user-interface/print/pdf.

About the last bullet, at the very least have a look at Open PDF in, Paper size (set to A4 by default) and PDF filename in which one of the tokens refers to [node:nid] while what we care about is orders. I changed the default value to this:

[site:name] - User [current-user:uid] - Order [current-page:url:args:last]

But you are free to change this as you please.

At this point the Print module and your library of choice should be ready to go. You can validate this by going to e.g. /printpdf/user/4/orders/3 (make sure you use valid user and order IDs). If all is well, this will open up the order in your browser's PDF plugin.

Now, if you go to e.g. /user/4/orders/3 you will see the order page. But something is missing, right? For every order, we need to add a link formated as /printpdf/​user/​[uid]/​orders/​[order_id]. To achieve this, we'll edit the view which displays the orders.

Installation Guide: part-2

  • While viewing any order, move you cursor inside the table and from the gear icon, click Edit view.
  • In Header, add a Global: Unfiltered text and paste this in it: <a href="/printpdf/​user/​[uid]/​orders/​[order_id]">Save order as PDF</a>
  • Enable Use replacement tokens from the first row
  • If you click on Replacement patterns you won't see any entries for [order_id] and [uid]. We need to create them.
  • In Fields, add Commerce Line Item: Order ID.
  • Uncheck Create a label, check Exclude from display. Click on Apply.
  • In Relationships, add Commerce Line Item: Order ID and Apply. This will make it possible to access the UID from the order.
  • Back in Fields, now add Commerce Order: Uid.
  • Uncheck Create a label, check Exclude from display. Click on Apply.
  • Now if you look back at the Replacement patterns in the Header, you will see [order_id] and [uid]. We're in business.
  • Finally, save the view.

You should now see the Save order as PDF link in the top left corner of the view. Clicking on this link will either open the PDF in your browser or initiate the download (see settings for Open PDF in @ /admin/config/user-interface/print/pdf). Done!

Note about styling

You may want to theme or style the link with some CSS. One way to do that would be to wrap the Header code in a div. Something like this:

<div class="save-as-pdf">
  <a href="/printpdf/user/[uid]/orders/[order_id]">Save order as PDF</a>
</div>

Having done this, you can now change the plain link into a nice button with a little CSS. In CK2, you could add such CSS to this file: /drupal/​profiles/​commerce_kickstart/​themes/​contrib/​omega_kickstart/​css/​global.css.

/* Save order as PDF button. */
.save-as-pdf {
  padding: 0.25em 1em;
  border: 1px solid #ccc;
  border-radius: 3px;
  margin: 1.5em 1em 1.5em 0;
  width: 120px;
  text-align: center;
}

Although Print does the job, it's worth noting that there are more than 50 pending patches and that the current 7.x-2.x-dev dates back to 2014-Apr-02 or more than 2 years ago. Has Print peaked? With 70,246 reported installs, it could sure use a little love!

* About DocRaptor. A client once asked me if she could save the whole website that we just built for them to a single PDF file, complete with spreads, blanks and high res images? In other words, replacing a corporate Adobe InDesign document that took for ever to update and that was costing them a fortune. How many of you think this is crazy? How many of you would take a crack at this project? Follow me on Twitter to find out what happened.