
Prior to this commit, the Odoo documentation was mainly split between two repositories: odoo/odoo/doc and odoo/documentation-user. Some bits of documentation were also hosted elsewhere (e.g., wiki, upgrade, ...). This was causing several problems among which: - The theme, config, Makefile, and similar technical resources had to be duplicated. This resulted in inconsistent layout, features, and build environments from one documentation to another. - Some pages did not fit either documentation as they were relevant for both users and developers. Some were relevant to neither of the two (e.g., DB management). - Cross-doc references had to be absolute links and they broke often. - Merging large image files in the developer documentation would bloat the odoo/odoo repository. Some contributions had to be lightened to avoid merging too many images (e.g., Odoo development tutorials). - Long-time contributors to the user documentation were chilly about going through the merging process of the developer documentation because of the runbot, mergebot, `odoo-dev` repository, etc. - Some contributors would look for the developer documentation in the `odoo/documentation-user` repository. - Community issues about the user documentation were submitted on the `odoo/odoo` repository and vice-versa. Merging all documentations in one repository will allow us to have one place, one theme, one work process, and one set of tools (build environment, ...) for all of the Odoo docs. As this is a good opportunity to revamp the layout of the documentation, a brand new theme replaces the old one. It features a new way to navigate the documentation, centered on the idea of always letting the reader know what is the context (enclosing section, child pages, page structure ...) of the page they are reading. The previous theme would quickly confuse readers as they navigated the documentation and followed cross-application links. The chance is also taken to get rid of all the technical dangling parts, performance issues, and left-overs. Except for some page-specific JS scripts, the Odoo theme Sphinx extension is re-written from scratch based on the latest Sphinx release to benefit from the improvements and ease future contributions. task-2351938 task-2352371 task-2205684 task-2352544 Closes #945
354 lines
12 KiB
ReStructuredText
354 lines
12 KiB
ReStructuredText
|
|
.. highlight:: xml
|
|
|
|
.. _reference/reports:
|
|
|
|
============
|
|
QWeb Reports
|
|
============
|
|
|
|
Reports are written in HTML/QWeb, like all regular views in Odoo. You can use
|
|
the usual :ref:`QWeb control flow tools <reference/qweb>`. The PDF rendering
|
|
itself is performed by wkhtmltopdf_.
|
|
|
|
If you want to create a report on a certain model, you will need to define
|
|
this :ref:`reference/reports/report` and the
|
|
:ref:`reference/reports/templates` it will use. If you wish, you can also
|
|
specify a specific :ref:`reference/reports/paper_formats` for this
|
|
report. Finally, if you need access to more than your model, you can define a
|
|
:ref:`reference/reports/custom_reports` class that gives you access to more
|
|
models and records in the template.
|
|
|
|
.. _reference/reports/report:
|
|
|
|
Report
|
|
======
|
|
|
|
Every report must be declared by a :ref:`report action
|
|
<reference/actions/report>`.
|
|
|
|
For simplicity, a shortcut ``<report>`` element is available to define a
|
|
report, rather than have to set up :ref:`the action
|
|
<reference/actions/report>` and its surroundings manually. That ``<report>``
|
|
can take the following attributes:
|
|
|
|
``id``
|
|
the generated record's :term:`external id`
|
|
``string`` (mapping to ``IrActionsReport.name`` field)
|
|
used as the file name if ``print_report_name`` is not specified.
|
|
Otherwise, only useful as a mnemonic/description of the report
|
|
when looking for one in a list of some sort
|
|
``name`` (mandatory) (mapping to ``IrActionsReport.report_name`` field)
|
|
the name of the template used to render the report
|
|
``model`` (mandatory)
|
|
the model your report will be about
|
|
``report_type`` (mandatory)
|
|
either ``qweb-pdf`` for PDF reports or ``qweb-html`` for HTML
|
|
``print_report_name``
|
|
python expression defining the name of the report.
|
|
``groups``
|
|
:class:`~odoo.fields.Many2many` field to the groups allowed to view/use
|
|
the current report
|
|
``attachment_use``
|
|
if set to True, the report will be stored as an attachment of the record
|
|
using the name generated by the ``attachment`` expression; you can use
|
|
this if you need your report to be generated only once (for legal reasons,
|
|
for example)
|
|
``attachment``
|
|
python expression that defines the name of the report; the record is
|
|
acessible as the variable ``object``
|
|
``paperformat``
|
|
external id of the paperformat you wish to use (defaults to the company's
|
|
paperformat if not specified)
|
|
|
|
Example::
|
|
|
|
<report
|
|
id="account_invoices"
|
|
model="account.invoice"
|
|
string="Invoices"
|
|
name="account.report_invoice"
|
|
report_type="qweb-pdf"
|
|
print_report_name="object._get_report_filename()"
|
|
attachment_use="True"
|
|
attachment="(object.state in ('open','paid')) and
|
|
('INV'+(object.number or '').replace('/','')+'.pdf')"
|
|
/>
|
|
|
|
.. _reference/reports/templates:
|
|
|
|
Report template
|
|
===============
|
|
|
|
|
|
Minimal viable template
|
|
-----------------------
|
|
|
|
A minimal template would look like::
|
|
|
|
<template id="report_invoice">
|
|
<t t-call="web.html_container">
|
|
<t t-foreach="docs" t-as="o">
|
|
<t t-call="web.external_layout">
|
|
<div class="page">
|
|
<h2>Report title</h2>
|
|
<p>This object's name is <span t-field="o.name"/></p>
|
|
</div>
|
|
</t>
|
|
</t>
|
|
</t>
|
|
</template>
|
|
|
|
Calling ``external_layout`` will add the default header and footer on your
|
|
report. The PDF body will be the content inside the ``<div
|
|
class="page">``. The template's ``id`` must be the name specified in the
|
|
report declaration; for example ``account.report_invoice`` for the above
|
|
report. Since this is a QWeb template, you can access all the fields of the
|
|
``docs`` objects received by the template.
|
|
|
|
There are some specific variables accessible in reports, mainly:
|
|
|
|
``docs``
|
|
records for the current report
|
|
``doc_ids``
|
|
list of ids for the ``docs`` records
|
|
``doc_model``
|
|
model for the ``docs`` records
|
|
``time``
|
|
a reference to :mod:`python:time` from the Python standard library
|
|
``user``
|
|
``res.user`` record for the user printing the report
|
|
``res_company``
|
|
record for the current ``user``'s company
|
|
|
|
If you wish to access other records/models in the template, you will need
|
|
:ref:`a custom report <reference/reports/custom_reports>`.
|
|
|
|
Translatable Templates
|
|
----------------------
|
|
|
|
If you wish to translate reports (to the language of a partner, for example),
|
|
you need to define two templates:
|
|
|
|
* The main report template
|
|
* The translatable document
|
|
|
|
You can then call the translatable document from your main template with the attribute
|
|
``t-lang`` set to a language code (for example ``fr`` or ``en_US``) or to a record field.
|
|
You will also need to re-browse the related records with the proper context if you use
|
|
fields that are translatable (like country names, sales conditions, etc.)
|
|
|
|
.. warning::
|
|
|
|
If your report template does not use translatable record fields, re-browsing the record
|
|
in another language is *not* necessary and will impact performances.
|
|
|
|
For example, let's look at the Sale Order report from the Sale module::
|
|
|
|
<!-- Main template -->
|
|
<template id="report_saleorder">
|
|
<t t-call="web.html_container">
|
|
<t t-foreach="docs" t-as="doc">
|
|
<t t-call="sale.report_saleorder_document" t-lang="doc.partner_id.lang"/>
|
|
</t>
|
|
</t>
|
|
</template>
|
|
|
|
<!-- Translatable template -->
|
|
<template id="report_saleorder_document">
|
|
<!-- Re-browse of the record with the partner lang -->
|
|
<t t-set="doc" t-value="doc.with_context(lang=doc.partner_id.lang)" />
|
|
<t t-call="web.external_layout">
|
|
<div class="page">
|
|
<div class="oe_structure"/>
|
|
<div class="row">
|
|
<div class="col-6">
|
|
<strong t-if="doc.partner_shipping_id == doc.partner_invoice_id">Invoice and shipping address:</strong>
|
|
<strong t-if="doc.partner_shipping_id != doc.partner_invoice_id">Invoice address:</strong>
|
|
<div t-field="doc.partner_invoice_id" t-options="{"no_marker": True}"/>
|
|
<...>
|
|
<div class="oe_structure"/>
|
|
</div>
|
|
</t>
|
|
</template>
|
|
|
|
|
|
The main template calls the translatable template with ``doc.partner_id.lang`` as a
|
|
``t-lang`` parameter, so it will be rendered in the language of the partner. This way,
|
|
each Sale Order will be printed in the language of the corresponding customer. If you wish
|
|
to translate only the body of the document, but keep the header and footer in a default
|
|
language, you could call the report's external layout this way::
|
|
|
|
<t t-call="web.external_layout" t-lang="en_US">
|
|
|
|
.. tip::
|
|
|
|
Please take note that this works only when calling external templates, you will not be
|
|
able to translate part of a document by setting a ``t-lang`` attribute on an xml node other
|
|
than ``t-call``. If you wish to translate part of a template, you can create an external
|
|
template with this partial template and call it from the main one with the ``t-lang``
|
|
attribute.
|
|
|
|
|
|
Barcodes
|
|
--------
|
|
|
|
Barcodes are images returned by a controller and can easily be embedded in
|
|
reports thanks to the QWeb syntax (e.g. see :ref:`reference/qweb/attributes`):
|
|
|
|
.. code-block:: html
|
|
|
|
<img t-att-src="'/report/barcode/QR/%s' % 'My text in qr code'"/>
|
|
|
|
More parameters can be passed as a query string
|
|
|
|
.. code-block:: html
|
|
|
|
<img t-att-src="'/report/barcode/?
|
|
type=%s&value=%s&width=%s&height=%s'%('QR', 'text', 200, 200)"/>
|
|
|
|
|
|
Useful Remarks
|
|
--------------
|
|
* Twitter Bootstrap and FontAwesome classes can be used in your report
|
|
template
|
|
* Local CSS can be put directly in the template
|
|
* Global CSS can be inserted in the main report layout by inheriting its
|
|
template and inserting your CSS::
|
|
|
|
<template id="report_saleorder_style" inherit_id="report.style">
|
|
<xpath expr=".">
|
|
<t>
|
|
.example-css-class {
|
|
background-color: red;
|
|
}
|
|
</t>
|
|
</xpath>
|
|
</template>
|
|
* If it appears that your PDF report is missing the styles, please check
|
|
:ref:`these instructions <reference/backend/reporting/printed-reports/pdf-without-styles>`.
|
|
|
|
.. _reference/reports/paper_formats:
|
|
|
|
Paper Format
|
|
============
|
|
|
|
Paper formats are records of ``report.paperformat`` and can contain the
|
|
following attributes:
|
|
|
|
``name`` (mandatory)
|
|
only useful as a mnemonic/description of the report when looking for one
|
|
in a list of some sort
|
|
``description``
|
|
a small description of your format
|
|
``format``
|
|
either a predefined format (A0 to A9, B0 to B10, Legal, Letter,
|
|
Tabloid,...) or ``custom``; A4 by default. You cannot use a non-custom
|
|
format if you define the page dimensions.
|
|
``dpi``
|
|
output DPI; 90 by default
|
|
``margin_top``, ``margin_bottom``, ``margin_left``, ``margin_right``
|
|
margin sizes in mm
|
|
``page_height``, ``page_width``
|
|
page dimensions in mm
|
|
``orientation``
|
|
Landscape or Portrait
|
|
``header_line``
|
|
boolean to display a header line
|
|
``header_spacing``
|
|
header spacing in mm
|
|
|
|
Example::
|
|
|
|
<record id="paperformat_frenchcheck" model="report.paperformat">
|
|
<field name="name">French Bank Check</field>
|
|
<field name="default" eval="True"/>
|
|
<field name="format">custom</field>
|
|
<field name="page_height">80</field>
|
|
<field name="page_width">175</field>
|
|
<field name="orientation">Portrait</field>
|
|
<field name="margin_top">3</field>
|
|
<field name="margin_bottom">3</field>
|
|
<field name="margin_left">3</field>
|
|
<field name="margin_right">3</field>
|
|
<field name="header_line" eval="False"/>
|
|
<field name="header_spacing">3</field>
|
|
<field name="dpi">80</field>
|
|
</record>
|
|
|
|
.. _reference/reports/custom_reports:
|
|
|
|
Custom Reports
|
|
==============
|
|
|
|
The report model has a default ``get_html`` function that looks for a model
|
|
named :samp:`report.{module.report_name}`. If it exists, it will use it to
|
|
call the QWeb engine; otherwise a generic function will be used. If you wish
|
|
to customize your reports by including more things in the template (like
|
|
records of others models, for example), you can define this model, overwrite
|
|
the function ``_get_report_values`` and pass objects in the ``docargs`` dictionary:
|
|
|
|
.. code-block:: python
|
|
|
|
from odoo import api, models
|
|
|
|
class ParticularReport(models.AbstractModel):
|
|
_name = 'report.module.report_name'
|
|
|
|
@api.model
|
|
def _get_report_values(self, docids, data=None):
|
|
report_obj = self.env['ir.actions.report']
|
|
report = report_obj._get_report_from_name('module.report_name')
|
|
docargs = {
|
|
'doc_ids': docids,
|
|
'doc_model': report.model,
|
|
'docs': self,
|
|
}
|
|
return docargs
|
|
|
|
.. _reference/reports/custom_fonts:
|
|
|
|
Custom fonts
|
|
============
|
|
If you want to use custom fonts you will need to add your custom font and the related less/CSS to the ``web.reports_assets_common`` assets bundle.
|
|
Adding your custom font(s) to ``web.assets_common`` or ``web.assets_backend`` will not make your font available in QWeb reports.
|
|
|
|
Example::
|
|
|
|
<template id="report_assets_common_custom_fonts" name="Custom QWeb fonts" inherit_id="web.report_assets_common">
|
|
<xpath expr="." position="inside">
|
|
<link href="/your_module/static/src/less/fonts.less" rel="stylesheet" type="text/less"/>
|
|
</xpath>
|
|
</template>
|
|
|
|
You will need to define your ``@font-face`` within this less file, even if you've used in another assets bundle (other than ``web.reports_assets_common``).
|
|
|
|
Example::
|
|
|
|
@font-face {
|
|
font-family: 'MonixBold';
|
|
src: local('MonixBold'), local('MonixBold'), url(/your_module/static/src/fonts/MonixBold-Regular.otf) format('opentype');
|
|
}
|
|
|
|
.h1-title-big {
|
|
font-family: MonixBold;
|
|
font-size: 60px;
|
|
color: #3399cc;
|
|
}
|
|
|
|
After you've added the less into your assets bundle you can use the classes - in this example ``h1-title-big`` - in your custom QWeb report.
|
|
|
|
Reports are web pages
|
|
=====================
|
|
|
|
Reports are dynamically generated by the report module and can be accessed
|
|
directly via URL:
|
|
|
|
For example, you can access a Sale Order report in html mode by going to
|
|
\http://<server-address>/report/html/sale.report_saleorder/38
|
|
|
|
Or you can access the pdf version at
|
|
\http://<server-address>/report/pdf/sale.report_saleorder/38
|
|
|
|
.. _wkhtmltopdf: https://wkhtmltopdf.org
|