Compare commits
79 Commits
15.0-javas
...
master-wow
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
27ceec8674 | ||
|
|
5fb2d7c1c2 | ||
|
|
7c1dc39d03 | ||
|
|
4233250b82 | ||
|
|
2d93b03dd0 | ||
|
|
24d0a9f71d | ||
|
|
c48359e77c | ||
|
|
1086e0a9cf | ||
|
|
9989c83fd9 | ||
|
|
eb9cd7558c | ||
|
|
d015bc03fa | ||
|
|
172c4490ef | ||
|
|
e6db26a654 | ||
|
|
81261e3c9d | ||
|
|
7b4879a06c | ||
|
|
3dd71a4817 | ||
|
|
a826ed027d | ||
|
|
8db85a0caa | ||
|
|
d16c2472f5 | ||
|
|
3af790ba8e | ||
|
|
992fbc6ece | ||
|
|
772e0945a9 | ||
|
|
efb327479f | ||
|
|
aec3e2d9d9 | ||
|
|
3e674f3178 | ||
|
|
27fe4b06a5 | ||
|
|
5327f9ece9 | ||
|
|
f0b550fa16 | ||
|
|
85fc0b6063 | ||
|
|
54203049fa | ||
|
|
431839da7d | ||
|
|
f0f9023062 | ||
|
|
075894d56b | ||
|
|
edf4c45c3b | ||
|
|
0c5ceef042 | ||
|
|
9bd739b36f | ||
|
|
2b2611e462 | ||
|
|
0bdc750700 | ||
|
|
bbaa1856c5 | ||
|
|
7ea917988c | ||
|
|
71a5d15df4 | ||
|
|
35e77b69bb | ||
|
|
adf90f60c4 | ||
|
|
334483cf78 | ||
|
|
b5e78103b5 | ||
|
|
0cb3072c0e | ||
|
|
2dfdf8600f | ||
|
|
e9a6934319 | ||
|
|
642f68cad1 | ||
|
|
6f550c494e | ||
|
|
7e466dd686 | ||
|
|
c80f8ee403 | ||
|
|
3235a7e612 | ||
|
|
7fc45f6e68 | ||
|
|
32de28100e | ||
|
|
34565a1608 | ||
|
|
a9d7bf46a6 | ||
|
|
9075b02cb7 | ||
|
|
c580e3db4e | ||
|
|
f29549b144 | ||
|
|
5e91babfb0 | ||
|
|
2503b1249a | ||
|
|
f553a6b744 | ||
|
|
a1707b2eb1 | ||
|
|
533e11c19e | ||
|
|
efdff9f6e5 | ||
|
|
678eca0721 | ||
|
|
b8ff49a6f1 | ||
|
|
06688f4dc7 | ||
|
|
fc60cda6e5 | ||
|
|
32a7b54872 | ||
|
|
a67e991124 | ||
|
|
9195e02602 | ||
|
|
c0aba501da | ||
|
|
c1b8e7f7a1 | ||
|
|
7d9e8af153 | ||
|
|
3ac968915b | ||
|
|
217b8d0542 | ||
|
|
76b8472e3b |
4
Makefile
@@ -24,7 +24,7 @@ SOURCE_DIR = content
|
||||
|
||||
HTML_BUILD_DIR = $(BUILD_DIR)/html
|
||||
ifdef VERSIONS
|
||||
HTML_BUILD_DIR := $(HTML_BUILD_DIR)/15.0
|
||||
HTML_BUILD_DIR := $(HTML_BUILD_DIR)/master
|
||||
endif
|
||||
ifneq ($(CURRENT_LANG),en)
|
||||
HTML_BUILD_DIR := $(HTML_BUILD_DIR)/$(CURRENT_LANG)
|
||||
@@ -69,7 +69,7 @@ gettext:
|
||||
$(HTML_BUILD_DIR)/_static/style.css: extensions/odoo_theme/static/style.scss extensions/odoo_theme/static/scss/*.scss
|
||||
@echo "Compiling stylesheets..."
|
||||
mkdir -p $(HTML_BUILD_DIR)/_static
|
||||
pysassc extensions/odoo_theme/static/style.scss $(HTML_BUILD_DIR)/_static/style.css
|
||||
python3 -m pysassc extensions/odoo_theme/static/style.scss $(HTML_BUILD_DIR)/_static/style.css
|
||||
@echo "Compilation finished."
|
||||
|
||||
#=== Development and debugging rules ===#
|
||||
|
||||
14
README.md
@@ -4,11 +4,11 @@
|
||||
|
||||
### Requirements
|
||||
|
||||
- [Git](https://www.odoo.com/documentation/15.0/contributing/documentation.html#install-git)
|
||||
- [Python 3.6, 3.7, or 3.8](https://www.odoo.com/documentation/15.0/contributing/documentation.html#python)
|
||||
- Python dependencies listed in the file [`requirements.txt`](https://github.com/odoo/documentation/tree/15.0/requirements.txt).
|
||||
- [Make](https://www.odoo.com/documentation/15.0/contributing/documentation.html#make)
|
||||
- A local copy of the [odoo/odoo repository in 15.0](https://github.com/odoo/odoo/tree/15.0) (Optional)
|
||||
- [Git](https://www.odoo.com/documentation/master/contributing/documentation.html#install-git)
|
||||
- [Python 3.7 or 3.8](https://www.odoo.com/documentation/master/contributing/documentation.html#python)
|
||||
- Python dependencies listed in the file [`requirements.txt`](https://github.com/odoo/documentation/tree/master/requirements.txt).
|
||||
- [Make](https://www.odoo.com/documentation/master/contributing/documentation.html#make)
|
||||
- A local copy of the [odoo/odoo repository in master](https://github.com/odoo/odoo/tree/master) (Optional)
|
||||
|
||||
### Instructions
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
2. Open the file `documentation/_build/html/index.html` in your web browser to display the render.
|
||||
|
||||
3. See [this guide](https://www.odoo.com/documentation/15.0/contributing/documentation.html#preview-your-changes)
|
||||
3. See [this guide](https://www.odoo.com/documentation/master/contributing/documentation.html#preview-your-changes)
|
||||
for more detailed instructions.
|
||||
|
||||
Optional: to fully build the developer documentation with inline docstrings for documented Python
|
||||
@@ -34,7 +34,7 @@ be shown.
|
||||
## Contribute to the documentation
|
||||
|
||||
For contributions to the content of the documentation, please refer to the
|
||||
[Introduction Guide](https://www.odoo.com/documentation/15.0/contributing/documentation.html).
|
||||
[Introduction Guide](https://www.odoo.com/documentation/master/contributing/documentation.html).
|
||||
|
||||
To **report a content issue**, **request new content** or **ask a question**, use the
|
||||
[repository's issue tracker](https://github.com/odoo/documentation-user/issues) as usual.
|
||||
|
||||
17
conf.py
@@ -19,7 +19,7 @@ copyright = 'Odoo S.A.'
|
||||
# `version` if the version info for the project being documented, acts as replacement for |version|,
|
||||
# also used in various other places throughout the built documents.
|
||||
# `release` is the full version, including alpha/beta/rc tags. Acts as replacement for |release|.
|
||||
version = release = '15.0'
|
||||
version = release = 'master'
|
||||
|
||||
# The minimal Sphinx version required to build the documentation.
|
||||
needs_sphinx = '3.0.0'
|
||||
@@ -70,20 +70,23 @@ if not odoo_dir.is_dir():
|
||||
f"Could not find Odoo sources directory at {odoo_dir.absolute()}.\n"
|
||||
f"The 'Developer' documentation will be built but autodoc directives will be skipped.\n"
|
||||
f"In order to fully build the 'Developer' documentation, clone the repository with "
|
||||
f"`git clone https://github.com/odoo/odoo` or create a symbolic link."
|
||||
f"`git clone https://github.com/odoo/odoo` or create a symbolink link."
|
||||
)
|
||||
else:
|
||||
sys.path.insert(0, str(odoo_dir.absolute()))
|
||||
if sys.version_info < (3, 7) and sys.version_info > (3, 6):
|
||||
# running odoo needs python 3.7 min but monkey patch version_info to be
|
||||
# able to build the doc in python 3.6
|
||||
sys.version_info = (3, 7, 0)
|
||||
from odoo import release as odoo_release # Don't collide with Sphinx's 'release' config option
|
||||
odoo_version = odoo_release.version.replace('~', '-') \
|
||||
if 'alpha' not in odoo_release.version else 'master'
|
||||
odoo_version = odoo_release.version if 'alpha' not in odoo_release.version else 'master'
|
||||
if release != odoo_version:
|
||||
_logger.warning(
|
||||
f"Found Odoo sources directory but with version '{odoo_version}' incompatible with "
|
||||
f"documentation version '{version}'.\n"
|
||||
f"The 'Developer' documentation will be built but autodoc directives will be skipped.\n"
|
||||
f"In order to fully build the 'Developer' documentation, checkout the matching branch "
|
||||
f"with `cd odoo && git checkout {version}`."
|
||||
f"In order to fully build the 'Developer' documentation, checkout the matching branch"
|
||||
f" with `cd odoo && git checkout {version}`."
|
||||
)
|
||||
else:
|
||||
_logger.info(f"Found Odoo sources directory matching documentation version {release}.")
|
||||
@@ -181,7 +184,7 @@ html_permalinks = True # Sphinx >= 3.5
|
||||
# Additional JS & CSS files that can be imported with the 'custom-js' and 'custom-css' metadata.
|
||||
# Lists are empty because the files are specified in extensions/themes.
|
||||
html_js_files = []
|
||||
html_css_files = []
|
||||
html_css_files = ["css/js.css"]
|
||||
|
||||
# PHP lexer option to not require <?php
|
||||
highlight_options = {
|
||||
|
||||
@@ -18,4 +18,5 @@ These guides provide instructions on how to install, maintain and upgrade Odoo d
|
||||
|
||||
administration/install
|
||||
administration/maintain
|
||||
administration/upgrade
|
||||
administration/odoo_sh
|
||||
|
||||
@@ -302,13 +302,13 @@ Prepare
|
||||
Python
|
||||
^^^^^^
|
||||
|
||||
Odoo requires Python 3.6 or later to run. Visit `Python's download page <https://www.python.org/downloads/windows/>`_
|
||||
Odoo requires Python 3.7 or later to run. Visit `Python's download page <https://www.python.org/downloads/windows/>`_
|
||||
to download and install the latest version of Python 3 on your machine.
|
||||
|
||||
During installation, check **Add Python 3 to PATH**, then click **Customize Installation** and make
|
||||
sure that **pip** is checked.
|
||||
|
||||
.. note:: If Python 3 is already installed, make sure that the version is 3.6 or above, as previous
|
||||
.. note:: If Python 3 is already installed, make sure that the version is 3.7 or above, as previous
|
||||
versions are not compatible with Odoo.
|
||||
|
||||
.. code-block:: doscon
|
||||
@@ -466,10 +466,10 @@ Prepare
|
||||
Python
|
||||
^^^^^^
|
||||
|
||||
Odoo requires Python 3.6 or later to run. Use your package manager to download and install Python 3
|
||||
Odoo requires Python 3.7 or later to run. Use your package manager to download and install Python 3
|
||||
on your machine if it is not already done.
|
||||
|
||||
.. note:: If Python 3 is already installed, make sure that the version is 3.6 or above, as previous
|
||||
.. note:: If Python 3 is already installed, make sure that the version is 3.7 or above, as previous
|
||||
versions are not compatible with Odoo.
|
||||
|
||||
.. code-block:: console
|
||||
@@ -635,10 +635,10 @@ Prepare
|
||||
Python
|
||||
^^^^^^
|
||||
|
||||
Odoo requires Python 3.6 or later to run. Use your preferred package manager (homebrew_, macports_)
|
||||
Odoo requires Python 3.7 or later to run. Use your preferred package manager (homebrew_, macports_)
|
||||
to download and install Python 3 on your machine if it is not already done.
|
||||
|
||||
.. note:: If Python 3 is already installed, make sure that the version is 3.6 or above, as previous
|
||||
.. note:: If Python 3 is already installed, make sure that the version is 3.7 or above, as previous
|
||||
versions are not compatible with Odoo.
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
@@ -7,8 +7,8 @@ Maintain
|
||||
.. toctree::
|
||||
|
||||
maintain/update
|
||||
maintain/db_upgrade
|
||||
maintain/enterprise
|
||||
maintain/hosting_changes
|
||||
maintain/db_premise
|
||||
maintain/online
|
||||
maintain/on_premise
|
||||
maintain/supported_versions
|
||||
|
||||
@@ -1,413 +0,0 @@
|
||||
|
||||
.. |assistance-contact| replace::
|
||||
If you need Odoo assistance on this matter, please contact your Odoo Account Manager or contact
|
||||
our `Sales department`_.
|
||||
.. _Sales department: mailto:sales@odoo.com
|
||||
|
||||
.. _db-upgrade:
|
||||
|
||||
================
|
||||
Versions upgrade
|
||||
================
|
||||
|
||||
.. _db-upgrade/overview:
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
.. _db-upgrade/process:
|
||||
|
||||
The upgrade process
|
||||
-------------------
|
||||
|
||||
This documentation is for our *On-Premise* (self-hosted) and *Odoo.sh* customers.
|
||||
|
||||
.. _db-upgrade/definition:
|
||||
|
||||
Definition
|
||||
~~~~~~~~~~
|
||||
|
||||
An upgrade is switching to a newer version of Odoo (e.g., Odoo 13.0 to Odoo 14.0)
|
||||
|
||||
An upgrade does not cover:
|
||||
|
||||
* changing :ref:`Editions <db-upgrade/faq/editions-change>` (i.e., Community to Enterprise edition)
|
||||
* switching :ref:`hosting type <db-upgrade/faq/hosting-types-switch>` (i.e., On-Premise to Online or
|
||||
Odoo.sh)
|
||||
* migration from another ERP to Odoo
|
||||
|
||||
.. note:: |assistance-contact|
|
||||
|
||||
.. _db-upgrade/process-workflow:
|
||||
|
||||
Process workflow
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
The upgrade process in a nutshell:
|
||||
|
||||
#. You create a test upgrade request.
|
||||
#. | The request is processed by Odoo:
|
||||
| This happens via an automated process that runs the database through an upgrade script and
|
||||
takes between 20 and 120 minutes. Only if an issue(s) arises will we have to intervene
|
||||
manually and adjust the script specifically to your database until the upgrade succeeds.
|
||||
#. Odoo delivers a test database.
|
||||
#. You test your database for possible discrepancies (see :ref:`db-upgrade/test-guidance`)
|
||||
#. If there are any discrepancies, you report them to the Upgrade support team via the
|
||||
:ref:`Help portal <db-upgrade/test-assistance>`.
|
||||
#. We will fix the issues and send you a new test database.
|
||||
#. Once you completed the testing and are happy with the result, you decide on a date and time when
|
||||
you stop users from accessing Odoo, freeze all data entries and create an upgrade request for the
|
||||
production upgrade.
|
||||
#. Odoo delivers the production database through the automated process.
|
||||
#. You restore it in your Production environment a few short hours later and continue working on the
|
||||
newly upgraded database.
|
||||
|
||||
.. _db-upgrade/service-level:
|
||||
|
||||
Service Level Agreement
|
||||
-----------------------
|
||||
|
||||
What is covered by the Enterprise Licence?
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Databases hosted on Odoo’s Cloud platforms (Saas and Odoo.sh) or On-Premise (Self-Hosting) enjoy the
|
||||
following service at all times.
|
||||
|
||||
The upgrade of:
|
||||
|
||||
* standard applications
|
||||
* Studio customization (as long as the Studio app is still active)
|
||||
* customizations done by our consulting and developer services *if* they are covered by a
|
||||
‘Maintenance of Customisations’ subscription
|
||||
|
||||
The Upgrade Service is limited to the technical conversion and adaptation of your database (standard
|
||||
modules and data) to make it compatible with the targeted version.
|
||||
|
||||
What upgrading does NOT cover
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* The cleaning of pre-existing data & configuration while upgrading
|
||||
* Any new developments and/or upgrade of your own :ref:`custom modules
|
||||
<db-upgrade/faq/custom-modules>`
|
||||
* `Training <https://www.odoo.com/learn>`_ on the new version
|
||||
|
||||
You can get more information about your Enterprise Licence on our :ref:`Odoo Enterprise Subscription
|
||||
Agreement <upgrade>` page.
|
||||
|
||||
.. note:: |assistance-contact|
|
||||
|
||||
.. _db-upgrade/get-started:
|
||||
|
||||
Get started
|
||||
===========
|
||||
|
||||
The upgrade process varies depending on where your database is hosted.
|
||||
|
||||
.. _db-upgrade/online:
|
||||
|
||||
Online (SaaS)
|
||||
-------------
|
||||
|
||||
If you are hosted Online, please check your `database manager <https://www.odoo.com/my/databases>`_.
|
||||
|
||||
.. _db-upgrade/odoo-sh:
|
||||
|
||||
Odoo.sh
|
||||
-------
|
||||
|
||||
If you are Odoo.sh hosted, check our :doc:`specific instructions to be able to upgrade
|
||||
<../odoo_sh/advanced/upgrade_your_database>`.
|
||||
|
||||
.. _db-upgrade/on-premise:
|
||||
|
||||
On-Premise
|
||||
----------
|
||||
|
||||
There are two possibilities:
|
||||
|
||||
#. Via the interface of our `website form <https://upgrade.odoo.com>`_
|
||||
#. | For technically-advanced users and partners, via the following command line (to be used on the
|
||||
machine where your database is hosted):
|
||||
| ``python <(curl -s https://upgrade.odoo.com/upgrade) test -d <your db name> -t 14.0``
|
||||
|
||||
What does it do?
|
||||
~~~~~~~~~~~~~~~~
|
||||
|
||||
The above command will dump your database to a file, then send it to the upgrade platform for
|
||||
upgrade, displaying you the live logs, then restore the upgraded database back on your server as a
|
||||
duplicate test database.
|
||||
|
||||
.. _db-upgrade/steps:
|
||||
|
||||
Steps
|
||||
=====
|
||||
|
||||
.. _db-upgrade/steps-test:
|
||||
|
||||
The testing phase
|
||||
-----------------
|
||||
|
||||
.. _db-upgrade/test-process:
|
||||
|
||||
Test process
|
||||
~~~~~~~~~~~~
|
||||
|
||||
Also referred to as the pre-production phase, the test phase allows you to review an upgraded
|
||||
version of your database without affecting your production database in any way.
|
||||
|
||||
We suggest that you run the test upgrade process at least once, but you can do it as often as you
|
||||
want (one at a time).
|
||||
|
||||
Once you receive your upgraded test database, you should check that all data, processes and
|
||||
functionality are still correct and working as expected.
|
||||
|
||||
If you do find discrepancies, you'll be able to:
|
||||
|
||||
* | :ref:`Report your issues <db-upgrade/test-assistance>`
|
||||
| and/or
|
||||
* Ask for a new :ref:`test request <db-upgrade/test-db-request>` after the reported issues have
|
||||
been fixed in the upgrade script.
|
||||
|
||||
When you do not find any discrepancies, you'll be able to:
|
||||
|
||||
* Move on to the upgrade of your :ref:`production database <db-upgrade/production-live>`.
|
||||
|
||||
.. _db-upgrade/test-db-request:
|
||||
|
||||
Request a test database
|
||||
~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
When filling the `website form <https://upgrade.odoo.com>`_, select *Testing* purpose.
|
||||
|
||||
.. image:: media/db-upgrade-test-purpose.png
|
||||
:align: center
|
||||
:alt: Selection of the "Testing" purpose in the upgrade form on Odoo
|
||||
|
||||
.. _db-upgrade/test-guidance:
|
||||
|
||||
Test guidance
|
||||
~~~~~~~~~~~~~
|
||||
|
||||
Every business and organization has its own operational needs and will have to test its specific
|
||||
Odoo instance respectively. However, we recommend you look at `the test scenario
|
||||
<https://docs.google.com/document/d/1ypNs7JKPOsjNbKpdiKFH7Al6g6whZ9jr7f7duAQ5E1w/>`_ we created, a
|
||||
high-level idea of what you should test and look out for.
|
||||
|
||||
.. todo:: change link "test scenario" once the related doc is published
|
||||
|
||||
.. _db-upgrade/test-assistance:
|
||||
|
||||
Assistance
|
||||
~~~~~~~~~~
|
||||
|
||||
If you encounter issues or problems in the **test database**, please contact the Odoo Upgrade
|
||||
Support:
|
||||
|
||||
#. Connect to our `Odoo Support page <https://www.odoo.com/help>`_.
|
||||
#. Under the *Ticket Description* section, select *An issue related to my upgrade* ticket type.
|
||||
|
||||
.. image:: media/db-upgrade-test-assistance.png
|
||||
:align: center
|
||||
:alt: Selection of "An issue related to my upgrade" as Ticket Type in the support form on Odoo
|
||||
|
||||
.. warning::
|
||||
If you choose another *Ticket Description* type, the request will be redirected to another
|
||||
team than the upgrade one and will slow down the processing and response time.
|
||||
|
||||
#. Please provide as much detail as you can. Where applicable, illustrate the current and previous
|
||||
flows with videos and/or screenshots. This will avoid clarifying questions and speed up the
|
||||
resolution process significantly.
|
||||
|
||||
.. image:: media/db-upgrade-test-assistance-details.png
|
||||
:align: center
|
||||
:alt: "Detailed Description" field in the support form on Odoo
|
||||
|
||||
.. note::
|
||||
* The purpose of the test phase is not to correct existing data or configurations in your
|
||||
database.
|
||||
* |assistance-contact|
|
||||
|
||||
.. _db-upgrade/steps-production:
|
||||
|
||||
The production launch
|
||||
---------------------
|
||||
|
||||
.. _db-upgrade/production-live:
|
||||
|
||||
Production goes live
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The production upgrade request is when you decide to upgrade your current database with all your
|
||||
production data (invoices, VAT returns, inventories, current orders) to a new version of your choice.
|
||||
|
||||
After your :ref:`tests <db-upgrade/steps-test>` are completed to your satisfaction, submit the
|
||||
request to upgrade your production database via our `website form <https://upgrade.odoo.com>`_.
|
||||
Select *Production* purpose.
|
||||
|
||||
.. image:: media/db-upgrade-production-purpose.png
|
||||
:align: center
|
||||
:alt: Selection of the "Production" purpose in the upgrade form on Odoo
|
||||
|
||||
.. danger::
|
||||
Going into production without first testing may lead to:
|
||||
|
||||
- business interruptions (e.g. no longer having the possibility to validate an action)
|
||||
- poor customer experiences (e.g. an eCommerce website that does not work correctly)
|
||||
|
||||
.. _db-upgrade/production-assistance:
|
||||
|
||||
Assistance
|
||||
~~~~~~~~~~
|
||||
|
||||
If you encounter issues or problems in the **production database**, please contact the **Odoo
|
||||
Support**:
|
||||
|
||||
#. Connect to our `Odoo Support page <https://www.odoo.com/help>`_.
|
||||
#. Under the *Ticket Description* section, select the appropriate type related to your issue but
|
||||
**do not select** the option *An issue related to my upgrade*.
|
||||
|
||||
.. note::
|
||||
After upgrading to production, the support will be provided by the Support team instead of the
|
||||
Upgrade team.
|
||||
|
||||
#. Please provide as much detail as you can. Where applicable, illustrate the current and previous
|
||||
flows with videos and/or screenshots. This will avoid clarifying questions and speed up the
|
||||
resolution process significantly.
|
||||
|
||||
.. image:: media/db-upgrade-production-assistance-details.png
|
||||
:align: center
|
||||
:alt: "Detailed Description" field in the support form on Odoo
|
||||
|
||||
.. warning::
|
||||
If you choose *An issue related to my upgrade* as ticket type, the request will be redirected
|
||||
to another team than the support one and will slow down the processing and response time.
|
||||
|
||||
.. _db-upgrade/faq:
|
||||
|
||||
FAQ
|
||||
===
|
||||
|
||||
.. _db-upgrade/faq/why:
|
||||
|
||||
Why upgrade?
|
||||
------------
|
||||
|
||||
* You benefit from the latest features of the :ref:`new major version
|
||||
<db-upgrade/faq/release-notes>` released by Odoo.
|
||||
* If you are in an :ref:`unsupported version <db-upgrade/supported-versions>`, you get a new version
|
||||
with support.
|
||||
|
||||
.. _db-upgrade/faq/when:
|
||||
|
||||
When to upgrade?
|
||||
----------------
|
||||
|
||||
Whenever you want. You can make your upgrade request as soon as a new version is released on our
|
||||
`website form <https://upgrade.odoo.com>`_.
|
||||
|
||||
.. _db-upgrade/faq/availability:
|
||||
|
||||
Availability of the new version
|
||||
-------------------------------
|
||||
|
||||
Please kindly note that as soon as we announce the release of a new major version (usually at the
|
||||
end of year), the Upgrade Service team needs to adapt the upgrade scripts to it, which is why the
|
||||
new version is not immediately available for existing databases.
|
||||
|
||||
.. _db-upgrade/faq/finalization:
|
||||
|
||||
Finalization of the upgrade (:abbr:`ETA (Estimated Time of Arrival)`)
|
||||
---------------------------------------------------------------------
|
||||
|
||||
Unfortunately, it is impossible to give time estimates for every upgrade request. Odoo offers so
|
||||
many possibilities (e.g. branding, workflows, customization, etc) that it can get tricky to upgrade,
|
||||
and translate to the new structure. If you use multiple apps managing sensitive data (e.g.,
|
||||
Accounting, Inventory, etc.), some cases may still require a human intervention, making the process
|
||||
slower.
|
||||
|
||||
This is especially true during the first months following the release of a new major version, which
|
||||
can significantly lengthen the upgrade delay.
|
||||
|
||||
In general, the ‘smaller’ the database, the quickest the upgrade. A single-user database that uses
|
||||
only CRM will be processed faster than a multi-company, multi-user database that uses Accounting,
|
||||
Sales, Purchase, and Manufacturing.
|
||||
|
||||
So, in a nutshell, what can impact your upgrade lead time?
|
||||
|
||||
* Source & targeted versions
|
||||
* Installed apps
|
||||
* Volume of data
|
||||
* Amount of customization (models, fields, methods, workflows, reports, website, etc.)
|
||||
* Installation of new apps or configuration changes after the start of the test phase
|
||||
|
||||
Usually, the delays experienced during the first request (waiting time between the time you
|
||||
submitted your first request for a test upgrade) can generally give you an idea of the time to wait
|
||||
for the production request.
|
||||
|
||||
.. _db-upgrade/faq/custom-modules:
|
||||
|
||||
Upgrade of the custom modules
|
||||
-----------------------------
|
||||
|
||||
As stated in our :doc:`/legal/terms/enterprise`, section :ref:`charges_standard`, this optional
|
||||
service is subject to additional fees.
|
||||
|
||||
If you have a custom code, you can choose to have it upgraded by our services, by one of our
|
||||
`partners <https://www.odoo.com/partners>`_ or you can do it yourself.
|
||||
|
||||
.. note:: |assistance-contact|
|
||||
|
||||
.. _db-upgrade/faq/editions-change:
|
||||
|
||||
Editions change (from Community to Enterprise)
|
||||
----------------------------------------------
|
||||
|
||||
An upgrade does not cover a change of `Editions <https://www.odoo.com/page/editions>`_
|
||||
|
||||
.. note:: |assistance-contact|
|
||||
|
||||
.. _db-upgrade/faq/hosting-types-switch:
|
||||
|
||||
Switching the hosting types (Self-hosted vs Online vs Odoo.sh)
|
||||
--------------------------------------------------------------
|
||||
|
||||
An upgrade does not cover a change of `Hosting types <https://www.odoo.com/page/hosting-types>`_.
|
||||
|
||||
Open the following link to get :doc:`more information about how to change your hosting type
|
||||
<hosting_changes>`.
|
||||
|
||||
.. note:: |assistance-contact|
|
||||
|
||||
.. _db-upgrade/faq/release-notes:
|
||||
|
||||
Release Notes by version
|
||||
------------------------
|
||||
|
||||
Open our `Release Note <https://www.odoo.com/page/release-notes>`_ page to get a summary of the new
|
||||
features and improvements made in each version.
|
||||
|
||||
.. _db-upgrade/assistance:
|
||||
|
||||
Assistance
|
||||
==========
|
||||
|
||||
.. _db-upgrade/contact:
|
||||
|
||||
Contact our Upgrade service support
|
||||
-----------------------------------
|
||||
|
||||
Should you have any more questions about the upgrade, do not hesitate to send a message to `Odoo
|
||||
Upgrade Team <mailto:upgrade@odoo.com>`_. We will be very pleased to answer it as soon as possible.
|
||||
|
||||
.. _db-upgrade/supported-versions:
|
||||
|
||||
Supported versions
|
||||
------------------
|
||||
|
||||
Please note that Odoo provides support and bug fixing only for the three last major versions of Odoo.
|
||||
|
||||
This is a factor to take into consideration before upgrading. If you are on an older version, we
|
||||
suggest you to prefer the most recent version to benefit from a longer support (before having to
|
||||
upgrade again).
|
||||
|
||||
You can get more information about our :doc:`supported versions <supported_versions>`.
|
||||
@@ -1,9 +1,6 @@
|
||||
|
||||
.. _db_premise:
|
||||
|
||||
===============================
|
||||
On-premises Database management
|
||||
===============================
|
||||
==============================
|
||||
On-premise database management
|
||||
==============================
|
||||
|
||||
Register a database
|
||||
===================
|
||||
@@ -21,7 +18,7 @@ Registration Error Message
|
||||
If you are unable to register your database, you will likely encounter this
|
||||
message:
|
||||
|
||||
.. image:: media/error_message_sub_code.png
|
||||
.. image:: on_premise/error_message_sub_code.png
|
||||
:align: center
|
||||
:alt: Something went wrong while registering your database,
|
||||
you can try again or contact Odoo Help
|
||||
@@ -44,14 +41,14 @@ Solutions
|
||||
* You can unlink the old database yourself on your `Odoo Contract
|
||||
<https://accounts.odoo.com/my/subscription>`__ with the button "Unlink database"
|
||||
|
||||
.. image:: media/unlink_single_db.png
|
||||
.. image:: on_premise/unlink_single_db.png
|
||||
:align: center
|
||||
|
||||
|
||||
A confirmation message will appear; make sure this is the correct database as
|
||||
it will be deactivated shortly:
|
||||
|
||||
.. image:: media/unlink_confirm_enterprise_edition.png
|
||||
.. image:: on_premise/unlink_confirm_enterprise_edition.png
|
||||
:align: center
|
||||
|
||||
|
||||
@@ -65,7 +62,7 @@ Solutions
|
||||
<https://accounts.odoo.com/my/subscription>`__, a short message will appear
|
||||
specifying which database is problematic:
|
||||
|
||||
.. image:: media/unlink_db_name_collision.png
|
||||
.. image:: on_premise/unlink_db_name_collision.png
|
||||
:align: center
|
||||
|
||||
|
||||
@@ -96,7 +93,7 @@ Error message due to too many users
|
||||
If you have more users in your local database than provisionned in your
|
||||
Odoo Enterprise subscription, you may encounter this message:
|
||||
|
||||
.. image:: media/add_more_users.png
|
||||
.. image:: on_premise/add_more_users.png
|
||||
:align: center
|
||||
:alt: This database will expire in X days, you
|
||||
have more users than your subscription allows
|
||||
@@ -125,7 +122,7 @@ Database expired error message
|
||||
If your database reaches its expiration date before your renew your subscription,
|
||||
you will encounter this message:
|
||||
|
||||
.. image:: media/database_expired.png
|
||||
.. image:: on_premise/database_expired.png
|
||||
:align: center
|
||||
:alt: This database has expired.
|
||||
|
||||
@@ -157,7 +154,7 @@ You can duplicate your database by accessing the database manager on your
|
||||
server (<odoo-server>/web/database/manager). In this page, you can easily
|
||||
duplicate your database (among other things).
|
||||
|
||||
.. image:: media/db_manager.gif
|
||||
.. image:: on_premise/db_manager.gif
|
||||
:align: center
|
||||
|
||||
|
||||
@@ -175,5 +172,5 @@ System Parameters`, we advise you to use a `uuid generator <https://www.uuidtool
|
||||
use the unix command ``uuidgen`` to generate a new uuid. You can then simply replace it like any
|
||||
other record by clicking on it and using the edit button.
|
||||
|
||||
.. image:: media/db_uuid.png
|
||||
.. image:: on_premise/db_uuid.png
|
||||
:align: center
|
||||
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 4.6 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 6.9 KiB After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 18 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
143
content/administration/maintain/online.rst
Normal file
@@ -0,0 +1,143 @@
|
||||
=================================
|
||||
Online (SaaS) database management
|
||||
=================================
|
||||
|
||||
To manage a database, sign in to https://www.odoo.com and access the `database management page
|
||||
<https://www.odoo.com/my/databases>`_ by clicking on the user icon, then on *My Databases*.
|
||||
|
||||
.. image:: online/my-databases.png
|
||||
:align: center
|
||||
:alt: Clicking on the user icon opens a drop-down menu. "My databases" button is highlighted.
|
||||
|
||||
.. note::
|
||||
Make sure you are connected as the administrator of the database you want to manage.
|
||||
|
||||
.. image:: online/dropdown-menu.png
|
||||
:align: right
|
||||
:alt: Clicking on the gear icon opens the drop-down menu.
|
||||
|
||||
Open the drop-down menu next to the database you want to manage by clicking on the gear icon.
|
||||
|
||||
Several actions are available:
|
||||
|
||||
- :ref:`online/upgrade`
|
||||
- :ref:`online/duplicate`
|
||||
- :ref:`online/rename`
|
||||
- :ref:`online/download`
|
||||
- :ref:`online/domains`
|
||||
- :ref:`online/tags`
|
||||
- :ref:`online/delete`
|
||||
- :ref:`online/contact-support`
|
||||
- :ref:`online/users`
|
||||
|
||||
.. _online/upgrade:
|
||||
|
||||
Upgrade
|
||||
=======
|
||||
|
||||
Upgrade the database to the latest Odoo version.
|
||||
|
||||
.. warning::
|
||||
Upgrading a database to a newer version of Odoo is a complex operation that requires time and
|
||||
caution. It is essential to test the upgrade before upgrading the production database.
|
||||
|
||||
.. seealso::
|
||||
- :doc:`../upgrade/process`
|
||||
|
||||
.. _online/duplicate:
|
||||
|
||||
Duplicate
|
||||
=========
|
||||
|
||||
Make an exact copy of the database to be able to perform testing without compromising the daily
|
||||
operations.
|
||||
|
||||
.. important::
|
||||
- By checking *For testing purposes*, all external communication (emails, payments, delivery
|
||||
orders, etc.) are disabled by default on the duplicated database.
|
||||
- Duplicate databases expire automatically after 15 days.
|
||||
|
||||
.. _online/rename:
|
||||
|
||||
Rename
|
||||
======
|
||||
|
||||
Rename the database and its URL.
|
||||
|
||||
.. _online/download:
|
||||
|
||||
Download
|
||||
========
|
||||
|
||||
Download instantly a ZIP file with a backup of the database.
|
||||
|
||||
.. note::
|
||||
Databases are backed up daily according to the `Odoo Cloud SLA
|
||||
<https://www.odoo.com/cloud-sla>`_.
|
||||
|
||||
.. _online/domains:
|
||||
|
||||
Domains
|
||||
=======
|
||||
|
||||
Configure custom domains to access the database via another URL.
|
||||
|
||||
.. seealso::
|
||||
- :doc:`/applications/websites/website/publish/domain_name`
|
||||
|
||||
.. _online/tags:
|
||||
|
||||
Tags
|
||||
====
|
||||
|
||||
Add tags to sort your databases out. You can search the tags in the search bar.
|
||||
|
||||
.. _online/delete:
|
||||
|
||||
Delete
|
||||
======
|
||||
|
||||
Delete a database instantly.
|
||||
|
||||
.. danger::
|
||||
Deleting a database means that all data is permanently lost. The deletion is instant and for all
|
||||
users. It is recommended to create a backup of the database before deleting it.
|
||||
|
||||
Read carefully the warning message that pops up and proceed only if you fully understand the
|
||||
implications of deleting a database:
|
||||
|
||||
.. image:: online/delete.png
|
||||
:align: center
|
||||
:alt: A warning message is prompted before deleting a database.
|
||||
|
||||
.. note::
|
||||
- Only an administrator can delete a database.
|
||||
- The database name is immediately available for a new database.
|
||||
- It is not possible to delete a database if it is expired or linked to a subscription. If
|
||||
needed, please get in touch with `Odoo Support <https://www.odoo.com/help>`_.
|
||||
- To delete your account, please get in touch with `Odoo Support <https://www.odoo.com/help>`_.
|
||||
|
||||
.. _online/contact-support:
|
||||
|
||||
Contact Support
|
||||
===============
|
||||
|
||||
Access the Odoo `support page <https://www.odoo.com/help>`_ with your database's details already
|
||||
pre-filled.
|
||||
|
||||
.. _online/users:
|
||||
|
||||
Invite / Remove Users
|
||||
=====================
|
||||
|
||||
To invite users, fill out the email address of the new user and click on *Invite*. To add multiple
|
||||
users, click on *Add more users*.
|
||||
|
||||
.. image:: online/invite-users.png
|
||||
:align: center
|
||||
:alt: Clicking on "Add more users" adds additional email fields.
|
||||
|
||||
To remove users, select the users to remove and click on *Remove*.
|
||||
|
||||
.. seealso::
|
||||
- :doc:`/applications/general/users/manage_users`
|
||||
BIN
content/administration/maintain/online/delete.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
content/administration/maintain/online/dropdown-menu.png
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
BIN
content/administration/maintain/online/invite-users.png
Normal file
|
After Width: | Height: | Size: 6.0 KiB |
BIN
content/administration/maintain/online/my-databases.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
@@ -9,5 +9,4 @@ Advanced
|
||||
|
||||
advanced/containers
|
||||
advanced/submodules
|
||||
advanced/upgrade_your_database
|
||||
advanced/frequent_technical_questions
|
||||
|
||||
@@ -184,4 +184,4 @@ as you can only have one database linked per subscription.
|
||||
|
||||
If you plan to make it your production,
|
||||
unlink your former database from the subscription, and register the newly imported database.
|
||||
Read the :ref:`database registration documentation <db_premise>` for instructions.
|
||||
Read the :doc:`database registration documentation <../../maintain/on_premise>` for instructions.
|
||||
|
||||
12
content/administration/upgrade.rst
Normal file
@@ -0,0 +1,12 @@
|
||||
:nosearch:
|
||||
|
||||
=======
|
||||
Upgrade
|
||||
=======
|
||||
|
||||
.. toctree::
|
||||
|
||||
upgrade/process
|
||||
upgrade/odoo_sh
|
||||
upgrade/service_level
|
||||
upgrade/faq
|
||||
171
content/administration/upgrade/faq.rst
Normal file
@@ -0,0 +1,171 @@
|
||||
.. |assistance-contact| replace::
|
||||
If you need Odoo assistance on this matter, please get in touch with your Odoo Account Manager or
|
||||
our `Sales department`_.
|
||||
.. _Sales department: mailto:sales@odoo.com
|
||||
|
||||
===
|
||||
FAQ
|
||||
===
|
||||
|
||||
.. _upgrade-faq/why:
|
||||
|
||||
Why upgrade
|
||||
===========
|
||||
|
||||
* You benefit from the latest features of the :ref:`new major version
|
||||
<upgrade-faq/release-notes>` released by Odoo.
|
||||
* If you are in an :ref:`unsupported version <upgrade/supported-versions>`, you get a new version
|
||||
with support.
|
||||
|
||||
.. _upgrade-faq/when:
|
||||
|
||||
When to upgrade
|
||||
===============
|
||||
|
||||
Whenever you want. You can make your upgrade request as soon as a new version is released or when
|
||||
your version turns unsupported, and you still wish to enjoy support.
|
||||
|
||||
.. _upgrade-faq/availability:
|
||||
|
||||
Availability of the new version
|
||||
===============================
|
||||
|
||||
As soon as Odoo announces the release of a new major version, you can create a test upgrade request
|
||||
to try the latest version. Please note that at this point, the upgrade scripts will only have been
|
||||
tested with demo data. Please report any issue you might encounter while testing via the `Odoo
|
||||
Support page <https://www.odoo.com/help>`_ and make sure to be happy with your test version before
|
||||
requesting the upgrade of your database in production.
|
||||
|
||||
.. _upgrade-faq/duration:
|
||||
|
||||
Duration of the upgrade
|
||||
=======================
|
||||
|
||||
It is impossible to give time estimates for every upgrade request.
|
||||
|
||||
In general, the "smaller" the database, the quickest the upgrade request is completed. A single-user
|
||||
database that uses only CRM will be processed faster than a multi-company, multi-user database that
|
||||
uses Accounting, Sales, Purchase, and Manufacturing.
|
||||
|
||||
You can expect the time it takes for the platform to upgrade the test database will be similar to
|
||||
the production upgrade.
|
||||
|
||||
.. _upgrade-faq/project:
|
||||
|
||||
The upgrade project
|
||||
===================
|
||||
|
||||
It depends on the user involvement (the time spent on testing, reporting problems, etc.) and the
|
||||
issues encountered that might need to be addressed by our technical team.
|
||||
|
||||
So, in a nutshell, what can impact your upgrade lead time?
|
||||
|
||||
* Source & targeted versions
|
||||
* Installed apps
|
||||
* Volume of data
|
||||
* Amount of customization (models, fields, methods, workflows, reports, website, etc.)
|
||||
* Installation of new apps or configuration changes after the start of the test phase
|
||||
* User commitment
|
||||
|
||||
.. _upgrade-faq/custom-modules:
|
||||
|
||||
Upgrade of the custom modules
|
||||
=============================
|
||||
|
||||
As stated in our :doc:`/legal/terms/enterprise`, section :ref:`charges_standard`, this optional
|
||||
service is subject to additional fees.
|
||||
|
||||
Depending on your situation, the custom code could be upgraded by our services, by one of our
|
||||
partners, or you can do it yourself.
|
||||
|
||||
.. note:: |assistance-contact|
|
||||
|
||||
.. _upgrade-faq/editions-change:
|
||||
|
||||
Editions change (from Community to Enterprise)
|
||||
==============================================
|
||||
|
||||
The upgrade always returns an Enterprise edition of Odoo, whether the database you sent was a
|
||||
community or enterprise edition. It is required to have an enterprise subscription to upgrade.
|
||||
|
||||
.. note:: |assistance-contact|
|
||||
|
||||
.. seealso::
|
||||
- `Editions <https://www.odoo.com/page/editions>`_
|
||||
|
||||
.. _upgrade-faq/hosting-types-switch:
|
||||
|
||||
Switching the hosting types (Self-Hosting vs. Online Hosting - SaaS vs. Cloud Platform - Odoo.sh)
|
||||
=================================================================================================
|
||||
|
||||
An upgrade does not cover a change of `Hosting types <https://www.odoo.com/page/hosting-types>`_.
|
||||
|
||||
Open the following link to get :doc:`more information about how to change your hosting type
|
||||
<../maintain/hosting_changes>`.
|
||||
|
||||
.. note:: |assistance-contact|
|
||||
|
||||
.. _upgrade-faq/release-notes:
|
||||
|
||||
Release Notes by version
|
||||
========================
|
||||
|
||||
Open our `Release Note <https://www.odoo.com/page/release-notes>`_ page to get a summary of the new
|
||||
features and improvements made in each version.
|
||||
|
||||
How long is my test available for
|
||||
---------------------------------
|
||||
|
||||
An Odoo Online (SaaS) test database is available for one month by default. We can extend this trial
|
||||
period upon request. For Odoo.sh or on-premise, there is no restriction.
|
||||
|
||||
How many tests to perform before upgrading to production?
|
||||
---------------------------------------------------------
|
||||
|
||||
As many as needed. When you are comfortable with the database, run a last test upgrade 48 hours
|
||||
before requesting your production upgrade and test your workflows one last time.
|
||||
|
||||
How to/Where to report upgrade issues?
|
||||
--------------------------------------
|
||||
|
||||
If you encounter issues during the upgrade process, please contact the Odoo Support through the
|
||||
`Odoo Support page <https://www.odoo.com/help>`_
|
||||
|
||||
- To report an issue discovered during the testing phase, please select **An issue related to my
|
||||
upgrade (test phase)**.
|
||||
- To report an issue discovered post-upgrade, please select **An issue related to my upgrade
|
||||
(production)**
|
||||
|
||||
Upgrading to production
|
||||
-----------------------
|
||||
|
||||
Once you have completed testing and are happy with the result, you decide on a date and time when
|
||||
you stop users from accessing Odoo, freeze all data entries, and create an upgrade request for the
|
||||
production upgrade.
|
||||
|
||||
|
||||
How is my data handled in the Upgrade Platform?
|
||||
-----------------------------------------------
|
||||
|
||||
The Odoo Upgrade platform uses the same Privacy Policy as the rest of Odoo.com services.
|
||||
|
||||
Your data is hosted on servers that follow our security guidelines, namely:
|
||||
|
||||
- SSL - All web connections to client instances are protected with 256-bit SSL encryption
|
||||
(HTTPS with a 2048-bit modulus SSL certificate), and running behind Grade A SSL stacks. All our
|
||||
certificate chains are using SHA-2 already.
|
||||
- Safe System - Our servers are running recent Linux distribution with up-to-date security patches,
|
||||
with firewall and intrusion countermeasures (not disclosed for obvious reasons).
|
||||
|
||||
Servers are located at the same locations as our Cloud providers with the following services:
|
||||
|
||||
- Restricted perimeter, physically accessed by authorized data center employees only
|
||||
- Physical access control with security badges or biometrical security
|
||||
- Security cameras monitoring the data center locations 24/7
|
||||
- Security personnel on-site 24/7
|
||||
|
||||
The uploaded and migrated databases uploaded to the Upgrade platform are kept for up to 3 months and
|
||||
are permanently deleted following that period.
|
||||
|
||||
You can learn more about privacy and data handling at Odoo by visiting our `General Data Protection
|
||||
Regulation page <https://www.odoo.com/gdpr>`_.
|
||||
@@ -1,9 +1,7 @@
|
||||
|
||||
=====================
|
||||
Upgrade your database
|
||||
=====================
|
||||
|
||||
.. _odoosh-advanced-upgrade_your_database:
|
||||
=======================
|
||||
Odoo.sh version upgrade
|
||||
=======================
|
||||
|
||||
Download and Upload your database
|
||||
=================================
|
||||
256
content/administration/upgrade/process.rst
Normal file
@@ -0,0 +1,256 @@
|
||||
.. |assistance-contact| replace::
|
||||
If you need Odoo assistance on this matter, please get in touch with your Odoo Account Manager or
|
||||
our `Sales department`_.
|
||||
.. _Sales department: mailto:sales@odoo.com
|
||||
|
||||
===============
|
||||
Upgrade process
|
||||
===============
|
||||
|
||||
.. _upgrade/overview:
|
||||
|
||||
Overview
|
||||
========
|
||||
|
||||
An upgrade is switching to a newer version of Odoo (e.g., Odoo 14.0 to Odoo 15.0).
|
||||
|
||||
An upgrade does not cover:
|
||||
|
||||
* Changing :ref:`editions <upgrade-faq/editions-change>` (i.e., Community to Enterprise edition)
|
||||
* Switching :ref:`hosting type <upgrade-faq/hosting-types-switch>` (i.e., On-Premise to Online or
|
||||
Odoo.sh)
|
||||
* Migration from another ERP to Odoo
|
||||
|
||||
.. note:: |assistance-contact|
|
||||
|
||||
.. _upgrade/process-workflow:
|
||||
|
||||
Process workflow
|
||||
----------------
|
||||
|
||||
The upgrade process in a nutshell:
|
||||
|
||||
#. You create a test upgrade request.
|
||||
#. | Odoo processes the request:
|
||||
| This happens via an automated process that runs the database through an upgrade script and
|
||||
takes between 20 and 120 minutes. Only if an issue(s) arises will we have to intervene
|
||||
manually and adjust the script specifically to your database until the upgrade succeeds.
|
||||
#. Odoo delivers a test database.
|
||||
#. You test your database for possible discrepancies (see :ref:`upgrade/test-guidance`)
|
||||
#. If there are any discrepancies, you report them to the Upgrade support team via the help portal
|
||||
(see :ref:`upgrade/test-assistance`).
|
||||
#. We will fix the issues and send you a new test database.
|
||||
#. Once you have completed the testing and are happy with the result, you decide on a date and time
|
||||
when you stop users from accessing Odoo, freeze all data entries, and create an upgrade request
|
||||
for the production upgrade.
|
||||
#. Odoo delivers the production database through the automated process.
|
||||
#. You restore it in your Production environment a few short hours later and continue working on the
|
||||
newly upgraded database (this is done automatically on SaaS).
|
||||
|
||||
.. _upgrade/get-started:
|
||||
|
||||
Get started
|
||||
===========
|
||||
|
||||
The upgrade process varies depending on where your database is hosted.
|
||||
|
||||
.. _upgrade/online:
|
||||
|
||||
Online Hosting (SaaS)
|
||||
---------------------
|
||||
|
||||
The upgrade request is made via your `database manager <https://www.odoo.com/my/databases>`_.
|
||||
|
||||
.. image:: process/online-access-databases.png
|
||||
:align: center
|
||||
:alt: Click on the profile button then on "My Databases"
|
||||
|
||||
.. image:: process/online-upgrade-button.png
|
||||
:align: center
|
||||
:alt: Click on the settings button next to your database, then on "Upgrade"
|
||||
|
||||
.. _upgrade/odoo-sh:
|
||||
|
||||
Cloud Platform (Odoo.sh)
|
||||
------------------------
|
||||
|
||||
:doc:`odoo_sh`
|
||||
|
||||
.. _upgrade/on-premise:
|
||||
|
||||
Self-Hosting (On-Premise)
|
||||
-------------------------
|
||||
|
||||
There are two possibilities:
|
||||
|
||||
#. Via `Odoo Upgrade service <https://upgrade.odoo.com>`_
|
||||
#. | For technically advanced users and partners, via the following command line on the machine
|
||||
where your database is hosted:
|
||||
| ``python <(curl -s https://upgrade.odoo.com/upgrade) test -d <your db name> -t <target
|
||||
version>``
|
||||
|
||||
The above command will dump your database to a file, send it to the upgrade platform for an upgrade,
|
||||
display you the live logs, and restore the upgraded database back on your server as a duplicate test
|
||||
database.
|
||||
|
||||
.. _upgrade/testing-phase:
|
||||
|
||||
Testing Phase (pre-production phase)
|
||||
====================================
|
||||
|
||||
This phase allows you to review an upgraded version of your database without affecting your
|
||||
production database in any way.
|
||||
|
||||
We suggest that you run the test upgrade process at least once, but you can do it as many times as
|
||||
you need (one at a time).
|
||||
|
||||
Once you receive your upgraded test database, check that all data, processes, and functionality are
|
||||
still correct and working as expected.
|
||||
|
||||
If you do find discrepancies, report your issues (see :ref:`upgrade/test-assistance`) and request
|
||||
a new test database (see :ref:`upgrade/test-db-request`) when the reported issues are fixed in
|
||||
the upgrade script.
|
||||
|
||||
If you do not find any discrepancies, you'll be able to move on to the upgrade of your
|
||||
:ref:`production database <upgrade/production-live>`.
|
||||
|
||||
.. _upgrade/test-db-request:
|
||||
|
||||
Request a test database
|
||||
-----------------------
|
||||
|
||||
When filling the `website form <https://upgrade.odoo.com>`_, select *Testing* purpose.
|
||||
|
||||
.. image:: process/test-purpose.png
|
||||
:align: center
|
||||
:alt: Selection of the "Testing" purpose in the upgrade form on Odoo
|
||||
|
||||
.. _upgrade/test-guidance:
|
||||
|
||||
Test guidance
|
||||
-------------
|
||||
|
||||
Every business and organization has its own operational needs and has to test its specific Odoo
|
||||
instance respectively. We recommend you look at `the test scenario
|
||||
<https://docs.google.com/document/d/1ypNs7JKPOsjNbKpdiKFH7Al6g6whZ9jr7f7duAQ5E1w/>` for further
|
||||
information.
|
||||
|
||||
.. todo:: change link "test scenario" once the related doc is published
|
||||
|
||||
.. _upgrade/test-assistance:
|
||||
|
||||
Assistance
|
||||
----------
|
||||
|
||||
If you encounter an issue in the **test database**, please get in touch with Odoo Upgrade Support
|
||||
via the `Odoo Support page <https://www.odoo.com/help>`_.
|
||||
|
||||
Under the *Ticket Description* section, select *An issue related to my upgrade* ticket type.
|
||||
|
||||
.. image:: process/test-assistance.png
|
||||
:align: center
|
||||
:alt: Selection of "An issue related to my upgrade" as Ticket Type in the support form on Odoo
|
||||
|
||||
.. warning::
|
||||
If you choose another *Ticket Description* type, the request will be redirected to another
|
||||
team. This will slow down the processing and response time.
|
||||
|
||||
Please provide as much detail as you can (i.e., videos and screenshots to illustrate your issue).
|
||||
This will avoid clarifying questions and speed up the resolution process significantly.
|
||||
|
||||
.. image:: process/test-assistance-details.png
|
||||
:align: center
|
||||
:alt: "Detailed Description" field in the support form on Odoo
|
||||
|
||||
.. note::
|
||||
* The purpose of the test phase is not to correct existing data or configurations in your
|
||||
database.
|
||||
* |assistance-contact|
|
||||
|
||||
.. _upgrade/steps-production:
|
||||
|
||||
The production launch
|
||||
---------------------
|
||||
|
||||
.. _upgrade/production-live:
|
||||
|
||||
Production goes live
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The production upgrade request is when you decide to upgrade your current database with all your
|
||||
production data (invoices, VAT returns, inventories, current orders) to a new version of your
|
||||
choice.
|
||||
|
||||
After your :ref:`tests <upgrade/testing-phase>` are completed to your satisfaction, submit the
|
||||
request to upgrade your production database via our `website form <https://upgrade.odoo.com>`_.
|
||||
Select *Production* purpose.
|
||||
|
||||
.. image:: process/production-purpose.png
|
||||
:align: center
|
||||
:alt: Selection of the "Production" purpose in the upgrade form on Odoo
|
||||
|
||||
.. danger::
|
||||
Going into production without first testing may lead to:
|
||||
|
||||
- business interruptions (e.g., no longer having the possibility to validate an action)
|
||||
- poor customer experiences (e.g., an eCommerce website that does not work correctly)
|
||||
|
||||
.. _upgrade/production-assistance:
|
||||
|
||||
Assistance
|
||||
~~~~~~~~~~
|
||||
|
||||
If you encounter issues or problems in the **production database**, please get in touch with **Odoo
|
||||
Support**:
|
||||
|
||||
#. Connect to our `Odoo Support page <https://www.odoo.com/help>`_.
|
||||
#. Under the *Ticket Description* section, select the appropriate type related to your issue but
|
||||
**do not select** the option *An issue related to my upgrade*.
|
||||
|
||||
.. note::
|
||||
After upgrading to production, the support will be provided by the Support team instead of the
|
||||
Upgrade team.
|
||||
|
||||
#. Please provide as much detail as you can (i.e., videos and screenshots to illustrate your issue).
|
||||
This will avoid clarifying questions and speed up the resolution process significantly.
|
||||
|
||||
.. image:: process/production-assistance-details.png
|
||||
:align: center
|
||||
:alt: "Detailed Description" field in the support form on Odoo
|
||||
|
||||
.. warning::
|
||||
If you choose *An issue related to my upgrade* as ticket type, the request will be redirected
|
||||
to another team than the support one and will slow down the processing and response time.
|
||||
|
||||
.. _upgrade/assistance:
|
||||
|
||||
Assistance
|
||||
==========
|
||||
|
||||
.. _upgrade/contact:
|
||||
|
||||
Contact our Upgrade service support
|
||||
-----------------------------------
|
||||
|
||||
Should you have any more questions about the upgrade, do not hesitate to send a message to `Odoo
|
||||
Upgrade Team <mailto:upgrade@odoo.com>`_. We will be happy to answer it as soon as possible.
|
||||
|
||||
.. _upgrade/supported-versions:
|
||||
|
||||
Supported versions
|
||||
------------------
|
||||
|
||||
Please note that Odoo provides support and bug fixing only for the three last major versions of
|
||||
Odoo.
|
||||
|
||||
This is a factor to take into consideration before upgrading. If you are on an older version, we
|
||||
suggest you to prefer the most recent version to benefit from longer support (before having to
|
||||
upgrade again).
|
||||
|
||||
You can get more information about our :doc:`supported versions <../maintain/supported_versions>`.
|
||||
|
||||
.. seealso::
|
||||
- :doc:`faq`
|
||||
- :doc:`odoo_sh`
|
||||
- :doc:`service_level`
|
||||
- :doc:`../maintain/supported_versions`
|
||||
|
After Width: | Height: | Size: 5.3 KiB |
BIN
content/administration/upgrade/process/online-upgrade-button.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 9.5 KiB After Width: | Height: | Size: 9.5 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 8.7 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
37
content/administration/upgrade/service_level.rst
Normal file
@@ -0,0 +1,37 @@
|
||||
.. |assistance-contact| replace::
|
||||
If you need Odoo assistance on this matter, please get in touch with your Odoo Account Manager or
|
||||
our `Sales department`_.
|
||||
.. _Sales department: mailto:sales@odoo.com
|
||||
|
||||
=======================
|
||||
Service Level Agreement
|
||||
=======================
|
||||
|
||||
What is covered by the Enterprise Licence?
|
||||
==========================================
|
||||
|
||||
Databases hosted on Odoo’s Cloud platforms (Saas and Odoo.sh) or On-Premise (Self-Hosting) enjoy the
|
||||
following service at all times.
|
||||
|
||||
The upgrade of:
|
||||
|
||||
* standard applications
|
||||
* Studio customization (as long as the Studio app is still active)
|
||||
* customizations done by our consulting and developer services *if* they are covered by a
|
||||
‘Maintenance of Customisations’ subscription
|
||||
|
||||
The Upgrade Service is limited to your database's technical conversion and adaptation (standard
|
||||
modules and data) to make it compatible with the targeted version.
|
||||
|
||||
What upgrading does NOT cover
|
||||
=============================
|
||||
|
||||
* The cleaning of pre-existing data & configuration while upgrading
|
||||
* Any new developments and/or upgrades of your own :ref:`custom modules
|
||||
<upgrade-faq/custom-modules>`
|
||||
* `Training <https://www.odoo.com/learn>`_ on the latest version
|
||||
|
||||
You can get more information about your Enterprise Licence on our :ref:`Odoo Enterprise Subscription
|
||||
Agreement <upgrade>` page.
|
||||
|
||||
.. note:: |assistance-contact|
|
||||
@@ -22,10 +22,6 @@ selected at the creation of the database.
|
||||
To install a new package, go to :menuselection:`Accounting --> Configuration --> Fiscal
|
||||
Localization`, click on **Install More Packages**, and install your country's module.
|
||||
|
||||
.. image:: media/fiscal_localization_packages_modules.png
|
||||
:align: center
|
||||
:alt: Install the appropriate module as fiscal localization package in Odoo Accounting.
|
||||
|
||||
Once done, select your country's package, and click on *Save*.
|
||||
|
||||
.. image:: media/fiscal_localization_packages_selection.png
|
||||
|
||||
@@ -6,10 +6,6 @@ Odoo Accounting can be used in many countries out of the box by installing the a
|
||||
Here is a list of all :doc:`Fiscal Localization Packages <fiscal_localization_packages>` that are
|
||||
available on Odoo.
|
||||
|
||||
.. image:: media/fiscal_localization_packages_modules.png
|
||||
:align: center
|
||||
:alt: Odoo Accounting.
|
||||
|
||||
Fiscal Localization Packages available
|
||||
======================================
|
||||
|
||||
|
||||
|
Before Width: | Height: | Size: 34 KiB |
@@ -43,6 +43,52 @@ In Odoo
|
||||
and the zip code). Go to :menuselection:`Settings --> Users & Companies --> Companies`
|
||||
to open and edit your Company record.
|
||||
|
||||
Automatically post taxes to the correct Tax Payable account
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
* For each one of your companies that uses TaxCloud, it might be necessary to create a
|
||||
**User-Defined Default** so that the new taxes generated by the TaxCloud integration are created
|
||||
with the correct Tax Payable account:
|
||||
|
||||
.. warning::
|
||||
A User-Defined Default impacts all records at creation. It means that **every** new tax will be
|
||||
set up to record income in the specified Tax Payable account, unless the tax is manually edited
|
||||
to specify a different income account (or there exists another User-Defined Default that takes
|
||||
precedence).
|
||||
|
||||
* In :menuselection:`Accounting --> Configuration --> Chart of Accounts`, select the Tax Payable
|
||||
account for the company. Take note of the account's ``id`` in the URL string.
|
||||
|
||||
.. image:: taxcloud/user-default-find-account-id.png
|
||||
:alt: The account's ID can be found in the URL string as 'id=...'.
|
||||
:align: center
|
||||
|
||||
* Activate the :ref:`developer mode <developer-mode>`, then go to
|
||||
:menuselection:`Settings --> Technical --> Actions --> User-Defined Defaults`, and
|
||||
click on *Create*.
|
||||
|
||||
* Click on *Field*, then, in the drop-down menu, on *Search More*.
|
||||
|
||||
.. image:: taxcloud/user-default-search-field.png
|
||||
:alt: Click on 'Search More' in the 'Field' drop-down menu.
|
||||
:align: center
|
||||
|
||||
* In the pop-up's search box, filter on the model ``tax.repartition.line`` and the field ``account``.
|
||||
Select the ``account`` field of the ``tax.repartition.line`` model.
|
||||
|
||||
.. image:: taxcloud/user-default-select-field.png
|
||||
:alt: Select the 'account' field of the 'tax.repartition.line' model.
|
||||
:align: center
|
||||
|
||||
* In the **Default Value** field, enter the ID of the company's Tax Payable account.
|
||||
Select the company for which this configuration should apply in the *Company* field.
|
||||
Click *Save*.
|
||||
|
||||
.. image:: taxcloud/user-default-enter-default-account-id.png
|
||||
:alt: Enter the ID of the company's Tax Payable account.
|
||||
:align: center
|
||||
|
||||
|
||||
How it works
|
||||
============
|
||||
|
||||
|
||||
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 20 KiB |
|
After Width: | Height: | Size: 16 KiB |
@@ -33,23 +33,45 @@ Activate through a browser extension
|
||||
:align: center
|
||||
:alt: View of odoo’s debug icon in a chrome’s toolbar
|
||||
|
||||
Activate through the command palette
|
||||
====================================
|
||||
|
||||
The command palette tool has a command to activate the debug mode: open it with
|
||||
the keyboard shortcut `ctrl+k`, then type `debug`: a command will show up to
|
||||
activate the debug mode.
|
||||
|
||||
.. image:: developer_mode/command_palette.png
|
||||
:align: center
|
||||
:alt: Command palette with debug command
|
||||
|
||||
Activate through the URL
|
||||
========================
|
||||
|
||||
In the URL add ``?debug=1`` or ``?debug=true`` after *web*.
|
||||
In the URL, add ``?debug=1`` or ``?debug=true`` after *web*. To deactivate the
|
||||
debug mode, add `?debug=0` instead.
|
||||
|
||||
.. image:: url.png
|
||||
:align: center
|
||||
:alt: Overview of an url with the debug mode command added in Odoo
|
||||
|
||||
.. tip::
|
||||
Developers: type ``?debug=assets`` and activate the mode with assets.
|
||||
Additional modes are available for developers: `?debug=assets` enables the
|
||||
:ref:`assets mode <frontend/framework/assets_debug_mode>`, and `?debug=tests` enables
|
||||
the :ref:`tests mode <frontend/framework/tests_debug_mode>`.
|
||||
|
||||
Locate the mode tools
|
||||
=====================
|
||||
|
||||
The Developer mode tools can be accessed from the *Open Developer Tools* button, located on the
|
||||
header of your pages.
|
||||
The Developer mode tools can be accessed from the *Open Developer Tools* button,
|
||||
located on the header of your pages. This menu contains additional tools that
|
||||
are useful to understand or edit technical data, such as the views or the actions.
|
||||
It contains some useful menu items such as:
|
||||
|
||||
- edit action
|
||||
- manage filters
|
||||
- edit the current view
|
||||
- see the `fields view get`
|
||||
- and much more.
|
||||
|
||||
.. image:: button_location.png
|
||||
:align: center
|
||||
|
||||
BIN
content/applications/general/developer_mode/command_palette.png
Normal file
|
After Width: | Height: | Size: 37 KiB |
@@ -2,7 +2,7 @@
|
||||
Paypal
|
||||
======
|
||||
|
||||
`Paypal <https://www.paypal.com//>` is available and popular worldwide. It doesn't charge any
|
||||
`Paypal <https://www.paypal.com/>`_ is available and popular worldwide. It doesn't charge any
|
||||
subscription fee and creating an account is very easy. That's why we definitely recommend it for
|
||||
starters in Odoo. It works as a seamless flow where the customer is routed to Paypal website to
|
||||
register the payment.
|
||||
|
||||
@@ -9,3 +9,5 @@ Overview
|
||||
|
||||
overview/getting_started
|
||||
overview/register
|
||||
overview/https
|
||||
overview/epos_ssc
|
||||
|
||||
@@ -0,0 +1,87 @@
|
||||
=========================================
|
||||
Self-signed certificate for ePOS printers
|
||||
=========================================
|
||||
|
||||
ePos printers are designed specifically to work with your Point of Sale system, which sends the
|
||||
tickets directly to the printer.
|
||||
|
||||
Some models don't require an IoT box, but the connection between your web browser and the printer
|
||||
may require a :doc:`secure connection with the HTTPS protocol <https>`. If so, a self-signed
|
||||
certificate is necessary to use your printer.
|
||||
|
||||
.. note::
|
||||
Please check the following list of compatible `Epson ePOS printers
|
||||
<https://c4b.epson-biz.com/modules/community/index.php?content_id=91>`_. This list includes the
|
||||
following models:
|
||||
|
||||
- TM-H6000IV-DT (Receipt printer only)
|
||||
- TM-T70II-DT
|
||||
- TM-T88V-DT
|
||||
- TM-L90-i
|
||||
- TM-T20II-i
|
||||
- TM-T70-i
|
||||
- TM-T82II-i
|
||||
- TM-T83II-i
|
||||
- TM-T88V-i
|
||||
- TM-U220-i
|
||||
- TM-m10
|
||||
- TM-m30
|
||||
- TM-P20 (Wi-Fi® model)
|
||||
- TM-P60II (Receipt: Wi-Fi® model)
|
||||
- TM-P60II (Peeler: Wi-Fi® model)
|
||||
- TM-P80 (Wi-Fi® model)
|
||||
|
||||
Generate a Self-signed certificate
|
||||
==================================
|
||||
|
||||
Access your ePOS printer's settings with your web browser by navigating to its IP address, for
|
||||
example, `http://192.168.1.25`.
|
||||
|
||||
.. note::
|
||||
- The printer automatically prints the IP address during startup.
|
||||
- We recommend assigning a **fixed IP address** to the printer from the network router.
|
||||
|
||||
Go to :menuselection:`Authentication --> Certificate List` and create a new **Self-Signed
|
||||
Certificate**.
|
||||
|
||||
- **Common Name**: the IP address of the ePos Printer, for example, `192.168.1.25`
|
||||
- **Validity Period**: `10`
|
||||
|
||||
Create and reboot the printer, go to :menuselection:`Security --> SSL/TLS`, and check if
|
||||
**Selfsigned Certificate** is selected.
|
||||
|
||||
Export the Self-signed certificate
|
||||
==================================
|
||||
|
||||
To avoid having to accept the self-signed certificate several times, you can export it and then
|
||||
import it to your web browser or mobile device.
|
||||
|
||||
To do so, access your ePOS printer's settings with your web browser by navigating to its IP address,
|
||||
for example, `https://192.168.1.25`. Then, accept the self-signed certificate.
|
||||
|
||||
.. note::
|
||||
Note that the protocol is now **HTTPS**.
|
||||
|
||||
Click on :menuselection:`Connection is not secure --> Certificate is not valid`.
|
||||
|
||||
.. image:: epos_ssc/browser-warning.png
|
||||
:align: center
|
||||
:alt: The web browser indicates that the connection to the printer is not secure.
|
||||
|
||||
Go to the *Details* tab and click on **Copy to file**.
|
||||
Select X.509 in base 64 and save it.
|
||||
|
||||
Import the Self-signed certificate to Windows (Using Chrome)
|
||||
============================================================
|
||||
|
||||
In your Chrome browser, go to :menuselection:`Settings --> Privacy and security --> Security -->
|
||||
Manage certificates`
|
||||
|
||||
Go to the *Trusted Root Certification Authorities* tab and click on **Import** and select
|
||||
your previous file. Accept all warnings and restart your browser.
|
||||
|
||||
Import the Self-signed certificate to your Android device
|
||||
=========================================================
|
||||
|
||||
On your Android device, open the settings and search for *certificate*. Then, click on **Certificate
|
||||
AC** (Install from device storage), and select the certificate.
|
||||
|
After Width: | Height: | Size: 17 KiB |
22
content/applications/sales/point_of_sale/overview/https.rst
Normal file
@@ -0,0 +1,22 @@
|
||||
=========================
|
||||
Secure connection (HTTPS)
|
||||
=========================
|
||||
|
||||
If **Direct Devices** is enabled in a Point of Sale settings (for example, if you use an ePos
|
||||
printer), HTTP becomes the default protocol.
|
||||
|
||||
Force your Point of Sale to use a secure connection (HTTPS)
|
||||
===========================================================
|
||||
|
||||
Add a new **key** in the **System Parameters** to force your Point of Sale to use a secure
|
||||
connection with the HTTPS protocol.
|
||||
|
||||
To do so, activate the :ref:`developer mode <developer-mode>`, go to :menuselection:`Settings -->
|
||||
Technical --> Parameters --> System Parameters`, then create a new parameter, add the following
|
||||
values and click on *Save*.
|
||||
|
||||
- **Key**: `point_of_sale.enforce_https`
|
||||
- **Value**: `True`
|
||||
|
||||
.. seealso::
|
||||
- :doc:`epos_ssc`
|
||||
@@ -9,3 +9,4 @@ Manage your products
|
||||
|
||||
products/import
|
||||
products/variants
|
||||
products/product_images
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
===================================================
|
||||
Automatically get product images with Google Images
|
||||
===================================================
|
||||
|
||||
The product images are very useful in Odoo, for example, to quickly find a product or check if you
|
||||
scanned the right one, but it can be a bit painful to set up especially if you have a lot of
|
||||
products. **Google Custom Search** allows finding images automatically for your product, based on
|
||||
their barcode, keeping your focus on what matters in your business.
|
||||
|
||||
.. _product_images/configuration:
|
||||
|
||||
Configuration
|
||||
=============
|
||||
|
||||
This functionnality requires configuration both on Google and on Odoo.
|
||||
|
||||
With a free Google account, you can get up to 100 free images per day. If you need a higher rate,
|
||||
you'll have to upgrade to a billing account.
|
||||
|
||||
.. _product_images/google-api-dashboard:
|
||||
|
||||
Google API dashboard
|
||||
--------------------
|
||||
|
||||
#. Go to the `Google Cloud Platform API & Services <https://console.developers.google.com/>`_ page
|
||||
to generate Google Custom Search API credentials. Log in with your Google account.
|
||||
|
||||
#. Select or create an API project to store the credentials. Give it an explicit name
|
||||
(e.g. Odoo Images).
|
||||
|
||||
#. In the credentials section, click on **Create Credentials** and select **API Keys**.
|
||||
|
||||
.. image:: product_images/gcp-api-services.png
|
||||
:align: center
|
||||
:alt: API & Services page on Google Cloud Platform
|
||||
|
||||
#. Save your **API Key**. You'll need it for the next step in Odoo!
|
||||
|
||||
#. Use the search bar to look for **Google Custom Search API** and select it.
|
||||
|
||||
.. image:: product_images/gcp-search.png
|
||||
:align: center
|
||||
:alt: Search bar containing "Custom Search API" on Google Cloud Platform
|
||||
|
||||
#. Enable the API.
|
||||
|
||||
.. image:: product_images/gcp-custom-search-api.png
|
||||
:align: center
|
||||
:alt: "Custom Search API" tile with Enable button highlighted on Google Cloud Platform
|
||||
|
||||
.. _product_images/google-pse-dashboard:
|
||||
|
||||
Google Programmable Search dashboard
|
||||
------------------------------------
|
||||
|
||||
#. Go to `Google Programmable Search Engine <https://programmablesearchengine.google.com/>`_ and
|
||||
click on **Get Started**. Log in with your Google account.
|
||||
|
||||
.. image:: product_images/google-pse.png
|
||||
:align: center
|
||||
:alt: Google Programmable Search Engine page with the **Get Started** button on the up-right
|
||||
of the page
|
||||
|
||||
#. Fill the language and the name of the search engine. Give it an explicit name
|
||||
(e.g. Odoo Images).
|
||||
|
||||
.. note::
|
||||
Google doesn't allow to create a search engine without having entered at least one specific
|
||||
site to search on. You can put any website (e.g. www.google.com) for this step, we will
|
||||
remove it later.
|
||||
|
||||
#. Validate the form by clicking on **Create**. Then, go to the edition mode of the search engine
|
||||
that you created (either by clicking on **Control Panel** on the confirmation page or by
|
||||
clicking on the name of your Search Engine on the Home page).
|
||||
|
||||
#. In the **basics** tab, make sure to enable **Image search**, **SafeSearch** and
|
||||
**Search the entire web**.
|
||||
|
||||
.. note::
|
||||
Once **Search the entire web** is enabled, you can safely delete the site that you put at the
|
||||
previous step.
|
||||
|
||||
#. Save your **Search Engine Id**. You’ll need it for the next step in Odoo!
|
||||
|
||||
.. _product_images/setup-in-odoo:
|
||||
|
||||
Odoo
|
||||
----
|
||||
|
||||
#. Go to :menuselection:`Settings --> General Settings --> Integrations`,
|
||||
activate **Google Images** and save.
|
||||
|
||||
#. Go back to :menuselection:`Settings --> General Settings--> Integrations`, enter your **API Key**
|
||||
and **Search Engine ID** in **Google Images** settings and save again.
|
||||
|
||||
.. _product_images/get-product-images:
|
||||
|
||||
Automatically get your product images in Odoo
|
||||
=============================================
|
||||
|
||||
The action to automatically get your product images in Odoo appears in any Products or Product
|
||||
Variants list view. Here is a step-by-step guide from the Inventory app.
|
||||
|
||||
#. Go to the Products menu (:menuselection:`Products --> Products` or :menuselection:`Products -->
|
||||
Product Variants`) from any application that uses products like Inventory or Sales.
|
||||
|
||||
#. On the list view, select the products that needs an image.
|
||||
|
||||
.. important::
|
||||
Only the 10,000 first selected products or product variants will be processed.
|
||||
|
||||
.. note::
|
||||
- Only the products or product variants with a barcode and without an image will be processed.
|
||||
- If you select a product that has one or more variants from the Products view, each variant
|
||||
matching the previous criteria will be processed.
|
||||
|
||||
#. In the action menu, select **Get Pictures from Google Images** and validate by clicking on
|
||||
**Get picture**.
|
||||
|
||||
#. You should see your images appearing incrementally.
|
||||
|
||||
.. note::
|
||||
- Only the 10 first images are fetched immediatly. If you selected more than 10, the rest will
|
||||
be fetched as a background job.
|
||||
- The background job process about 100 images in a minute. If you reach the quota authorized
|
||||
by Google (either with a free or a paid plan), the background job will put itself on hold
|
||||
for 24 hours and continue where it stopped the day before.
|
||||
|
||||
.. seealso::
|
||||
- `Create, modify, or close your Google Cloud Billing account
|
||||
<https://cloud.google.com/billing/docs/how-to/manage-billing-account>`_
|
||||
|
After Width: | Height: | Size: 23 KiB |
|
After Width: | Height: | Size: 9.5 KiB |
|
After Width: | Height: | Size: 4.6 KiB |
|
After Width: | Height: | Size: 29 KiB |
@@ -77,7 +77,7 @@ We can now apply the redirection from your domain name's manager account:
|
||||
|
||||
.. note:: Here are some specific guidelines to create a CNAME record:
|
||||
|
||||
- `GoDaddy <https://be.godaddy.com/fr/help/add-a-cname-record-19236>`__
|
||||
- `GoDaddy <https://www.godaddy.com/help/add-a-cname-record-19236>`__
|
||||
- `Namecheap <https://www.namecheap.com/support/knowledgebase/article.aspx/9646/10/how-can-i-set-up-a-cname-record-for-my-domain>`__
|
||||
- `OVH <https://www.ovh.co.uk/g1519.exchange_20132016_how_to_add_a_cname_record>`__
|
||||
|
||||
|
||||
@@ -220,7 +220,7 @@ Python comes with its own package manager: `pip
|
||||
a single command.
|
||||
|
||||
#. Download and install the recommended release (`see README file
|
||||
<https://github.com/odoo/documentation/tree/15.0/README.md>`_) of **Python 3** on your machine.
|
||||
<https://github.com/odoo/documentation/tree/master/README.md>`_) of **Python 3** on your machine.
|
||||
#. Make sure to have **pip** installed on your machine (on Windows, you can install pip alongside
|
||||
Python).
|
||||
#. Execute the following commands in a terminal to verify that both installations finished
|
||||
|
||||
@@ -36,8 +36,8 @@ A reference to the rendered :file:`prices.html` and :file:`variants.html` could
|
||||
|
||||
#. Absolute:
|
||||
|
||||
- ``https://odoo.com/documentation/15.0/applications/sales/sales/products_prices/prices.html``
|
||||
- ``https://odoo.com/documentation/15.0/applications/sales/sales/products_prices/products/variants.html``
|
||||
- ``https://odoo.com/documentation/master/applications/sales/sales/products_prices/prices.html``
|
||||
- ``https://odoo.com/documentation/master/applications/sales/sales/products_prices/products/variants.html``
|
||||
|
||||
#. Relative:
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ to make sure we start on the same page during the development of our new applica
|
||||
https://en.wikipedia.org/wiki/Multitier_architecture
|
||||
|
||||
.. _Python tutorial:
|
||||
https://docs.python.org/3.6/tutorial/
|
||||
https://docs.python.org/3.7/tutorial/
|
||||
|
||||
.. _two versions:
|
||||
https://www.odoo.com/page/editions
|
||||
|
||||
@@ -161,7 +161,7 @@ Install the dependencies
|
||||
Python
|
||||
------
|
||||
|
||||
Odoo requires Python 3.6 or later, if your computer is up-to-date you should already be at this
|
||||
Odoo requires Python 3.7 or later, if your computer is up-to-date you should already be at this
|
||||
version or higher.
|
||||
|
||||
You can check your Python version with:
|
||||
|
||||
@@ -9,3 +9,4 @@ API
|
||||
|
||||
api/odoo
|
||||
api/iap
|
||||
api/extract_api
|
||||
|
||||
555
content/developer/misc/api/extract_api.rst
Normal file
@@ -0,0 +1,555 @@
|
||||
:code-column:
|
||||
|
||||
===============
|
||||
Extract API
|
||||
===============
|
||||
|
||||
Odoo provides a service allowing you to automate the processing of your invoices. The service scans your document using an Optical
|
||||
Character Recognition (OCR) engine and then uses AI-based algorithms to extract the fields of interest such as the total, the due date, or
|
||||
the invoice lines. More functional information can be found on the `demo page <https://www.odoo.com/page/invoice-automation>`_.
|
||||
|
||||
This service is a paid service. Each invoice processing will cost you one credit. Three different sized packs can be bought on `iap.odoo.com <https://iap.odoo.com/iap/in-app-services/259?sortby=date>`_.
|
||||
|
||||
You can either use this service directly in the Odoo Accounting App or through the API. The Extract API which is detailed in the next section
|
||||
allows you to integrate our service directly into your own projects.
|
||||
|
||||
Invoices
|
||||
========
|
||||
The extract API use the JSON-RPC2_ protocol. The diffent routes are located at the following address: **https://iap-extract.odoo.com**.
|
||||
|
||||
Expected successful flow
|
||||
------------------------
|
||||
|
||||
1. Call :ref:`webservices/extract_api/invoice_parse` to submit your invoices (one call for each invoice). On success, you receive a `document_id` in the response.
|
||||
2. You then have to regularly poll :ref:`webservices/extract_api/invoice_get_results` to get the document's parsing status.
|
||||
3. Once the result received, you can validate it by calling :ref:`webservices/extract_api/invoice_validate` and sending the expected values.
|
||||
This step is optional but greatly helps the system to improve.
|
||||
|
||||
These 3 routes are detailed in this :ref:`section <webservices/extract_api/routes>`. The HTTP POST method should be used for all of them. A python implementation of the full flow
|
||||
can be found :download:`here <extract_api/implementation.py>` and a token for integration testing is provided in the :ref:`integration testing section <webservices/extract_api/integration_testing>`.
|
||||
|
||||
.. _webservices/extract_api/routes:
|
||||
|
||||
Routes
|
||||
------
|
||||
|
||||
.. _webservices/extract_api/invoice_parse:
|
||||
|
||||
``/iap/invoice_extract/parse``
|
||||
''''''''''''''''''''''''''''''
|
||||
|
||||
Description
|
||||
^^^^^^^^^^^
|
||||
Request a processing of the document from the OCR. The route will return a `document_id` you can use to obtain the result of your request.
|
||||
|
||||
Request Body
|
||||
^^^^^^^^^^^^
|
||||
|
||||
``jsonrpc`` (required)
|
||||
Must be exactly “2.0”.
|
||||
``method`` (required)
|
||||
Must be “call”.
|
||||
``id`` (required)
|
||||
An identifier established by the client. It allows the client to keep track of which response goes with which request. This makes asynchronous calls easier.
|
||||
``params``
|
||||
``account_token`` (required)
|
||||
The token of the account from which credits will be taken. Each successful call costs one token.
|
||||
``version`` (optional)
|
||||
The version will determine the format of your requests and the format of the server response. Some results can be unavailable in older versions. For the current
|
||||
version 1.2.0, send ‘120’. If not specified, the latest version will be used.
|
||||
``documents`` (required)
|
||||
The invoice must be provided as a string in the ASCII encoding. The list should contain only one string. If multiple strings are provided only the first string
|
||||
corresponding to a pdf will be processed. If no pdf is found, the first string will be processed. This field is a list only for legacy reasons. The supported extensions
|
||||
are *pdf*, *png*, *jpg* and *bmp*.
|
||||
``user_infos`` (required)
|
||||
Information concerning the person to whom the invoice is intended. This information is not required in order for the service to work but it greatly improves the quality of the result.
|
||||
|
||||
``user_company_vat`` (optional)
|
||||
VAT number of the client.
|
||||
``user_company_name`` (optional)
|
||||
Name of the client’s company.
|
||||
``user_company_country_code`` (optional)
|
||||
Country code of the client. Format: `ISO3166 alpha-2 <https://www.iban.com/country-codes>`_.
|
||||
``user_lang`` (optional)
|
||||
The client language. Format: *language_code + _ + locale* (ex: fr_FR, en_US).
|
||||
``user_email`` (optional)
|
||||
The client email.
|
||||
|
||||
.. rst-class:: setup doc-aside
|
||||
|
||||
.. switcher::
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"jsonrpc": string,
|
||||
"method": string,
|
||||
"params": {
|
||||
"account_token": string (hex),
|
||||
"version": int,
|
||||
"documents": [string],
|
||||
"user_infos": {
|
||||
"user_company_vat": string,
|
||||
"user_company_name": string,
|
||||
"user_company_country_code": string,
|
||||
"user_lang": string,
|
||||
"user_email": string,
|
||||
},
|
||||
},
|
||||
"id": string (hex),
|
||||
}
|
||||
|
||||
Response
|
||||
^^^^^^^^
|
||||
|
||||
``jsonrpc``
|
||||
A string specifying the version of the JSON-RPC protocol. It will be “2.0”.
|
||||
``id``
|
||||
The identifier you set in the request body.
|
||||
``result``
|
||||
``status_code``
|
||||
|STATUS_CODE|
|
||||
``status_msg``
|
||||
|STATUS_MSG|
|
||||
``document_id``
|
||||
Only present if the request is successful.
|
||||
|
||||
.. note:: The API does not actually use the JSON-RPC error scheme. Instead the API has its own error scheme bundled inside a successful JSON-RPC result.
|
||||
|
||||
============= ==============================================================
|
||||
status_code status_msg
|
||||
============= ==============================================================
|
||||
0 Success
|
||||
2 An error occurred
|
||||
3 You don't have enough credit
|
||||
6 Unsupported file format
|
||||
9 Server is currently under maintenance. Please try again later.
|
||||
============= ==============================================================
|
||||
|
||||
.. rst-class:: setup doc-aside
|
||||
|
||||
.. switcher::
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"jsonrpc": string,
|
||||
"id": string,
|
||||
"result": {
|
||||
"status_code": int,
|
||||
"status_msg": string,
|
||||
"document_id": int,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.. _webservices/extract_api/invoice_get_results:
|
||||
|
||||
``/iap/invoice_extract/get_results``
|
||||
''''''''''''''''''''''''''''''''''''
|
||||
|
||||
Description
|
||||
^^^^^^^^^^^
|
||||
Request the results of the documents ids obtained with the :ref:`/parse <webservices/extract_api/invoice_parse>` route. Can either return the results or a "request pending" message.
|
||||
|
||||
Request Body
|
||||
^^^^^^^^^^^^
|
||||
|
||||
``jsonrpc`` (required)
|
||||
|SAME_AS_PARSE|
|
||||
``method`` (required)
|
||||
|SAME_AS_PARSE|
|
||||
``id`` (required)
|
||||
|SAME_AS_PARSE|
|
||||
``params``:
|
||||
``version`` (required)
|
||||
|SAME_AS_PARSE|
|
||||
``documents_ids`` (required)
|
||||
The list of ``document_id`` for which you want to get the current parsing status.
|
||||
|
||||
.. rst-class:: setup doc-aside
|
||||
|
||||
.. switcher::
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"jsonrpc": string,
|
||||
"method": string,
|
||||
"params": {
|
||||
"version": int,
|
||||
"documents_ids": [int]
|
||||
},
|
||||
"id": string (hex),
|
||||
}
|
||||
|
||||
|
||||
Response
|
||||
^^^^^^^^
|
||||
|
||||
``jsonrpc``
|
||||
|SAME_AS_PARSE|
|
||||
``id``
|
||||
|SAME_AS_PARSE|
|
||||
``result``
|
||||
Dictionary where each key is a document_id. For each ``document_id``:
|
||||
|
||||
``status_code``
|
||||
|STATUS_CODE|
|
||||
``status_msg``
|
||||
|STATUS_MSG|
|
||||
``results``
|
||||
Only present if the request is successful.
|
||||
|
||||
.. warning:: result keys are strings despite the fact that the document_ids given in the request body are integers.
|
||||
|
||||
============= ==============================================================
|
||||
status_code status_msg
|
||||
============= ==============================================================
|
||||
0 Success
|
||||
1 Not ready
|
||||
2 An error occurred
|
||||
9 Server is currently under maintenance. Please try again later.
|
||||
============= ==============================================================
|
||||
|
||||
.. rst-class:: setup doc-aside
|
||||
|
||||
.. switcher::
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"jsonrpc": string,
|
||||
"id": string,
|
||||
"result": {
|
||||
"document_id_1": {
|
||||
"status_code": int,
|
||||
"status_msg": str,
|
||||
"results": [{"feature_1_name": feature_1_result,
|
||||
"feature_2_name": feature_2_result,
|
||||
…
|
||||
}]
|
||||
},
|
||||
"document_id_2": {
|
||||
"status_code": int,
|
||||
"status_msg": str,
|
||||
"results": [{"feature_1_name": feature_1_result,
|
||||
"feature_2_name": feature_2_result,
|
||||
…
|
||||
}]
|
||||
},
|
||||
...
|
||||
}
|
||||
}
|
||||
|
||||
.. _webservices/extract_api/invoice_get_results/feature_result:
|
||||
|
||||
``feature_result``
|
||||
''''''''''''''''''
|
||||
|
||||
Each field of interest we want to extract from the invoice such as the total or the due date are also called features. An exhaustive list of all the extracted features can be found in the table below.
|
||||
|
||||
For each feature, we return a list of candidates and we spotlight the candidate our model predicts to be the best fit for the feature.
|
||||
|
||||
``selected_value``
|
||||
The best candidate for this feature.
|
||||
``words``
|
||||
List of all the candidates for this feature ordered by decreasing score.
|
||||
|
||||
.. container:: doc-aside
|
||||
|
||||
.. switcher::
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"selected_value": candidate_12,
|
||||
"words": [candidate_12, candidate_3, candidate_4,...]
|
||||
}
|
||||
|
||||
|
||||
``candidate``
|
||||
'''''''''''''
|
||||
|
||||
For each candidate we give its representation and position in the document. Candidates are sorted by decreasing order of suitability.
|
||||
|
||||
``content``
|
||||
Representation of the candidate.
|
||||
``coords``
|
||||
``[center_x, center_y, width, height, rotation_angle]``. The position and dimensions are relative to the size of the page and are therefore between 0 and 1.
|
||||
The angle is a clockwise rotation measured in degrees.
|
||||
``page``
|
||||
Page of the original document on which the candidate is located (starts at 0).
|
||||
|
||||
.. container:: doc-aside
|
||||
|
||||
.. switcher::
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"content": string|float,
|
||||
"coords": [float, float, float, float, float],
|
||||
"page": int
|
||||
}
|
||||
|
||||
+-------------------------+------------------------------------------------------------------------------------+
|
||||
| Feature name | Specifities |
|
||||
+=========================+====================================================================================+
|
||||
| ``SWIFT_code`` | **content** is a dictionary encoded as a string. |
|
||||
| | |
|
||||
| | It contains information about the detected SWIFT code |
|
||||
| | (or `BIC <https://www.iso9362.org/isobic/overview.html>`_). |
|
||||
| | |
|
||||
| | Keys: |
|
||||
| | |
|
||||
| | ``bic`` |
|
||||
| | detected BIC (string). |
|
||||
| | ``name`` (optional) |
|
||||
| | bank name (string). |
|
||||
| | ``country_code`` |
|
||||
| | ISO3166 alpha-2 country code of the bank (string). |
|
||||
| | ``city`` (optional) |
|
||||
| | city of the bank (string). |
|
||||
| | ``verified_bic`` |
|
||||
| | True if the BIC has been found in our DB (bool). |
|
||||
| | |
|
||||
| | Name and city are present only if verified_bic is true. |
|
||||
+-------------------------+------------------------------------------------------------------------------------+
|
||||
| ``VAT_Number`` | **content** is a string |
|
||||
+-------------------------+------------------------------------------------------------------------------------+
|
||||
| ``country`` | **content** is a string |
|
||||
+-------------------------+------------------------------------------------------------------------------------+
|
||||
| ``currency`` | **content** is a string |
|
||||
+-------------------------+------------------------------------------------------------------------------------+
|
||||
| ``date`` | **content** is a string |
|
||||
| | |
|
||||
| | Format : *YYYY-MM-DD HH:MM:SS* |
|
||||
+-------------------------+------------------------------------------------------------------------------------+
|
||||
| ``due_date`` | Same as for ``date`` |
|
||||
+-------------------------+------------------------------------------------------------------------------------+
|
||||
| ``global_taxes`` | **content** is a float |
|
||||
| | |
|
||||
| | **candidate** has an additional field ``amount_type``. Its value is always percent.|
|
||||
| | |
|
||||
| | **selected_values** is a list of candidates. |
|
||||
+-------------------------+------------------------------------------------------------------------------------+
|
||||
| ``global_taxes_amount`` | **content** is a float |
|
||||
+-------------------------+------------------------------------------------------------------------------------+
|
||||
| ``invoice_id`` | **content** is a string |
|
||||
+-------------------------+------------------------------------------------------------------------------------+
|
||||
| ``subtotal`` | **content** is a float |
|
||||
+-------------------------+------------------------------------------------------------------------------------+
|
||||
| ``total`` | **content** is a float |
|
||||
+-------------------------+------------------------------------------------------------------------------------+
|
||||
| ``supplier`` | **content** is a string |
|
||||
+-------------------------+------------------------------------------------------------------------------------+
|
||||
|
||||
``feature_result`` for the ``invoice_lines`` feature
|
||||
''''''''''''''''''''''''''''''''''''''''''''''''''''
|
||||
|
||||
It follows a more specific structure. It is basically a list of dictionaries where each dictionary represents an invoice line. Each value follows
|
||||
a :ref:`webservices/extract_api/invoice_get_results/feature_result` structure.
|
||||
|
||||
.. container:: doc-aside
|
||||
|
||||
.. switcher::
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
[
|
||||
{
|
||||
"description": feature_result,
|
||||
"discount": feature_result,
|
||||
"product": feature_result,
|
||||
"quantity": feature_result,
|
||||
"subtotal": feature_result,
|
||||
"total": feature_result,
|
||||
"taxes": feature_result,
|
||||
"total": feature_result,
|
||||
"unit": feature_result,
|
||||
"unit_price": feature_result
|
||||
},
|
||||
...
|
||||
]
|
||||
|
||||
.. _webservices/extract_api/invoice_validate:
|
||||
|
||||
``/iap/invoice_extract/validate``
|
||||
'''''''''''''''''''''''''''''''''
|
||||
|
||||
Description
|
||||
^^^^^^^^^^^
|
||||
Route that validates the different features of an invoice. The validation step is an optional step but is strongly recommended. By telling the system if it were right or wrong for each
|
||||
feature you give an important feedback. It has no direct impact but it helps the system to greatly improve its prediction accuracy for the invoices you will send in the future.
|
||||
|
||||
Request Body
|
||||
^^^^^^^^^^^^
|
||||
|
||||
``jsonrpc`` (required)
|
||||
|SAME_AS_PARSE|
|
||||
``method`` (required)
|
||||
|SAME_AS_PARSE|
|
||||
``params``
|
||||
``documents_id`` (required)
|
||||
Id of the document for which you want to validate the result.
|
||||
``values``
|
||||
Contains the validation for each feature. The field ``merged_line`` indicates if the ``invoice_lines`` have been merged or not.
|
||||
|
||||
.. note:: You don't have to validate all the features in order for the validation to succeed. However :ref:`/validate <webservices/extract_api/invoice_validate>` can't be called multiple times for a same invoice.
|
||||
Therefore you should validate all the features you want to validate at once.
|
||||
|
||||
.. rst-class:: setup doc-aside
|
||||
|
||||
.. switcher::
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"jsonrpc": string,
|
||||
"method": string,
|
||||
"params": {
|
||||
"document_id": int,
|
||||
"values": {
|
||||
"merged_lines": bool
|
||||
"feature_name_1": validation_1,
|
||||
"feature_name_2": validation_2,
|
||||
...
|
||||
}
|
||||
},
|
||||
"id": string (hex),
|
||||
}
|
||||
|
||||
``validation``
|
||||
''''''''''''''
|
||||
|
||||
A **validation** for a given feature is a dictionary containing the textual representation of the expected value for this given feature.
|
||||
This format apply for all the features except for ``global_taxes`` and ``invoice_lines`` which have more complex validation format.
|
||||
|
||||
.. rst-class:: setup doc-aside
|
||||
|
||||
.. switcher::
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{ "content": string|float }
|
||||
|
||||
validation for ``global_taxes``
|
||||
'''''''''''''''''''''''''''''''
|
||||
|
||||
**content** is a list of dictionaries. Each dictionary represents a tax:
|
||||
|
||||
``amount``
|
||||
Amount on which the tax is applied.
|
||||
``tax_amount``
|
||||
Amount of the tax.
|
||||
``tax_amount_type``
|
||||
Indicates if the ``tax_amount`` is a percentage or a fixed value. The type must be specified using the literal string "fixed" or "percent".
|
||||
``tax_price_include``
|
||||
Indicates if ``amount`` already contains the tax or not.
|
||||
|
||||
.. rst-class:: setup doc-aside
|
||||
|
||||
.. switcher::
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{"content": [
|
||||
{
|
||||
"amount": float,
|
||||
"tax_amount": float,
|
||||
"tax_amount_type": "fixed"|"percent",
|
||||
"tax_price_include": bool
|
||||
},
|
||||
...
|
||||
]}
|
||||
|
||||
validation for ``invoice_lines``
|
||||
''''''''''''''''''''''''''''''''
|
||||
|
||||
**lines** is a list of dictionaries. Each dictionary represents an invoice line. The dictionary keys speak for themselves.
|
||||
|
||||
.. rst-class:: setup doc-aside
|
||||
|
||||
.. switcher::
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{"lines": [
|
||||
{
|
||||
"description": string,
|
||||
"quantity": float,
|
||||
"unit_price": float,
|
||||
"product": string,
|
||||
"taxes_amount": float,
|
||||
"taxes": [
|
||||
{
|
||||
"amount": float,
|
||||
"type": "fixed"|"percent",
|
||||
"price_include": bool
|
||||
},
|
||||
...
|
||||
],
|
||||
"subtotal": float,
|
||||
"total": float
|
||||
},
|
||||
...
|
||||
]}
|
||||
|
||||
Response
|
||||
--------
|
||||
|
||||
``jsonrpc``
|
||||
|SAME_AS_PARSE|
|
||||
``id``
|
||||
|SAME_AS_PARSE|
|
||||
``result``
|
||||
``status_code``
|
||||
|STATUS_CODE|
|
||||
``status_msg``
|
||||
|STATUS_MSG|
|
||||
|
||||
============= ==========================================================
|
||||
status_code status_msg
|
||||
============= ==========================================================
|
||||
0 Success
|
||||
12 Validation format is incorrect
|
||||
============= ==========================================================
|
||||
|
||||
.. rst-class:: setup doc-aside
|
||||
|
||||
.. switcher::
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
{
|
||||
"jsonrpc": string,
|
||||
"id": string,
|
||||
"result": {
|
||||
"status_code": int,
|
||||
"status_msg": string,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.. _webservices/extract_api/integration_testing:
|
||||
|
||||
Integration Testing
|
||||
===================
|
||||
|
||||
You can test your integration by using *integration_token* as ``account_token`` in the :ref:`/parse <webservices/extract_api/invoice_parse>` request.
|
||||
|
||||
Using this token put you in test mode and allows you to simulate the entire flow without really parsing a document and without being billed one credit for each successful invoice parsing.
|
||||
|
||||
The only technical differences in test mode is that the document you send is not parsed by the system and that the response you get from :ref:`/get_results <webservices/extract_api/invoice_get_results>`
|
||||
is a hard-coded one.
|
||||
|
||||
A python implementation of the full flow can be found :download:`here <extract_api/implementation.py>`.
|
||||
|
||||
.. _JSON-RPC2: https://www.jsonrpc.org/specification
|
||||
|
||||
.. |SAME_AS_PARSE| replace:: Same as for :ref:`/parse <webservices/extract_api/invoice_parse>`.
|
||||
|
||||
.. |STATUS_CODE| replace:: The code indicating the status of the request. ``status_code`` is 0 in case of success. Other ``status_code`` are detailed in the table below.
|
||||
|
||||
.. |STATUS_MSG| replace:: A string giving verbose details about the request status.
|
||||
100
content/developer/misc/api/extract_api/implementation.py
Normal file
@@ -0,0 +1,100 @@
|
||||
import base64
|
||||
import time
|
||||
import sys
|
||||
import json
|
||||
import requests
|
||||
|
||||
account_token = "integration_token" # Use your token
|
||||
domain_name = "https://iap-extract.odoo.com"
|
||||
path_to_pdf = "/path/to/invoice_file"
|
||||
|
||||
API_VERSION = 120 # Do not change
|
||||
SUCCESS = 0
|
||||
NOT_READY = 1
|
||||
|
||||
def jsonrpc(path, params):
|
||||
payload = {
|
||||
'jsonrpc': '2.0',
|
||||
'method': 'call',
|
||||
'params': params,
|
||||
'id': 0,
|
||||
}
|
||||
req = requests.post(domain_name+path, json=payload, timeout=10)
|
||||
req.raise_for_status()
|
||||
resp = req.json()
|
||||
return resp
|
||||
|
||||
|
||||
with open(path_to_pdf, "rb") as file:
|
||||
params = {
|
||||
'account_token': account_token,
|
||||
'version': API_VERSION,
|
||||
'documents': [base64.b64encode(file.read()).decode('ascii')],
|
||||
}
|
||||
|
||||
response = jsonrpc("/iap/invoice_extract/parse", params)
|
||||
print("/parse call status: ", response['result']['status_msg'])
|
||||
|
||||
if response['result']['status_code'] != SUCCESS:
|
||||
sys.exit(1)
|
||||
|
||||
# You received an id that you can use to poll the server to get the result of the ocr when it will be ready
|
||||
document_id = response['result']['document_id']
|
||||
params = {
|
||||
'version': API_VERSION,
|
||||
'document_ids': [document_id], # you can request the results of multiple documents at once if wanted
|
||||
}
|
||||
|
||||
response = jsonrpc("/iap/invoice_extract/get_results", params)
|
||||
document_id = str(document_id) # /get_results expects a string despite the fact that the returned document_id is a int
|
||||
|
||||
while response['result'][document_id]['status_code'] == NOT_READY: # 1 is the status code indicating that the server is still processing the document
|
||||
print("Still processing... Retrying in 5 seconds")
|
||||
time.sleep(5)
|
||||
response = jsonrpc("/iap/invoice_extract/get_results", params)
|
||||
|
||||
with open('results.txt', 'w') as outfile:
|
||||
json.dump(response, outfile, indent=2)
|
||||
print("\nResult saved in results.txt")
|
||||
|
||||
if response['result'][document_id]['status_code'] != SUCCESS:
|
||||
print(response['result'][document_id]['status_msg']) # if it isn't a success, print the error message
|
||||
sys.exit(1)
|
||||
|
||||
document_results = response['result'][document_id]['results'][0]
|
||||
print("\nTotal:", document_results['total']['selected_value']['content'])
|
||||
print("Subtotal:", document_results['subtotal']['selected_value']['content'])
|
||||
print("Invoice id:", document_results['invoice_id']['selected_value']['content'])
|
||||
print("Date:", document_results['date']['selected_value']['content'])
|
||||
print("...\n")
|
||||
|
||||
params = {
|
||||
'document_id': document_id,
|
||||
'values': {
|
||||
'total': {'content': 100.0},
|
||||
'subtotal': {'content': 100.0},
|
||||
'global_taxes': {'content': []},
|
||||
'global_taxes_amount': {'content': 0.0},
|
||||
'date': {'content': '2020-09-25'},
|
||||
'due_date': {'content': '2020-09-25'},
|
||||
'invoice_id': {'content': document_results['invoice_id']['selected_value']['content']},
|
||||
'partner': {'content': 'twinnta'},
|
||||
'VAT_Number': {'content': 'BE23252248420'},
|
||||
'currency': {'content': 'USD'},
|
||||
'merged_lines': False,
|
||||
'invoice_lines': {'lines': [{'description': 'Total TVA ',
|
||||
'quantity': 1.0,
|
||||
'unit_price': 100.0,
|
||||
'product': False,
|
||||
'taxes_amount': 0.0,
|
||||
'taxes': [],
|
||||
'subtotal': 100.0,
|
||||
'total': 100.0}]
|
||||
}
|
||||
}
|
||||
}
|
||||
response = jsonrpc("/iap/invoice_extract/validate", params)
|
||||
if response['result']['status_code'] == SUCCESS:
|
||||
print("/validate call status: Success")
|
||||
else:
|
||||
print("/validate call status: wrong format")
|
||||
@@ -1,12 +1,12 @@
|
||||
:nosearch:
|
||||
:types: reference
|
||||
|
||||
================
|
||||
Reference Guides
|
||||
================
|
||||
=========
|
||||
Reference
|
||||
=========
|
||||
|
||||
.. toctree::
|
||||
:titlesonly:
|
||||
|
||||
reference/addons
|
||||
reference/javascript
|
||||
reference/backend
|
||||
reference/frontend
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
:nosearch:
|
||||
|
||||
=============
|
||||
Server Addons
|
||||
=============
|
||||
|
||||
.. toctree::
|
||||
:titlesonly:
|
||||
|
||||
addons/orm
|
||||
addons/data
|
||||
addons/actions
|
||||
addons/views
|
||||
addons/module
|
||||
addons/reports
|
||||
addons/security
|
||||
addons/testing
|
||||
addons/http
|
||||
addons/mixins
|
||||
19
content/developer/reference/backend.rst
Normal file
@@ -0,0 +1,19 @@
|
||||
:nosearch:
|
||||
|
||||
=======
|
||||
Backend
|
||||
=======
|
||||
|
||||
.. toctree::
|
||||
:titlesonly:
|
||||
|
||||
backend/orm
|
||||
backend/data
|
||||
backend/actions
|
||||
backend/views
|
||||
backend/module
|
||||
backend/reports
|
||||
backend/security
|
||||
backend/testing
|
||||
backend/http
|
||||
backend/mixins
|
||||
|
Before Width: | Height: | Size: 108 KiB After Width: | Height: | Size: 108 KiB |
@@ -118,11 +118,10 @@ Available manifest fields are:
|
||||
Whether the module should be considered as a fully-fledged application
|
||||
(``True``) or is just a technical module (``False``) that provides some
|
||||
extra functionality to an existing application module.
|
||||
``css`` (``list(str)``)
|
||||
Specify css files with custom rules to be imported, these files should be
|
||||
located in ``static/src/css`` inside the module.
|
||||
``images`` (``list(str)``)
|
||||
Specify image files to be used by the module.
|
||||
``assets`` (``dict``)
|
||||
A definition of how all static files are loaded in various assets bundles.
|
||||
See the :ref:`assets <reference/assets>` page for more details on how to
|
||||
describe bundles.
|
||||
``installable`` (``bool`` default: ``True``)
|
||||
Whether a user should be able to install the module from the Web UI or not.
|
||||
``maintainer`` (``str``)
|
||||
@@ -120,13 +120,15 @@ Subclasses of :class:`odoo.tests.common.BaseCase` (usually through
|
||||
:class:`~odoo.tests.common.TransactionCase`,
|
||||
:class:`~odoo.tests.common.SavepointCase` or
|
||||
:class:`~odoo.tests.common.HttpCase`) are automatically tagged with
|
||||
``standard``, ``at_install`` and their source module's name by default.
|
||||
``standard`` and ``at_install`` by default.
|
||||
|
||||
Invocation
|
||||
^^^^^^^^^^
|
||||
|
||||
:option:`--test-tags <odoo-bin --test-tags>` can be used to select/filter tests
|
||||
to run on the command-line.
|
||||
to run on the command-line. It implies :option:`--test-enable <odoo-bin --test-enable>`,
|
||||
so it's not necessary to specify :option:`--test-enable <odoo-bin --test-enable>`
|
||||
when using :option:`--test-tags <odoo-bin --test-tags>`.
|
||||
|
||||
This option defaults to ``+standard`` meaning tests tagged ``standard``
|
||||
(explicitly or implicitly) will be run by default when starting Odoo
|
||||
@@ -157,7 +159,7 @@ have to be selected explicitly:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ odoo-bin --test-enable --test-tags nice
|
||||
$ odoo-bin --test-tags nice
|
||||
|
||||
Note that only the tests tagged ``nice`` are going to be executed. To run
|
||||
*both* ``nice`` and ``standard`` tests, provide multiple values to
|
||||
@@ -166,10 +168,10 @@ are *additive* (you're selecting all tests with *any* of the specified tags)
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ odoo-bin --test-enable --test-tags nice,standard
|
||||
$ odoo-bin --test-tags nice,standard
|
||||
|
||||
The config switch parameter also accepts the ``+`` and ``-`` prefixes. The
|
||||
``+`` prefix is implied and therefore, totaly optional. The ``-`` (minus)
|
||||
``+`` prefix is implied and therefore, totally optional. The ``-`` (minus)
|
||||
prefix is made to deselect tests tagged with the prefixed tags, even if they
|
||||
are selected by other specified tags e.g. if there are ``standard`` tests which
|
||||
are also tagged as ``slow`` you can run all standard tests *except* the slow
|
||||
@@ -177,7 +179,7 @@ ones:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ odoo-bin --test-enable --test-tags 'standard,-slow'
|
||||
$ odoo-bin --test-tags 'standard,-slow'
|
||||
|
||||
When you write a test that does not inherit from the
|
||||
:class:`~odoo.tests.common.BaseCase`, this test will not have the default tags,
|
||||
@@ -194,6 +196,36 @@ they're not going to get run:
|
||||
class SmallTest(unittest.TestCase):
|
||||
...
|
||||
|
||||
Besides tags you can also specify specific modules, classes or functions to
|
||||
test. The full syntax of the format accepted by :option:`--test-tags <odoo-bin --test-tags>`
|
||||
is:
|
||||
|
||||
.. code-block::
|
||||
|
||||
[-][tag][/module][:class][.method]
|
||||
|
||||
So if you want to test the `stock_account` module, you can use:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ odoo-bin --test-tags /stock_account
|
||||
|
||||
If you want to test a specific function with a unique name, it can be specified
|
||||
directly:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ odoo-bin --test-tags .test_supplier_invoice_forwarded_by_internal_user_without_supplier
|
||||
|
||||
This is equivalent to
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ odoo-bin --test-tags /account:TestAccountIncomingSupplierInvoice.test_supplier_invoice_forwarded_by_internal_user_without_supplier
|
||||
|
||||
if the name of the test is unambiguous. Multiple modules, classes and functions
|
||||
can be specified at once separated by a `,` like with regular tags.
|
||||
|
||||
.. _reference/testing/tags:
|
||||
|
||||
Special tags
|
||||
@@ -213,43 +245,36 @@ Special tags
|
||||
Note that this is *not exclusive* with ``at_install``, however since you
|
||||
will generally not want both ``post_install`` is usually paired with
|
||||
``-at_install`` when tagging a test class.
|
||||
- *module_name*: Odoo tests classes extending
|
||||
:class:`~odoo.tests.common.BaseCase` are implicitly tagged with the
|
||||
technical name of their module. This allows easily selecting or excluding
|
||||
specific modules when testing e.g. if you want to only run tests from
|
||||
``stock_account``:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ odoo-bin --test-enable --test-tags stock_account
|
||||
|
||||
Examples
|
||||
^^^^^^^^
|
||||
|
||||
.. important::
|
||||
|
||||
Tests will be executed only in the installed or updated modules. So
|
||||
modules have to be selected with the :option:`-u <odoo-bin -u>` or
|
||||
:option:`-i <odoo-bin -i>` switches. For simplicity, those switches are
|
||||
Tests will be executed only in installed modules. If you're starting from
|
||||
a clean database, you'll need to install the modules with the
|
||||
:option:`-i <odoo-bin -i>` switch at least once. After that it's no longer
|
||||
needed, unless you need to upgrade the module, in which case
|
||||
:option:`-u <odoo-bin -u>` can be used. For simplicity, those switches are
|
||||
not specified in the examples below.
|
||||
|
||||
Run only the tests from the sale module:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ odoo-bin --test-enable --test-tags sale
|
||||
$ odoo-bin --test-tags /sale
|
||||
|
||||
Run the tests from the sale module but not the ones tagged as slow:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ odoo-bin --test-enable --test-tags 'sale,-slow'
|
||||
$ odoo-bin --test-tags '/sale,-slow'
|
||||
|
||||
Run only the tests from stock or tagged as slow:
|
||||
|
||||
.. code-block:: console
|
||||
|
||||
$ odoo-bin --test-enable --test-tags '-standard, slow, stock'
|
||||
$ odoo-bin --test-tags '-standard, slow, /stock'
|
||||
|
||||
.. note:: ``-standard`` is implicit (not required), and present for clarity
|
||||
|
||||
@@ -1925,54 +1925,56 @@ Map
|
||||
|
||||
<span class="badge" style="background-color:#AD5E99">Enterprise feature</span>
|
||||
|
||||
This view is able to display records on a map and the routes between them. The record are represented by pins. It also allows the visualization of fields from the model in a popup tied to the record's pin.
|
||||
This view is able to display records on a map and the routes between them. The records are represented by pins. It also allows the visualization of fields from the model in a popup tied to the record's pin.
|
||||
|
||||
.. note::
|
||||
|
||||
The model on which the view is applied should contains a res.partner many2one since the view relies on the res.partner's address and coordinates fields to localize the records.
|
||||
The model on which the view is applied should contain a `res.partner` many2one since the view relies on the `res.partner`'s address and coordinates fields to localize the records.
|
||||
|
||||
.. _reference/views/map/api:
|
||||
|
||||
Api
|
||||
API
|
||||
~~~
|
||||
|
||||
The view uses location data platforms' api to fetch the tiles (the map's background), do the geoforwarding (converting addresses to a set of coordinates) and fetch the routes.
|
||||
The view implements two api, the default one, openstreet map is able to fetch `tiles`_ and do `geoforwarding`_. This api does not require a token.
|
||||
As soon as a valid `MapBox`_ token is provided in the general settings the view switches to the Mapbox api. This api is faster and allows the computation of routes. The token are available by `signing up`_ to MapBox
|
||||
The view uses location data platforms' API to fetch the tiles (the map's background), do the geoforwarding (converting addresses to a set of coordinates) and fetch the routes.
|
||||
The view implements two API, OpenStreetMap and MapBox. OpenStreetMap is used by default and is able to fetch `tiles`_ and do `geoforwarding`_. This API does not require a token.
|
||||
As soon as a valid `MapBox`_ token is provided in the general settings the view switches to the MapBox API. This API is faster and allows the computation of routes. A token can be obtained by `signing up`_ to MapBox.
|
||||
|
||||
.. _reference/views/structural components:
|
||||
|
||||
Structural components
|
||||
~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
The view's root element is ``<map>`` multiple attributes are allowed
|
||||
The view's root element is ``<map>``. It can have the following attributes:
|
||||
|
||||
``res_partner``
|
||||
Contains the res.partner many2one. If not provided the view will resort to create an empty map.
|
||||
Contains the `res.partner` many2one. If not provided the view resorts to create an empty map.
|
||||
``default_order``
|
||||
If a field is provided the view will override the model's default order. The field must be part of the model on which the view is applied not from res.partner
|
||||
If a field is provided the view overrides the model's default order. The field must be part of the model on which the view is applied, not from `res.partner`.
|
||||
``routing``
|
||||
if ``true`` the routes between the records will be shown. The view still needs a valid MapBox token and at least two located records. (i.e the records has a res.partner many2one and the partner has a address or valid coordinates)
|
||||
if ``1`` display the routes between the records. The view needs a valid MapBox token and at least two located records (i.e the records have a `res.partner` many2one and the partner has an address or valid coordinates).
|
||||
``hide_name``
|
||||
if ``true`` hide a name from the marker's popup (default: false)
|
||||
if ``1`` hide the name from the pin's popup (default: ``0``).
|
||||
``hide_address``
|
||||
if ``true`` hide a address from the marker's popup (default: false)
|
||||
if ``1`` hide the address from the pin's popup (default: ``0``).
|
||||
``hide_title``
|
||||
if ``1`` hide the title from the pin list (default: ``0``).
|
||||
``panel_title``
|
||||
String to display as title of the pin list. If not provided, the title is the action's name or "Items" if the view is not in an action.
|
||||
``limit``
|
||||
Maximum number of records to fetch (default: 80). It must be a positive integer.
|
||||
|
||||
The ``<map>`` element can contain multiple ``<field>`` elements. Each ``<field>`` element will be interpreted as a line in the marker's popup. The field's attributes are the following:
|
||||
The ``<map>`` element can contain multiple ``<field>`` elements. Each ``<field>`` element is interpreted as a line in the pin's popup. The field's attributes are the following:
|
||||
|
||||
``name``
|
||||
The field to display.
|
||||
``string``
|
||||
This string will be displayed before the field's content. It Can be used as a description.
|
||||
``limit``
|
||||
The size of a page (default: 80). It must be a positive integer.
|
||||
|
||||
No attribute or element is mandatory but as stated above if no res.partner many2one is provided the view won't be able to locate records.
|
||||
String to display before the field's content. It can be used as a description.
|
||||
|
||||
For example here is a map:
|
||||
.. code-block:: xml
|
||||
|
||||
<map res_partner="partner_id" default_order="date_begin" routing="true" hide_name="true">
|
||||
<map res_partner="partner_id" default_order="date_begin" routing="1" hide_name="1">
|
||||
<field name="partner_id" string="Customer Name"/>
|
||||
</map>
|
||||
|
||||
22
content/developer/reference/frontend.rst
Normal file
@@ -0,0 +1,22 @@
|
||||
:nosearch:
|
||||
|
||||
========
|
||||
Frontend
|
||||
========
|
||||
|
||||
.. toctree::
|
||||
:titlesonly:
|
||||
|
||||
frontend/framework_overview
|
||||
frontend/assets
|
||||
frontend/javascript_modules
|
||||
frontend/owl_components
|
||||
frontend/registries
|
||||
frontend/services
|
||||
frontend/hooks
|
||||
frontend/fields
|
||||
frontend/patching_code
|
||||
frontend/javascript_cheatsheet
|
||||
frontend/javascript_reference
|
||||
frontend/mobile
|
||||
frontend/qweb
|
||||
366
content/developer/reference/frontend/assets.rst
Normal file
@@ -0,0 +1,366 @@
|
||||
|
||||
.. _reference/assets:
|
||||
|
||||
======
|
||||
Assets
|
||||
======
|
||||
|
||||
Managing assets in Odoo is not as straightforward as it is in some other apps.
|
||||
One of the reasons is that we have a variety of situations where some, but not all
|
||||
of the assets are required. For example, the needs of the web client, the point of
|
||||
sale app, the website or even the mobile application are different. Also, some
|
||||
assets may be large, but are seldom needed: in that case we may want them
|
||||
to be :ref:`loaded lazily (on demand) <frontend/assets/lazy_loading>`.
|
||||
|
||||
Asset types
|
||||
===========
|
||||
|
||||
There are three different asset types: code (`js` files), style (`css` or `scss`
|
||||
files) and templates (`xml` files).
|
||||
|
||||
Code
|
||||
Odoo supports :ref:`three different kinds of javascript files<frontend/js_modules>`.
|
||||
All these files are then processed (native JS modules are transformed into odoo
|
||||
modules), then minified (if not in `debug=assets` :ref:`mode <frontend/framework/assets_debug_mode>`)
|
||||
and concatenated. The result is then saved as a file attachment. These file
|
||||
attachments are usually loaded via a `<script>` tag in the `<head>` part of
|
||||
the page (as a static file).
|
||||
|
||||
Style
|
||||
Styling can be done with either `css` or `scss <https://sass-lang.com/>`_. Like
|
||||
the javascript files, these files are processed (`scss` files are converted into
|
||||
`css`), then minified (again, if not in `debug=assets` :ref:`mode <frontend/framework/assets_debug_mode>`)
|
||||
and concatenated. The result is then saved as a file attachment. They are
|
||||
then usually loaded via a `<link>` tag in the `<head>` part of the page (as
|
||||
a static file).
|
||||
|
||||
Template
|
||||
Templates (static `xml` files) are handled in a different way: they are simply
|
||||
read from the file system whenever they are needed, and concatenated.
|
||||
|
||||
Whenever the browser loads odoo, it calls the `/web/webclient/qweb/` controller
|
||||
to fetch the :ref:`templates <reference/qweb>`.
|
||||
|
||||
It is useful to know that in most cases, a browser only performs a request the
|
||||
first time it loads a page. This is because each of these assets are
|
||||
associated with a checksum, which is injected into the page source. The checksum
|
||||
is then added to the url, which means that it is possible to safely set the cache
|
||||
headers to a long period.
|
||||
|
||||
Bundles
|
||||
=======
|
||||
|
||||
Odoo assets are grouped by *bundles*. Each bundle (a *list of file paths*
|
||||
of specific types: `xml`, `js`, `css` or `scss`) is listed in the
|
||||
:ref:`module manifest <reference/module/manifest>`. Files can be declared using
|
||||
`glob <https://en.wikipedia.org/wiki/Glob_(programming)>`_ syntax, meaning that
|
||||
you can declare several asset files using a single line.
|
||||
|
||||
The bundles are defined in each module's :file:`__manifest__.py`,
|
||||
with a dedicated `assets` key which contains a dictionary. The dictionary maps
|
||||
bundle names (keys) to the list of files they contain (values). It looks
|
||||
like this:
|
||||
|
||||
.. code-block:: py
|
||||
|
||||
'assets': {
|
||||
'web.assets_backend': [
|
||||
'web/static/src/xml/**/*',
|
||||
],
|
||||
'web.assets_common': [
|
||||
'web/static/lib/bootstrap/**/*',
|
||||
'web/static/src/js/boot.js',
|
||||
'web/static/src/js/webclient.js',
|
||||
],
|
||||
'web.qunit_suite_tests': [
|
||||
'web/static/src/js/webclient_tests.js',
|
||||
],
|
||||
},
|
||||
|
||||
Here is a list of some important bundles that most odoo developers will need to
|
||||
know:
|
||||
|
||||
- `web.assets_common`: this bundle contains most assets which are common to the
|
||||
web client, the website and also the point of sale. This is supposed to contain
|
||||
lower level building blocks for the odoo framework. Note that it contains the
|
||||
:file:`boot.js` file, which defines the odoo module system.
|
||||
|
||||
- `web.assets_backend`: this bundle contains the code specific to the web client
|
||||
(notably the web client/action manager/views)
|
||||
|
||||
- `web.assets_frontend`: this bundle is about all that is specific to the public
|
||||
website: ecommerce, portal, forum, blog, ...
|
||||
|
||||
- `web.assets_qweb`: all static XML templates used in the backend environment
|
||||
and in the point of sale.
|
||||
|
||||
- `web.qunit_suite_tests`: all javascript qunit testing code (tests, helpers, mocks)
|
||||
|
||||
- `web.qunit_mobile_suite_tests`: mobile specific qunit testing code
|
||||
|
||||
|
||||
Operations
|
||||
----------
|
||||
|
||||
Typically, handling assets is simple: you just need to add some new files
|
||||
to a frequently used bundle like `assets_common` or `assets_backend`. But there are other operations
|
||||
available to cover some more specific use cases.
|
||||
|
||||
Note that all directives targeting a certain asset file (i.e. `before`, `after`,
|
||||
`replace` and `remove`) need that file to be declared beforehand, either
|
||||
in manifests higher up in the hierarchy or in ``ir.asset`` records with a lower
|
||||
sequence.
|
||||
|
||||
`append`
|
||||
~~~~~~~~
|
||||
|
||||
This operation adds one or multiple file(s). Since it is the most common
|
||||
operation, it can be done by simply using the file name:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
'web.assets_common': [
|
||||
'my_addon/static/src/js/**/*',
|
||||
],
|
||||
|
||||
By default, adding a simple string to a bundle will append the files matching the
|
||||
glob pattern at the end of the bundle. Obviously, the pattern may also be directly
|
||||
a single file path.
|
||||
|
||||
`prepend`
|
||||
~~~~~~~~~
|
||||
|
||||
Add one or multiple file(s) at the beginning of the bundle.
|
||||
|
||||
Useful when you need to put a certain file before the others in a bundle (for
|
||||
example with css files). The `prepend` operation is invoked with the following
|
||||
syntax: `('prepend', <path>)`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
'web.assets_common': [
|
||||
('prepend', 'my_addon/static/src/css/bootstrap_overridden.scss'),
|
||||
],
|
||||
|
||||
`before`
|
||||
~~~~~~~~
|
||||
|
||||
Add one or multiple file(s) before a specific file.
|
||||
|
||||
Prepending a file at the beginning of a bundle might not be precise enough. The
|
||||
`before` directive can be used to add the given file(s) right *before* the target
|
||||
file. It is declared by replacing the normal path with a 3-element tuple
|
||||
`('before', <target>, <path>)`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
'web.assets_common': [
|
||||
('before', 'web/static/src/css/bootstrap_overridden.scss', 'my_addon/static/src/css/bootstrap_overridden.scss'),
|
||||
],
|
||||
|
||||
`after`
|
||||
~~~~~~~
|
||||
|
||||
Add one or multiple file(s) after a specific file.
|
||||
|
||||
Same as `before`, with the matching file(s) appended right *after* the target file.
|
||||
It is declared by replacing the normal path with a 3-element tuple
|
||||
`('after', <target>, <path>)`.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
'web.assets_common': [
|
||||
('after', 'web/static/src/css/list_view.scss', 'my_addon/static/src/css/list_view.scss'),
|
||||
],
|
||||
|
||||
`include`
|
||||
~~~~~~~~~
|
||||
|
||||
Use nested bundles.
|
||||
|
||||
The `include` directive is a way to use a bundle in other bundles to minimize
|
||||
the size of your manifest. In Odoo we use sub bundles (prefixed with an underscore
|
||||
by convention) to batch files used in multiple other bundles. You can then
|
||||
specify the sub bundle as a pair `('include', <bundle>)` like this:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
'web.assets_common': [
|
||||
('include', 'web._primary_variables'),
|
||||
],
|
||||
|
||||
`remove`
|
||||
~~~~~~~~
|
||||
|
||||
Remove one or multiple file(s).
|
||||
|
||||
In some cases, you may want to remove one or multiple files from a bundle. This
|
||||
can be done using the `remove` directive by specifying a pair
|
||||
`('remove', <target>)`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
'web.assets_common': [
|
||||
('remove', 'web/static/src/js/boot.js'),
|
||||
],
|
||||
|
||||
`replace`
|
||||
~~~~~~~~~
|
||||
|
||||
Replace an asset file with one or multiple file(s).
|
||||
|
||||
Let us say that an asset needs not only to be removed, but you also want to insert
|
||||
your new version of that asset at the same exact position. This can be done with
|
||||
the `replace` directive, using a 3-element tuple `('replace', <target>, <path>)`:
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
'web.assets_common': [
|
||||
('replace', 'web/static/src/js/boot.js', 'my_addon/static/src/js/boot.js'),
|
||||
],
|
||||
|
||||
|
||||
Loading order
|
||||
-------------
|
||||
|
||||
The order in which assets are loaded is sometimes critical and must be deterministic,
|
||||
mostly for stylesheets priorities and setup scripts. Assets in Odoo are processed
|
||||
as follows:
|
||||
|
||||
#. When an asset bundle is called (e.g. `t-call-assets="web.assets_common"`), an empty
|
||||
list of assets is generated
|
||||
|
||||
#. All records of type `ir.asset` matching the bundle are fetched and sorted
|
||||
by sequence number. Then all records with a sequence strictly less than 16 are
|
||||
processed and applied to the current list of assets.
|
||||
|
||||
#. All modules declaring assets for said bundle in their manifest apply their
|
||||
assets operations to this list. This is done following the order of modules dependencies
|
||||
(e.g. `web` assets is processed before `website`). If a directive tries to add
|
||||
a file already present in the list, nothing is done for that file. In other word,
|
||||
only the first occurrence of a file is kept in the list.
|
||||
|
||||
#. The remaining `ir.asset` records (those with a sequence greater than or equal
|
||||
to 16) are then processed and applied as well.
|
||||
|
||||
Assets declared in the manifest may need to be loaded in a particular order, for
|
||||
example :file:`jquery.js` must be loaded before all other jquery scripts when loading the
|
||||
lib folder. One solution would be to create an :ref:`ir.asset <frontend/assets/ir_asset>`
|
||||
record with a lower sequence or a 'prepend' directive, but there is another simpler
|
||||
way to do so.
|
||||
|
||||
Since the unicity of each file path in the list of assets is guaranteed, you can
|
||||
mention any specific file before a glob that includes it. That file will thus appear
|
||||
in the list before all the others included in the glob.
|
||||
|
||||
.. code-block:: python
|
||||
|
||||
'web.assets_common': [
|
||||
'my_addon/static/lib/jquery/jquery.js',
|
||||
'my_addon/static/lib/jquery/**/*',
|
||||
],
|
||||
|
||||
.. note::
|
||||
|
||||
A module *b* removing/replacing the assets declared in a module *a* will have
|
||||
to depend on it. Trying to operate on assets that have yet to be declared will
|
||||
result in an error.
|
||||
|
||||
.. _frontend/assets/lazy_loading:
|
||||
|
||||
Lazy loading
|
||||
============
|
||||
|
||||
It is sometimes useful to load files and/or asset bundles dynamically, for
|
||||
example to only load a library once it is needed. To do that, the Odoo framework
|
||||
provides a few helper functions, located in :file:`@web/core/assets`.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
await loadAssets({
|
||||
jsLibs: ["/web/static/lib/stacktracejs/stacktrace.js"],
|
||||
});
|
||||
|
||||
|
||||
.. js:function:: loadAssets(assets)
|
||||
|
||||
:param Object assets: a description of various assets that should be loaded
|
||||
:returns: Promise<void>
|
||||
|
||||
Load the assets described py the `assets` parameter. It is an object that
|
||||
may contain the following keys:
|
||||
|
||||
.. list-table::
|
||||
:widths: 20 20 60
|
||||
:header-rows: 1
|
||||
|
||||
* - Key
|
||||
- Type
|
||||
- Description
|
||||
* - `jsLibs`
|
||||
- `string[]`
|
||||
- a list of urls of javascript files
|
||||
* - `cssLibs`
|
||||
- `string[]`
|
||||
- a list of urls of css files
|
||||
|
||||
|
||||
.. js:function:: useAssets(assets)
|
||||
|
||||
:param Object assets: a description of various assets that should be loaded
|
||||
|
||||
This hook is useful when components need to load some assets in their
|
||||
`onWillStart` method. It internally calls `loadAssets`.
|
||||
|
||||
.. _frontend/assets/ir_asset:
|
||||
|
||||
The asset model (`ir.asset`)
|
||||
============================
|
||||
|
||||
In most cases the assets declared in the manifest will largely suffice. Yet for
|
||||
more flexibility, the framework also supports dynamic assets declared in the
|
||||
database.
|
||||
|
||||
This is done by creating `ir.asset` records. Those will be processed as if they
|
||||
were found in a module manifest, and they give the same expressive power as their
|
||||
manifest counterparts.
|
||||
|
||||
.. autoclass:: odoo.addons.base.models.ir_asset.IrAsset
|
||||
|
||||
`name`
|
||||
Name of the asset record (for identification purpose).
|
||||
|
||||
`bundle`
|
||||
Bundle in which the asset will be applied.
|
||||
|
||||
`directive` (default= `append`)
|
||||
This field determines how the `path` (and `target` if needed) will be interpreted.
|
||||
Here is the list of available directives along with their required arguments:
|
||||
|
||||
- **append**: `path`
|
||||
- **prepend**: `path`
|
||||
- **before**: `target`, `path`
|
||||
- **after**: `target`, `path`
|
||||
- **include**: `path` (interpreted as a **bundle name**)
|
||||
- **remove**: `path` (interpreted as a **target asset** to remove)
|
||||
- **replace**: `target`, `path`
|
||||
|
||||
`path`
|
||||
A string defining one of the following:
|
||||
|
||||
- a **relative path** to an asset file in the addons file system;
|
||||
- a **glob pattern** to a set of asset files in the addons file system;
|
||||
- a **URL** to an attachment or external asset file;
|
||||
- a **bundle name**, when using the `include` directive.
|
||||
|
||||
`target`
|
||||
Target file to specify a position in the bundle. Can only be used with the
|
||||
directives `replace`, `before` and `after`.
|
||||
|
||||
`active` (default= `True`)
|
||||
Whether the record is active
|
||||
|
||||
`sequence` (default= `16`)
|
||||
Loading order of the asset records (ascending). A sequence lower than 16 means
|
||||
that the asset will be processed *before* the ones declared in the manifest.
|
||||
|
||||
161
content/developer/reference/frontend/fields.rst
Normal file
@@ -0,0 +1,161 @@
|
||||
|
||||
======
|
||||
Fields
|
||||
======
|
||||
|
||||
In Odoo, the word *field* is mostly used to denote a part of a model, usually
|
||||
represented by a column in a database. Fields are represented by components in
|
||||
the user interface (mostly in the form and list view). In this page, we document
|
||||
how these field components work and how to use them.
|
||||
|
||||
How to define a field
|
||||
=====================
|
||||
|
||||
TODO
|
||||
|
||||
How to use a field
|
||||
==================
|
||||
|
||||
TODO
|
||||
|
||||
Reference List
|
||||
==============
|
||||
|
||||
.. list-table::
|
||||
:widths: 15 20 20 45
|
||||
:header-rows: 1
|
||||
|
||||
* - Name
|
||||
- Technical name
|
||||
- Type
|
||||
- Short Description
|
||||
* - :ref:`EmailField <frontend/fields/email_field>`
|
||||
- `text`
|
||||
- `char`
|
||||
- display email addresses
|
||||
* - :ref:`FieldText <frontend/fields/field_text>`
|
||||
- `text`
|
||||
- `char`
|
||||
- display text values
|
||||
* - :ref:`PercentageField <frontend/fields/percentage_field>`
|
||||
- `text`
|
||||
- `char`
|
||||
- display percentages
|
||||
* - :ref:`PhoneField <frontend/fields/phone_field>`
|
||||
- `text`
|
||||
- `char`, `number`
|
||||
- display phone numbers
|
||||
* - :ref:`UrlField <frontend/fields/url_field>`
|
||||
- `text`
|
||||
- `char`
|
||||
- display URLs
|
||||
* - :ref:`OtherField <frontend/fields/other_field>`
|
||||
- `other_name`
|
||||
- `text`, `many2one`
|
||||
- represents some values
|
||||
|
||||
.. _frontend/fields/email_field:
|
||||
|
||||
EmailField
|
||||
----------
|
||||
|
||||
- Location: `@web/fields/email_field`
|
||||
- Technical name: `email`
|
||||
- Supported types: `char`
|
||||
|
||||
The `EmailField` component represents a textual value containing an email address. The field
|
||||
is an input with the `email` type in edit mode, and a link with an `href` in readonly mode with
|
||||
the `mailto:` prefix. It allows the user to handle the click to open an email application if available.
|
||||
|
||||
.. _frontend/fields/field_text:
|
||||
|
||||
FieldText
|
||||
---------
|
||||
|
||||
- Location: `@web/fields/text_field`
|
||||
- Technical name: `text`
|
||||
- Supported types: `char`
|
||||
|
||||
The `FieldText` component represents a textual value. It is the default field
|
||||
for all fields of type `char`.
|
||||
|
||||
.. _frontend/fields/percentage_field:
|
||||
|
||||
PercentageField
|
||||
---------------
|
||||
|
||||
- Location: `@web/fields/percentage_field`
|
||||
- Technical name: `percentage`
|
||||
- Supported types: `number`
|
||||
|
||||
The `PercentageField` component represents a percentage. To use the field, you must give a
|
||||
float value between 0 and 1. Then, the field will format the value to an understandable value
|
||||
in percent (e.g. `0.567` would be converted to `56.7%`). When the user enters the edit mode,
|
||||
the value is still visible as a percentage, but the value that is saved is always a float value.
|
||||
|
||||
.. _frontend/fields/phone_field:
|
||||
|
||||
PhoneField
|
||||
----------
|
||||
|
||||
- Location: `@web/fields/phone_field`
|
||||
- Technical name: `phone`
|
||||
- Supported types: `char`, `number`
|
||||
|
||||
The `PhoneField` component represents a textual value containing a phone number. The field
|
||||
is an input with the `phone` type in edit mode, and a link with an `href` in readonly mode with
|
||||
the `tel:` prefix. It allows the user to handle the click to start a call to the number.
|
||||
|
||||
.. _frontend/fields/url_field:
|
||||
|
||||
UrlField
|
||||
--------
|
||||
|
||||
- Location: `@web/fields/url_field`
|
||||
- Technical name: `url`
|
||||
- Supported types: `char`
|
||||
|
||||
The `UrlField` component represents a textual value containing a URL. The field
|
||||
is a text input in edit mode, and a link with an `href` to the given value.
|
||||
|
||||
It supports the following options:
|
||||
|
||||
.. list-table::
|
||||
:widths: 20 20 60
|
||||
:header-rows: 1
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Description
|
||||
* - `website_path`
|
||||
- `boolean`
|
||||
- optional. if `true`, the href will be the exact given value. No prefix will be added to format the URL
|
||||
|
||||
.. _frontend/fields/other_field:
|
||||
|
||||
Other Field
|
||||
-----------
|
||||
|
||||
- Location: `@web/fields/other_field`
|
||||
- Technical name: `blabla`
|
||||
- Supported types: `char`, `many2one`
|
||||
|
||||
The `OtherField` component represents ...
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<field name="my_field" widget="blabla" options="{'horizontal':true}"/>
|
||||
|
||||
It supports the following options:
|
||||
|
||||
|
||||
.. list-table::
|
||||
:widths: 20 20 60
|
||||
:header-rows: 1
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Description
|
||||
* - `horizontal`
|
||||
- `boolean`
|
||||
- optional. if `true`, radio buttons will be displayed horizontally (default=`false`)
|
||||
649
content/developer/reference/frontend/framework_overview.rst
Normal file
@@ -0,0 +1,649 @@
|
||||
==================
|
||||
Framework Overview
|
||||
==================
|
||||
|
||||
Introduction
|
||||
============
|
||||
|
||||
The Odoo Javascript framework is a set of features/building blocks provided by
|
||||
the ``web/`` addon to help build odoo applications running in the browser. At
|
||||
the same time, the Odoo Javascript framework is a single page application,
|
||||
usually known as the *web client* (available at the url ``/web``).
|
||||
|
||||
The web client started as an application made with a custom class and widget
|
||||
system, but it is now transitioning to using native javascript classes instead,
|
||||
and Owl as a component system. This explains why both systems are currently in
|
||||
use in the codebase.
|
||||
|
||||
From a high-level perspective, the web client is a single-page application: it
|
||||
does not need to request a full page from the server each time the user performs
|
||||
an action. Instead, it only requests what it needs and then replaces/updates the
|
||||
current screen accordingly. Also, it manages the url to keep it in sync with
|
||||
the current state.
|
||||
|
||||
The javascript framework (all or some parts) is also used in other situations,
|
||||
such as the Odoo website or the point of sale. This reference is mostly focused
|
||||
on the web client.
|
||||
|
||||
.. note::
|
||||
|
||||
It is common in the Odoo ecosystem to see the words *frontend* and *backend*
|
||||
as synonyms for the odoo website (public) and the web client, respectively.
|
||||
This terminology is not to be confused with the more common use of
|
||||
browser-code (frontend) and server (backend).
|
||||
|
||||
.. note::
|
||||
|
||||
In this documentation, the word *component* always refers to new Owl
|
||||
components, and *widget* refers to old Odoo widgets.
|
||||
|
||||
.. note::
|
||||
|
||||
All new development should be done in Owl, if possible!
|
||||
|
||||
Code structure
|
||||
==============
|
||||
|
||||
The ``web/static/src`` folder contains all the ``web/`` javascript (and css and
|
||||
templates) codebase. Here is a list of the most important folders:
|
||||
|
||||
- ``core/`` most of the low level features
|
||||
- ``fields/`` all field components
|
||||
- ``views/`` all javascript views components (``form``, ``list``, ...)
|
||||
- ``search/`` control panel, search bar, search panel, ...
|
||||
- ``webclient/`` the web client specific code: navbar, user menu, action service, ...
|
||||
|
||||
The ``web/static/src`` is the root folder. Everything inside can simply be
|
||||
imported by using the ``@web`` prefix. For example, here is how one can import
|
||||
the ``memoize`` function located in ``web/static/src/core/utils/functions``:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
import { memoize } from "@web/core/utils/functions";
|
||||
|
||||
WebClient Architecture
|
||||
======================
|
||||
|
||||
As mentioned above, the web client is an owl application. Here is a slightly
|
||||
simplified version of its template:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<t t-name="web.WebClient" owl="1">
|
||||
<body class="o_web_client">
|
||||
<NavBar/>
|
||||
<ActionContainer/>
|
||||
<MainComponentsContainer/>
|
||||
</body>
|
||||
</t>
|
||||
|
||||
As we can see, it basically is a wrapper for a navbar, the current action and
|
||||
some additional components. The ``ActionContainer`` is a higher order component
|
||||
that will display the current action controller (so, a client action, or a
|
||||
specific view in the case of actions of type ``act_window``). Managing actions
|
||||
is a huge part of its work: the action service keeps in memory a stack of
|
||||
all active actions (represented in the breadcrumbs), and coordinates each
|
||||
change.
|
||||
|
||||
Another interesting thing to note is the ``MainComponentsContainer``: it is
|
||||
simply a component that displays all components registered in the
|
||||
``main_components`` registry. This is how other parts of the system can extend
|
||||
the web client.
|
||||
|
||||
.. _frontend/framework/environment:
|
||||
|
||||
Environment
|
||||
===========
|
||||
|
||||
As an Owl application, the Odoo web client defines its own environment (components
|
||||
can access it using ``this.env``). Here is a description of what Odoo adds to
|
||||
the shared ``env`` object:
|
||||
|
||||
.. list-table::
|
||||
:widths: 25 75
|
||||
:header-rows: 1
|
||||
|
||||
* - Key
|
||||
- Value
|
||||
* - `qweb`
|
||||
- required by Owl (contains all templates)
|
||||
* - `bus`
|
||||
- :ref:`main bus <frontend/framework/bus>`, used to coordinate some generic events
|
||||
* - `services`
|
||||
- all deployed :ref:`services <frontend/services>` (should usually be accessed
|
||||
with the `useService` hook)
|
||||
* - `debug`
|
||||
- string. If non empty, the web client is in :ref:`debug mode <frontend/framework/debug_mode>`
|
||||
* - `_t`
|
||||
- translation function
|
||||
* - `isSmall`
|
||||
- boolean. If true, the web client is currently in mobile mode (screen width <= 767px)
|
||||
|
||||
So, for example, to translate a string in a component (note: templates are
|
||||
automatically translated, so no specific action is required in that case), one
|
||||
can do this:
|
||||
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
const someString = this.env._t('some text');
|
||||
|
||||
.. note::
|
||||
|
||||
Having a reference to the environment is quite powerful, because it provides
|
||||
access to all services. This is useful in many cases: for example,
|
||||
user menu items are mostly defined as a string, and a function taking the `env`
|
||||
as unique argument. This is enough to express all user menu needs.
|
||||
|
||||
Building Blocks
|
||||
===============
|
||||
|
||||
Most of the web client is built with a few types of abstractions: registries,
|
||||
services, components and hooks.
|
||||
|
||||
Registries
|
||||
----------
|
||||
|
||||
:ref:`Registries <frontend/registries>` are basically a simple key/value mapping
|
||||
that stores some specific kind of objects. They are an important part of the
|
||||
extensibility of the UI: once some object is registered, the rest of the web
|
||||
client can use it. For example, the field registry contains all field components
|
||||
(or widgets) that can be used in views.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
import { registry } from "./core/registry";
|
||||
|
||||
class MyFieldChar extends owl.Component {
|
||||
// some code
|
||||
}
|
||||
|
||||
registry.category("fields").add("my_field_char", MyFieldChar);
|
||||
|
||||
Note that we import the main registry from ``@web/core/registry`` then open the
|
||||
sub registry ``fields``.
|
||||
|
||||
Services
|
||||
--------
|
||||
|
||||
:ref:`Services <frontend/services>` are long lived pieces of code that provide a
|
||||
feature. They may be imported by components (with ``useService``) or by other
|
||||
services. Also, they can declare a set of dependencies. In that sense, services
|
||||
are basically a DI (dependency injection) system. For example, the ``notification``
|
||||
service provides a way to display a notification, or the ``rpc`` service is the
|
||||
proper way to perform a request to the Odoo server.
|
||||
|
||||
The following example registers a simple service that displays a notification
|
||||
every 5 second:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
import { registry } from "./core/registry";
|
||||
|
||||
const myService = {
|
||||
dependencies: ["notification"],
|
||||
start(env, { notification }) {
|
||||
let counter = 1;
|
||||
setInterval(() => {
|
||||
notification.add(`Tick Tock ${counter++}`);
|
||||
}, 5000);
|
||||
}
|
||||
};
|
||||
|
||||
serviceRegistry.add("myService", myService);
|
||||
|
||||
Components and Hooks
|
||||
--------------------
|
||||
|
||||
:ref:`Components <frontend/components>` and :ref:`hooks <frontend/hooks>` are ideas coming from the
|
||||
`Owl component system <https://github.com/odoo/owl/blob/master/doc/readme.md>`_.
|
||||
Odoo components are simply owl components that are part of the web client.
|
||||
|
||||
`Hooks <https://github.com/odoo/owl/blob/master/doc/reference/hooks.md>`_ are a
|
||||
way to factorize code, even if it depends on lifecycle. This is a
|
||||
composable/functional way to inject a feature in a component. They can be seen
|
||||
as a kind of mixin.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
function useCurrentTime() {
|
||||
const state = useState({ now: new Date() });
|
||||
const update = () => state.now = new Date();
|
||||
let timer;
|
||||
onWillStart(() => timer = setInterval(update, 1000));
|
||||
onWillUnmount(() => clearInterval(timer));
|
||||
return state;
|
||||
}
|
||||
|
||||
Context
|
||||
=======
|
||||
|
||||
An important concept in the Odoo javascript is the *context*: it provides a way
|
||||
for code to give more context to a function call or a rpc, so other parts of the
|
||||
system can properly react to that information. In some way, it is like a bag of
|
||||
information that is propagated everywhere. It is useful in some situations, such
|
||||
as letting the Odoo server know that a model rpc comes from a specific form view,
|
||||
or activating/disabling some features in a component.
|
||||
|
||||
There are two different contexts in the Odoo web client: the *user context* and
|
||||
the *action context* (so, we should be careful when using the word *context*: it
|
||||
could mean a different thing depending on the situation).
|
||||
|
||||
.. note::
|
||||
The `context` object may be useful in many cases, but one should be careful
|
||||
not to overuse it! Many problems can be solved in a standard way without
|
||||
modifying the context.
|
||||
|
||||
.. _frontend/framework/user_context:
|
||||
|
||||
User Context
|
||||
------------
|
||||
|
||||
The *user context* is a small object containing various informations related to
|
||||
the current user. It is available through the `user` service:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
class MyComponent extends Component {
|
||||
setup() {
|
||||
const user = useService("user");
|
||||
console.log(user.context);
|
||||
}
|
||||
}
|
||||
|
||||
It contains the following information:
|
||||
|
||||
|
||||
.. list-table::
|
||||
:widths: 20 20 60
|
||||
:header-rows: 1
|
||||
|
||||
* - Name
|
||||
- Type
|
||||
- Description
|
||||
* - `allowed_company_ids`
|
||||
- `number[]`
|
||||
- the list of active company ids for the user
|
||||
* - `lang`
|
||||
- `string`
|
||||
- the user language code (such as "en_us")
|
||||
* - `tz`
|
||||
- `string`
|
||||
- the user current timezone (for example "Europe/Brussels")
|
||||
|
||||
In practice, the `orm` service automatically adds the user context to each of
|
||||
its requests. This is why it is usually not necessary to import it directly in
|
||||
most cases.
|
||||
|
||||
.. note::
|
||||
The first element of the `allowed_company_ids` is the main company of the user.
|
||||
|
||||
Action Context
|
||||
--------------
|
||||
|
||||
The :ref:`ir.actions.act_window<reference/actions/window>` and
|
||||
:ref:`ir.actions.client<reference/actions/client>` support an optional `context` field.
|
||||
This field is a `char` that represents an object. Whenever the corresponding
|
||||
action is loaded in the web client, this context field will be evaluated as an
|
||||
object and given to the component that corresponds to the action.
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<field name="context">{'search_default_customer': 1}</field>
|
||||
|
||||
It can be used in many different ways. For example, the views add the
|
||||
action context to every requests made to the server. Another important use is to
|
||||
activate some search filter by default (see example above).
|
||||
|
||||
Sometimes, when we execute new actions manually (so, programmatically, in javascript),
|
||||
it is useful to be able to extend the action context. This can be done with the
|
||||
`additional_context` argument.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// in setup
|
||||
let actionService = useService("action");
|
||||
|
||||
// in some event handler
|
||||
actionService.doAction("addon_name.something", {
|
||||
additional_context:{
|
||||
default_period_id: defaultPeriodId
|
||||
}
|
||||
});
|
||||
|
||||
In this example, the action with xml_id `addon_name.something` will be loaded,
|
||||
and its context will be extended with the `default_period_id` value. This is a
|
||||
very important usecase that lets developers combine actions together by providing
|
||||
some information to the next action.
|
||||
|
||||
.. _frontend/framework/pyjs:
|
||||
|
||||
Python Interpreter
|
||||
==================
|
||||
|
||||
The Odoo framework features a built-in small python interpreter. Its purpose
|
||||
is to evaluate small python expressions. This is important, because views in
|
||||
Odoo have modifiers written in python, but they need to be evaluated by the
|
||||
browser.
|
||||
|
||||
Example:
|
||||
|
||||
.. code-block:: js
|
||||
|
||||
import { evaluateExpr } from "@web/core/py_js/py";
|
||||
|
||||
evaluateExpr("1 + 2*{'a': 1}.get('b', 54) + v", { v: 33 }); // returns 142
|
||||
|
||||
|
||||
The ``py`` javascript code exports 5 functions:
|
||||
|
||||
.. js:function:: tokenize(expr)
|
||||
|
||||
:param string expr: the expression to tokenize
|
||||
:returns: Token[] a list of token
|
||||
|
||||
.. js:function:: parse(tokens)
|
||||
|
||||
:param Token[] tokens: a list of tokens
|
||||
:returns: AST an abstract syntax tree structure representing the expression
|
||||
|
||||
.. js:function:: parseExpr(expr)
|
||||
|
||||
:param string expr: a string representing a valid python expression
|
||||
:returns: AST an abstract syntax tree structure representing the expression
|
||||
|
||||
.. js:function:: evaluate(ast[, context])
|
||||
|
||||
:param AST ast: a AST structure that represents an expression
|
||||
:param Object context: an object that provides an additional evaluation context
|
||||
:returns: any the resulting value of the expression, with respect to the context
|
||||
|
||||
.. js:function:: evaluateExpr(expr[, context])
|
||||
|
||||
:param string expr: a string representing a valid python expression
|
||||
:param Object context: an object that provides an additional evaluation context
|
||||
:returns: any the resulting value of the expression, with respect to the context
|
||||
|
||||
.. _frontend/framework/domains:
|
||||
|
||||
Domains
|
||||
=======
|
||||
|
||||
Broadly speaking, domains in Odoo represent a set of records that matches some
|
||||
specified conditions. In javascript, they are usually represented either as a
|
||||
list of conditions (or of operators: `|`, `&` or `!` in prefix notation), or as string
|
||||
expressions. They don't have to be normalized (the `&` operator is implied if
|
||||
necessary). For example:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// list of conditions
|
||||
[]
|
||||
[["a", "=", 3]]
|
||||
[["a", "=", 1], ["b", "=", 2], ["c", "=", 3]]
|
||||
["&", "&", ["a", "=", 1], ["b", "=", 2], ["c", "=", 3]]
|
||||
["&", "!", ["a", "=", 1], "|", ["a", "=", 2], ["a", "=", 3]]
|
||||
|
||||
// string expressions
|
||||
"[('some_file', '>', a)]"
|
||||
"[('date','>=', (context_today() - datetime.timedelta(days=30)).strftime('%Y-%m-%d'))]"
|
||||
"[('date', '!=', False)]"
|
||||
|
||||
String expressions are more powerful than list expressions: they can contain
|
||||
python expressions and unevaluated values, that depends on some evaluation context.
|
||||
However, manipulating string expressions is more difficult.
|
||||
|
||||
Since domains are quite important in the web client, Odoo provides a `Domain`
|
||||
class:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
new Domain([["a", "=", 3]]).contains({ a: 3 }) // true
|
||||
|
||||
const domain = new Domain(["&", "&", ["a", "=", 1], ["b", "=", 2], ["c", "=", 3]]);
|
||||
domain.contains({ a: 1, b: 2, c: 3 }); // true
|
||||
domain.contains({ a: -1, b: 2, c: 3 }); // false
|
||||
|
||||
// next expression returns ["|", ("a", "=", 1), ("b", "<=", 3)]
|
||||
Domain.or([[["a", "=", 1]], "[('b', '<=', 3)]"]).toString();
|
||||
|
||||
Here is the `Domain` class description:
|
||||
|
||||
.. js:class:: Domain([descr])
|
||||
|
||||
:param descr: a domain description
|
||||
:type descr: string | any[] | Domain
|
||||
|
||||
.. js:method:: contains(record)
|
||||
|
||||
:param Object record: a record object
|
||||
:returns: boolean
|
||||
|
||||
Returns true if the record matches all the condition specified by the domain
|
||||
|
||||
.. js:method:: toString()
|
||||
|
||||
:returns: string
|
||||
|
||||
Returns a string description for the domain
|
||||
|
||||
.. js:method:: toList([context])
|
||||
|
||||
:param Object context: evaluation context
|
||||
:returns: any[]
|
||||
|
||||
Returns a list description for the domain. Note that this method takes an
|
||||
optional `context` object that will be used to replace all free variables.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
new Domain(`[('a', '>', b)]`).toList({ b:3 }); // [['a', '>', 3]]
|
||||
|
||||
The `Domain` class also provides 4 useful static methods to combine domains:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// ["&", ("a", "=", 1), ("uid", "<=", uid)]
|
||||
Domain.and([[["a", "=", 1]], "[('uid', '<=', uid)]"]).toString();
|
||||
|
||||
// ["|", ("a", "=", 1), ("uid", "<=", uid)]
|
||||
Domain.or([[["a", "=", 1]], "[('uid', '<=', uid)]"]).toString();
|
||||
|
||||
// ["!", ("a", "=", 1)]
|
||||
Domain.not([["a", "=", 1]]).toString();
|
||||
|
||||
// ["&", ("a", "=", 1), ("uid", "<=", uid)]
|
||||
Domain.combine([[["a", "=", 1]], "[('uid', '<=', uid)]"], "AND").toString();
|
||||
|
||||
|
||||
.. staticmethod:: Domain.and(domains)
|
||||
|
||||
:param domains: a list of domain representations
|
||||
:type domains: string[] | any[][] | Domain[]
|
||||
:returns: Domain
|
||||
|
||||
Returns a domain representing the intersection of all domains.
|
||||
|
||||
.. staticmethod:: Domain.or(domains)
|
||||
|
||||
:param domains: a list of domain representations
|
||||
:type domains: string[] | any[][] | Domain[]
|
||||
:returns: Domain
|
||||
|
||||
Returns a domain representing the union of all domains.
|
||||
|
||||
.. staticmethod:: Domain.not(domain)
|
||||
|
||||
:param domain: a domain representation
|
||||
:type domain: string | any[] | Domain
|
||||
:returns: Domain
|
||||
|
||||
Returns a domain representing the negation of the domain argument
|
||||
|
||||
.. staticmethod:: Domain.combine(domains, operator)
|
||||
|
||||
:param domains: a list of domain representations
|
||||
:type domains: string[] | any[][] | Domain[]
|
||||
:param operator: an operator
|
||||
:type operator: 'AND' or 'OR'
|
||||
|
||||
:returns: Domain
|
||||
|
||||
Returns a domain representing either the intersection or the union of all the
|
||||
domains, depending on the value of the operator argument.
|
||||
|
||||
.. _frontend/framework/bus:
|
||||
|
||||
Bus
|
||||
===
|
||||
|
||||
The web client :ref:`environment <frontend/framework/environment>` object contains an event
|
||||
bus, named `bus`. Its purpose is to allow various parts of the system to properly
|
||||
coordinate themselves, without coupling them. The `env.bus` is an owl
|
||||
`EventBus <https://github.com/odoo/owl/blob/master/doc/reference/event_bus.md>`_,
|
||||
that should be used for global events of interest.
|
||||
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// for example, in some service code:
|
||||
env.bus.on("WEB_CLIENT_READY", null, doSomething);
|
||||
|
||||
Here is a list of the events that can be triggered on this bus:
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Message
|
||||
- Payload
|
||||
- Trigger
|
||||
* - ``ACTION_MANAGER:UI-UPDATED``
|
||||
- a mode indicating what part of the ui has been updated ('current', 'new' or 'fullscreen')
|
||||
- the rendering of the action requested to the action manager is done
|
||||
* - ``ACTION_MANAGER:UPDATE``
|
||||
- next rendering info
|
||||
- the action manager has finished computing the next interface
|
||||
* - ``MENUS:APP-CHANGED``
|
||||
- none
|
||||
- the menu service's current app has changed
|
||||
* - ``ROUTE_CHANGE``
|
||||
- none
|
||||
- the url hash was changed
|
||||
* - ``RPC:REQUEST``
|
||||
- rpc id
|
||||
- a rpc request has just started
|
||||
* - ``RPC:RESPONSE``
|
||||
- rpc id
|
||||
- a rpc request is completed
|
||||
* - ``WEB_CLIENT_READY``
|
||||
- none
|
||||
- the web client has been mounted
|
||||
* - ``FOCUS-VIEW``
|
||||
- none
|
||||
- the main view should focus itself
|
||||
* - ``CLEAR-CACHES``
|
||||
- none
|
||||
- all internal caches should be cleared
|
||||
* - ``CLEAR-UNCOMMITTED-CHANGES``
|
||||
- list of functions
|
||||
- all views with uncommitted changes should clear them, and push a callback in the list
|
||||
|
||||
|
||||
Browser Object
|
||||
==============
|
||||
|
||||
The javascript framework also provides a special object ``browser`` that
|
||||
provides access to many browser APIs, like ``location``, ``localStorage``
|
||||
or ``setTimeout``. For example, here is how one could use the
|
||||
``browser.setTimeout`` function:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
import { browser } from "@web/core/browser/browser";
|
||||
|
||||
// somewhere in code
|
||||
browser.setTimeout(someFunction, 1000);
|
||||
|
||||
It is mostly interesting for testing purposes: all code using the browser object
|
||||
can be tested easily by mocking the relevant functions for the duration of the
|
||||
test.
|
||||
|
||||
It contains the following content:
|
||||
|
||||
.. list-table::
|
||||
|
||||
* - `addEventListener`
|
||||
- `cancelAnimationFrame`
|
||||
- `clearInterval`
|
||||
* - `clearTimeout`
|
||||
- `console`
|
||||
- `Date`
|
||||
* - `fetch`
|
||||
- `history`
|
||||
- `localStorage`
|
||||
* - `location`
|
||||
- `navigator`
|
||||
- `open`
|
||||
* - `random`
|
||||
- `removeEventListener`
|
||||
- `requestAnimationFrame`
|
||||
* - `sessionStorage`
|
||||
- `setInterval`
|
||||
- `setTimeout`
|
||||
* - `XMLHttpRequest`
|
||||
-
|
||||
-
|
||||
|
||||
.. _frontend/framework/debug_mode:
|
||||
|
||||
Debug mode
|
||||
==========
|
||||
|
||||
Odoo can sometimes operate in a special mode called the `debug` mode. It is used
|
||||
for two main purposes:
|
||||
|
||||
- display additional information/fields for some particular screens,
|
||||
- provide some additional tools to help developer debug the Odoo interface.
|
||||
|
||||
The `debug` mode is described by a string. An empty string means that the `debug`
|
||||
mode is not active. Otherwise, it is active. If the string contains `assets` or
|
||||
`tests`, then the corresponding specific sub modes are activated (see below). Both
|
||||
modes can be active at the same time, for example with the string `assets,tests`.
|
||||
|
||||
The `debug` mode current value can be read in the :ref:`environment<frontend/framework/environment>`:
|
||||
`env.debug`.
|
||||
|
||||
.. tip::
|
||||
|
||||
To show menus, fields or view elements only in debug mode, you should target
|
||||
the group `base.group_no_one`:
|
||||
|
||||
.. code-block:: xml
|
||||
|
||||
<field name="fname" groups="base.group_no_one"/>
|
||||
|
||||
.. seealso::
|
||||
- :ref:`Activate the debug mode <developer-mode>`
|
||||
|
||||
|
||||
.. _frontend/framework/assets_debug_mode:
|
||||
|
||||
Assets mode
|
||||
-----------
|
||||
|
||||
The `debug=assets` sub mode is useful to debug javascript code: once activated,
|
||||
the :ref:`assets<reference/assets>` bundles are no longer minified, and source-maps
|
||||
are generated as well. This makes it useful to debug all kind of javascript code.
|
||||
|
||||
.. _frontend/framework/tests_debug_mode:
|
||||
|
||||
Tests mode
|
||||
----------
|
||||
|
||||
There is another sub mode named `tests`: if enabled, the server injects the
|
||||
bundle `web.assets_tests` in the page. This bundle contains mostly test tours
|
||||
(tours whose purpose is to test a feature, not to show something interesting to
|
||||
users). The `tests` mode is then useful to be able to run these tours.
|
||||
|
||||
.. seealso::
|
||||
- `Owl Repository <https://github.com/odoo/owl>`_
|
||||
203
content/developer/reference/frontend/hooks.rst
Normal file
@@ -0,0 +1,203 @@
|
||||
.. _frontend/hooks:
|
||||
|
||||
=====
|
||||
Hooks
|
||||
=====
|
||||
|
||||
`Owl hooks <https://github.com/odoo/owl/blob/master/doc/reference/hooks.md>`_ are a
|
||||
way to factorize code, even if it depends on some component lifecycle. Most hooks
|
||||
provided by Owl are related to the lifecycle of a component, but some of them (such as
|
||||
`useComponent <https://github.com/odoo/owl/blob/master/doc/reference/hooks.md#usecomponent>`_)
|
||||
provide a way to build specific hooks.
|
||||
|
||||
Using these hooks, it is possible to build many customized hooks that help solve
|
||||
a specific problem, or make some common tasks easier. The rest of this page
|
||||
documents the list of hooks provided by the Odoo web framework.
|
||||
|
||||
.. list-table::
|
||||
:widths: 30 70
|
||||
:header-rows: 1
|
||||
|
||||
* - Name
|
||||
- Short Description
|
||||
* - :ref:`useAssets <frontend/hooks/useassets>`
|
||||
- load assets
|
||||
* - :ref:`useBus <frontend/hooks/usebus>`
|
||||
- subscribe and unsubscribe to a bus
|
||||
* - :ref:`usePager <frontend/hooks/usepager>`
|
||||
- Display the pager of the control panel of a view.
|
||||
* - :ref:`usePosition <frontend/hooks/useposition>`
|
||||
- position an element relative to a target
|
||||
|
||||
.. _frontend/hooks/useassets:
|
||||
|
||||
useAssets
|
||||
=========
|
||||
|
||||
Location
|
||||
--------
|
||||
|
||||
`@web/core/assets`
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
See the section on :ref:`lazy loading assets <frontend/assets/lazy_loading>` for
|
||||
more details.
|
||||
|
||||
.. _frontend/hooks/usebus:
|
||||
|
||||
useBus
|
||||
======
|
||||
|
||||
Location
|
||||
--------
|
||||
|
||||
`@web/core/utils/hooks`
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Add and clear an event listener to a bus. This hook ensures that
|
||||
the listener is properly cleared when the component is unmounted.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
import { useBus } from "@web/core/utils/hooks";
|
||||
|
||||
class MyComponent {
|
||||
setup() {
|
||||
useBus(this.env.bus, "some-event", event => {
|
||||
console.log(event);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. js:function:: useBus(bus, eventName, callback)
|
||||
|
||||
:param EventBus bus: the target event bus
|
||||
:param string eventName: the name of the event that we want to listen to
|
||||
:param function callback: listener callback
|
||||
|
||||
.. _frontend/hooks/usepager:
|
||||
|
||||
usePager
|
||||
========
|
||||
|
||||
Location
|
||||
--------
|
||||
|
||||
`@web/search/pager_hook`
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Display the :ref:`Pager <frontend/pager>` of the control panel of a view. This hooks correctly sets `env.config` to provide the props to the pager.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
import { usePager } from "@web/search/pager_hook";
|
||||
|
||||
class CustomView {
|
||||
setup() {
|
||||
const state = owl.hooks.useState({
|
||||
offset: 0,
|
||||
limit: 80,
|
||||
total: 50,
|
||||
});
|
||||
usePager(() => {
|
||||
return {
|
||||
offset: this.state.offset,
|
||||
limit: this.state.limit,
|
||||
total: this.state.total,
|
||||
onUpdate: (newState) => {
|
||||
Object.assign(this.state, newState);
|
||||
},
|
||||
};
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. js:function:: usePager(getPagerProps)
|
||||
|
||||
:param function getPagerProps: function that returns the pager props.
|
||||
|
||||
.. _frontend/hooks/useposition:
|
||||
|
||||
usePosition
|
||||
===========
|
||||
|
||||
Location
|
||||
--------
|
||||
|
||||
`@web/core/position/position_hook`
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
Helps positioning a component (or a specific HTMLElement) relatively to a target
|
||||
HTMLElement. This hook ensures the positioning is updated when the window is
|
||||
resized/scrolled.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
import { usePosition } from "@web/core/position/position_hook";
|
||||
|
||||
class MyPopover {
|
||||
setup() {
|
||||
// Here, the target is an HTMLElement
|
||||
usePosition(this.props.target);
|
||||
}
|
||||
}
|
||||
MyPopover.template = owl.tags.xml`<div>I am positioned through a wonderful hook!</div>`
|
||||
|
||||
|
||||
.. note::
|
||||
The following CSS classes can be used to style the target HTMLElement:
|
||||
|
||||
- `o-popper-position`
|
||||
- `o-popper-position--{D}{V}` where `{D}` and `{V}` are replaced by the first letter of the corresponding Direction and Variant (see Options table below for valid directions and variants). E.g.: for position `bottom-end`, the class name will be `o-popper-position--be`.
|
||||
|
||||
API
|
||||
---
|
||||
|
||||
.. js:function:: usePosition(reference[, options])
|
||||
|
||||
:param reference: the target HTMLElement to be positioned from
|
||||
:type reference: HTMLElement or ()=>HTMLElement
|
||||
:param Options options: the positioning options (see table below)
|
||||
|
||||
.. list-table::
|
||||
:widths: 20 20 60
|
||||
:header-rows: 1
|
||||
|
||||
* - Option
|
||||
- Type
|
||||
- Description
|
||||
* - `popper`
|
||||
- string | undefined
|
||||
- this is the element that will get positioned. You can provide here a
|
||||
`useRef reference <https://github.com/odoo/owl/blob/master/doc/reference/hooks.md#useref>`_.
|
||||
If not provided, `this.el` is used (default: `undefined`).
|
||||
* - `container`
|
||||
- HTMLElement
|
||||
- the container from which the popper is expected not to overflow. If
|
||||
overflowing occurs, other popper positions are tried until a not
|
||||
overflowing one is found. (default: the `<html/>` node)
|
||||
* - `margin`
|
||||
- number
|
||||
- added margin between popper and reference elements (default: `0`)
|
||||
* - `position`
|
||||
- string
|
||||
- the desired position. It is a string composed of one direction and one
|
||||
variant separated by a dash character. Valid directions are: `top`,
|
||||
`bottom`, `right`, `left`. Valid variants are: `start`,
|
||||
`middle`, `end`. The variant can be omitted (default variant is
|
||||
`middle`). Examples of valid positions: `right-end`, `top-start`,
|
||||
`left-middle`, `left`. (default position: `bottom`)
|
||||
|
Before Width: | Height: | Size: 7.0 KiB After Width: | Height: | Size: 7.0 KiB |
|
Before Width: | Height: | Size: 7.5 KiB After Width: | Height: | Size: 7.5 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 21 KiB After Width: | Height: | Size: 21 KiB |
|
After Width: | Height: | Size: 405 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 13 KiB |
BIN
content/developer/reference/frontend/images/odoo_sepia.png
Normal file
|
After Width: | Height: | Size: 96 KiB |
BIN
content/developer/reference/frontend/images/rainbow_man.png
Normal file
|
After Width: | Height: | Size: 120 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 9.8 KiB After Width: | Height: | Size: 9.8 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
392
content/developer/reference/frontend/javascript_modules.rst
Normal file
@@ -0,0 +1,392 @@
|
||||
.. _frontend/js_modules:
|
||||
|
||||
==================
|
||||
Javascript Modules
|
||||
==================
|
||||
|
||||
Odoo supports three different kinds of javascript files:
|
||||
|
||||
- :ref:`plain javascript files <frontend/modules/plain_js>` (no module system),
|
||||
- :ref:`native javascript module <frontend/modules/native_js>`.
|
||||
- :ref:`Odoo modules <frontend/modules/odoo_module>` (using a custom module system),
|
||||
|
||||
As described in the :ref:`assets management page <reference/assets>`,
|
||||
all javascript files are bundled together and served to the browser.
|
||||
Note that native javascript files are processed by the Odoo server and transformed into Odoo custom modules.
|
||||
|
||||
Let us briefly explain the purpose behind each kind of javascript file. Plain
|
||||
javascript files should be reserved only for external libraries and some small
|
||||
specific low level purposes. All new javascript files should be created in the
|
||||
native javascript module system. The custom module system is only useful for old,
|
||||
not yet converted files.
|
||||
|
||||
.. _frontend/modules/plain_js:
|
||||
|
||||
Plain Javascript files
|
||||
======================
|
||||
|
||||
Plain javascript files can contain arbitrary content. It is advised to use the
|
||||
*iife* :dfn:`immediately invoked function execution` style when writing such a file:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
(function () {
|
||||
// some code here
|
||||
let a = 1;
|
||||
console.log(a);
|
||||
})();
|
||||
|
||||
The advantages of such files is that we avoid leaking local variables to the
|
||||
global scope.
|
||||
|
||||
Clearly, plain javascript files do not offer the benefits of a module system, so
|
||||
one needs to be careful about the order in the bundle (since the browser will
|
||||
execute them precisely in that order).
|
||||
|
||||
.. note::
|
||||
In Odoo, all external libraries are loaded as plain javascript files.
|
||||
|
||||
.. _frontend/modules/native_js:
|
||||
|
||||
Native Javascript Modules
|
||||
=========================
|
||||
|
||||
Most new Odoo javascript code should use the native javascript module system. This
|
||||
is simpler, and brings the benefits of a better developer experience with a better
|
||||
integration with the IDE.
|
||||
|
||||
There is a very important point to know: Odoo needs to know which files
|
||||
should be translated into :ref:`Odoo modules <frontend/modules/odoo_module>` and which
|
||||
files should not be translated. This is an opt-in system: Odoo will look at the
|
||||
first line of a JS file and check if it contains the string *@odoo-module*. If so, it will
|
||||
automatically be converted to an Odoo module.
|
||||
|
||||
For example, let us consider the following module, located in :file:`web/static/src/file_a.js`:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module **/
|
||||
import { someFunction } from './file_b';
|
||||
|
||||
export function otherFunction(val) {
|
||||
return someFunction(val + 3);
|
||||
}
|
||||
|
||||
Note the comment in the first line: it describes that this file should be converted.
|
||||
Any file without this comment will be kept as-is (which will most likely be an
|
||||
error). This file will then be translated into an Odoo module that look like this:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define('@web/file_a', function (require) {
|
||||
'use strict';
|
||||
let __exports = {};
|
||||
|
||||
const { someFunction } = require("@web/file_b");
|
||||
|
||||
__exports.otherFunction = function otherFunction(val) {
|
||||
return someFunction(val + 3);
|
||||
};
|
||||
|
||||
return __exports;
|
||||
)};
|
||||
|
||||
So, as you can see, the transformation is basically adding `odoo.define` on top,
|
||||
and updating the import/export statements.
|
||||
|
||||
Another important point is that the translated module has an official name:
|
||||
*@web/file_a*. This is the actual name of the module. Every relative imports
|
||||
will be converted as well. Every file located in an Odoo addon
|
||||
:file:`some_addon/static/src/path/to/file.js` will be assigned a name prefixed by the
|
||||
addon name like this: *@some_addon/path/to/file*.
|
||||
|
||||
Relative imports work, but only if the modules are in the same Odoo addon. So, imagine that we have
|
||||
the following file structure:
|
||||
|
||||
::
|
||||
|
||||
addons/
|
||||
web/
|
||||
static/
|
||||
src/
|
||||
file_a.js
|
||||
file_b.js
|
||||
stock/
|
||||
static/
|
||||
src/
|
||||
file_c.js
|
||||
|
||||
The file :file:`file_b` can import :file:`file_a` like this:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module **/
|
||||
import {something} from `./file_a`
|
||||
|
||||
But :file:`file_c` need to use the full name:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module **/
|
||||
import {something} from `@web/file_a`
|
||||
|
||||
|
||||
Aliased modules
|
||||
---------------
|
||||
|
||||
Because :ref:`Odoo modules <frontend/modules/odoo_module>` follow a different module naming pattern, a system exists to allow a smooth
|
||||
transition towards the new system. Currently, if a file is converted to a module (and therefore
|
||||
follow the new naming convention), other files not yet converted to ES6-like syntax in the project
|
||||
won't be able to require the module. Aliases are here to map old names with new ones by creating a
|
||||
small proxy function. The module can then be called by its new *and* old name.
|
||||
|
||||
To add such alias, the comment tag on top of the file should look like this:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module alias=web.someName**/
|
||||
import { someFunction } from './file_b';
|
||||
|
||||
export default function otherFunction(val) {
|
||||
return someFunction(val + 3);
|
||||
}
|
||||
|
||||
Then, the translated module will also create an alias with the requested name:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define(`web.someName`, function(require) {
|
||||
return require('@web/file_a')[Symbol.for("default")];
|
||||
});
|
||||
|
||||
The default behaviour of aliases is to re-export the ``default`` value of the
|
||||
module they alias. This is because "classic" modules generally export a single
|
||||
value which would be used directly, roughly matching the semantics of default
|
||||
exports.
|
||||
However it is also possible to delegate more directly, and follow the exact
|
||||
behaviour of the aliased module:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
/** @odoo-module alias=web.someName default=0**/
|
||||
import { someFunction } from './file_b';
|
||||
|
||||
export function otherFunction(val) {
|
||||
return someFunction(val + 3);
|
||||
}
|
||||
|
||||
In that case, this will define an alias with exactly the values exported by the
|
||||
original module:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define(`web.someName`, function(require) {
|
||||
return require('@web/file_a');
|
||||
});
|
||||
|
||||
.. note::
|
||||
Only one alias can be defined using this method. If you were to need another one to have, for
|
||||
example, three names to call the same module, you would have to add a proxy manually.
|
||||
This is not good practice and should be avoided unless there is no other options.
|
||||
|
||||
Limitations
|
||||
-----------
|
||||
|
||||
For performance reasons, Odoo does not use a full javascript
|
||||
parser to transform native modules. There are, therefore, a number of limitations including but not
|
||||
limited to:
|
||||
|
||||
- an `import` or `export` keyword cannot be preceded by a non-space character,
|
||||
- a multiline comment or string cannot have a line starting by `import` or `export`
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// supported
|
||||
import X from "xxx";
|
||||
export X;
|
||||
export default X;
|
||||
import X from "xxx";
|
||||
|
||||
/*
|
||||
* import X ...
|
||||
*/
|
||||
|
||||
/*
|
||||
* export X
|
||||
*/
|
||||
|
||||
|
||||
// not supported
|
||||
|
||||
var a= 1;import X from "xxx";
|
||||
/*
|
||||
import X ...
|
||||
*/
|
||||
|
||||
- when you export an object, it can't contain a comment
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// supported
|
||||
export {
|
||||
a as b,
|
||||
c,
|
||||
d,
|
||||
}
|
||||
|
||||
export {
|
||||
a
|
||||
} from "./file_a"
|
||||
|
||||
|
||||
// not supported
|
||||
export {
|
||||
a as b, // this is a comment
|
||||
c,
|
||||
d,
|
||||
}
|
||||
|
||||
export {
|
||||
a /* this is a comment */
|
||||
} from "./file_a"
|
||||
|
||||
- Odoo needs a way to determine if a module is described by a path (like :file:`./views/form_view`)
|
||||
or a name (like `web.FormView`). It has to use a heuristic to do just that: if there is a `/` in
|
||||
the name, it is considered a path. This means that Odoo does not really support module names with
|
||||
a `/` anymore.
|
||||
|
||||
As "classic" modules are not deprecated and there is currently no plan to remove them, you can and should keep using
|
||||
them if you encounter issues with, or are constrained by the limitations of, native modules. Both styles can coexist
|
||||
within the same Odoo addon.
|
||||
|
||||
|
||||
.. _frontend/modules/odoo_module:
|
||||
|
||||
Odoo Module System
|
||||
===================
|
||||
|
||||
Odoo has defined a small module system (located in the file
|
||||
:file:`addons/web/static/src/js/boot.js`, which needs to be loaded first). The Odoo
|
||||
module system, inspired by AMD, works by defining the function `define`
|
||||
on the global odoo object. We then define each javascript module by calling that
|
||||
function. In the Odoo framework, a module is a piece of code that will be executed
|
||||
as soon as possible. It has a name and potentially some dependencies. When its
|
||||
dependencies are loaded, a module will then be loaded as well. The value of the
|
||||
module is then the return value of the function defining the module.
|
||||
|
||||
As an example, it may look like this:
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
// in file a.js
|
||||
odoo.define('module.A', function (require) {
|
||||
"use strict";
|
||||
|
||||
var A = ...;
|
||||
|
||||
return A;
|
||||
});
|
||||
|
||||
// in file b.js
|
||||
odoo.define('module.B', function (require) {
|
||||
"use strict";
|
||||
|
||||
var A = require('module.A');
|
||||
|
||||
var B = ...; // something that involves A
|
||||
|
||||
return B;
|
||||
});
|
||||
|
||||
An alternative way to define a module is to give explicitly a list of dependencies
|
||||
in the second argument.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define('module.Something', ['module.A', 'module.B'], function (require) {
|
||||
"use strict";
|
||||
|
||||
var A = require('module.A');
|
||||
var B = require('module.B');
|
||||
|
||||
// some code
|
||||
});
|
||||
|
||||
|
||||
If some dependencies are missing/non ready, then the module will simply not be
|
||||
loaded. There will be a warning in the console after a few seconds.
|
||||
|
||||
Note that circular dependencies are not supported. It makes sense, but it means that one
|
||||
needs to be careful.
|
||||
|
||||
Defining a module
|
||||
-----------------
|
||||
|
||||
The `odoo.define` method is given three arguments:
|
||||
|
||||
- `moduleName`: the name of the javascript module. It should be a unique string.
|
||||
The convention is to have the name of the odoo addon followed by a specific
|
||||
description. For example, `web.Widget` describes a module defined in the `web`
|
||||
addon, which exports a `Widget` class (because the first letter is capitalized)
|
||||
|
||||
If the name is not unique, an exception will be thrown and displayed in the
|
||||
console.
|
||||
|
||||
- `dependencies`: the second argument is optional. If given, it should be a list
|
||||
of strings, each corresponding to a javascript module. This describes the
|
||||
dependencies that are required to be loaded before the module is executed. If
|
||||
the dependencies are not explicitly given here, then the module system will
|
||||
extract them from the function by calling toString on it, then using a regexp
|
||||
to find all the `require` statements.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define('module.Something', ['web.ajax'], function (require) {
|
||||
"use strict";
|
||||
|
||||
var ajax = require('web.ajax');
|
||||
|
||||
// some code here
|
||||
return something;
|
||||
});
|
||||
|
||||
- finally, the last argument is a function which defines the module. Its return
|
||||
value is the value of the module, which may be passed to other modules requiring
|
||||
it. Note that there is a small exception for asynchronous modules, see the
|
||||
next section.
|
||||
|
||||
If an error happens, it will be logged (in debug mode) in the console:
|
||||
|
||||
* `Missing dependencies`:
|
||||
These modules do not appear in the page. It is possible that the JavaScript
|
||||
file is not in the page or that the module name is wrong
|
||||
* `Failed modules`:
|
||||
A javascript error is detected
|
||||
* `Rejected modules`:
|
||||
The module returns a rejected Promise. It (and its dependent modules) is not
|
||||
loaded.
|
||||
* `Rejected linked modules`:
|
||||
Modules who depend on a rejected module
|
||||
* `Non loaded modules`:
|
||||
Modules who depend on a missing or a failed module
|
||||
|
||||
Asynchronous modules
|
||||
---------------------
|
||||
|
||||
It can happen that a module needs to perform some work before it is ready. For
|
||||
example, it could do an rpc to load some data. In that case, the module can
|
||||
simply return a promise. The module system will simply
|
||||
wait for the promise to complete before registering the module.
|
||||
|
||||
.. code-block:: javascript
|
||||
|
||||
odoo.define('module.Something', function (require) {
|
||||
"use strict";
|
||||
|
||||
var ajax = require('web.ajax');
|
||||
|
||||
return ajax.rpc(...).then(function (result) {
|
||||
// some code here
|
||||
return something;
|
||||
});
|
||||
});
|
||||