Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions content/developer/howtos/rdtraining/01_architecture.rst
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,12 @@ on your background.

For reference this is the official `Python tutorial`_.

.. note::
Since version 15.0, Odoo is actively transitioning to using its own in-house developed `OWL
framework <https://odoo.github.io/owl/>`_ as part of its presentation tier. The legacy JavaScript
framework is still supported but will be depreciated over time. This will be discussed further in
advanced topics.

Odoo modules
============

Expand Down
12 changes: 12 additions & 0 deletions content/developer/howtos/rdtraining/02_setup.rst
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,18 @@ For Python, we use PEP8 with these options ignored:

For JavaScript, we use ESLint and you can find a `configuration file example here`_.

If you do not know how to set up a linter:

- `Here is an explanation of how to set up a Python linter in VSCode <https://code.visualstudio.com/docs/python/linting>`_. There are multiple
linter options you are free to choose from, but `Flake8 <https://pypi.org/project/flake8/>`_ is a popular choice.
- To setup ESLint in VSCode, you must download the `ESLint extension`_ and follow its instructions
for installing ESLint. Don't forget to create and set up the `.eslintrc` file to follow the
configuration file mentioned above.
- Another useful VSCode plugin is `Trailing Spaces`_ to quickly notice trailing spaces while
you're working.

.. _Trailing Spaces: https://marketplace.visualstudio.com/items?itemName=shardulm94.trailing-spaces
.. _ESLint extension: https://marketplace.visualstudio.com/items?itemName=dbaeumer.vscode-eslint
.. _configuration file example here: https://github.com/odoo/odoo/wiki/Javascript-coding-guidelines#use-a-linter
.. _VSCode: https://code.visualstudio.com/
.. _VSCodium: https://vscodium.com/
Expand Down
10 changes: 8 additions & 2 deletions content/developer/howtos/rdtraining/13_inheritance.rst
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,12 @@ The decorator :func:`~odoo.api.model` is necessary for the :meth:`~odoo.models.M
method because the content of the recordset ``self`` is not relevant in the context of creation,
but it is not necessary for the other CRUD methods.

It is also important to note that even though we can directly override the
:meth:`~odoo.models.Model.unlink` method, you will almost always want to write a new method with
the decorator :func:`~odoo.api.ondelete` instead. Methods marked with this decorator will be
called during :meth:`~odoo.models.Model.unlink` and avoids some issues that can occur during
uninstalling the model's module when :meth:`~odoo.models.Model.unlink` is directly overridden.

In Python 3, ``super()`` is equivalent to ``super(TestModel, self)``. The latter may be necessary
when you need to call the parent method with a modified recordset.

Expand All @@ -85,8 +91,8 @@ when you need to call the parent method with a modified recordset.

- Prevent deletion of a property if its state is not 'New' or 'Canceled'

Tip: override :meth:`~odoo.models.Model.unlink` and remember that ``self`` can be a recordset
with more than one record.
Tip: create a new method with the :func:`~odoo.api.ondelete` decorator and remember that
``self`` can be a recordset with more than one record.

- At offer creation, set the property state to 'Offer Received'. Also raise an error if the user
tries to create an offer with a lower amount than an existing offer.
Expand Down
24 changes: 12 additions & 12 deletions content/developer/howtos/rdtraining/14_other_module.rst
Original file line number Diff line number Diff line change
Expand Up @@ -133,24 +133,24 @@ information:
Moreover, an invoice line needs to be linked to an invoice. The easiest and most efficient way
to link a line to an invoice is to include all lines at invoice creation. To do this, the
``invoice_line_ids`` field is included in the ``account.move`` creation, which is a
:class:`~odoo.fields.One2many`. One2many and Many2many use special 'commands' described in
:ref:`reference/orm/models/crud`. This format is a list of triplets executed sequentially, where
each triplet is a command to execute on the set of records. Here is a simple example to include
a One2many field ``line_ids`` at creation of a ``test.model``::
:class:`~odoo.fields.One2many`. One2many and Many2many use special 'commands' which have been
made human readable with the :class:`~odoo.fields.Command` namespace. This namespace represents
a triplet command to execute on a set of records. The triplet was originally the only option to
do these commands, but it is now standard to use the namespace instead. The format is to place
them in a list which is executed sequentially. Here is a simple example to include a One2many
field ``line_ids`` at creation of a ``test.model``::

from odoo import Command

def inherited_action(self):
self.env["test.model"].create(
{
"name": "Test",
"line_ids": [
(
0,
0,
{
"field_1": "value_1",
"field_2": "value_2",
},
)
Command.create({
"field_1": "value_1",
"field_2": "value_2",
})
],
}
)
Expand Down
6 changes: 3 additions & 3 deletions content/developer/howtos/rdtraining/16_guidelines_pr.rst
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@ to improve the quality of the Odoo Apps code.

.. exercise:: Polish your code.

Refactor your code to respect the coding guidelines. Don't forget to respect the module
structure, the variable names, the method name convention, the model attribute order and the
xml ids.
Refactor your code to respect the coding guidelines. Don't forget to run your linter and
respect the module structure, the variable names, the method name convention, the model
attribute order and the xml ids.

Your first Pull Request (PR)
============================
Expand Down
37 changes: 19 additions & 18 deletions content/developer/howtos/rdtraining/B_acl_irrules.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,9 @@ Advanced B: ACL and Record Rules
<howto/rdtraining>`.

