Odoo Help


Invoice number into the pdf file name

Christian Douville
on 3/8/13, 11:10 AM 18,920 views

On Print Invoice action, the .pdf file name is not, by default, completed with the invoice number. Is there any variable i can put into the Report name header that would retrieve the Invoice number ?

Thanks. The pdf content does report the invoice number. My aim is to have the file name with the invoice number. Something like "Invoice IN-FR-1303-0008.pdf"

Christian Douville
on 3/8/13, 12:29 PM

I also need this so tired of renaming filenames for every report.

Altınkaya Elektronik Cihaz Kutuları imalat Ticaret ltd sti, Ahmet Altinisik
on 3/8/13, 5:59 PM

Additional information, the xml for creating the report contains attachment="(object.state in ('open','paid')) and ('INVOICE_'+(object.number or '').replace('/','')+'.pdf')", so the assumption is that the number should be available into the file name

Christian Douville
on 3/12/13, 6:59 AM

Implementing/activating the Knowledge module provides the solution, as the pdf document is attached to the Account with the accurate file name (ie INVOICE + invoice number+.pdf)

Christian Douville
on 3/14/13, 7:39 AM

@Christian You have to download again the file so it is a workaround but not the solution you have to download it again after downloading the file.

Altınkaya Elektronik Cihaz Kutuları imalat Ticaret ltd sti, Ahmet Altinisik
on 3/14/13, 7:58 AM

The same problem for me!

I really want to have the same functionality as for "save as attachment" for all of the print buttons! Drives me nuts to always download the document twice just for the right file name...

Any idea?!?

Michael Karrer
on 3/27/13, 8:16 AM

You must edit the account/report/account_print_invoice.rml filename dynamically.

<document filename="Invoices.pdf">

is one of the first lines. I am not exactly sure how to do this, but I would love to know the answer.

Not sure i have to do it, as the Settings-Technical/Actions/Reports and Settings-Technical/Actions/Action Bindings look like doing this (with the optional parameters)

Christian Douville
on 3/29/13, 3:50 AM

Yes, i agree, but that action is not applied to files created when you hit the print button, just the file that is attached to the invoice after you hit the print button. There must be a way to apply that same action to the file that is automatically downloaded when you hit print.

AJ Schrafel Paper Corp
on 3/29/13, 1:30 PM
Nikunj Nakum
On 8/2/14, 3:18 AM

yes you can give 'name': 'Invoice ' + 'today date' in return from wizard to print report.

for example: this is function is call from print button in wizard.

