1

I am aiming to plug the customer's gift message onto the packing slip in place of where it shows the payment method.

I've been spinning my wheels for a while now trying to get this to work. As far as which files to edit and how to format the message I'm fine. However, trying to access the GiftMessage data from within the AbstractPdf class has been futile.

Files of interest: magento/module-sales/Model/Order/Pdf/AbstractPdf.php (This is where I want to pull in the Gift Message data) magento/module-sales/Model/Order/Pdf/Shipment.php

What I've tried: I've tried adding to the constructor the GiftMessage\MessageFactory class, but it doesn't work and I don't know why. I just get a HTTP Error 500 when trying to print the packing slip and it puts nothing in the log files.

    public function __construct(
    \Magento\GiftMessage\Model\MessageFactory $giftMessage,
    \Magento\Payment\Helper\Data $paymentData,
    \Magento\Framework\Stdlib\StringUtils $string,
    \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
    \Magento\Framework\Filesystem $filesystem,
    Config $pdfConfig,
    \Magento\Sales\Model\Order\Pdf\Total\Factory $pdfTotalFactory,
    \Magento\Sales\Model\Order\Pdf\ItemsFactory $pdfItemsFactory,
    \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
    \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation,
    \Magento\Sales\Model\Order\Address\Renderer $addressRenderer,
    array $data = []
) {
    $this->giftMessage = $giftMessage;
    $this->addressRenderer = $addressRenderer;
    $this->_paymentData = $paymentData;
    $this->_localeDate = $localeDate;
    $this->string = $string;
    $this->_scopeConfig = $scopeConfig;
    $this->_mediaDirectory = $filesystem->getDirectoryWrite(DirectoryList::MEDIA);
    $this->_rootDirectory = $filesystem->getDirectoryRead(DirectoryList::ROOT);
    $this->_pdfConfig = $pdfConfig;
    $this->_pdfTotalFactory = $pdfTotalFactory;
    $this->_pdfItemsFactory = $pdfItemsFactory;
    $this->inlineTranslation = $inlineTranslation;
    parent::__construct($data);
}

One file I found in the Gift Message module is OrderGet.php. This file seems to have a function that lets you grab a message using an order as a parameter. Is it possible to easily make use of this class?

5

1 Answer 1

0

I know this has been a year, but I've managed to achieve this on 2.3.4. Hopefully this may help someone later down the line and saves them some time:

I'm not going to go through the technical parts of creating an extension. Assuming you know not to override the vendor folder, you'll know how to get the extension set up.

Anyway, here's my di.xml:

<?xml version="1.0" ?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:ObjectManager/etc/config.xsd">
  <preference for="Magento\Sales\Model\Order\Pdf\Shipment" type="Vendor\Module\Model\Order\Pdf\Shipment" />
</config>

To explain that, a lot of PDF modifications are done using the Order\Pdf\Invoice model. That's for invoices (duh), what we need is Order\Pdf\Shipment.

Next, we need to create our own model. Much like the invoice work you've probably seen, you need to extend the pdf class.

So in Vendor/Module/Model/Order/Pdf I created Shipment.php. This is the full code. I'll explain a couple bits afterwards:

<?php
/**
 * Copyright © Magento, Inc. All rights reserved.
 * See COPYING.txt for license details.
 */
namespace Vendor\Module\Model\Order\Pdf;

use Magento\Catalog\Model\ProductRepositoryFactory;
use Magento\Sales\Model\Order\Pdf\Invoice as InvoicePdf;

