Add custom attribute to Magento’s PDF invoice

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!

Related Inchoo Services

You made it all the way down here so you must have enjoyed this post! You may also like:

Automatically invoice/ship/complete order in Magento Branko Ajzele
Branko Ajzele, | 32

Automatically invoice/ship/complete order in Magento

Magento’s “Quote/Order/Invoice” workflow Branko Ajzele
Branko Ajzele, | 37

Magento’s “Quote/Order/Invoice” workflow

Enhanced Catalog Product Grid – Custom Attribute Filter Milovan Gal
Milovan Gal, | 55

Enhanced Catalog Product Grid – Custom Attribute Filter

66 comments

  1. i try this for my custom attribute publisher with code
    $Publisher = $this->getPublisherValue($item);
    // draw publisher name
    $lines[1][] = array(
    ‘text’ => Mage::helper(‘core/string’)->str_split($Publisher, 35),
    ‘feed’ => 35
    );

    private function getPublisherValue($item)
    {
    $prod = Mage::getModel(‘catalog/product’)->load($item->getProductId());

    if(!($return_publisher = $prod->getPublisher()))
    return ‘N/A’;
    else
    return $return_publisher;
    }
    but it showing a attribute code like 250,251

    1. @ Steve

      I am using Magento 1.9 and this module is working for me. Did you include your Invoice.xml file under app > etc > modules?

  2. Hi I managed to add the product image to my invoice, but somehow some of the product without custom option will have its image squeeze to the top..

    I change the default line height @

    app/code/local/Inchoo/Invoice/Model/Order/Pdf/Items/Invoice/Default.php

    $lineBlock = array(
    ‘lines’ => $lines,
    ‘height’ => 55

    Manage to make those product with no custom option look normal…but those with custom option with have very big gap… with make a single page invoice become 2-3pages.

    Anyone encounter these or have an solution.
    pls share and thank u in advance!

  3. Very good post, it turns out that the version of magento 1.4 community edition I worked super well, but when migrating to version 1.7.0.2 I see no way for me to work the Print button, the page is blank and I do not I get the window to save the pdf.

    In the log I get this error:

    PHP Fatal error: Call to a member function GetPDF () on a non-object in /var/www/local.booktocuba.com/application/booktocuba/app/code/core/Mage/Adminhtml/Controller/Sales/Invoice.php on line 119, referer: http://local.booktocuba.com/index.php/admin/sales_invoice/view/invoice_id/1921/

    I tried to modify the file

    lib / Zend / Pdf / FileParserDataSource.php

    because, as in other post is incompatible with the 5.4 version of Zend Framework php and have had no success.

    Can you help to solve it ….

    thank you very much

    Rober.

  4. The way you are loading the product attribute is very resource hungry, it would be better to use getAttributeRawValue to fetch it or to pass the product attribute to the quote in your config.xml. It would be wise to edit this.

  5. is it possible to add product image in pdf? i.e. Amasty/ AheadWorks color swatch extension uses multiple images on configurable products which swatches images upon selection.

    Is it possible to locate those images in invoice and add specific images to PDF?

    Any answer/hint will be highly appreciated

  6. How To Add item numbers to items in Magento Invoice PDF

    I am trying to add serial numbers (1,2,3 etc) to the items in Magento’s invoice pdf under a column called Serial Number.

    I have Added Serial No column in app\code\core\Mage\Sales\Model\Order\Pdf\ invoice .php file
    And in
    app\code\core\Mage\Sales\Model\Order\Pdf\Items\Invoice – Default.php

    $lines[count($lines)][] = array(
    ‘text’ => ((count($lines) == 0)?’1’:(count($lines)+1)),
    ‘feed’ => 35,
    ‘font’ => ‘bold’,
    );
    But it Doesn’t Work

  7. Hello Sir,
    i have a problem with magento 1.7.0.2 …
    when i am creating invoice pdf ..from admin ..
    at the top of invoice pdf there are no invoice date ..there are only invoice no. or order date. ..but i want order no. with this …

  8. @Simon you can use $page->drawText(‘My attribute text’, ‘x coordinate’, ‘y coordinate’, ‘UTF-8’) to display the attribute in the invoice PDF. If you want to get familiar with PDF creating functions, please take a look here: http://devzone.zend.com/1064/zend_pdf-tutorial/

    What attribute do you want to display in the invoice page? Is it order data or you want to use some text field, which will be populated in admin panel?

  9. Does anyone have an idea on how to add an attribute to the Invoice and print it out? I need to add a text field to describe the order on the invoice. Thanks

  10. I was trying to use this method to call another attribute in magento ce 1.7.0.2 and nothing worked… I am not sure how it is suppose to be now with the new edition of Magento. Please comment or maybe re post this for a new version. Thank you

  11. Just a simple question – I am trying to line up the shipping address to fit the integrated label statioery and all i need to do is move the top section up a little and the bottom section down a little. Nowhere can I find an explanation how to do this. Does anyone know?

  12. @Cesko. Sorry for the misunderstanding . As i couldn’t get it working, I looked deeper in the code on the default.php.I ve got my module working now for two customs attributes but I am being stuck “how to display the tax rate in a column klike the sku qty. I can get the taxe rate id but can’t display the value. As i have been looking for a solution, I am getting blind.Any idea how to do this ?

  13. @laurent, I think there is a missunderstanding. I didn’t use the inchoo module, only I wrote here to get help to modify something in pdf invoice.
    If You are using this inchoo module, I think that You have to modify the file app/code/local/Inchoo/Invoice/Model/Order/Pdf/Invoice.php and app/code/local/Inchoo/Invoice/Model/Order/Pdf/Abstract.php.

  14. @cesko

    Thanks for your quick help. I am a newbie but there is something I don’t understand. If you use a new inchoo module, why do you get the invoice.php from the mage directory instead of the newly created inchoo one. I thought this module was supposed to overwrite it ? Am I wrong ?
    Thanks for the tips. I ll have another go and let you know

  15. @laurent, I have checked the invoice.php and Abstract.php in 1.6.1 and appear same 1.6.2 where I’m working.
    Did you copy the code in app\code\local\Mage\Sales\Model\Order\Pdf\invoice.php?
    Also You will need to change some x,y coordinates of some objects inside invoice.php and Abstract.php files, otherwise the invoice date will appear overlying the order date.

  16. Hi I have solved. I just add the following code:

    $page->drawText(Mage::helper('sales')->__('Invoice Date: ') . Mage::helper('core')->formatDate($invoice->getCreatedAtDate(), 'medium', false), 35, 770, 'UTF-8');

    in app\code\local\Mage\Sales\Model\Order\Pdf\invoice.php.

    Thanks anyway for help.

  17. Thanks for your sharing !

    I have tried to get it working on 1.6.1 and no luck.

    Nothing s happening when i click opn the print button in the back office. it charges the old pdf invoice. any idea. ?

    How do i display a new columm with the Vat rate and a custom attribute called price_kg.

    Many thanks for your help

  18. Hey @Cesko give us more hints …

    What exactly you don’t know?

    You don’t know how to extract the date or you don’t know how to position / draw text in pdf documents?

    What is the context of your changes? I which file you want to apply your changes?

  19. Hi, I’m coming crazy to add the date into pdf invoice and pdf credit memo.
    Please someone can help me?
    Thanks.

  20. I am not a developer I am just the persona in charge of the web, I am trying to make changes in the invoice. The go thru the magento panel or i need my programer to do any change???

  21. On the Magento wiki there is also a great tutorial about how to customize the pdf in Megento – http://www.magentocommerce.com/wiki/5_-_modules_and_development/orders/editing_an_invoice_pdf

    @jeff b
    In inchoo product image extension he get the product with

    Mage::getModel('catalog/product')->load($productId);

    and on this object you can get all the product info – try writing

    $product = Mage::getModel('catalog/product')->load($productId);
    print_r($product->getData());

    and see all the variables you can use…

    An alternative is to use our new extension http://ext4mage.com/html2pdf-magento-extension.html

  22. @Amanda, do you mean to move, the shipping address at the bottom, not to add it? What do you mean with “… so I can use intergrated labels, maybe with a PPI impression?” … do you mean to put some logo / image near to the shipping address?

  23. @Alan, From next article you can learn how to create custom configuration fields in Magento: http://www.ecomdev.org/2010/10/27/custom-configuration-fields-in-magento.html

    In your case you will need to change:

    <frontend_type>text</frontend_type>
    
    to
    
    <frontend_type>textarea</frontend_type>

    After that to retrieve the value of your custom configuration field, just call somewhere in the code:

    $text = Mage::getStoreConfig('mycustom_section/mycustom_group/mycustom_field')

    Cheers!

  24. @Tiffany I’ll give you a hint. Take a look at file app/code/core/Mage/Sales/Model/Order/Pdf/Invoice.php … In method getPdf($invoices = array()) after the line:

    $order = $invoice->getOrder();

    you can call:

    $poNumber = $order->getPayment()->getPoNumber();

    N.B.

    Please don’t override core files and wrap your idea in Magento extension.

  25. Any one know how to add the shipping address at the bottom so I can use intergrated labels, maybe with a PPI impression?

    Thanks x

  26. How would you go about adding a custom item (like a texarea) to Sales > PDF Print-outs and then using it in the invoice?

    Thanks

  27. I’m trying to find the code to call the PO Number data from the database. Does anyone know what that might be? Any feedback would be much appreciated!

  28. Great guide, i am having problems with the custom options spanning across the page instead of appearing in a list. Anyone know how to fix this in Magento 1.5.1.0?

  29. Got it working for every attribute I need, however, it shows the ID (“10” instead of “Nike”) of the value instead of the value as text.

    What should be added or changed to get this to work?

  30. Hi! some one help me how can take the shipment tracking number from shipment tables & store it in another table……

  31. I installed your module as instructed but i don’t get ware house location attribute in my invoice.

    Magento version 1.4.2
    runing on local machine.

  32. I have a question you might know the answer for.

    I am trying to get the pdf show RTL. i know how to change the font. but no way i can find how to get it to show right to left. any chance someone might know how it can be done?

  33. @Toni thanks – so how could i add the delivery address to the footer of the invoice? using this method?

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <blockquote cite=""> <code> <del datetime=""> <em> <s> <strike> <strong>. You may use following syntax for source code: <pre><code>$current = "Inchoo";</code></pre>.

Tell us about your project

Drop us a line. We'd love to know more about your project.