Due to the severe lack of Odoo resources, this is little tutorial (for the lack of a better work) serves as a basic boilerplate for creating QWeb reports from scratch in Odoo. Without further aidue.

For this example, we’re going to override the Quotation and Sale Order template within the Sales addon.

Initial Steps

Inside your addons directory, create a new addon using the odoo “scaffold” command

$ odoo.py scaffold my_sale_template
$ mkdir my_sale_template/reports
$ touch my_sale_template/reports/{report_menu.xml,report_sale.xml}

Now we need to append to the data dictionary inside of our manifest.py to make our addon aware of the xml files we intend to use.

'data': [
	'reports/report_menu.xml',
    	'reports/report_sale.xml',
]

While we’re there, we also need to append “sale” to the depends dictionary inside our manifest.

'depends': ['base','sale']

Lastly, let’s add the barebones xml to both report_sale.xml and report_menu.xml to make our addon installable by Odoo.

<odoo>
	<data>
	</data>
</odoo>

Optional

Not required but feel free to update the Summary, Description, Author, etc meta inside of manifest.py

Installing our addon

Make sure you’re in debug mode on your instance of Odoo (append debug= after /web? in the Odoo URL so it looks like /web?debug=), head to Apps and on top of the page, click the “Update Apps List” button. Once updated, search for your addon and hit “Install”

Creating the report

Inside of our reports/report_sale.xml file, let’s add the following inside of the tags to get us started.

<template id="report_saleorder">
    <t t-call="web.html_container">
        <t t-foreach="docs" t-as="o">
    	<div class="header">
    		This is my header
    	</div>
    	<div class="article">
    		This is my content
    	</div>
    	<div class="footer">
    		This is my footer
    	</div>
        </t>
    </t>
</template>

Now update Odoo to make it aware of our changes by either upgrading our addon via the Apps section of the site, or restarting odoo using the update flag

$ odoo.py -c /path/to/your/config -u my_sale_template

Since we have not overridden the print menu within the base sale addon, for now we can point the action to our report manually by updating the Template Name under Reports => Quotation / Order in the Technical menu.

Edit the report template name and add my_sale_template.report_saleorder

Odoo Settings

Note: Whilst manually updating the template name works, it is not ideal as the sale module in Odoo would revert it back to the default template every time there is an update to the Sale base addon.

Now create a sale order, go to print and select Quotation / Sale Order

Odoo Settings

If all worked correctly, it should look like the above. To print different fields to use in our report,

<t t-foreach="docs" t-as="o">

is used to iterate over all fields within the object.

For example, if we want to get the customer display_name, we can simply append

<span t-field="o.partner_id.display_name"/>

anywhere within the Header, Article and Footer divs.

Overriding the menu

To ensure our report continues to work between updates to the Sale base addon, we need to override the menu action.

This can be tricky as it requires finding the relevant report menu xml within the base sale addon. The easiest way is to perform a text search across all files inside the report folder of the base sale addon.

Inside of your Odoo sale/report base addon directory, search for the original id of sale order report, which in our case, is sale.report_saleorder. An easy and Unix-y way is to look for the file= attribute within the menu using xargs and grep (if you’re on Windows, no clue, sorry!! :))

find . | xargs grep "file=\"sale.report_saleorder" 

And our result:

./sale_report.xml:            file="sale.report_saleorder" 
./sale_report.xml:            file="sale.report_saleorder_pro_forma"

Boom! Opening up sale_report.xml we see 2 reports, one for “Quotation / Order” and the other for “PRO-FORMA Invoice”. For the sake of our example, We only want the one for our Quotation / Order as this is the report we’re overriding.

Copy the entire report tag for Quotation / Order and paste it into our report_menus.xml file in our addon in between the tags and make the following changes:

Before

id="action_report_saleorder"

After

id="sale.action_report_saleorder"

Before

file="sale.report_saleorder"
name="sale.report_saleorder"

After

file="my_sale_template.report_saleorder"
name="my_sale_template.report_saleorder"

Pointing the menu action at our newly created template.

When you’re done, it should look like below:

<report 
    id="sale.action_report_saleorder"
    string="Quotation / Order"
    model="sale.order" 
    report_type="qweb-pdf"
    file="my_sale_template.report_saleorder" 
    name="my_sale_template.report_saleorder"
    print_report_name="(object.state in ('draft', 'sent') and 'Quotation - %s' % (object.name)) or 'Order - %s' % (object.name)"
 />

Further reading: Odoo QWeb Reports