We now have an order receipt email rendered from a special commerce-order-receipt twig template.
We can use the same template when generating a PDF of an order.
The PDF generation is done by entity_print. That module allows entity types to define renderers, so we need to define one for commerce_order that renders the twig template and returns it.

Default renderer: http://cgit.drupalcode.org/entity_print/tree/src/Renderer/ContentEntityR...

CommentFileSizeAuthor
#87 2831952-87.patch12.87 KBmglaman
#86 2831952-86.patch6.73 KBmglaman
#85 interdiff-2831952-84-85.txt5.24 KBmglaman
#85 create_an_entity_pri-2831952-85.patch7.04 KBmglaman
#84 create_an_entity_pri-2831952-83.patch7.66 KBmglaman
#74 2831952--74.patch7.41 KBStryKaizer
#73 2831952--73.patch7.41 KBStryKaizer
#73 interdiff.txt2.41 KBStryKaizer
#68 commerce-order-2831952-67.patch5.79 KBdrupalnesia
#66 changes_64-66.txt958 bytesmartin_klima
#66 commerce-order-2831952-66.patch6.45 KBmartin_klima
#64 commerce-order-2831952-64.patch6.35 KBvanlindholm
#48 commerce-order-2831952-47.patch6.69 KBAnonymous (not verified)
#47 commerce-order-2831952-46.patch6.38 KBAnonymous (not verified)
#41 create_an_entity_print-2831952-41.patch6.71 KBsorabh.v6
#41 create_an_entity_print-2831952-41-interdiff.txt287 bytessorabh.v6
#41 Screenshot from 2017-10-12 14-47-07.png108.2 KBsorabh.v6
#37 interdif.txt2.16 KBbenjy
#37 2831952-37.patch6.34 KBbenjy
#37 Order 1 receipt - wkhtmltopdf.pdf18.72 KBbenjy
#31 Order 1 receipt.pdf8.61 KBbojanz
#31 2831952-31-entity-print.patch6.61 KBbojanz
#27 interdiff.txt4.26 KBbenjy
#27 2831952-27.patch6.14 KBbenjy
#26 Order 2 receipt.pdf8.26 KBsumanthkumarc
#24 create_an_entity_print-2831952-24.patch5.67 KBsumanthkumarc
#21 create_an_entity_print-2831952-21.patch5.36 KBsumanthkumarc
#19 create_an_entity_print-2831952-19.patch5.33 KBsumanthkumarc
#13 interdiff.txt870 bytesbenjy
#13 2831952-13.patch4.74 KBbenjy
#13 Screen Shot 2017-01-18 at 12.10.03 pm.png75.66 KBbenjy
#12 2831952-12.patch3.89 KBbenjy
#10 interdiff.txt755 bytesbenjy
#10 2831952-9.patch2.71 KBbenjy
#9 interdiff.txt4.11 KBbenjy
#9 2831952-8.patch3.45 KBbenjy
#9 commerce-order-1.pdf18.89 KBbenjy
#9 export.png21.28 KBbenjy
#6 entity_print_renderer_for_orders-2831952-6.patch3.07 KBvasike
#3 entity_print_renderer_for_orders-2831952-3.patch3.11 KBvasike

Issue fork commerce-2831952

Command icon Show commands

Start within a Git clone of the project using the version control instructions.

Or, if you do not have SSH keys set up on git.drupalcode.org:

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

bojanz created an issue. See original summary.

mglaman’s picture

vasike’s picture

here is patch for this issue

new CommerceOrderEntityRenderer that use the order receipt template for Entity Print render.

Also added Entity print issue about Commerce order - #2721405: Remove entity_print_commerce_order from Drupal 8 version.
It seems the module has a solution for printing Commerce orders on D7.

vasike’s picture

Some questions for some extra configs:
- Email : Use the pdf as email attachement it Entity print installed?
- Entity print renderer : use order receipt template or a view mode?

bojanz’s picture

I'm fine with leaving "pdf as an email attachment" to a documentation page. I'd appreciate it if you could write the code sample that does it, though.

The order receipt template should be used.

vasike’s picture

Updates:

New patch : Rename Renderer class name for Commerce order, from CommerceOrderEntityRenderer to OrderEntityRenderer.

