That’s good, we saw how to get the PDF version of a Magento invoice available in the frontend (inside the customer dashboard). Now I need to slightly modify the invoice PDF keeping all the original formatting but changing only the document number (on the PDF the Invoice # 10000000x). I need to format it as “1/0000000x” because on year change we should move from 100000000 to 200000000 base numbering to get the effect of a progressive numbering restarting on each business year. It may seems stupid, but fiscal laws are usually stupid.
To deal with that without rewriting completely the PDF generator already (and working…) in Magento we can try to only overload things regarding the invoice number (called “incremental id” in magento).
Where is the PDF code?
First we need to identify the PDF generator. There are a couple of file we are interested in:
/app/core/Mage/Sales/Model/Order/Pdf/Invoice.php /app/core/Mage/Sales/Model/Order/Pdf/Abstract.php
The “Abstract.php” file contains a class which implements the common code to the invoice and order PDF generators. “Invoice.php” is a specific class only to the invoice PDF generator. Since the invoice model extends the abstract model, we only override the invoice model and we inherit the abstract model functionalities.
Our module
As in the previous example, we need a module we call “Pdf”. Its code will be placed inside “app/local/Pdf” and its “definition” file (so Magento knows about it and loads it) will be “/app/etc/modules/Pdf.xml”. It will look like:
<?xml version="1.0"?> <config> <modules> <Pdf> <active>true</active> <codePool>local</codePool> </Pdf> </modules> </config>
Now we want to prepare a class which will extend the original Magento class that generate the invoice PDF. The we’ll force Magento to use our class instead of the original one. Our class can be empty at start, since we want only to wrap the original one to add or override some functionality.
To avoid confusion, we place the class inside the file:
/app/local/Pdf/Sales/Model/Order/Pdf/Invoice.php
So looking at the path we suddenly know which is the model we are redefining. To start, out Invoice.php whould be:
class Pdf_Sales_Model_Order_Pdf_Invoice extends Mage_Sales_Model_Order_Pdf_Invoice { }
as per Magento standard the class name is the path to reach the file that contains the class it self and it extends the core model which generates the invoice PDF. Now we want to force Magento to use our class when someone want to create a PDF. To do that, we modify the “etc/config.xml” of the module:
<?xml version="1.0"?> <config> <modules> <Pdf> <version>1.0.0</version> </Pdf> </modules> <global> <models> <sales> <rewrite> <order_pdf_invoice>Pdf_Sales_Model_Order_Pdf_Invoice</order_pdf_invoice> </rewrite> </sales> </models> </global> ... </config>
The bolded part of this XML says: about models of the “sales” core module, we want to rewrite the “Order/Pdf/Invoice.php” with the class “Pdf_Sales_Model_Order_Pdf_Invoice”.
Now if you try to print an invoice, nothing of different happens, since we just wrap the generator.
Change the document number
Looking at where the document number is inserted, we see that the core Abstract.php file containing the base class for PDF generators, has the method:
public function insertDocumentNumber(Zend_Pdf_Page $page, $text) { ... }
so this should be a good point to start. We redefine this method with the aim to change the variable “$text” (which contains the document number plus a label) to something of different. So in out class we add a new version of this method:
class Pdf_Sales_Model_Order_Pdf_Invoice extends Mage_Sales_Model_Order_Pdf_Invoice { public function insertDocumentNumber(Zend_Pdf_Page $page, $text) { $number = substr($text, strrpos($text, ' ')+1); $x = strpos($number, '0'); $root = substr($number, 0, $x); $base = substr($number, $x); parent::insertDocumentNumber($page, 'Number: ' . $root . '/' . $base); } }
and at the end we recall the original one so the number is inserted in the right position, but with a different value.
It may sound incredible, but that’s all.
Below a screenshot of a modified PDF invlice. To modify other parts of the invoice, you should override other methods: this part of Magento is not really broken up in small pieces, so some operations require to copy and paste long blocks of the original code.