How to create Qweb based pdf reports
Odoo plays a crucial role in enhancing business efficiency. Analyzing
different facets is essential for the organization's progress within
the ERP system, and this is where reporting comes into play.
Qweb serves as a reporting engine designed to generate PDF reports by
efficiently managing data through XML. The Qweb template engine
typically transforms XML into HTML, and the actual rendering of PDFs
is carried out by the wkhtmltopdf tool. Reports are generated
through a combination of report actions and report templates
specified for the respective actions.
Report Action:
Report actions are initiated when there is a need to generate
reports. These actions are written within the XML file established
in the report section of the module. A typical representation of a
report action could be as follows:
<record id="action_report_student_detail" model="ir.actions.report">
<field name="name">Student Detail</field>
<field name="model">student.detail</field>
<field name="report_type">qweb-pdf</field>
<field name="report_name">student_registration.report_student_detail</field>
<field name="report_file">student_registration.report_student_detail</field>
<field name="print_report_name">'Student Report - %s' % (object.name)</field>
<field name="binding_model_id" ref="model_student_detail"/>
<field name="binding_type">report</field>
</record>
This specific report is related to the sale order module. Let's break
down the key attributes in this XML record:
1. id: This uniquely identifies the record. In this case, it
is set to "action_report_student_detail."
2. model: Specifies the model with which the report is
associated. In this case, the report is associated with the
"student.detail" model.
3. report_type: Defines the type of report. Here, it's set to
"qweb-pdf," indicating that the report is in QWeb PDF format.
4. report_name: Specifies the technical name of the report. In
this example, it is "student_registration.report_student_detail."
5. report_file: Specifies the name of the report file. In
this case, it is also "student_registration.report_student_detail"
6. print_report_name: Defines the name that will be displayed
when the report is printed
7. binding_model_id: Refers to the model (in this case,
"model_student_detail") to which the report is bound.
8. binding_type attribute: Specifies the type of binding,
which is set to "report" in this case.
Report Templates:
The report structure is defined within the report templates, which
are XML files located inside the module's report file. Within these
templates, HTML is utilized to tailor the report layout according to
specific design requirements.
<template id="report_student_detail">
<t t-call="web.html_container">
<t t-call="web.internal_layout">
<t t-foreach="docs" t-as="rec">
<div class="text-center">
<h2>
<u>Student Report</u>
</h2>
</div>
<span>Name:</span>
<t t-esc="rec.name"/>
</t>
</t>
</t>
</template>
The id of the template is external if that is mentioned in the report
action. By calling the external_layout, the report will get the
default layout of Odoo. The template always contains the variables
like time, user, res_company, website, web_base_url, and
context_timestamp.
Python Function:
The corresponding Python function for printing the report might look
like this:
def action_print(self):
return (self.env.ref(
student_registration.action_report_student_detail')
.report_action(self))
Then the output of the function will is as shown below:
Multi Print:
In Odoo 17, there's a new feature called "do_multi_print" that makes
it easy to print several reports at the same time. This can be
achieved through the following JavaScript function:
/** @odoo-module **/
import { _t } from "@web/core/l10n/translation";
import { registry } from "@web/core/registry";
import { sprintf } from "@web/core/utils/strings";
async function doMultiPrint(env, action) {
for (const report of action.params.reports) {
if (report.type != "ir.actions.report") {
env.services.notification.add(_t("Incorrect type of action submitted as a report, skipping action"), {
title: _t("Report Printing Error"),
});
continue
} else if (report.report_type === "qweb-html") {
env.services.notification.add(
sprintf(
_t("HTML reports cannot be auto-printed, skipping report: %s"),
report.name)
, {
title: _t("Report Printing Error"),
});
continue
}
// WARNING: potential issue if pdf generation fails, then action_service defaults
// to HTML and rest of the action chain will break w/potentially never resolving promise
await env.services.action.doAction({ type: "ir.actions.report", ...report });
}
if (action.params.anotherAction) {
return env.services.action.doAction(action.params.anotherAction);
} else if (action.params.onClose) {
// handle special cases such as barcode
action.params.onClose()
} else {
return env.services.action.doAction("reload_context");
}
}
registry.category("actions").add("do_multi_print", doMultiPrint);
The provided JavaScript code defines an Odoo module that facilitates
the printing of multiple reports. The doMultiPrint function, marked
with the Odoo module comment, is asynchronous and takes two
parameters: env and action. The function iterates through the
specified reports, checks their types and report formats, and
triggers the printing using Odoo's env.services.action.doAction
method. The module registers the doMultiPrint function under the
"actions" category in the Odoo registry, making it available for use
as an action in the Odoo system.
The Python function for performing multi-printing is exemplified
below.
def action_print(self):
return {
'type': 'ir.actions.client',
'tag': 'do_multi_print',
'context': {},
'params': {
'reports': [self.env.ref(
'student_registration.action_report_student_detail')
.report_action(self), self.env.ref(
'student_registration.action_report_student_attendance')
.report_action(self)]
}
}
Here,
● 'type': 'ir.actions.client': Specifies the type of action as a
client action in Odoo.
● 'tag': 'do_multi_print': Associates this action with the previously
defined client action named do_multi_print.
● 'context': {}: Provides an empty context for the action.
● 'params': Contains a dictionary with a key 'reports', which holds a
list of reports to be printed.
The list includes two reports, presumably related to student details
and student attendance.
First print is:
The second print is:
By utilizing the do_multi_print feature, this method enables the
simultaneous printing of any number of reports.