About "pdf as an email attachment"

  • First Configure the Mail System - use Swift Mailer or something that allow mail attachements.
  • Alter commerce_order.order_receipt_subscriber service - use a custom class in a custom module.
    https://www.drupal.org/docs/8/api/services-and-dependency-injection/alte...
  • Build custom CustomOrderReceiptSubscriber class which should have the code for attaching the Entity prin pdf for the order - custom code in the sendOrderReceipt method.
    For this, maybe #2716005: Add export to email functionality Entity print issue could help with some helper code (methods) to get the pdf files easier.

    I was able to add a pdf attachement with the following code

        // Create the Print engine plugin.
        $print_engine = \Drupal::service('plugin.manager.entity_print.print_engine')->createSelectedInstance('pdf');
        // get blob
        $printBuilder = \Drupal::service('entity_print.print_builder');
        $renderer = $printBuilder->rendererFactory->create([$order]);
        $content  = array_map([$renderer, 'render'], [$order]);
        $render       = [
          '#theme' => 'entity_print__' . $order->getEntityTypeId() . '__' . $order->bundle(),
          '#title' => $this->t('View @type', ['@type' => $print_engine->getExportType()->label()]),
          '#content' => $content,
          '#attached' => [],
        ];
        $use_default_css = \Drupal::config('entity_print.settings')->get('default_css');
        // Allow other modules to alter the generated Print object.
        $printBuilder->dispatcher->dispatch(PrintEvents::PRE_SEND, new PreSendPrintEvent($print_engine, [$order]));
    
        $print_engine->addPage($renderer->generateHtml([$order], $render, $use_default_css, TRUE));
        $blob = $print_engine->getBlob();
    
        $destination = file_default_scheme() . '://' . $order->bundle() . $order->id() . '.pdf';
    
        // save file
        /** @var \Drupal\file\FileInterface $file */
        $file = file_save_data($blob, $destination, FILE_EXISTS_REPLACE);
        $attachment = new \stdClass();
        $attachment->uri = $file->getFileUri();
        $attachment->filename = $file->getFilename();
        $attachment->filemime = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $file->getFileUri());
        $params['files'][] = $file;
    

    But i think Entity print should provide a more "direct" solution to get the file.

benjy’s picture

I would consider adding a save() method or such to the print builder class if saving to disk is a common requirement, i've seen a few people doing it, that's why we added getBlob().

You could use printHtml() to get the HTML which makes things a little nicer.

$printBuilder = \Drupal::service('entity_print.print_builder');
$html = $printBuilder->printHtml($entity);
$print_engine->addPage($html);
$blob = $print_engine->getBlob();

Also when I reviewed this patch earlier today I realised I was always planning on reducing the number of dependencies for RendererBase, i'm looking at doing that here; #2843832: Reduce the dependencies for renderers which will probably be the last API change for the 8.2.x branch before I tag an RC.

vasike’s picture

@benjy : thanks for the support. the code did work.
one remark - $print_engine was missing

Here is the updated code, i tested successfully.

    // Build the entity print file for order receipt.
    $print_engine = \Drupal::service('plugin.manager.entity_print.print_engine')->createSelectedInstance('pdf');
    $printBuilder = \Drupal::service('entity_print.print_builder');
    $html = $printBuilder->printHtml($order);
    $print_engine->addPage($html);
    $blob = $print_engine->getBlob();

    // Save the file.
    $destination = file_default_scheme() . '://' . $order->bundle() . $order->id() . '.pdf';
   /** @var \Drupal\file\FileInterface $file */
    $file = file_save_data($blob, $destination, FILE_EXISTS_REPLACE);
    $attachment = new \stdClass();
    $attachment->uri = $file->getFileUri();
    $attachment->filename = $file->getFilename();
    $attachment->filemime = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $file->getFileUri());
    
    // Attach the file to order receipt email.
    $params['files'][] = $attachment;

@benjy : indeed it's nicer, but, still, do you think there could be a quicker way to do it?
as EntityPrintController::viewPrint, maybe a EntityPrintController::getFile or something?
thank you

benjy’s picture

I tested this patch with a couple of changes alongside #2843832: Reduce the dependencies for renderers and it works as expected, sample PDF attached.

Not sure if there were any plans but we could add the options into the sidebar like so:

export

Unless entity_print was a requirement it would need a if module exists, then render the Download PDF receipt link.

benjy’s picture