To follow the exercise, it is recommended that you fetch the branch
14.0-core from the repository XXX, it
contains a version of the module created during the core training we can use
15.0-core from the
`technical training solutions <https://github.com/odoo/technical-training-solutions/tree/15.0-core>`__ repository.
It contains a version of the module created during the core training we can use
as a starting point.

So far we have mostly concerned ourselves with implementing useful features.
Expand All @@ -33,7 +34,7 @@ However:
* Real-estate agents don't need or get to decide what property types or tags are
*available*.
* Real-estate agents can have *exclusive* properties, we do not want one agent
to be able to manage another's exclusivities.
to be able to manage another's exclusives.
* All real-estate agents should be able to confirm the sale of a property they
can manage, but we do not want them to be able to validate or mark as paid
any invoice in the system.
Expand All @@ -44,7 +45,7 @@ However:

Because it's easier for users to disable unnecessary security rules than it
is to create them from nothing, it's better to err on the side of caution
and limiting access: users can relax that access if necessary or convenient.
and limit access: users can relax that access if necessary or convenient.

Groups
======
Expand Down Expand Up @@ -223,7 +224,7 @@ individual records:
<field name="name">A description of the rule's role</field>
<field name="model_id" ref="model_to_manage"/>
<field name="perm_read" eval="False"/>
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
<field name="groups" eval="[Command.link(ref('base.group_user'))]"/>
<field name="domain_force">[
'|', ('user_id', '=', user.id),
('user_id', '=', False)
Expand Down Expand Up @@ -294,7 +295,7 @@ do so.
There are two main ways to bypass existing security checks in Odoo, either
wilfully or as a side-effect:

* The ``sudo()`` method will create a new recorset in "sudo mode", this ignores
* The ``sudo()`` method will create a new recordset in "sudo mode", this ignores
all access rules and access rights (although hard-coded group and user checks
may still apply).
* Performing raw SQL queries will bypass access rules and access rights as a
Expand Down Expand Up @@ -366,9 +367,9 @@ Explicit security checks can be performed by:
specific models or records.
* Checking that the current user has specific groups hard-coded to allow or deny
an operation (``self.env.user.has_group``).
* Calling the ``check_access_rights(operation)`` method on a recorset, this
* Calling the ``check_access_rights(operation)`` method on a recordset, this
verifies whether the current user has access to the model itself.
* Calling ``check_access_rule(operations)`` on a non-empty recorset, this
* Calling ``check_access_rule(operations)`` on a non-empty recordset, this
verifies that the current user is allowed to perform the operation on *every*
record of the set.

Expand All @@ -380,7 +381,7 @@ Explicit security checks can be performed by:

Before creating the invoice, use ``check_access_rights`` and
``check_access_rule`` to ensure that the current user can update properties
in general, and this specific property in particular.
in general as well as the specific property the invoice is for.

Re-run the bypass script, check that the error occurs before the print.

Expand All @@ -393,7 +394,7 @@ Multi-company security

:ref:`reference/howtos/company` for an overview of multi-company facilities
in general, and :ref:`multi-company security rules <howto/company/security>`
this in particular.
in particular.

Documentation on rules in general can, again, be found at
:ref:`reference/security/rules`.
Expand All @@ -403,15 +404,15 @@ Multi-company security
At the end of this section, agents should only have access to properties
of their agency (or agencies).

For one reason or an other we might need to manage our real-estate business
as multiple companies e.g. we might have largely autonomous agencies, or a
For one reason or another we might need to manage our real-estate business
as multiple companies e.g. we might have largely autonomous agencies, a
franchise setup, or multiple brands (possibly from having acquired other
real-estate businesses) which remain legally or financially separate from one
another.

Odoo can be used to manage multiple companies inside the same system, however
the actual handling is up to individual modules: Odoo itself provides the tools
to manage the issue like company-dependent fields and *multi-company rules*,
to manage the issue of company-dependent fields and *multi-company rules*,
which is what we're going to concern ourselves with.

We want different agencies to be "siloed" from one another, with properties
Expand Down Expand Up @@ -447,7 +448,7 @@ associated with *one* of the companies the user has access to:

Multi-company rules are usually :ref:`global <reference/security/rules/global>`,
otherwise there is a high risk that additional rules would allow bypassing
the muti-company rules.
the multi-company rules.

.. exercise::

Expand All @@ -472,15 +473,15 @@ Visibility != security
.. admonition:: **Goal**

At the end of this section, real-estate agents should not see the Settings
menu of the rea-estate application, but should still be able to set the
menu of the real-estate application, but should still be able to set the
property type or tags.

Specific Odoo models can be associated directly with groups (or companies, or
users). It is important to figure out whether this association is a *security*
or a *visibility* feature before using it:

* *Visibility* features mean a user can still access the model or record
otherwise, either through an other part of the interface or by :doc:`perform
otherwise, either through another part of the interface or by :doc:`performing
operations remotely using RPC <../../misc/api/odoo>`, things might just not be
visible in the web interface in some contexts.
* *Security* features mean a user can not access records, fields or operations.
Expand All @@ -507,10 +508,10 @@ Here are some examples:

.. exercise::

Real Estate agents can not add property types or tags, and can see their
Real Estate agents can not add property types or tags, but can see their
options from the Property form view when creating it.

The Settings menu just adds noise to their interface, it should only be
The Settings menu just adds noise to their interface, make it only
visible to managers.

Despite not having access to the Property Types and Property Tags menus anymore,
Expand Down
58 changes: 26 additions & 32 deletions content/developer/howtos/rdtraining/C_data.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ Advanced C: Master and Demo Data

.. tip:: This tutorial assumes you followed the Core Training.

To do the exercise, fetch the branch 14.0-core from the repository XXX.
To do the exercise, fetch the branch 15.0-core from the
`technical training solutions <https://github.com/odoo/technical-training-solutions/tree/15.0-core>`__ repository.
It contains a basic module we will use as a starting point

Data Types
Expand All @@ -23,23 +24,23 @@ We already met technical data previously since we have defined
:ref:`security rules<howto/rdtraining/N_security>`, :ref:`views<reference/views>` and
:ref:`actions<reference/actions>`. Those are one kind of master data.

On top of technical data, business data can be defined: countries, currencies, units of measure but
also complete country localization (legal reports, tax definitions, chart of account), and much
On top of technical data, business data can be defined, e.g. countries, currencies, units of measure,
as well as complete country localization (legal reports, tax definitions, chart of account), and much
more...

Demo Data
---------

Next to master data which are requirements for the modules to work properly, we also like having
data for demonstration purpose setups:
In additional to master data, which are requirements for a module to work properly, we also like
having data for demonstration purposes:

* Help the sales representatives to make their demos quickly.
* Have a set of working data for developers to test the new features and see what it looks like
with something they might not have created without it.
* Help the sales representatives make their demos quickly.
* Have a set of working data for developers to test new features and see how these new features look
with data they might not have added themselves.
* Test that the data is loaded correctly, without raising an error.
* Be ready to use most of the features quickly when creating a new database.
* Setup most of the features to be used quickly when creating a new database.

Demo data is automatically loaded when you start the server if you didn't say explicitly you don't
Demo data is automatically loaded when you start the server if you don't explicitly say you don't
want it. This can be done in the database manager or with the command line.

.. code-block:: console
Expand Down Expand Up @@ -70,15 +71,15 @@ Manifest
**Reference**: the documentation related to this topic can be found in
:ref:`Module Manifests<reference/module/manifest>`.

The data is declared either in CSV either in XML.
Data is declared either in CSV or in XML.
Each file containing data must be added in the manifest for them to be loaded.

The keys to use in the manifest to add new data are ``data`` for the master data and ``demo`` for
the demo data. Both values should be a list of strings representing the relative path to the files
the demo data. Both values should be a list of strings representing the relative paths to the files
declaring the data.

Usually, the demo data is set in a ``demo`` folder, the views and actions are put in a ``views``
folder, the security related data is put in a ``security`` folder, and the other data is set in a
Usually, demo data is in a ``demo`` folder, views and actions are in a ``views``
folder, security related data is in a ``security`` folder, and other data is in a
``data`` folder.

If your work tree looks like this:
Expand Down Expand Up @@ -129,7 +130,7 @@ CSV
:ref:`CSV data files<reference/data/csvdatafiles>`.

The easiest way to declare simple data is by using the CSV format. This is however limited in terms
of features: use it for long lists of simple models, but prefer XML in the other cases.
of features: use it for long lists of simple models, but prefer XML otherwise.

.. code-block:: text

Expand All @@ -153,7 +154,7 @@ XML
**Reference**: the documentation related to this topic can be found in
:ref:`Data Files<reference/data>`.

When the data to create is a bit more complex it can be useful, or even needed, to do it in XML.
When the data to create is more complex it can be useful, or even necessary, to do it in XML.

.. code-block:: xml

Expand Down Expand Up @@ -243,7 +244,7 @@ works too if you are in the module declaring it).
Deco Addict Big Villa 1500001 14
============== ========= ======= ========

