OpenERP : How to use a custom RML report parser class

RML parser classes are registered globally as Services. For example the Sale Order parser class is registered in addons/sale/report/sale_order.py with :

report_sxw.report_sxw('report.sale.order', 'sale.order', 'addons/sale/report/sale_order.rml', parser=order, header="external")

If you try to create another parser with the same name, you get an error :

The report "sale.order" already exists!

A simple way to replace the sale.order parser and use a custom parser class is to remove it from the global service registry with :

Here is a full example we used to conditionally hide the Discount column in the sale order report if there is no discount :

from sale.report import sale_order
from report import report_sxw

# create a custom parser inherited from sale order parser:
class new_order_parser(sale_order.order):
    '''Custom parser with an additional method
    '''
    def __init__(self, cr, uid, name, context):
		super(new_order_parser, self).__init__(cr, uid, name, context=context)
    self.localcontext.update({
        'has_line_discount': self._has_line_discount,
    })

    def _has_line_discount(self, order):
        return any([l.discount for l in order.order_line])


# remove previous sale.report service :
from netsvc import Service
del Service._services['report.sale.order']

# register the new report service :
report_sxw.report_sxw(
'report.sale.order',
'sale.order',
'addons/path/to/the/sale_order.rml',
parser=new_order_parser
)