diff --git a/content/developer/reference/backend/views.rst b/content/developer/reference/backend/views.rst
index 78f416b54..18ef37dc4 100644
--- a/content/developer/reference/backend/views.rst
+++ b/content/developer/reference/backend/views.rst
@@ -124,7 +124,7 @@ an impact on all view types.
``info``, ``warning``, ``danger`` and ``secondary`` displays. The list view supports ``bf``,
``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.
This attribute is false by default.
@@ -577,213 +577,6 @@ attributes:
measures (useful for fields that do not make sense aggregated, such as fields in different
units, e.g. € and $).
-.. _reference/views/dashboard:
-
-Dashboard
----------
-
-.. raw:: html
-
- Enterprise feature
-
-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
-
-
-
-
-
-
-
-
-
-
-
-The root element of the Dashboard view is , 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
-
-
-
-
-
- ``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
-
-
-
- ``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:
Form
diff --git a/content/developer/tutorials.rst b/content/developer/tutorials.rst
index 1a2d3088d..3aea79e78 100644
--- a/content/developer/tutorials.rst
+++ b/content/developer/tutorials.rst
@@ -15,7 +15,6 @@ Tutorials
tutorials/unit_tests
tutorials/mixins
tutorials/pdf_reports
- tutorials/dashboards
.. cards::
@@ -66,9 +65,3 @@ Tutorials
:target: tutorials/pdf_reports
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".
diff --git a/content/developer/tutorials/dashboards.rst b/content/developer/tutorials/dashboards.rst
deleted file mode 100644
index 861585f5c..000000000
--- a/content/developer/tutorials/dashboards.rst
+++ /dev/null
@@ -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
- `_ 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
-` 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 `__
-(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
- `_
- into a new directory called ``data`` in your estate module and copy `these lines
- `_
- 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
-
-
-
-
-
-
-
-In this example, ```` adds styling and ```` 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 `` element. An example is:
-
-.. code-block:: xml
-
-
-
-
-
-
-
-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
-
-
-
-
-
-
-The `ref` attribute can be added to `` 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
-`_
-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 `__
- and these `exercises `__ 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 `__
- 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.
diff --git a/content/developer/tutorials/dashboards/report_dashboard.png b/content/developer/tutorials/dashboards/report_dashboard.png
deleted file mode 100644
index a95028623..000000000
Binary files a/content/developer/tutorials/dashboards/report_dashboard.png and /dev/null differ
diff --git a/content/developer/tutorials/dashboards/report_list_detail.png b/content/developer/tutorials/dashboards/report_list_detail.png
deleted file mode 100644
index 62d44e92c..000000000
Binary files a/content/developer/tutorials/dashboards/report_list_detail.png and /dev/null differ
diff --git a/content/developer/tutorials/dashboards/simple_dashboard.png b/content/developer/tutorials/dashboards/simple_dashboard.png
deleted file mode 100644
index 9a25d81a9..000000000
Binary files a/content/developer/tutorials/dashboards/simple_dashboard.png and /dev/null differ
diff --git a/content/developer/tutorials/pdf_reports.rst b/content/developer/tutorials/pdf_reports.rst
index acdeea0d6..391ed847e 100644
--- a/content/developer/tutorials/pdf_reports.rst
+++ b/content/developer/tutorials/pdf_reports.rst
@@ -50,11 +50,6 @@ Therefore, it is expected that your work tree will look something like this:
├── __init__.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``.
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!