Add custom attribute to Magento’s PDF invoice

Hello everyone! Today I’ll show you how to add custom attribute to Magento’s generated PDF invoice in just a few steps. Since this article is pretty straight-forward, here we go.

One of my recent tasks was to create a custom attribute for products called inchoo_warehouse_location, and output it when click on “Print” (invoice in admin section) occurs. Since PDF generation is Magento’s core functionality, we’ll have to rewrite it a bit.

Step 1

Create the following three files in your Magento’s installation:
app/code/local/Inchoo/Invoice/Model/Order/Pdf/Items/Invoice/Default.php
app/code/local/Inchoo/Invoice/Model/Order/Pdf/Invoice.php
app/code/local/Inchoo/Invoice/etc/config.xml

Those will be used for our extension that will modify Magento’s core functionality.

Step 2

Fill in the data to according files:
config.xml

<?xml version="1.0"?>
<config>
    <modules>
        <Inchoo_Invoice>
            <version>0.1.0</version>
        </Inchoo_Invoice>
    </modules>
    <global>
        <models>
            <sales>
                <rewrite>
                    <order_pdf_invoice>Inchoo_Invoice_Model_Order_Pdf_Invoice</order_pdf_invoice>
                    <order_pdf_items_invoice_default>Inchoo_Invoice_Model_Order_Pdf_Items_Invoice_Default</order_pdf_items_invoice_default>
                </rewrite>
            </sales>
        </models>
    </global>
</config>

Default.php

<?php
/**
 * Inchoo PDF rewrite for custom attribute
 * Attribute "inchoo_warehouse_location" has to be set manually
 * Original: Sales Order Invoice Pdf default items renderer
 *
 * @category   Inchoo
 * @package    Inhoo_Invoice
 * @author     Mladen Lotar - Inchoo <mladen.lotar@inchoo.net>
 */
 
class Inchoo_Invoice_Model_Order_Pdf_Items_Invoice_Default extends Mage_Sales_Model_Order_Pdf_Items_Invoice_Default
{
    /**
     * Draw item line
	 **/
    public function draw()
    {
        $order  = $this->getOrder();
        $item   = $this->getItem();
        $pdf    = $this->getPdf();
        $page   = $this->getPage();
        $lines  = array();
 
		//Inchoo - Added custom attribute to PDF, first get it if exists
		$WarehouseLocation = $this->getWarehouseLocationValue($item);
 
        // draw Product name
        $lines[0] = array(array(
            'text' => Mage::helper('core/string')->str_split($item->getName(), 60, true, true),
            'feed' => 35,
        ));
 
		//Inchoo - Added custom attribute
		//draw Warehouse Location
        $lines[0][] = array(
            'text'  => Mage::helper('core/string')->str_split($WarehouseLocation, 25),
            'feed'  => 245
        );
 
        // draw SKU
        $lines[0][] = array(
            'text'  => Mage::helper('core/string')->str_split($this->getSku($item), 25),
            'feed'  => 325
        );
 
        // draw QTY
        $lines[0][] = array(
            'text'  => $item->getQty()*1,
            'feed'  => 435
        );
 
        // draw Price
        $lines[0][] = array(
            'text'  => $order->formatPriceTxt($item->getPrice()),
            'feed'  => 395,
            'font'  => 'bold',
            'align' => 'right'
        );
 
        // draw Tax
        $lines[0][] = array(
            'text'  => $order->formatPriceTxt($item->getTaxAmount()),
            'feed'  => 495,
            'font'  => 'bold',
            'align' => 'right'
        );
 
        // draw Subtotal
        $lines[0][] = array(
            'text'  => $order->formatPriceTxt($item->getRowTotal()),
            'feed'  => 565,
            'font'  => 'bold',
            'align' => 'right'
        );
 
        // custom options
        $options = $this->getItemOptions();
        if ($options) {
            foreach ($options as $option) {
                // draw options label
                $lines[][] = array(
                    'text' => Mage::helper('core/string')->str_split(strip_tags($option['label']), 70, true, true),
                    'font' => 'italic',
                    'feed' => 35
                );
 
                if ($option['value']) {
                    $_printValue = isset($option['print_value']) ? $option['print_value'] : strip_tags($option['value']);
                    $values = explode(', ', $_printValue);
                    foreach ($values as $value) {
                        $lines[][] = array(
                            'text' => Mage::helper('core/string')->str_split($value, 50, true, true),
                            'feed' => 40
                        );
                    }
                }
            }
        }
 
        $lineBlock = array(
            'lines'  => $lines,
            'height' => 10
        );
 
        $page = $pdf->drawLineBlocks($page, array($lineBlock), array('table_header' => true));
        $this->setPage($page);
 
    }
 
	/*
	 * Return Value of custom attribute
	 * */
	private function getWarehouseLocationValue($item)
	{
		$prod = Mage::getModel('catalog/product')->load($item->getProductId());
 
		if(!($return_location = $prod->getInchooWarehouseLocation()))
			return 'N/A';
		else
			return $return_location;
	}
}

And finally Invoice.php

<?php
/**
 * Inchoo PDF rewrite for custom attribute
 * * Attribute "inchoo_warehouse_location" has to be set manually
 * Original: Sales Order Invoice PDF model
 *
 * @category   Inchoo
 * @package    Inhoo_Invoice
 * @author     Mladen Lotar - Inchoo <mladen.lotar@inchoo.net>
 */
