[IMP] developer/howtos: proofread adv topics
- Cleaned up the language a tiny bit - Fixed small errors/typos - Add some missing info for dashboard topic - Updated unit test exercise to match what's in the solutions repo Part-of: odoo/documentation#1146
This commit is contained in:
parent
c1b8e7f7a1
commit
c0aba501da
@ -33,7 +33,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.
|
||||
@ -44,7 +44,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
|
||||
======
|
||||
@ -294,7 +294,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
|
||||
@ -366,9 +366,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.
|
||||
|
||||
@ -380,7 +380,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.
|
||||
|
||||
@ -393,7 +393,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`.
|
||||
@ -403,15 +403,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
|
||||
@ -447,7 +447,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::
|
||||
|
||||
@ -472,7 +472,7 @@ 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
|
||||
@ -480,7 +480,7 @@ 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.
|
||||
@ -507,10 +507,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,
|
||||
|
@ -23,23 +23,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
|
||||
@ -70,15 +70,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:
|
||||
@ -129,7 +129,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
|
||||
|
||||
@ -153,7 +153,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
|
||||
|
||||
@ -243,7 +243,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``
|
||||
~~~~~~~~
|
||||
@ -279,13 +279,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
|
||||
|
||||
@ -324,15 +324,8 @@ common ORM methods.
|
||||
</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
|
||||
==================
|
||||
|
@ -15,11 +15,11 @@ Advanced E: Python Unit Tests
|
||||
|
||||
Writing tests is a necessity for multiple reasons. Here is a non exhaustive list:
|
||||
|
||||
* Ensure it will not be broken in the future
|
||||
* Ensure code will not be broken in the future
|
||||
* Define the scope of your code
|
||||
* Give examples of use cases
|
||||
* It is one way to technically document the code
|
||||
* Help you develop by defining your goal before working towards it
|
||||
* Help your coding by defining your goal before working towards it
|
||||
|
||||
Running Tests
|
||||
=============
|
||||
@ -79,7 +79,7 @@ Integration Bots
|
||||
================
|
||||
|
||||
.. note:: This section is only for Odoo employees and people that are contributing to
|
||||
`github.com/odoo`. We highly recommend having your own CI if it is not the case.
|
||||
`github.com/odoo`. We highly recommend having your own CI otherwise.
|
||||
|
||||
When a test is written, it is important to make sure it always passes when modifications are
|
||||
applied to the source code. To automate this task, we use a development practice called
|
||||
@ -100,7 +100,7 @@ GitHub.
|
||||
|
||||
You can see the state of a commit/branch by filtering on the runbot dashboard.
|
||||
|
||||
A **bundle** is created for each branch. A bundle consists of a configuration and contains the
|
||||
A **bundle** is created for each branch. A bundle consists of a configuration and
|
||||
batches.
|
||||
|
||||
A **batch** is a set of builds, depending on the parameters of the bundle.
|
||||
@ -116,17 +116,17 @@ process. Generally it is used to split the post install tests in 4 parallel inst
|
||||
A sub-build is green if all the tests are passing and there are no errors/warnings logged.
|
||||
|
||||
.. note::
|
||||
* All tests are run whatever the modifications done. Correcting a typo in an error message or
|
||||
refactoring a whole module triggers the same tests. It will install all the modules. This means
|
||||
something might not work if Runbot green but your changes depend on something you don't depend
|
||||
on.
|
||||
* All tests are run regardless of the modifications done. Correcting a typo in an error message or
|
||||
refactoring a whole module triggers the same tests. All modules will be installed as well. This means
|
||||
something might not work even if the Runbot is green, i.e. your changes depend on a module that the
|
||||
module the changes are in doesn't depend on.
|
||||
* The localization modules (i.e. country-specific modules) are not installed on Runbot (except
|
||||
the generic one), some modules with external dependencies can be excluded also.
|
||||
* There is a nightly build running additional tests, like module operations, localization, single
|
||||
the generic one). Some modules with external dependencies can also be excluded.
|
||||
* There is a nightly build running additional tests: module operations, localization, single
|
||||
module installs, multi-builds for nondeterministic bugs, etc.
|
||||
These are not kept in the standard CI to shorten the time of execution.
|
||||
|
||||
You can also login on a build built by Runbot. There are 3 users usable: `admin`, `demo` and
|
||||
You can also login to a build built by Runbot. There are 3 users usable: `admin`, `demo` and
|
||||
`portal`. The password is the same as the login. This is useful to quickly test things on different
|
||||
versions without having to build it locally. The full logs are also available; these are used for
|
||||
monitoring.
|
||||
@ -138,9 +138,9 @@ You will most likely have to gain a little bit more experience before having the
|
||||
robodoo, but here are a few remarks anyways.
|
||||
|
||||
Robodoo is the guy spamming the CI status as tags on your PRs, but he is also the guy that kindly
|
||||
integrates your commits on the main repositories.
|
||||
integrates your commits into the main repositories.
|
||||
|
||||
When the last batch is green, the reviewer can ask robodoo to merge your PR (actually it is more
|
||||
When the last batch is green, the reviewer can ask robodoo to merge your PR (it is more
|
||||
a `rebase` than a `merge`). It will then go to the mergebot.
|
||||
|
||||
Mergebot
|
||||
@ -166,8 +166,8 @@ your branch on the target and rerun the tests locally.
|
||||
Modules
|
||||
=======
|
||||
|
||||
Because Odoo is modular, the tests need to be modular also. This means the modules are defined in
|
||||
the module that adds the functionality you add; and that tests cannot depend on functionality
|
||||
Because Odoo is modular, the tests need to be also modular. This means tests are defined in
|
||||
the module that adds the functionality you are adding in and tests cannot depend on functionality
|
||||
coming from modules your module doesn't depend on.
|
||||
|
||||
**Reference**: the documentation related to this topic can be found in
|
||||
@ -193,7 +193,7 @@ coming from modules your module doesn't depend on.
|
||||
|
||||
If the behavior you want to test can be changed by the installation of another module, you need to
|
||||
ensure that the tag `at_install` is set; otherwise you can use the tag `post_install` to speed up
|
||||
the CI, and ensure it is not changed if it shouldn't.
|
||||
the CI and ensure it is not changed if it shouldn't.
|
||||
|
||||
Writing a test
|
||||
==============
|
||||
@ -233,13 +233,13 @@ import the test folder/module in the ``__init__.py`` of the module.
|
||||
├── __init__.py
|
||||
└── __manifest__.py
|
||||
|
||||
.. note:: Some older tests are extending ``odoo.tests.common.TransactionCase``, but they are less
|
||||
.. note:: Some older tests extend ``odoo.tests.common.TransactionCase``, but they are less
|
||||
scalable. The difference is that the setup is done per test method and not per test class.
|
||||
The data changed are rollbacked between each test in `SavepointCase` to have the same behavior as
|
||||
in `TransactionCase`.
|
||||
Changed data is rolled back between each test in `SavepointCase` to have the same behavior as
|
||||
`TransactionCase`.
|
||||
|
||||
All the tests should extend ``odoo.tests.common.SavepointCase``. You usually define a
|
||||
``setUpClass``, and the tests. After doing the `setUpClass`, you have an `env` available on the
|
||||
``setUpClass`` and the tests. After writing the `setUpClass`, you have an `env` available in the
|
||||
class and can start interacting with the ORM.
|
||||
|
||||
These test classes are built on top of the ``unittest`` python module.
|
||||
@ -285,12 +285,18 @@ These test classes are built on top of the ``unittest`` python module.
|
||||
with self.assertRaises(UserError):
|
||||
self.properties.forbidden_action_on_sold_property()
|
||||
|
||||
.. note:: For more readability, split your tests into multiple files depending on the scope of the
|
||||
tests. You can also have a Common class that most of the tests should inherit from; that common
|
||||
.. note:: For better readability, split your tests into multiple files depending on the scope of the
|
||||
tests. You can also have a Common class that most of the tests should inherit from; this common
|
||||
class can define the whole set up for the module. For instance in
|
||||
`account <https://github.com/odoo/odoo/blob/14.0/addons/account/tests/common.py>`__.
|
||||
|
||||
.. exercise:: Ensure no one can create an offer for a sold Property, and create a test for it.
|
||||
.. exercise:: Update the code so no one can:
|
||||
|
||||
- Create an offer for a sold property
|
||||
- Sell a property with no accepted offers on it
|
||||
|
||||
and create tests for both of these cases. Additionally check that selling a property that can
|
||||
be sold is correctly marked as sold after selling it.
|
||||
|
||||
|
||||
.. exercise:: Someone keeps breaking the reset of Garden Area and Orientation when you uncheck the
|
||||
|
@ -319,7 +319,7 @@ View
|
||||
Now that we have our model, we can make its dashboard view. There is no difference to how its made
|
||||
except that its file is located in the ``report`` folder. Since it is a new model not linked to
|
||||
any other model, we will also have to add a new menuitem to view our dashboard. Typically SQL views
|
||||
are added under a first level menu called ``Reporting` (because it's a report, surprise!). Do you
|
||||
are added under a first level menu called *Reporting* (because it's a report, surprise!). Do you
|
||||
remember how to add a ``menuitem``? If not, revisit :ref:`howto/rdtraining/06_firstui`) again.
|
||||
|
||||
.. exercise:: Create report view.
|
||||
@ -352,3 +352,17 @@ from this report.
|
||||
|
||||
**Tip 2** If you have a field that you do not want as a measure (i.e. in your pivot or
|
||||
graph views), then you can add ``store=False`` to it and it will not show.
|
||||
|
||||
**Tip 3** If you have a SQL View that depends on context then instead of overriding
|
||||
``BaseModel.init()`` set the ``_table_query`` property::
|
||||
|
||||
@property
|
||||
def _table_query(self):
|
||||
return 'SELECT %s FROM %s' % (self._select(), self._from())
|
||||
|
||||
The *select* and *from* methods remain the same.
|
||||
|
||||
`Here is an example <https://github.com/odoo/odoo/blob/14.0/addons/account/report/account_invoice_report.py>`__
|
||||
of a report that depends on the currently selected companies (in a multi-company environment) context to
|
||||
determine the currency exchange rates to use for accurately displaying amounts when the selected companies
|
||||
have different currencies.
|
Loading…
Reference in New Issue
Block a user