[REM] developer: remove references to web_dashboard view
Since odoo/enterprise#31641 the dashboard view no longer exists since it
is now replaced with spreadsheet_dashboard, therefore we remove it from
the backend Views documentation.
Task: 3226581
X-original-commit: e2c880aafe
Part-of: odoo/documentation#4035
This commit is contained in:
parent
56a5b0480e
commit
e18b24a176
@ -124,7 +124,7 @@ an impact on all view types.
|
|||||||
``info``, ``warning``, ``danger`` and ``secondary`` displays. The list view supports ``bf``,
|
``info``, ``warning``, ``danger`` and ``secondary`` displays. The list view supports ``bf``,
|
||||||
``it``, ``success``, ``info``, ``warning``, ``danger``, ``muted`` and ``primary`` displays.
|
``it``, ``success``, ``info``, ``warning``, ``danger``, ``muted`` and ``primary`` displays.
|
||||||
|
|
||||||
* ``sample`` (``kanban`` & ``list`` & ``gantt`` & ``graph`` & ``pivot`` & ``cohort`` & ``dashboard``)
|
* ``sample`` (``kanban`` & ``list`` & ``gantt`` & ``graph`` & ``pivot`` & ``cohort``)
|
||||||
|
|
||||||
Populate the view with a set of sample records if none are found for the current model.
|
Populate the view with a set of sample records if none are found for the current model.
|
||||||
This attribute is false by default.
|
This attribute is false by default.
|
||||||
@ -580,213 +580,6 @@ attributes:
|
|||||||
measures (useful for fields that do not make sense aggregated, such as fields in different
|
measures (useful for fields that do not make sense aggregated, such as fields in different
|
||||||
units, e.g. € and $).
|
units, e.g. € and $).
|
||||||
|
|
||||||
.. _reference/views/dashboard:
|
|
||||||
|
|
||||||
Dashboard
|
|
||||||
---------
|
|
||||||
|
|
||||||
.. raw:: html
|
|
||||||
|
|
||||||
<span class="badge" style="background-color:#AD5E99">Enterprise feature</span>
|
|
||||||
|
|
||||||
Like pivot and graph view, The dashboard view is used to display aggregate data.
|
|
||||||
However, the dashboard can embed sub views, which makes it possible to have a
|
|
||||||
more complete and interesting look on a given dataset.
|
|
||||||
|
|
||||||
The dashboard view can display sub views, aggregates for some fields (over a
|
|
||||||
domain), or even *formulas* (expressions which involves one or more aggregates).
|
|
||||||
For example, here is a very simple dashboard:
|
|
||||||
|
|
||||||
.. code-block:: xml
|
|
||||||
|
|
||||||
<dashboard>
|
|
||||||
<view type="graph" ref="sale_report.view_order_product_graph"/>
|
|
||||||
<group string="Sale">
|
|
||||||
<aggregate name="price_total" field="price_total" widget="monetary"/>
|
|
||||||
<aggregate name="order_id" field="order_id" string="Orders"/>
|
|
||||||
<formula name="price_average" string="Price Average"
|
|
||||||
value="record.price_total / record.order_id" widget="percentage"/>
|
|
||||||
</group>
|
|
||||||
<view type="pivot" ref="sale_report.view_order_product_pivot"/>
|
|
||||||
</dashboard>
|
|
||||||
|
|
||||||
The root element of the Dashboard view is <dashboard>, it does not accept any
|
|
||||||
attributes.
|
|
||||||
|
|
||||||
There are 5 possible type of tags in a dashboard view:
|
|
||||||
|
|
||||||
.. rst-class:: o-definition-list
|
|
||||||
|
|
||||||
``view``
|
|
||||||
declares a sub view.
|
|
||||||
|
|
||||||
Admissible attributes are:
|
|
||||||
|
|
||||||
.. rst-class:: o-definition-list
|
|
||||||
|
|
||||||
``type`` (mandatory)
|
|
||||||
The type of the sub view. For example, *graph* or *pivot*.
|
|
||||||
|
|
||||||
``ref`` (optional)
|
|
||||||
An xml id for a view. If not given, the default view for the model will
|
|
||||||
be used.
|
|
||||||
|
|
||||||
``name`` (optional)
|
|
||||||
A string which identifies this element. It is mostly
|
|
||||||
useful to be used as a target for an xpath.
|
|
||||||
|
|
||||||
``group``
|
|
||||||
defines a column layout. This is actually very similar to the group element
|
|
||||||
in a form view.
|
|
||||||
|
|
||||||
Admissible attributes are:
|
|
||||||
|
|
||||||
.. rst-class:: o-definition-list
|
|
||||||
|
|
||||||
``string`` (optional)
|
|
||||||
A description which will be displayed as a group title.
|
|
||||||
|
|
||||||
``colspan`` (optional)
|
|
||||||
The number of subcolumns in this group tag. By default, 6.
|
|
||||||
|
|
||||||
``col`` (optional)
|
|
||||||
The number of columns spanned by this group tag (only makes sense inside
|
|
||||||
another group). By default, 6.
|
|
||||||
|
|
||||||
|
|
||||||
``aggregate``
|
|
||||||
declares an aggregate. This is the value of an aggregate for a given field
|
|
||||||
over the current domain.
|
|
||||||
|
|
||||||
Note that aggregates are supposed to be used inside a group tag (otherwise
|
|
||||||
the style will not be properly applied).
|
|
||||||
|
|
||||||
Admissible attributes are:
|
|
||||||
|
|
||||||
.. rst-class:: o-definition-list
|
|
||||||
|
|
||||||
``field`` (mandatory)
|
|
||||||
The field name to use for computing the aggregate. Possible field types
|
|
||||||
are:
|
|
||||||
|
|
||||||
- ``integer`` (default group operator is sum)
|
|
||||||
- ``float`` (default group operator is sum)
|
|
||||||
- ``many2one`` (default group operator is count distinct)
|
|
||||||
|
|
||||||
``name`` (mandatory)
|
|
||||||
A string to identify this aggregate (useful for formulas)
|
|
||||||
|
|
||||||
``string`` (optional)
|
|
||||||
A short description that will be displayed above the value. If not
|
|
||||||
given, it will fall back to the field string.
|
|
||||||
|
|
||||||
``domain`` (optional)
|
|
||||||
An additional restriction on the set of records that we want to aggregate.
|
|
||||||
This domain will be combined with the current domain.
|
|
||||||
|
|
||||||
``domain_label`` (optional)
|
|
||||||
When the user clicks on an aggregate with a domain, it will be added to
|
|
||||||
the search view as a facet. The string displayed for this facet can
|
|
||||||
be customized with this attribute.
|
|
||||||
|
|
||||||
``group_operator`` (optional)
|
|
||||||
A valid postgreSQL aggregate function identifier to use when aggregating
|
|
||||||
values (see https://www.postgresql.org/docs/12/static/functions-aggregate.html).
|
|
||||||
If not provided, By default, the group_operator from the field definition is used.
|
|
||||||
Note that no aggregation of field values is achieved if the group_operator value is "".
|
|
||||||
|
|
||||||
.. note:: The special aggregate function ``count_distinct`` (defined in odoo) can also be used here
|
|
||||||
|
|
||||||
.. code-block:: xml
|
|
||||||
|
|
||||||
<aggregate name="price_total_max" field="price_total" group_operator="max"/>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
``col`` (optional)
|
|
||||||
The number of columns spanned by this tag (only makes sense inside a
|
|
||||||
group). By default, 1.
|
|
||||||
|
|
||||||
``widget`` (optional)
|
|
||||||
A widget to format the value (like the widget attribute for fields).
|
|
||||||
For example, monetary.
|
|
||||||
|
|
||||||
``help`` (optional)
|
|
||||||
A help message to dipslay in a tooltip (equivalent of help for a field in python)
|
|
||||||
|
|
||||||
``measure`` (optional)
|
|
||||||
This attribute is the name of a field describing the measure that has to be used
|
|
||||||
in the graph and pivot views when clicking on the aggregate.
|
|
||||||
The special value __count__ can be used to use the count measure.
|
|
||||||
|
|
||||||
.. code-block:: xml
|
|
||||||
|
|
||||||
<aggregate name="total_ojects" string="Total Objects" field="id" group_operator="count" measure="__count__"/>
|
|
||||||
|
|
||||||
``clickable`` (optional)
|
|
||||||
A boolean indicating if this aggregate should be clickable or not (default to true).
|
|
||||||
Clicking on a clickable aggregate will change the measures used by the subviews
|
|
||||||
and add the value of the domain attribute (if any) to the search view.
|
|
||||||
|
|
||||||
``value_label`` (optional)
|
|
||||||
A string put on the right of the aggregate value.
|
|
||||||
For example, it can be useful to indicate the unit of measure
|
|
||||||
of the aggregate value.
|
|
||||||
|
|
||||||
``formula``
|
|
||||||
declares a derived value. Formulas are values computed from aggregates.
|
|
||||||
|
|
||||||
Note that like aggregates, formulas are supposed to be used inside a group
|
|
||||||
tag (otherwise the style will not be properly applied).
|
|
||||||
|
|
||||||
Admissible attributes are:
|
|
||||||
|
|
||||||
.. rst-class:: o-definition-list
|
|
||||||
|
|
||||||
``value`` (mandatory)
|
|
||||||
A string expression that will be evaluated, with the builtin python
|
|
||||||
evaluator (in the web client). Every aggregate can be used in the
|
|
||||||
context, in the ``record`` variable. For example,
|
|
||||||
``record.price_total / record.order_id``.
|
|
||||||
|
|
||||||
``name`` (optional)
|
|
||||||
A string to identify this formula
|
|
||||||
|
|
||||||
``string`` (optional)
|
|
||||||
A short description that will be displayed above the formula.
|
|
||||||
|
|
||||||
``col`` (optional)
|
|
||||||
The number of columns spanned by this tag (only makes sense inside a
|
|
||||||
group). By default, 1.
|
|
||||||
|
|
||||||
``widget`` (optional)
|
|
||||||
A widget to format the value (like the widget attribute for fields).
|
|
||||||
For example, monetary. By default, it is 'float'.
|
|
||||||
|
|
||||||
``help`` (optional)
|
|
||||||
A help message to dipslay in a tooltip (equivalent of help for a field in python)
|
|
||||||
|
|
||||||
``value_label`` (optional)
|
|
||||||
A string put on the right of the formula value.
|
|
||||||
For example, it can be useful to indicate the unit of measure
|
|
||||||
of the formula value.
|
|
||||||
|
|
||||||
``widget``
|
|
||||||
Declares a specialized widget to be used to display the information. This is
|
|
||||||
a mechanism similar to the widgets in the form view.
|
|
||||||
|
|
||||||
Admissible attributes are:
|
|
||||||
|
|
||||||
.. rst-class:: o-definition-list
|
|
||||||
|
|
||||||
``name`` (mandatory)
|
|
||||||
A string to identify which widget should be instantiated. The view will
|
|
||||||
look into the ``widget_registry`` to get the proper class.
|
|
||||||
|
|
||||||
``col`` (optional)
|
|
||||||
The number of columns spanned by this tag (only makes sense inside a
|
|
||||||
group). By default, 1.
|
|
||||||
|
|
||||||
.. _reference/views/form:
|
.. _reference/views/form:
|
||||||
|
|
||||||
Form
|
Form
|
||||||
|
@ -15,7 +15,6 @@ Tutorials
|
|||||||
tutorials/unit_tests
|
tutorials/unit_tests
|
||||||
tutorials/mixins
|
tutorials/mixins
|
||||||
tutorials/pdf_reports
|
tutorials/pdf_reports
|
||||||
tutorials/dashboards
|
|
||||||
|
|
||||||
.. cards::
|
.. cards::
|
||||||
|
|
||||||
@ -66,9 +65,3 @@ Tutorials
|
|||||||
:target: tutorials/pdf_reports
|
:target: tutorials/pdf_reports
|
||||||
|
|
||||||
Use QWeb, Odoo's powerful templating engine, to create custom PDF reports for your documents.
|
Use QWeb, Odoo's powerful templating engine, to create custom PDF reports for your documents.
|
||||||
|
|
||||||
.. card:: Visualize data in dashboards
|
|
||||||
:target: tutorials/dashboards
|
|
||||||
|
|
||||||
Create data visualization dashboards using the enterprise edition "Dashboard" view and
|
|
||||||
so-called "SQL views".
|
|
||||||
|
@ -1,370 +0,0 @@
|
|||||||
============================
|
|
||||||
Visualize data in dashboards
|
|
||||||
============================
|
|
||||||
|
|
||||||
.. important::
|
|
||||||
This tutorial is an extension of the :doc:`getting_started` tutorial. Make sure you have
|
|
||||||
completed it and use the `estate` module you have built as a base for the exercises in this
|
|
||||||
tutorial. Fetch the branch `{BRANCH}-core` from the `technical-training-solutions
|
|
||||||
<https://github.com/odoo/technical-training-solutions/tree/{BRANCH}-core>`_ repository if you
|
|
||||||
want to start from a clean base.
|
|
||||||
|
|
||||||
The term "Dashboard" is used in Odoo for objects that display data, but involves different
|
|
||||||
implementations. This tutorial will only focus on the Enterprise view that is used to provide
|
|
||||||
aggregated data visualization. They can be added as a ``view_mode`` to an existing model (i.e. a
|
|
||||||
view you can switch to via the view buttons in the top right of a view), but they are also often
|
|
||||||
used as a view for to a special model customized for data visualization. You may hear these
|
|
||||||
special views referred to as SQL views.
|
|
||||||
|
|
||||||
It is useful to note there is a "Dashboard" app in Odoo Community. This app allows users to create
|
|
||||||
their own customized view of data, but the customization is only visible to each user and can
|
|
||||||
only be viewed within the "Dashboard" app. Technically it is possible to make global dashboards
|
|
||||||
using this ``board`` module, but it is much easier to do as an Enterprise view. Plus it looks nicer
|
|
||||||
and has extra features not available in ``board``. Some other dashboards within Odoo also exist,
|
|
||||||
but they are custom made and are beyond the scope of this tutorial.
|
|
||||||
|
|
||||||
The documentation related to this topic can be found in :ref:`reference/views/dashboard`.
|
|
||||||
|
|
||||||
File Structure
|
|
||||||
==============
|
|
||||||
|
|
||||||
You probably have already guessed that since dashboard views are an Enterprise view, they must have
|
|
||||||
a dependency on an Enterprise module. The Enterprise module is ``web_dashboard``. Don't forget to
|
|
||||||
add it to your manifest file! It is standard to add dashboards intended to be used as a
|
|
||||||
``view_mode`` for one of your module's models (in the ``model`` folder) to the views directory
|
|
||||||
(i.e. the same file that contains the other views for the same model).
|
|
||||||
|
|
||||||
It is standard to create a separate Enterprise module to add extra Enterprise views and features to
|
|
||||||
a Community module. This is done in a similar manner as the module link technique covered within
|
|
||||||
:ref:`tutorials/getting_started/14_other_module`. The difference is that instead of linking 2
|
|
||||||
different modules, we are extending our `estate` module. We do this by creating a new module and
|
|
||||||
adding both the Community module and its necessary Enterprise module dependencies to its manifest.
|
|
||||||
You will commonly see "enterprise" in the module's directory name. To keep this tutorial simple, we
|
|
||||||
will add dashboards to our existing ``estate`` module.
|
|
||||||
|
|
||||||
SQL Views have 2 parts: their xml file (don't forget to add it to your manifest file) and their
|
|
||||||
Python file (don't forget to add it to the appropriate ``__init.py__`` files). The former is the
|
|
||||||
same format as the ``view_mode`` xml while the latter contains a custom model and SQL code to
|
|
||||||
populate its fields. It is standard to add SQL view files to the ``report/`` directory. It
|
|
||||||
is also common to include "report" in the name of the SQL view's files. You may be
|
|
||||||
wondering why do we put the files in a report directory? We saw earlier that the dashboard is
|
|
||||||
for data visualization, therefore it is not editable. You can think of dashboards as interactive
|
|
||||||
reports where you can click on statistics, graphs, and charts to see the specific data contributing
|
|
||||||
to them. Note it is also standard to store the xml code for :doc:`PDF report templates
|
|
||||||
<pdf_reports>` in the report directory.
|
|
||||||
|
|
||||||
It is expected that your work tree will look something like:
|
|
||||||
|
|
||||||
.. code-block:: bash
|
|
||||||
|
|
||||||
estate
|
|
||||||
├── models
|
|
||||||
│ ├── *.py
|
|
||||||
│ └── __init__.py
|
|
||||||
├── report
|
|
||||||
│ ├── __init__.py
|
|
||||||
│ ├── estate_report.py
|
|
||||||
│ └── estate_report_views.xml
|
|
||||||
├── security
|
|
||||||
│ └── ir.model.access.csv
|
|
||||||
├── views
|
|
||||||
│ ├── *.xml
|
|
||||||
│ └── estate_property_views.xml
|
|
||||||
├── __init__.py
|
|
||||||
└── __manifest__.py
|
|
||||||
|
|
||||||
Dashboard View
|
|
||||||
==============
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
**Goal**: at the end of this section, we will have a new dashboard view that displays
|
|
||||||
different property statistics.
|
|
||||||
|
|
||||||
.. image:: dashboards/simple_dashboard.png
|
|
||||||
:align: center
|
|
||||||
:alt: Basic Dashboard view
|
|
||||||
|
|
||||||
Dashboards can display data in different ways, including:
|
|
||||||
|
|
||||||
* showing an ``aggregate`` of a field
|
|
||||||
* using aggregated fields in a ``formula``
|
|
||||||
* using a ``widget``
|
|
||||||
* using another ``view`` as a subview
|
|
||||||
|
|
||||||
There are many useful statistics and visuals we can provide for our real estate example using
|
|
||||||
these options. A full example to reference while doing the exercises in this section is
|
|
||||||
`viewable here <https://github.com/odoo/enterprise/blob/6fd3244ae168dc73c348a9c1870796e89d8ef594/crm_enterprise/views/crm_lead_views.xml#L106-L133>`__
|
|
||||||
(restricted github repository link).
|
|
||||||
|
|
||||||
Data
|
|
||||||
----
|
|
||||||
|
|
||||||
To fully enjoy our dashboard view, we will need good test data to populate it. Test data will
|
|
||||||
allow us to check that the resulting look and statistics are correct. It is a good idea to test
|
|
||||||
with data that will cover most or all of your expected use cases, but is also easy to verify with
|
|
||||||
that your statistics are correct. In our goal's case we are looking at count, sum, average,
|
|
||||||
minimum, and maximum statistics, therefore a good representation set for our dashboard is:
|
|
||||||
|
|
||||||
* At least 3 properties with different property types, expected prices, and average living area.
|
|
||||||
* At least 1 sold property and at least 1 canceled property
|
|
||||||
|
|
||||||
If you don't have a set of data like this already, you can either:
|
|
||||||
|
|
||||||
* Complete :doc:`define_module_data` (if you haven't done so already) and add the extra cases to
|
|
||||||
your demo data (you may need to create a new database to load in the demo data).
|
|
||||||
* Manually create the data in your database.
|
|
||||||
* Copy this `data file
|
|
||||||
<https://github.com/odoo/technical-training-solutions/blob/{BRANCH}-K_dashboard/estate/data/estate_demo.xml>`_
|
|
||||||
into a new directory called ``data`` in your estate module and copy `these lines
|
|
||||||
<https://github.com/odoo/technical-training-solutions/blob/{BRANCH}-K_dashboard/estate/__manifest__.py#L21-L23>`_
|
|
||||||
into your __manifest__.py file (you may need to create a new database to load in the demo data).
|
|
||||||
|
|
||||||
Click through your database data and make sure it is what you expect. Of course you can add the
|
|
||||||
data after you write your dashboard code and then test that your view is working as expected.
|
|
||||||
|
|
||||||
Aggregations
|
|
||||||
------------
|
|
||||||
|
|
||||||
Building a dashboard view is very similar to what you have previously done in
|
|
||||||
:ref:`tutorials/getting_started/07_basicviews`. For the dashboard view, we use the `dashboard` root
|
|
||||||
element and choose from its possible tags (see all the possibilities and their attributes in the
|
|
||||||
:ref:`reference/views/dashboard` documentation). So a simple dashboard example is:
|
|
||||||
|
|
||||||
.. code-block:: xml
|
|
||||||
|
|
||||||
<dashboard>
|
|
||||||
<group>
|
|
||||||
<aggregate name="min_expected_price" string="Min Expected Price" field="expected_price"
|
|
||||||
group_operator="min" help="Lowest expected price."/>
|
|
||||||
</group>
|
|
||||||
</dashboard>
|
|
||||||
|
|
||||||
In this example, ``<group>`` adds styling and ``<aggregate>`` declares an aggregation. We
|
|
||||||
indicate which ``field`` we want to aggregate, what ``string`` to display with the value, and
|
|
||||||
how to aggregate it with the `group_operator` attribute. The `group_operator` can use any valid
|
|
||||||
PostgreSQL aggregate function plus the special Odoo defined ``count_distinct``.
|
|
||||||
|
|
||||||
Hopefully you remember how to add views to a window action `view_mode` (hint, it was
|
|
||||||
covered in :ref:`tutorials/getting_started/06_firstui`). Now let's make some dashboards!
|
|
||||||
|
|
||||||
.. exercise:: Make a dashboard view.
|
|
||||||
|
|
||||||
- Create a dashboard of aggregated values for the ``estate.property`` model. You can
|
|
||||||
look at the **Goal** of this section for some inspiration. Remember to check that your
|
|
||||||
statistics are calculating as you expect and note that the calculated values take into
|
|
||||||
consideration any applied view filters!
|
|
||||||
|
|
||||||
- Bonus: Add in some aggregations that need a `domain` to make sense (remember domains were
|
|
||||||
also covered in :ref:`tutorials/getting_started/07_basicviews`).
|
|
||||||
|
|
||||||
Pie Charts
|
|
||||||
----------
|
|
||||||
|
|
||||||
Adding pie charts to dashboards is a piece of cake using the `<widget>` element. An example is:
|
|
||||||
|
|
||||||
.. code-block:: xml
|
|
||||||
|
|
||||||
<dashboard>
|
|
||||||
<group>
|
|
||||||
<widget name="pie_chart" title="Property Types" attrs="{'groupby': 'property_type_id'}"/>
|
|
||||||
</group>
|
|
||||||
</dashboard>
|
|
||||||
|
|
||||||
In this example, we indicate that we're using the `pie_chart` widget with the `name` attribute and
|
|
||||||
the ``title`` for the pie chart, and that we're grouping it by property type.
|
|
||||||
|
|
||||||
.. exercise:: Add some pie charts.
|
|
||||||
|
|
||||||
- Add the pie charts from the **Goal** of this section to your dashboard. Hint: you will need
|
|
||||||
to add `'measure': selling_price` to your pie chart `attrs` if you want to show selling
|
|
||||||
prices grouped by property type.
|
|
||||||
|
|
||||||
- Hover over and click on the pie charts to check your charts counts values and don't forget
|
|
||||||
that filters will also apply to the charts.
|
|
||||||
|
|
||||||
- Bonus: Add a domain to your selling price pie chart to only include "sold" properties (i.e.
|
|
||||||
not "offer_accepted" ones). Note that the `'` will need to be escaped since it is declared
|
|
||||||
as part of the `attrs`.
|
|
||||||
|
|
||||||
Subviews
|
|
||||||
--------
|
|
||||||
|
|
||||||
Similar to how we can use the list view within the form view (we saw this automatically happen for
|
|
||||||
One2many relationships in :ref:`tutorials/getting_started/08_relations`), we can add other views
|
|
||||||
within our dashboard view. The most commonly added are the pivot and graph views, but the cohort
|
|
||||||
view is also an option. A dashboard with only subviews is:
|
|
||||||
|
|
||||||
.. code-block:: xml
|
|
||||||
|
|
||||||
<dashboard>
|
|
||||||
<view type="graph"/>
|
|
||||||
<view type="pivot"/>
|
|
||||||
</dashboard>
|
|
||||||
|
|
||||||
The `ref` attribute can be added to `<view>` elements to use a specific XML id for that view. If
|
|
||||||
no XML id is provided for a graph or pivot view, then the default view will be used.
|
|
||||||
The cohort view will not work in the dashboard without a specific XML id. If you have already
|
|
||||||
created some of these views, then you are welcome to add them to your dashboard! Sample graph and
|
|
||||||
pivot views are included in the `solution code
|
|
||||||
<https://github.com/odoo/technical-training-solutions/blob/{BRANCH}-K_dashboard/estate/views/estate_property_views.xml#L169-L191>`_
|
|
||||||
that you are welcome to use as well.
|
|
||||||
|
|
||||||
.. exercise:: Add subviews.
|
|
||||||
|
|
||||||
- Add in a graph and a pivot view to your dashboard. Try playing around with the layout of
|
|
||||||
your subviews in relation to your pie charts and aggregated values and refer to the **Goal**
|
|
||||||
of this section for an often used layout. Remember to check that your subviews are
|
|
||||||
displaying your data as expected (and yes, they are also affected by the filters!).
|
|
||||||
|
|
||||||
SQL Views
|
|
||||||
=========
|
|
||||||
|
|
||||||
.. warning::
|
|
||||||
|
|
||||||
This section expects you to have a basic knowledge of SQL. If you have little to no SQL
|
|
||||||
knowledge then `this is a good tutorial to start with <https://selectstarsql.com/>`__
|
|
||||||
and these `exercises <https://www.pgexercises.com/>`__ are good for those who need
|
|
||||||
a refresher or extra practice.
|
|
||||||
|
|
||||||
.. note::
|
|
||||||
|
|
||||||
**Goal**: at the end of this section, we will have a new SQL view that displays different
|
|
||||||
property statistics.
|
|
||||||
|
|
||||||
.. image:: dashboards/report_dashboard.png
|
|
||||||
:align: center
|
|
||||||
:alt: SQL view
|
|
||||||
|
|
||||||
|
|
||||||
Occasionally we want to show data that goes beyond what our model already has in it. We could add
|
|
||||||
a lot of stored computed or related fields (non-stored fields cannot be aggregated
|
|
||||||
or displayed in pie charts), but it would be impractical to store a bunch of fields only for this
|
|
||||||
purpose. We can instead add a custom SQL view to minimize the computational load and keep our
|
|
||||||
model clean of unnecessary fields.
|
|
||||||
|
|
||||||
Model
|
|
||||||
-----
|
|
||||||
|
|
||||||
We will start with the more difficult part: our special report model. This file starts the same as
|
|
||||||
any other model, except that we add 2 attributes ``_auto`` and ``_rec_name``::
|
|
||||||
|
|
||||||
from odoo import fields, models, tools
|
|
||||||
|
|
||||||
|
|
||||||
class EstateReport(models.Model):
|
|
||||||
_name = 'estate.report'
|
|
||||||
_description = "Stock Report"
|
|
||||||
_rec_name = 'id'
|
|
||||||
_auto = False
|
|
||||||
|
|
||||||
``_auto = False`` indicates that we do not want to store the model in the database, and we will
|
|
||||||
create a custom table by overriding the ``BaseModel.init()`` method. ``_rec_name`` indicates
|
|
||||||
which of the model's fields represents a record's name (i.e. the name that will be used in the
|
|
||||||
navigation breadcrumb when opening a record's form view). In this case, I left it as 'id' because
|
|
||||||
our property offers don't have a name. We will need the `tools` import later (i.e.
|
|
||||||
``odoo/odoo/tools``, which is full of all sorts of useful helper methods you will probably use in
|
|
||||||
the future). Note that it is standard to include ``report`` in the model's name.
|
|
||||||
|
|
||||||
Remember, your new model will need to be added to your security file, as you learned in
|
|
||||||
:ref:`tutorials/getting_started/05_securityintro`!
|
|
||||||
|
|
||||||
Then we define the fields we need for our dashboard the same way as any other model (like you
|
|
||||||
learned in :ref:`tutorials/getting_started/04_basicmodel`), except that every field is
|
|
||||||
``readonly=True``. After all, our model is for read-only purposes only.
|
|
||||||
|
|
||||||
Now we override the ``BaseModel.init()`` method mentioned earlier::
|
|
||||||
|
|
||||||
def init(self):
|
|
||||||
tools.drop_view_if_exists(self.env.cr, self._table)
|
|
||||||
self.env.cr.execute("""CREATE or REPLACE VIEW %s as (
|
|
||||||
SELECT
|
|
||||||
%s
|
|
||||||
FROM
|
|
||||||
%s
|
|
||||||
)""" % (self._table, self._select(), self._from()))
|
|
||||||
|
|
||||||
We use ``tools.drop_view_if_exists`` to ensure that we don't create a conflicting view and then
|
|
||||||
execute the SQL query. It is standard to separate the different parts of the query to
|
|
||||||
allow for easier model extension. Exactly how the query is split up across methods is not
|
|
||||||
standardized, but you will often see at minimum ``_select`` and ``_from`` methods [or something
|
|
||||||
similar], and of course all these methods will return strings. The columns from the SELECT
|
|
||||||
will populate our model's fields, so ensure that your column names match your field names
|
|
||||||
or use alias names that match.
|
|
||||||
|
|
||||||
.. exercise:: Create report model.
|
|
||||||
|
|
||||||
- Create a report model with the following fields:
|
|
||||||
|
|
||||||
========================= ========================= =========================
|
|
||||||
Field Type Note
|
|
||||||
========================= ========================= =========================
|
|
||||||
id Integer Corresponds to ``id`` of ``estate.property.offer``
|
|
||||||
offer_state Selection Equals ``state`` choices of ``estate.property.offer``
|
|
||||||
property_id Many2one ``estate.property``
|
|
||||||
property_state Selection Equals ``state`` choices of ``estate.property``
|
|
||||||
property_type_id Many2one ``estate.property.type``
|
|
||||||
========================= ========================= =========================
|
|
||||||
|
|
||||||
and write the SQL query necessary to populate the fields (hint, you will need 2 JOINs).
|
|
||||||
|
|
||||||
You won't be able to check if your model is correct until we create a view for it, but you are
|
|
||||||
welcome to check your query directly in your database to see if the results are as you expect.
|
|
||||||
If you struggle with this exercise, then
|
|
||||||
`here is an example <https://github.com/odoo/odoo/blob/7417d8fc138b9de550bc631435bcc08628c29bed/addons/crm/report/crm_activity_report.py>`__
|
|
||||||
to reference.
|
|
||||||
|
|
||||||
View
|
|
||||||
----
|
|
||||||
|
|
||||||
Now that we have our model, we can make its dashboard view. There is no difference in how it's made,
|
|
||||||
except that its file is in the ``report`` folder. Since it is a new model not linked to
|
|
||||||
any other model, we will also have to add a new menuitem to view our dashboard. Typically, SQL views
|
|
||||||
are added under a first-level menu called *Reporting* (because it's a report, surprise!). Do you
|
|
||||||
remember how to add a ``menuitem``? If not, revisit :ref:`tutorials/getting_started/06_firstui`) again.
|
|
||||||
|
|
||||||
.. exercise:: Create report view.
|
|
||||||
|
|
||||||
- Recreate the dashboard in the **Goal** of this section. Hint: it uses the ``formula`` element,
|
|
||||||
which we did not need for our previous dashboard.
|
|
||||||
|
|
||||||
- Bonus: Create ``list`` and ``form`` views for your new report model so we don't have to see the ugly
|
|
||||||
defaults when you click on your pie charts.
|
|
||||||
|
|
||||||
Extra Tips
|
|
||||||
----------
|
|
||||||
|
|
||||||
**Tip 1** A common mistake in SQL views is not considering the duplication of certain data
|
|
||||||
due to table JOINs. For example, in our **Goal**, we have a pie chart of the offers' property types.
|
|
||||||
We may be tempted to add a similar pie chart with a domain to only include canceled properties,
|
|
||||||
so we think we are only counting the number of canceled properties by property type. In reality, we
|
|
||||||
are still looking at all the offers per property, so any property with more than 1 offer will be
|
|
||||||
counted per offer. This example is easily double-checked by clicking on the pie chart to see its
|
|
||||||
list view:
|
|
||||||
|
|
||||||
.. image:: dashboards/report_list_detail.png
|
|
||||||
:align: center
|
|
||||||
:alt: Pie chart list view
|
|
||||||
|
|
||||||
But for cases such as average aggregations or using a subview such as the pivot view, it is easy to
|
|
||||||
miss this mistake. It is also easy to miss this mistake when you have insufficient test data.
|
|
||||||
To add a number of properties canceled by property type pie chart to this
|
|
||||||
report, we would either have to do a hack (too advanced for this tutorial) or simply exclude it
|
|
||||||
from this report.
|
|
||||||
|
|
||||||
**Tip 2** If you have a field that you do not want as a measure (i.e., in your pivot or
|
|
||||||
graph views), then you can add ``store=False`` to it, and it will not show.
|
|
||||||
|
|
||||||
**Tip 3** If you have a SQL View that depends on context, then instead of overriding
|
|
||||||
``BaseModel.init()`` set the ``_table_query`` property::
|
|
||||||
|
|
||||||
@property
|
|
||||||
def _table_query(self):
|
|
||||||
return 'SELECT %s FROM %s' % (self._select(), self._from())
|
|
||||||
|
|
||||||
The *select* and *from* methods remain the same.
|
|
||||||
|
|
||||||
`Here is an example <{GITHUB_PATH}/addons/account/report/account_invoice_report.py>`__
|
|
||||||
of a report that depends on the currently selected companies (in a multi-company environment) context to
|
|
||||||
determine the currency exchange rates to use for accurately displaying amounts when the selected companies
|
|
||||||
have different currencies.
|
|
Binary file not shown.
Before Width: | Height: | Size: 22 KiB |
Binary file not shown.
Before Width: | Height: | Size: 20 KiB |
Binary file not shown.
Before Width: | Height: | Size: 45 KiB |
@ -50,11 +50,6 @@ Therefore, it is expected that your work tree will look something like this:
|
|||||||
├── __init__.py
|
├── __init__.py
|
||||||
└── __manifest__.py
|
└── __manifest__.py
|
||||||
|
|
||||||
Note that you will often see other non-QWeb and non-XML files containing "report" in their name also within
|
|
||||||
the report folder. These are unrelated to the reports covered in this tutorial and are covered in
|
|
||||||
the :doc:`dashboards` tutorial. For now you can think of them as customized views that use direct
|
|
||||||
SQL queries (sometimes referred to as SQL Views).
|
|
||||||
|
|
||||||
Don't forget to add whatever files your template and action view will be into to your ``__manifest__.py``.
|
Don't forget to add whatever files your template and action view will be into to your ``__manifest__.py``.
|
||||||
In this case, you will want to add the files to the ``data`` list and remember that the files listed in a manifest
|
In this case, you will want to add the files to the ``data`` list and remember that the files listed in a manifest
|
||||||
are loaded sequentially!
|
are loaded sequentially!
|
||||||
|
Loading…
Reference in New Issue
Block a user