.. exercise:: Both properties should be Residential properties.
.. exercise:: Ensure both of your demo properties are created with their Property Type set to Residential.

``eval``
~~~~~~~~
Expand Down Expand Up @@ -279,13 +280,13 @@ Sometimes, you need to call the ORM to do a ``search``. This is not feasible wit
</record>
</odoo>

In this code snippet, it is needed because the master data actually depends on the localization
In this code snippet, it is needed because the master data depends on the localization
installed.

``function``
~~~~~~~~~~~~

You might also need to execute python code when loading the data.
You might also need to execute python code when loading data.

.. code-block:: xml

Expand All @@ -303,36 +304,29 @@ Add X2many fields
-----------------

**Reference**: the documentation related to this topic can be found in
:ref:`Common ORM methods<reference/orm/models/crud>`.
:class:`~odoo.fields.Command`.

If you need to add related data in a One2many or a Many2many field, you can do so by using the
common ORM methods.
:class:`~odoo.fields.Command` methods.

.. code-block:: xml

<odoo>
<record id="id1" model="tutorial.example">
<field name="related_ids" eval="[
(0, 0, {
Command.create({
'name': 'My name',
}),
(0, 0, {
Command.create({
'name': 'Your name',
}),
(4, ref('model.xml_id')),
Command.link(ref('model.xml_id')),
]"/>
</record>
</odoo>

.. code-block:: text

id,parent_id:id,name
"child1","module.parent","Name1"
"child2","module.parent","Name2"
"child3","module.parent","Name3"

.. exercise:: Create one new Property, but this time with some offers created directly inside the
One2many field linking to the Offers.
One2many field linked to the Offers.

Accessing the data
==================
Expand Down
Loading