def print_report(self,cr, uid, ids, context=None):
        if context is None:
           context = {}
        data = self.read(cr, uid, ids)[0]
        self_browse = self.browse(cr, uid, ids)
        datas = {
            'ids': [data.get('id')],
            'model': 'sale.order',
            'form': data
        return {
            'type': 'ir.actions.report.xml',
            'report_name': 'custom.invvoice.report',
            'datas': datas,
            'name': 'Invoice ' + self_browse[0].start_date + ' To ' + self_browse[0].end_date  




Thanks @ Nikunj Nakum Your code is working

Ankit H Gandhi(AHG)
on 7/21/15, 7:23 AM
On 9/25/15, 10:16 AM

I think you can use this module


Kind regard, 

Thanks @Lara

on 11/17/15, 4:11 AM
Jérôme Thériault
On 5/17/17, 8:45 AM

For Odoo 9+:

Go to configuration, reports, look for the report you want, then use the Printed Report Filename field which can contain python expressions. Two variables can be used inside: object which is the object being printed, and time which is python time module. So you can input "object.name" without the quotes.

No need for extra module or code.

More here: http://gitlab.opengest.solutions/opengest/odoo/commit/da3d2fb1dc76654e630fba27ca3dcf03002d9431

Look for print_report_name

harsh jain
On 9/29/14, 5:51 PM

# -*- coding: utf-8 -*-

import ast
import base64
import csv
import glob
import itertools
import logging
import operator
import datetime
import hashlib
import os
import re
import simplejson
import time
import urllib
import urllib2
import urlparse
import xmlrpclib
import zlib
from xml.etree import ElementTree
from cStringIO import StringIO

import babel.messages.pofile
import werkzeug.utils
import werkzeug.wrappers
    import xlwt
except ImportError:
    xlwt = None

import openerp
import openerp.modules.registry
from openerp.tools.translate import _
from openerp.tools import config

from openerp.addons.web import http
openerpweb = http
from openerp.addons.web.controllers.main import Reports

def content_disposition(filename, req):
    filename = filename.encode('utf8')
    escaped = urllib2.quote(filename)
    browser = req.httprequest.user_agent.browser
    version = int((req.httprequest.user_agent.version or '0').split('.')[0])
    if browser == 'msie' and version < 9:
        return "attachment; filename=%s" % escaped
    elif browser == 'safari':
        return "attachment; filename=%s" % filename
        return "attachment; filename*=UTF-8''%s" % escaped


class change_main(Reports):

    def index1(self, req, action, token):
        action = simplejson.loads(action)

        report_srv = req.session.proxy("report")
        context = dict(req.context)

        report_data = {}
        report_ids = context["active_ids"]
        if 'report_type' in action:
            report_data['report_type'] = action['report_type']
        if 'datas' in action:
            if 'ids' in action['datas']:
                report_ids = action['datas'].pop('ids')

        report_id = report_srv.report(
            req.session._db, req.session._uid, req.session._password,
            action["report_name"], report_ids,
            report_data, context)

        report_struct = None
        while True:
            report_struct = report_srv.report_get(
                req.session._db, req.session._uid, req.session._password, report_id)
            if report_struct["state"]:


        report = base64.b64decode(report_struct['result'])
        if report_struct.get('code') == 'zlib':
            report = zlib.decompress(report)
        report_mimetype = self.TYPES_MAPPING.get(
            report_struct['format'], 'octet-stream')
        file_name = action.get('name', 'report')
        if 'name' not in action:
            reports = req.session.model('ir.actions.report.xml')
            res_id = reports.search([('report_name', '=', action['report_name']),],
                                    0, False, False, context)
            if len(res_id) > 0:
                file_name = reports.read(res_id[0], ['name'], context)['name']
                file_name = action['report_name']
        file_name = '%s.%s' % (file_name, report_struct['format'])
        if context['active_model'] in ['sale.order','purchase.order','account.invoice']:
            model1 =req.session.model(context['active_model'])
            if read['name']!=False:
                file_name = read['name'] + ' ' + read['partner_id'][1]
                print file_name
                file_name = '%s.%s' % (file_name, report_struct['format'])
            # PATCH END
        return req.make_response(report,
                 ('Content-Disposition', content_disposition(file_name, req)),
                 ('Content-Type', report_mimetype),
                 ('Content-Length', len(report))],
             cookies={'fileToken': token})


harsh jain
on 9/29/14, 5:52 PM
Michael Karrer
On 3/27/13, 8:16 AM

The same problem for me!

I really want to have the same functionality as for "save as attachment" for all of the print buttons! Drives me nuts to always download the document twice just for the right file name...

Any idea?!?

Hi to all, I updated my answer to shows invoice-number-into-the-pdf-file-name

on 8/4/14, 8:49 AM
On 8/1/14, 9:46 AM

In Existing Report Module after adding the below code able to generate Invoice Number in PDF File.

server\openerp\report\report_sxw.py in the create_single_pdf method.

    def create_single_pdf(self, cr, uid, ids, data, report_xml, context=None):
        if not context:
        logo = None
        context = context.copy()
        title = report_xml.name
        rml = report_xml.report_rml_content
        model = context.get('active_model')
        record_id = context.get('active_id')    
        pool = pooler.get_pool(cr.dbname)

        invoice_obj = pool.get('account.invoice')
        type = report_xml.report_type
        if model == 'account.invoice' and record_id:
            invoice_val = invoice_obj.browse(cr, uid, record_id)     
            orderreference_type = invoice_val.reference or invoice_val.origin + report_xml.report_type
            type = orderreference_type.replace("pdf", ".pdf");        

        # if no rml file is found
        if not rml:
            return False
        rml_parser = self.parser(cr, uid, self.name2, context=context)
        objs = self.getObjects(cr, uid, ids, context)
        rml_parser.set_context(objs, data, ids, report_xml.report_type)
        processed_rml = etree.XML(rml)
        if report_xml.header:
            rml_parser._add_header(processed_rml, self.header)
        processed_rml = self.preprocess_rml(processed_rml,report_xml.report_type)
        if rml_parser.logo:
            logo = base64.decodestring(rml_parser.logo)
        create_doc = self.generators[report_xml.report_type]
        pdf = create_doc(etree.tostring(processed_rml),rml_parser.localcontext,logo,title.encode('utf8'))
        return pdf, type
        #return pdf, report_xml.report_type

Note: Core Report Module added extra code (Invoice Number in PDF File). But Better way to override  create_single_pdf method in a custom module.


On 9/17/14, 5:16 PM


I too faced the same problem of printing invoice pdf with Invoice number.pdf as its name.

I modified @Nikunj Nakum  answer and I got the result. Below given is the code

  # Class             :    account_invoice (inherited)
  # Method          :    custom_invoice_print button
  # Description   :    This function prints the invoice and mark it as sent, so that
  #                            we can see more easily the next step of the workflow. 

  #                            Prints Invoice with invoice number as its name

  def custom_invoice_print(self, cr, uid, ids, context=None):
        self.write(cr, uid, ids, {'sent': True}, context=context)
        data = self.read(cr, uid, ids)[0]
        self_browse = self.browse(cr, uid, ids)
        datas = {
             'ids': ids,
             'model': 'account.invoice',
             'form': self.read(cr, uid, ids[0], context=context)
        return {
            'type': 'ir.actions.report.xml',
            'report_name': 'account.invoice2',
            'datas': datas,
            'name': 'Invoice ' + self_browse[0].number  ,
            'nodestroy' : True

Result:  Invoice INV14-09_018.pdf

Thanks.. It's woking well..

on 10/30/14, 5:34 AM

Can we use this in place of the standards print buttons ? (the one in the bar and th one in the drop down menu) If yes, how ?

on 11/5/14, 5:44 AM

I'm not sure of the place to put it...

Pascal Tremblay
on 12/13/14, 6:34 PM

Should it works in Odoo V8 too?

Pascal Tremblay
on 12/23/14, 8:58 AM
Pascal Tremblay
On 12/27/14, 10:38 AM

Here is our solution to customize the sale order report PDF name with the « print » buttons.


On 8/1/14, 7:54 AM

I have also the same problem..

The problem seems to be unsolved. Is there possibly an easy solution? When I send the invoice or sale order via email, everything is well. The file name have the number included. But when I only print the invoice, I have no number in the file name. Thanks for any help

Gunther Kohn
on 11/26/14, 8:47 AM

About This Community

This platform is for beginners and experts willing to share their Odoo knowledge. It's not a forum to discuss ideas, but a knowledge base of questions and their answers.


Odoo Training Center

Access to our E-learning platform and experience all Odoo Apps through learning videos, exercises and Quizz.

Test it now

Question tools

9 follower(s)


Asked: 3/8/13, 11:10 AM
Seen: 18920 times
Last updated: 5/17/17, 8:45 AM