+++ b/modules/order/src/Form/OrderForm.php
@@ -96,6 +96,14 @@ class OrderForm extends ContentEntityForm {
+    $form['export'] = [
+      '#type' => 'details',
+      '#title' => $this->t('Export'),
...
+    $form['export']['download'] = $this->fieldAsReadOnly('Download PDF Receipt', '');
+    $form['export']['email'] = $this->fieldAsReadOnly('Email PDF Receipt', '');

Ooops, these weren't meant to be in the patch, I just hacked it in for the screenshot :)

@vasike - i've opened #2843869: Provide an API to save the printed document to disk to look at making the save to disk stuff easier.

benjy’s picture

I've posted a patch for a savePrintable() method in #2843869: Provide an API to save the printed document to disk which would reduce the code to:

    // Build the entity print file for order receipt.
    $print_engine = \Drupal::service('plugin.manager.entity_print.print_engine')->createSelectedInstance('pdf');
    $print_builder = \Drupal::service('entity_print.print_builder');

    // Save the file.
    $uri = $print_builder->savePrintable([$order], $print_engine);
    $attachment = new \stdClass();
    $attachment->uri = $uri;
    $attachment->filename = basename($uri);
    $attachment->filemime = finfo_file(finfo_open(FILEINFO_MIME_TYPE), $uri);
    
    // Attach the file to order receipt email.
    $params['files'][] = $attachment;

Please review if you have time. I'll re-roll the patch here shortly with the download links in the sidebar as proposed in #9 unless anyone has any other ideas?

benjy’s picture

Here's the latest version of the patch, works with entity print dev right now but i'll tag a release once this goes in.

@bojanz, I pinged you on IRC, was looking for some input on where to put a "Download receipt" link for the PDF. I was thinking on the right-hand side as per #9 but I see it's a twig template. Maybe we want some kind of generic way for other modules to integrate order actions into that sidebar? Or we can add a new section directly in the twig template, will need some direction on what you want to call it though.

benjy’s picture

OK, I added the link to the template directly. I put it under "Order actions" which is kind of a lie because it does a check on the entity_print_view_pdf variable specifically but at least there is opportunity to make that more generic in the future.

The default link text would be "View PDF" as per the extra field from the Entity Print module but that is customisable from: /admin/commerce/config/order-types/default/edit/display

Download PDF

sumanthkumarc’s picture

@bojanz and @benjy should we make the entity_print module a requirement for order module or is there other ways of checking it?

name: Commerce Order
type: module
description: 'Defines the Order entity and associated features.'
package: Commerce
core: 8.x
dependencies:
  - commerce
  - commerce:commerce_price
  - commerce:commerce_store
  - entity_reference_revisions
  - options
  - profile
  - state_machine
  - entity_print

Also adding to @benjy about side bar tabs, it would be good if we had a class(like checkoutPane) which we can extend and it has method(like buildPane) which returns render array what needs to be showed there.

Also i suppose we can have a link/button in the CompletionMessage Pane , where we can print the order invoice for end user. right now it just shows a message. Maybe we can build a configuration about enabling the link for invoice printing in that pane?

benjy’s picture

I don't think it needs to be a hard dependency, the extra field is only there when Entity Print is installed and the check in the template is enough.

sumanthkumarc’s picture

  entity_print.renderer.commerce_order:
    class: Drupal\commerce_order\Renderer\OrderEntityRenderer
    arguments: ['@renderer', '@entity_print.asset_renderer', '@event_dispatcher', '@entity_type.manager', '@commerce_order.order_total_summary']

I see that this service has "entity_print.asset_renderer" as argument, this throws below error:

Symfony\Component\DependencyInjection\Exception\ServiceNotFoundException: The service "entity_print.renderer.commerce_order" has a [error] dependency on a non-existent service "entity_print.asset_renderer".

Also i see OrderEntityRenderer extends ContentEntityRenderer

benjy’s picture

hmm, that's an annoying one because I just split that dependency out to improve the Entity Print code. We could use a ServiceProvider but let me think on it a little, see if there are better options. @bojanz, any thoughts on that?

bojanz’s picture

Yes, it needs to be in a ServiceProvider. We had the same problem inside the commerce_log submodule, you can't use services.yml for services of modules you don't depend on.

Example: https://github.com/drupalcommerce/commerce/blob/8.x-2.x/modules/log/src/...

sumanthkumarc’s picture

Moved the service from yml to service provider as @bojanz suggested. Attaching patch.

@benjy which link should i use to test the print of order(like pdf you have attached)? i tried /print/pdf/order/{order_id}, but it says access denied, eventhough i'm user 1.

bojanz’s picture

Status: Needs review » Needs work
+class OrderServiceProvider extends ServiceProviderBase {

That won't work, the class needs to match the full module name. CommerceOrderServiceProvider

sumanthkumarc’s picture

benjy’s picture

The View PDF link should appear on the order, it probably needs to be dragged into view on the order display?

Direct link would be: /print/pdf/commerce_order/{order_id}

+++ b/modules/order/src/Renderer/OrderEntityRenderer.php
@@ -0,0 +1,91 @@
+  protected function getLabel(EntityInterface $entity) {

This should be `public function getFilename(array $entities)` if we want to override the filename.

sumanthkumarc’s picture

@benjy Thanks

Also i'm getting the below error:

TypeError: Argument 2 passed to Drupal\commerce_order\Renderer\OrderEntityRenderer::__construct() must be an instance of Drupal\entity_print\Asset\AssetRendererInterface, none given, called in /var/www/html/ipassio_dev/core/lib/Drupal/Component/DependencyInjection/Container.php on line 268 in Drupal\commerce_order\Renderer\OrderEntityRenderer->__construct() (line 47 of modules/contrib/commerce/modules/order/src/Renderer/OrderEntityRenderer.php).

trying to debug this.

i will give anew patch once i fix this and able to test the pdf printing.

sumanthkumarc’s picture

@benjy and @bojanz thanks. This patch is working correctly.

sumanthkumarc’s picture

Status: Needs work » Needs review

NR

sumanthkumarc’s picture

FileSize
8.26 KB

attaching the pdf as well, which shows overrided pdf name.

benjy’s picture

Re-rolled for #2845323: Transliteration of printed document filename - and simplified the filename method. Tested and everything is working, I had to drag the View PDF field into display on the order manage display interface though. Maybe we should add an event listener to do that automatically in Commerce when entity print is enabled? Or, provide our own extra field?

sumanthkumarc’s picture

@benjy and @bojanz, or in case anyone comes here wondering about the print pdf link, you can try the below code if you don't want to drag the field:

NOTE: $order is order object below.

    $route_params = [
      'entity_type' => 'commerce_order',
      'entity_id' => $order->getOrderNumber(),
      'export_type' => trim('pdf', '_engine'),
    ];

    $pdf_link = Url::fromRoute('entity_print.view', $route_params);
    $pane_form['message']['pdf_link'] = [
      '#type' => 'link',
      '#title' => t('PRINT / VIEW INVOICE'),
      '#url' => $pdf_link,
      '#attributes' => [
        'class' => [
          'button',
        ],
      ],
    ];
sumanthkumarc’s picture

@benjy also, did you raise a PR for this??

benjy’s picture

No, i've not created a PR.

bojanz’s picture

Status: Needs review » Needs work
FileSize
6.61 KB
8.61 KB

Here is an updated patch:
1) Made the "View PDF" extra field shown by default (via commerce_order_entity_extra_field_info_alter())
2) Moved the field from the otherwise empty Order Actions fieldset to the top fieldset (below the timestamps)
3) Code tweaks of all kinds.

Attached is a sample PDF. I am not happy with how it looks. Notice how it doesn't cover the entire page.
@benjy Any tips for improving this? Is this a dompdf limitation? I'm fine with having a separate template with its own styling, if needed.

TODO:
We need to hide the link if the order is still a draft, because the receipt template assumes that the order has already been placed.

benjy’s picture

Dompdf does interpret a few styles differently to a browser, you can usually tweak the CSS to get it something like. I'll try take a look at the generated output to see if there is anything obvious.

+++ b/modules/order/src/CommerceOrderServiceProvider.php
@@ -0,0 +1,33 @@
+class CommerceOrderServiceProvider extends ServiceProviderBase {

I've been thinking, Entity Print is still in beta, I could change how this works to use a entity handler, that would let us avoid the service provider pattern which i'm not a fan of, thoughts?

bojanz’s picture

A "print" handler would be wonderful.

mglaman’s picture

+1 to print handler. I think it'd be great to just add something to the entity definition for integration.

benjy’s picture

Opened #2857785: Add a print entity handler - will work on it the next week or so.

benjy’s picture

If anyone would like to review there is now a patch in #2857785: Add a print entity handler

benjy’s picture

Status: Needs work » Needs review
FileSize
18.72 KB
6.34 KB
2.16 KB

I've re-rolled this patch to work with the entity handler. I think the issue with Dompdf is the implicit display: table that it struggles with, see the attached PDF from wkhtmltopdf which works fine.

bmcclure’s picture

Latest patch is working well for me.

Didn't work locally on my VM but I believe it needs external http access to the site to generate the PDF with the default entity_print settings. When running it from anywhere public, this is working great for me.

Would be handy to use a different template since the messaging should ideally be different between invoices and order emails, but this is sufficient for me at the moment.

benjy’s picture

Didn't work locally on my VM but I believe it needs external http access to the site to generate the PDF with the default entity_print settings

This depends on the print engine and how they gather up the assets. The module has settings to make common issues work from development environments like HTTP auth and HTTPS if you don't have a certificate locally. It should have provided some helpful errors so if that wasn't the case, feel free to open an issue in the Entity Print queue and we can work this one out.

sumanthkumarc’s picture

+1 for the entity handler and the patch. it works fine. there was %20 in the filename instead of space when i saved pdf. and site logo in pdf was shrinked. i guess it has to do with dompdf!!

sorabh.v6’s picture

Hi All,

Patch is working for me, but I think there's a need to mention entity_print module as a dependency. So, I updated patch in #37.

I also think the layout of the order container in the pdf is not centered. Image is attached -

benjy’s picture

@sorabh.v6 - no it isn't a hard dependency so shouldn't be in the info file. Try wkhtmltopdf which has better rendering support for display: table and correctly renders the table centred.

sorabh.v6’s picture

@benjy When I was looking at code in OrderRenderer, Phpstorm started showing error regarding ContentEntityRenderer that it is not found. So, I thought maybe print_entity is necessary.

Thanks

flocondetoile’s picture

Hello,

I'am using the savePrintable() method (with this patch #37) to generate the commerce order receipt to a pdf file and attach it to an email (in an Event subscriber). But the template used is always the original template (located in the commerce_order module), and not the custom template overrided in the default theme.

Any input ?

flocondetoile’s picture

Well. I was able to "solve" this issue by bypassing it. Simply by overriding templates from a module and not the default theme, with some custom themes implementations in a hook_theme() form a custom module.

For example

/**
 * Implements hook_theme().
 */
function MYMODULE_theme($existing, $type, $theme, $path) {
  $themes = [];

  $themes['commerce_order_receipt__default'] = [
    'variables' => [
      'order_entity' => NULL,
      'billing_information' => NULL,
      'shipping_information' => NULL,
      'payment_method' => NULL,
      'totals' => NULL,
    ],
    'base hook' => 'commerce_order_receipt',
  ];

  $themes['entity_print__commerce_order'] = [
    'variables' => [
      'title' => '',
      'content' => NULL,
      'entity_print_css' => NULL,
    ],
    'base hook' => 'entity_print',
  ];

  return $themes;
}

And then the templates overriden are well used by the savePrintable() method. Note that the templates located in the default theme are well used with the "View PDF' link (from the admin theme).

But this issue could conduct to a poorly Themer experience. I wonder if there is a solution to check if the default theme has some templates suggestion when using the entity_print handler class ?

postback’s picture

I can confirm #45.

The /print/pdf/myentity/4 and /print/pdf/myentity/4/debug URL's use the twig template created inside a custom theme (i.e. themes/custom/mytheme/templates/entity-print--myentity.html.twig).

Yet, generating the PDF with code, doesn't use that template, it uses the one in /modules/contrib/entity_print/templates


$print_engine = \Drupal::service('plugin.manager.entity_print.print_engine')->createSelectedInstance('pdf');
$print_builder = \Drupal::service('entity_print.print_builder');

$uri = $print_builder->savePrintable([$myentity], $print_engine, 'public','somefilename.pdf');

#45 solved this for me.

The only caveat is that you need to input #45 in a .module file of a custom module, causing things like {{ base_path }} and {{ directory }} not linking to the custom theme I defined. But I'm using hard coded absolute paths to solve this, for the time being.

Anonymous’s picture

I have the need to render the store which is responsible for the order. I added the store variable to the renderSingle() method. The patch attached in #42 didn't apply, so I created a new one based on #37.

Anonymous’s picture

Ah forgot to add the store to the theme function.

The last submitted patch, 47: commerce-order-2831952-46.patch, failed testing. View results

Status: Needs review » Needs work

The last submitted patch, 48: commerce-order-2831952-47.patch, failed testing. View results

Anonymous’s picture

Status: Needs work » Needs review

Maybe this is the wrong thread, I just want to add a notice about the requirements for an order receipt. In Germany we have the need to show additional informations on the receipt (Attached terms of service, bank account data, cancellation terms,..). I am sure these requirement will differ from country to country, but some of them are equal. So do we make this order receipt renderer more generally or is every sitebuilder responsible to extend and or attach informations to the order receipt?

The last submitted patch, 6: entity_print_renderer_for_orders-2831952-6.patch, failed testing. View results

The last submitted patch, 9: 2831952-8.patch, failed testing. View results

The last submitted patch, 13: 2831952-13.patch, failed testing. View results

The last submitted patch, 24: create_an_entity_print-2831952-24.patch, failed testing. View results

The last submitted patch, 10: 2831952-9.patch, failed testing. View results

The last submitted patch, 12: 2831952-12.patch, failed testing. View results

The last submitted patch, 31: 2831952-31-entity-print.patch, failed testing. View results

The last submitted patch, 21: create_an_entity_print-2831952-21.patch, failed testing. View results

The last submitted patch, 41: create_an_entity_print-2831952-41.patch, failed testing. View results

The last submitted patch, 27: 2831952-27.patch, failed testing. View results

The last submitted patch, 37: 2831952-37.patch, failed testing. View results

flocondetoile’s picture

@Almare you can use hook_preprocess_HOOK() to add anything to the order receipt template. Informations you mention (Attached terms of service, bank account data, cancellation terms,..) are really specific for each project and its requirements.

So adding the store to the template seems to me a bit out of scope, or at least, a specific narrow use case. For example, I manage these informations (bank data, payment information) in a custom config form (and with some condition on the payment gateway used) , and I inject them into the order receipt via a preprocess hook.

vanlindholm’s picture

I had problems with #37 with php 7.2 in the OrderRenderer due to:

count(): Parameter must be an array or an object that implements Countable

This patch addresses that. It is essentially #37 with a fix for the count issue.

Status: Needs review » Needs work

The last submitted patch, 64: commerce-order-2831952-64.patch, failed testing. View results

martin_klima’s picture

Status: Needs work » Needs review
FileSize
6.45 KB
958 bytes

Patch #64 causes warnings if entity_print module is not enabled.
I applied patch #64 to latest 2.x-dev commit, fixed code and created new patch against 2.x-dev.

drupalnesia’s picture

This patch caused two VIEW PDF elements, because already added by this patch:
- Display custom fields on order admin view page

drupalnesia’s picture

Path #66 has double View PDF because missing field already fixed by Display custom fields on order admin view page

nessunluogo’s picture

Thank you all for this extremely useful functionality!
I just tested successfully patch #68 on current stable commerce installation.

petergus’s picture

Since I was confused as to why it wasn't working I will drop a hint here: I had to add the field to the order type display /admin/commerce/config/order-types/default/edit/display

Otherwise patch 68 works.

Just wish there was a way to style the pdf?? Found this for styling https://www.drupal.org/node/2706755

Neograph734’s picture

Hi all, thanks for your effort on this. I am a bit confused while testing though.

I suppose I need this patch together with #2915559: Display custom fields on order admin view page. This however only enabled the View PDF link on the admin page. Shouldn't users be able to download their own receipts from the account page http://example.com/user/[uid]/orders/[order_id] as well? Or did I miss something?

Update: I have updated the patch in #2915559-14: Display custom fields on order admin view page to also show the fields on the user order page.

petergus’s picture

I am using this with entity print module, but the date is missing. I have tried the following code from commerce-order--admin but it doesnt get any data.

<h3 class="entity-meta__title">
  {{ order_state }}
</h3>
{% for key in ['completed', 'placed', 'changed'] %}
  {% if order[key] %}
    <div class="form-item">
      {{ order[key] }}
    </div>
  {% endif %}
{% endfor %}

Is there another way, or can I get the data from order_entity somehow?

StryKaizer’s picture

Attached patch adds a provider to "commerce_order_receipt" to allow overwriting the 'commerce-order-receipt' template specificly for entity_print.

You can now use:
commerce-order-receipt.html.twig
commerce-order-receipt--email.html.twig
commerce-order-receipt--entity-print.html.twig

StryKaizer’s picture

FileSize
7.41 KB
jastraat’s picture

The patch in #74 works so far although I need to experiment with modifying/customizing some of the templates. As someone mentioned earlier, if you want a link to the PDF to appear on the order view page though, you also need the patch from https://www.drupal.org/project/commerce/issues/2915559#comment-13188309

jastraat’s picture

Edit: issues with the patch in #74 appear to have been related to a conflict with commerce_purchase_order. After uninstalling commerce_purchase_order, the templates for order receipt print as expected.

We are using this patch successfully on our site with the latest (2.17) version of Commerce.

jastraat’s picture

Status: Needs review » Reviewed & tested by the community

Marking as reviewed because we are using this in production but I believe the patch may need tests.

hockey2112’s picture

I'm looking for a way to automatically attach a PDF version of the receipt to the order receipt email. It appears that some of the methods in this thread are intended to do that, but it is a bit difficult to follow. Does anyone have a complete working example, or can you point me in the right direction? Thanks!

jastraat’s picture

You essentially need this patch + HTML enabled email with swiftmailer + entity_print

The default templates are pretty minimal though, so you will definitely want to have a custom version of commerce-order-receipt.html.twig (in a module likely since your theme may not apply in email.)

kaipipek’s picture

There is a bug in the provided template. Order item quantity is always returned as integer even when it is a decimal value for some order item line types. Instead of just order_item.getQuantity|number_format is should be something like this:

{% if order_item.getQuantity|number_format != order_item.getQuantity|round(2) %}
{{ order_item.getQuantity|number_format(2, '.', ',') }}
{% else %}
{{ order_item.getQuantity|number_format }}
{% endif %}
mglaman’s picture

RE: #80

Reposting from #2918482: Create a shipment notification when shipment is completed, this is not a bug.

Decimal value quantities are non-standard. We also use number_format in the default order receipt. Any project utilizing decimal quantities will have to override this template, just like the order receipt template and any other customizations that had to be made.

kaipipek’s picture

What do you mean decimal value quantities are non-standard? They are standard since Drupal 8. There is no need for additional modules like before.

mglaman’s picture

Assigned: Unassigned » mglaman

What do you mean decimal value quantities are non-standard? They are standard since Drupal 8. There is no need for additional modules like before.

In Drupal Commerce. We assume quantities will always be non-decimal.

Reviewing this patch so we can finally land it 🛠

mglaman’s picture

Rerolled against 8.x-2.x

  1. +++ b/modules/order/commerce_order.module
    @@ -58,6 +59,7 @@ function commerce_order_theme($existing, $type, $theme, $path) {
     /**
    +<<<<<<< ours
      * Implements hook_theme_suggestions_commerce_order_item().
      */
    

    🤦‍♂️

  2. +++ b/modules/order/commerce_order.module
    @@ -158,9 +174,15 @@ function commerce_order_theme_suggestions_commerce_order(array $variables) {
    +  if($variables['provider']){
    ...
    +    if($variables['provider']){
    

    phpcs

  3. +++ b/modules/order/src/Entity/Order.php
    @@ -55,6 +55,7 @@ use Drupal\profile\Entity\ProfileInterface;
    + *     "entity_print" = "Drupal\commerce_order\Renderer\OrderRenderer"
    

    The naming feels weird here, like it isn't explicitly intended to render for Entity Print.

    Why use this over the entity view builder, etc?

  4. +++ b/modules/order/src/Renderer/OrderRenderer.php
    @@ -0,0 +1,122 @@
    +    $entities_label = $this->filenameGenerator->generateFilename($entities, function ($order) {
    +      /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    +      return $order->id();
    +    });
    +    $count = is_array($entities_label) ? count($entities_label) : 1;
    

    Feels weird that the method maybe returns an array. Are we sure it doesn't always return one?

  5. +++ b/modules/order/src/Renderer/OrderRenderer.php
    @@ -0,0 +1,122 @@
    +  protected function renderSingle(OrderInterface $order) {
    +    $build = [
    +      '#theme' => 'commerce_order_receipt',
    +      '#order_entity' => $order,
    +      '#totals' => $this->orderTotalSummary->buildTotals($order),
    +      '#provider' => 'entity_print'
    +    ];
    +    if ($billing_profile = $order->getBillingProfile()) {
    +      $build['#billing_information'] = $this->profileViewBuilder->view($billing_profile);
    +    }
    +
    +    return $build;
    +  }
    

    I don't think this needs to be in its own method. Someone can just override the entire render method if they so choose.

mglaman’s picture

Assigned: mglaman » Unassigned
Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests
FileSize
7.04 KB
5.24 KB

An updated patch addressing my comment #84. We need to add a test for this, which has the @requires module entity_print and add Entity Print to the require-dev in our composer.json.

I still am not sure about the namespace for the renderer. It makes sense as Renderer outside of Entity Print. But elsewhere it does look right. I'm also not a fan of the "provider" added in #73. I can understand needing to customize the PDF version (especially with how finicky dompdf can be.) But, there isn't any other way since other entities you can rely on the PDF display format.

  1. +++ b/modules/order/commerce_order.module
    @@ -43,6 +43,7 @@ function commerce_order_theme($existing, $type, $theme, $path) {
    +        'provider' => '',
    
    @@ -158,9 +174,15 @@ function commerce_order_theme_suggestions_commerce_order(array $variables) {
    +  if($variables['provider']){
    +    $suggestions[] = $variables['theme_hook_original'] . '__' . $variables['provider'];
    +  }
    ...
    +    if($variables['provider']){
    +      $suggestions[] = $variables['theme_hook_original'] . '__' . $order->bundle() . '__' . $variables['provider'];
    +    }
    
    +++ b/modules/order/src/Mail/OrderReceiptMail.php
    @@ -64,6 +64,7 @@ class OrderReceiptMail implements OrderReceiptMailInterface {
    +      '#provider' => 'email'
    

    I get the concept. But it feels weird adding "provider".

  2. +++ b/modules/order/src/Renderer/OrderRenderer.php
    @@ -0,0 +1,122 @@
    +    $this->profileViewBuilder = $entity_type_manager->getViewBuilder('profile');
    

    No need to inject it as a property, we can fetch it when needed to lower the cost of constructing this class.

  3. +++ b/modules/order/src/Renderer/OrderRenderer.php
    @@ -0,0 +1,122 @@
    +    $entities_label = $this->filenameGenerator->generateFilename($entities, function ($order) {
    +      /** @var \Drupal\commerce_order\Entity\OrderInterface $order */
    +      return $order->id();
    +    });
    +    $count = is_array($entities_label) ? count($entities_label) : 1;
    

    This always returns a string

mglaman’s picture

FileSize
6.73 KB

This still needs a test. But I've removed the provider key for a specific theme hook that the EntityPrint render can use: https://git.drupalcode.org/issue/commerce-2831952/-/commit/b4a03e6503317...

mglaman’s picture

Status: Needs work » Needs review
Issue tags: -Needs tests
FileSize
12.87 KB

Okay! This adds a test. It also verifies the proper template is used, via a test module which overrides it.

Interdiff: https://git.drupalcode.org/issue/commerce-2831952/-/commit/045645dd803e3...

GitLab diff: https://git.drupalcode.org/issue/commerce-2831952/-/compare/8.x-2.x...28...

mglaman’s picture

Got a +1 from @StryKaizer in Drupal Slack

Not sure if there is any other usecase, looks good for me :slightly_smiling_face:

  • mglaman committed 78adb69 on 8.x-2.x
    Issue #2831952 by benjy, mglaman, sumanthkumarc, StryKaizer, vasike,...
mglaman’s picture

Status: Needs review » Fixed

Thanks, everyone, for their work and input on this. 🥳 Committed!

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

trickfun’s picture

Thanks for the great work but the output load wrong twig.
I have 2 type of orders. default and parker.

When i try to print PDF of parker order type, in the html i have this suggestions:

x commerce-order-receipt--entity-print.html.twig
x commerce-order-receipt--entity-print.html.twig
* commerce-order-receipt--entity-print--parked.html.twig
* commerce-order-receipt.html.twig

but both orders are always rendered with commerce-order-receipt--entity-print.html.twig.

I put twig files into templates folder of the active theme and set up hook_theme into custom module but no success.
I need to write HOOK_preprocess_entity_print to change twig file.


function gey_commerce_order_preprocess_entity_print(&$vars) {
    //kint($vars);
    $vars['content'][0][0]['#theme'] = 'commerce_order_receipt__entity_print__parked';
}

It's the right choice or something is wrong?
thank in advance

ShenHua’s picture

As in the screen attached in #41

Entity_print still prints the order not centered but aligned to the right. Any way to fix this?

OK, I figured it out. Just have to use the print-style.css, and commerce-order-receipt.html.twig in one's template.
Then when styling, the key is to know that A4 page (I found it with Illustrator) is 595px wide.

Then just have to apply the max-width as 595px to the main tables, and viola, it's centered fine.

arefen’s picture

Hi. How can I use this functionality?
I install entity_print module and use the latest version of drupal commerce but I can't see any button for print order on the order page.