class Shipment extends \Magento\Sales\Model\Order\Pdf\Shipment
{
    public function __construct(
        \Magento\Payment\Helper\Data $paymentData,
        \Magento\Framework\Stdlib\StringUtils $string,
        \Magento\Framework\App\Config\ScopeConfigInterface $scopeConfig,
        \Magento\Framework\Filesystem $filesystem,
        \Magento\Sales\Model\Order\Pdf\Config $pdfConfig,
        \Magento\Sales\Model\Order\Pdf\Total\Factory $pdfTotalFactory,
        \Magento\Sales\Model\Order\Pdf\ItemsFactory $pdfItemsFactory,
        \Magento\Framework\Stdlib\DateTime\TimezoneInterface $localeDate,
        \Magento\Framework\Translate\Inline\StateInterface $inlineTranslation,
        \Magento\Sales\Model\Order\Address\Renderer $addressRenderer,
        \Magento\Store\Model\StoreManagerInterface $storeManager,
        \Magento\Framework\Locale\ResolverInterface $localeResolver,
        \Magento\GiftMessage\Api\OrderRepositoryInterface $orderGiftRepo,
        \Magento\Framework\ObjectManagerInterface $objectManager,
        array $data = []
    ) {
        parent::__construct(
            $paymentData,
            $string,
            $scopeConfig,
            $filesystem,
            $pdfConfig,
            $pdfTotalFactory,
            $pdfItemsFactory,
            $localeDate,
            $inlineTranslation,
            $addressRenderer,
            $storeManager,
            $localeResolver,
            $data
        );
        $this->orderGiftRepo = $orderGiftRepo;
        $this->_objectManager = $objectManager;
    }
    public function getPdf($shipments = [])
    {
        $this->_beforeGetPdf();
        $this->_initRenderer('shipment');

        $pdf = new \Zend_Pdf();
        $this->_setPdf($pdf);
        $style = new \Zend_Pdf_Style();
        $this->_setFontBold($style, 10);
        foreach ($shipments as $shipment) {
            if ($shipment->getStoreId()) {
                $this->_localeResolver->emulate($shipment->getStoreId());
                $this->_storeManager->setCurrentStore($shipment->getStoreId());
            }
            $page = $this->newPage();
            $order = $shipment->getOrder();
            /* Add image */
            $this->insertLogo($page, $shipment->getStore());
            /* Add address */
            $this->insertAddress($page, $shipment->getStore());
            /* Add head */
            $this->insertOrder(
                $page,
                $shipment,
                $this->_scopeConfig->isSetFlag(
                    self::XML_PATH_SALES_PDF_SHIPMENT_PUT_ORDER_ID,
                    \Magento\Store\Model\ScopeInterface::SCOPE_STORE,
                    $order->getStoreId()
                )
            );
            /* Add document text and number */
            $this->insertDocumentNumber($page, __('Packing Slip # ') . $shipment->getIncrementId());
            /* Add table */
            $this->_drawHeader($page);
            if($order->getId()) {


                if ($order->getGiftMessageId() != 0) { //If there's no gift message, this will return 0. Need to catch it to prevent an exception.
                    if ($giftWrap = $this->getGiftMessages($order->getId())) {
                        //$logger->info("hello" . $order->getId());
                        $page->drawText(strip_tags(ltrim('### GIFT INFORMATION ###:')), 25, 815, 'UTF-8');
                        $page->drawText(strip_tags(ltrim('Sender: ' . $giftWrap["sender"])), 25, 800, 'UTF-8');
                        $page->drawText(strip_tags(ltrim('Recipient: ' . $giftWrap["recipient"])), 25, 785, 'UTF-8');
                        $page->drawText(strip_tags(ltrim('Message: ' . $giftWrap["message"])), 25, 770, 'UTF-8');
                    }
                }
            }
            /* Add body */
            foreach ($shipment->getAllItems() as $item) {
                if ($item->getOrderItem()->getParentItem()) {
                    continue;
                }
                /* Draw item */
                $this->_drawItem($item, $page, $order);
                $page = end($pdf->pages);
            }
            if ($shipment->getStoreId()) {
                $this->_localeResolver->revert();
            }
        }
        $this->_afterGetPdf();
        return $pdf;
    }
    public function getGiftMessages($order_id) {
        $giftMessage = $this->orderGiftRepo->get($order_id);
        return $giftMessage;
    }


}

I needed to include the OrderRepositoryInterface API (take a peek at vendor/magento/module-gift-message/api/ if you feel like it for reference).

I also needed to include all the parent references in the constructor class, otherwise you'll get an error.

I then included the getPdf class from vendor/magento/module-sales/Model/Order/Pdf/Shipment.php. I'm not really a back end specialist, so I don't know if it all needed to be included, but hey, it works.

The actual retrival of the message is straightforward:

public function getGiftMessages($order_id) {
    $giftMessage = $this->orderGiftRepo->get($order_id);
    return $giftMessage;
}

It needs the order ID. The ->get method returns an array of recipient, sender and message.

Now for the most important section of code (which processes the gift data):

    if($order->getId()) {
        if ($order->getGiftMessageId() != 0) { //If there's no gift message, this will return 0. Need to catch it to prevent an exception.
            if ($giftWrap = $this->getGiftMessages($order->getId())) {
                //$logger->info("hello" . $order->getId());
                $page->drawText(strip_tags(ltrim('### GIFT INFORMATION ###:')), 25, 815, 'UTF-8');
                $page->drawText(strip_tags(ltrim('Sender: ' . $giftWrap["sender"])), 25, 800, 'UTF-8');
                $page->drawText(strip_tags(ltrim('Recipient: ' . $giftWrap["recipient"])), 25, 785, 'UTF-8');
                $page->drawText(strip_tags(ltrim('Message: ' . $giftWrap["message"])), 25, 770, 'UTF-8');
            }
        }
    }

If you attempt to grab a gift message from an order when there's no gift message, Magento will error (I think it's a no such entity exception). I'm not exactly sure why this isn't more forgiving, but still.

Anyway, we need to firstly ensure the Order has a gift message. That's why I need $order->getGiftMessageId() != 0. You see, any orders with a gift message ID of '0' don't have a gift message.

Now we're on the home straight!

        if ($giftWrap = $this->getGiftMessages($order->getId())) {
            //$logger->info("hello" . $order->getId());
            $page->drawText(strip_tags(ltrim('### GIFT INFORMATION ###:')), 25, 815, 'UTF-8');
            $page->drawText(strip_tags(ltrim('Sender: ' . $giftWrap["sender"])), 25, 800, 'UTF-8');
            $page->drawText(strip_tags(ltrim('Recipient: ' . $giftWrap["recipient"])), 25, 785, 'UTF-8');
            $page->drawText(strip_tags(ltrim('Message: ' . $giftWrap["message"])), 25, 770, 'UTF-8');
        }

Now we're able to pull through the gift message details, we can then draw them in the correct place. I've chosen the top left hand corner of the page.

Test that, and it should work!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.