class Inchoo_Invoice_Model_Order_Pdf_Invoice extends Mage_Sales_Model_Order_Pdf_Invoice
{
	public function getPdf($invoices = array())
    {
        $this->_beforeGetPdf();
        $this->_initRenderer('invoice');
 
        $pdf = new Zend_Pdf();
        $this->_setPdf($pdf);
        $style = new Zend_Pdf_Style();
        $this->_setFontBold($style, 10);
 
        foreach ($invoices as $invoice) {
            if ($invoice->getStoreId()) {
                Mage::app()->getLocale()->emulate($invoice->getStoreId());
            }
            $page = $pdf->newPage(Zend_Pdf_Page::SIZE_A4);
            $pdf->pages[] = $page;
 
            $order = $invoice->getOrder();
 
            /* Add image */
            $this->insertLogo($page, $invoice->getStore());
 
            /* Add address */
            $this->insertAddress($page, $invoice->getStore());
 
            /* Add head */
            $this->insertOrder($page, $order, Mage::getStoreConfigFlag(self::XML_PATH_SALES_PDF_INVOICE_PUT_ORDER_ID, $order->getStoreId()));
 
            $page->setFillColor(new Zend_Pdf_Color_GrayScale(1));
            $this->_setFontRegular($page);
            $page->drawText(Mage::helper('sales')->__('Invoice # ') . $invoice->getIncrementId(), 35, 780, 'UTF-8');
 
            /* Add table */
            $page->setFillColor(new Zend_Pdf_Color_RGB(0.93, 0.92, 0.92));
            $page->setLineColor(new Zend_Pdf_Color_GrayScale(0.5));
            $page->setLineWidth(0.5);
 
            $page->drawRectangle(25, $this->y, 570, $this->y -15);
            $this->y -=10;
 
            /* Add table head */
            $page->setFillColor(new Zend_Pdf_Color_RGB(0.4, 0.4, 0.4));
            $page->drawText(Mage::helper('sales')->__('Products'), 35, $this->y, 'UTF-8');
			//Added for custom attribute "inchoo_warehouse_location"
            $page->drawText(Mage::helper('sales')->__('Warehouse Location'), 245, $this->y, 'UTF-8');
			$page->drawText(Mage::helper('sales')->__('SKU'), 325, $this->y, 'UTF-8');
            $page->drawText(Mage::helper('sales')->__('Price'), 380, $this->y, 'UTF-8');
            $page->drawText(Mage::helper('sales')->__('Qty'), 430, $this->y, 'UTF-8');
            $page->drawText(Mage::helper('sales')->__('Tax'), 480, $this->y, 'UTF-8');
            $page->drawText(Mage::helper('sales')->__('Subtotal'), 535, $this->y, 'UTF-8');
 
            $this->y -=15;
 
            $page->setFillColor(new Zend_Pdf_Color_GrayScale(0));
 
            /* Add body */
            foreach ($invoice->getAllItems() as $item){
                if ($item->getOrderItem()->getParentItem()) {
                    continue;
                }
 
                if ($this->y < 15) {
                    $page = $this->newPage(array('table_header' => true));
                }
 
                /* Draw item */
                $page = $this->_drawItem($item, $page, $order);
            }
 
            /* Add totals */
            $page = $this->insertTotals($page, $invoice);
 
            if ($invoice->getStoreId()) {
                Mage::app()->getLocale()->revert();
            }
        }
        $this->_afterGetPdf();
 
        return $pdf;
    }
 
	public function newPage(array $settings = array())
    {
        /* Add new table head */
        $page = $this->_getPdf()->newPage(Zend_Pdf_Page::SIZE_A4);
        $this->_getPdf()->pages[] = $page;
        $this->y = 800;
 
        if (!empty($settings['table_header'])) {
            $this->_setFontRegular($page);
            $page->setFillColor(new Zend_Pdf_Color_RGB(0.93, 0.92, 0.92));
            $page->setLineColor(new Zend_Pdf_Color_GrayScale(0.5));
            $page->setLineWidth(0.5);
            $page->drawRectangle(25, $this->y, 570, $this->y-15);
            $this->y -=10;
 
            $page->setFillColor(new Zend_Pdf_Color_RGB(0.4, 0.4, 0.4));
            $page->drawText(Mage::helper('sales')->__('Product'), 35, $this->y, 'UTF-8');
			//Added for custom attribute "inchoo_warehouse_location"
			$page->drawText(Mage::helper('sales')->__('Warehouse Location'), 245, $this->y, 'UTF-8');
            $page->drawText(Mage::helper('sales')->__('SKU'), 325, $this->y, 'UTF-8');
            $page->drawText(Mage::helper('sales')->__('Price'), 380, $this->y, 'UTF-8');
            $page->drawText(Mage::helper('sales')->__('Qty'), 430, $this->y, 'UTF-8');
            $page->drawText(Mage::helper('sales')->__('Tax'), 480, $this->y, 'UTF-8');
            $page->drawText(Mage::helper('sales')->__('Subtotal'), 535, $this->y, 'UTF-8');
 
            $page->setFillColor(new Zend_Pdf_Color_GrayScale(0));
            $this->y -=20;
        }
        return $page;
    }
}

Step 3

Now, you’ve done it. Test it out by going to “Sales->Invoices->(View any of them)->Print”. You shoud be asked to download PDF, and when you do, it should contain “Warehouse Location” by each of order items.

All you have to do is test it out and / or change it according to your needs!

I hope this was of help to someone!

Cheers!