Rationale
=========
Since v8, the `display_name` field is present on all models. By default,
`display_name` uses `name_get` which has pretty much the same purpose
(return record name used by the web client). Gradually, many (backend)
developers (and the ORM: https://github.com/odoo/odoo/commit/6da1c3ac4c036eac289597602976538e243cb939)
started using `display_name` (more convenient than
`record.name_get()[0][1]`) but it still had the `name_get` override.
It becomes more complex than necessary and poeple start to misunderstand
the two (and sometimes override both, leading to inconstiencies between
`display_name`/`name_get`).
To simplify the ORM and the API, we decided to keep only one of them,
the `display_name` field:
- It is much more convenient from a backend point of view
(`record.name_get()[0][1]` vs `record.display_name`)
- It is cached during the same transaction (and invalidated if
its dependencies change)
- It can be overridden like any other compute field (override
`_compute_display_name` with any extra dependencies)
- `name_get` is replaced by `read(['display_name'])`
(API perceptive), which can actually be more efficient
(if `display_name`'s depends are correct, the ORM will only fetch the
fields it needs instead of every prefetchable field)
Changes
=======
- Deprecates `name_get` for the v17 and based the method on
`display_name` (the opposite of before)
- Converts all usage of `name_get`
- Overrides of `name_get` are now overrides of `_compute_display_name`
- For `res.partner`, rename the field store `display_name` into
`complete_name` because `display_name` context-dependent and it makes
no sense to have a compute store that is context-dependent.
- Previously, it was possible to return multiple names for the same
record with `name_get`, but it was tricky and most of the usage of
this `name_get` didn't take this into account. The only example of
this is the `name_get` of `product.product`
(now use `", ".join(<names>)`).
Part-of: odoo/odoo#122085
When user deletes 'Portal User Template' record from 'res.users' model and when
'action_open_template_user' function is executed at that time traceback is
generated on the user side as well as in the log.
Steps to reproduce:
1. Install Website module.
2. Go to settings > Users&Companies > Users.
3. Remove Internal Users from default filter.
4. Add Inactive Users in filter and delete Portal User Template.
5. Go to Website Settings > Privacy > Customer Account.
6. Click on Free sign up and then on Save button.
7. Now in Website Settings click on Default Access Rights button.
8. The error will occur.
Applying this commit will fix this issue.
sentry-4184456381
closesodoo/odoo#125761
X-original-commit: f1906f4bb21a88e0c8008393557a16b098dea3c2
Signed-off-by: Rémy Voet <ryv@odoo.com>
Enforce strict types for returned values for
* create
* write
* unlink
* default_get
to make those methods more consistent and reliable.
Also make sure they can be called with empty self/values,
i.e. that they follow the same behavior as the base methods
defined in the main orm Model.
closesodoo/odoo#116809
Related: odoo/enterprise#38880
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
Steps to reproduce:
- install sale_management module;
- go to settings of sale_management and check "Automatic invoice" parameter;
- in debug mode, we can see the template selected (do not change it);
- save the settings;
(This is just one example)
Issue:
The parameter is not added to the "ir_config_parameter" table.
Cause:
The improvement which consists in comparing the settings which one wishes to record with those which already exist in order to set the parameters which are different creates a problem.
Indeed, the current settings are retrieved directly from the model with their default value if there is one.
These are the values that will be used for the comparison.
Because of this, when we want to save a parameter which is set to its default value (on first save), the logic will not notice a difference.
Therefore, the parameter will not be saved in the "ir_config_parameter" table.
Consequence:
In the code, when we wanted to look up the value of a parameter, if it is not saved, we use its default value instead of saving it with its default value.
Example:
```
field_example = fields.Integer(string='Example', default=1000, config_parameter='model.field_example')
value_field_example = params.get_param('model.field_example', default=1000)
```
The default value is repeated.
Solution:
To know whether or not we add a new parameter in the "ir_config_parameter" table, we must look at what already exists in the table and not in the settings defined in the model.
opw-3057306
closesodoo/odoo#106188
X-original-commit: d881dfaaa163b409a94494e35afa2cbda7cf2aa2
Related: odoo/enterprise#34258
Signed-off-by: Victor Feyens (vfe) <vfe@odoo.com>
The code removed by this revision was added at a time any user
could access the `res.config.settings` model, including non-admins.
odoo/odoo@a468aee518
So, it made sense at the time to make the module installation checkboxes
readonly for non-admin users accessing the settings.
However, since revision
https://github.com/odoo/odoo/commit/65530dfd6a0486f44134917f5cc42a2c30b95762#diff-e275aaa5de11da2815c2f0cc18bc046f967df5e4eba94999ee55ffe8926c87bdR109
the `res.config.settings` model is restricted to admins only,
who have the write access the `ir.module.module` model.
This override is therefore pointless,
as since then it's impossible for non-admins to access
the settings.
closesodoo/odoo#105254
X-original-commit: d43896c0bb88310ec2bbb87c4dc355d2bd7faad9
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
- Deprecated `norecompute` (on Environment class) because it is useless
and do nothing.
- Deprecated `cache_restart` (`res.company`) because `clear_caches` do
the stuff.
- Deprecated `write_company_and_print_report` (`res.company`) because
since https://github.com/odoo/odoo/pull/33863/, it is unused
- Deprecated `open_company_edit_report` (`res.company`) because since
25f7040998, it is unused.
Part-of: odoo/odoo#99550
The arguments for the method `fields_get` are `allfields` and
`attributes`, but this model is overriding it with different name,
provoking the error:
TypeError: fields_get() got an unexpected keyword argument 'allfields'
This commits fixes it renamign the argument to the correct one.
TT40013
closesodoo/odoo#103771
X-original-commit: 3884136b73b1efe4de6a28b9447a72a5d257666c
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
Refactor the `load_views` API so it no longer sends multiple times the same
fields description.
e.g.
When `load_views` is called to get the kanban, tree and form views,
the list of fields of the model was sent 4 times:
- Once for each view, with only the fields used in the view,
in `['fields_views']['kanban']['fields']` for instance
- Once globally, with all the fields of the model, in `['fields']`
The goal of this revision is to change that so it sends the list of all fields
only once.
In addition, if a view contains x2many fields,
the fields description of the comodel is also sent.
It was sent in the `views` key of the view fields dict.
e.g.
When calling `load_views` of `res.partner` to get the kanban,
tree and form views,
the `res.partner` fields description was actually sent 6 times:
- Once for each view
- Once globally
- Once for each view of the many2many field `child_ids` of the form view, in
- `['fields_views']['form']['fields']['child_ids']['views']['kanban']['fields']`
- `['fields_views']['form']['fields']['child_ids']['views']['form']['fields']`
The change suggested in this revision is to:
- Remove the fields description for each view in `['fields_views']`.
As it no longer contains the fields,
the key becomes `['views']` instead of `['fields_views']`.
- Replace the dict key `['fields']` by `['models']`,
which is a dict with as key the model name and as values
the model fields description. It contains the fields description
for all models implied in the view:
the model of the main view and the model of all one2many and many2many fields.
With this change, the fields description will only be sent once by model
implied in the view.
In addition, the web client was getting the information about the fields
sometimes in the global fields description list (e.g. `['fields']`),
sometimes in the fields description list of the view type
(e.g. `['fields_views']['form']['fields']`),
making it a pain to try to make changes / performance gain
in these field description dictionaries, because you never knew in which dict
the web client was getting its info.
Now, as there is only one place to get the fields description from,
it's clearer and cleaner.
- one2many and many2many fields views are passed directly in the main view
architecture rather than being put in the `views` key
of the field description.
This is actually easier to treat by the web client,
and this will allow in a future work to cache an entire view in one block
of text rather than having to combine multiple cached blocks of text
to return one view.
- one2many and many2many fields which do not have directly embedded views
have their views directly injected in the architecture,
so the web client doesn't have to do RPC calls to `load_views`
for each one2many and many2many fields not having embedded views.
For instance, this allow to reduce the number of RPC calls to `load_views`
from 8 to 1 when loading the form of `product.product`.
Currently, this behavior is limited to 1 level deep but we consider making it
go all the way down in future works. We did not do it for the moment because
in certain cases it rises the processing time and the size (bytes) too much.
e.g. the sale.order view can be 5 levels deep,
meaning you can reach 4 dialogs on top the main view.
```
sale.order form > order_line > sale.order.line form > invoice_lines >
account.move.line form > asset_ids > account.asset form >
depreciation_move_ids > account.move form.
```
This will also benefit in future works to cache an entire view in one block
of text rather to having to combine multiple cached block of text
to get one view.
- `fields_view_get` becomes `get_view`.
As it no longer returns the fields description,
keeping the `fields` in the name `fields_view_get` no longer makes sense.
Hence removing `fields` from the method name, it becomes `view_get`.
As it gets renamed anyway, we take the opportunity to rename it `get_view`,
which is more in line with the general getter/setter guidelines
in the model object world.
- `_fields_view_get` becomes `_get_view`. For the same reasons than above.
- `load_views` becomes `get_views`.
This is not mandatory, there is no technical reason to rename `load_views` as
it practically sends the same info as before,
the view architectures and their fields description. Just in another way.
We just take the opportunity of this pull request to suggest a cleaner API:
`_get_view`, `get_view` and `get_views`.
- Arguments `toolbar=False, submenu=False` fo the methods
`_fields_view_get` and `fields_view_get` are converted to a kwargs `**options`
in `_get_view` and `get_view`.
The rationale is that submenu was already no longer used (deprecated)
and the mobile options is introduced.
The mobile options is necessary to tell the server to send the mobile views
for x2many fields (kanban instead of tree).
Instead of adding a new argument each time we add a new option to
`fields_view_get`, it seems wiser to have a kwargs `**options` to avoid
to re-write all overrides each time a new option is introduced.
- `_fields_view_get` returned a dict containing the arch in text and some of the
view information. Now, `get_view` returns a tuple with the view architecture
as an `etree` node, and the view as a browse record. The rationale is that all
overrides of `_fields_view_get` were about modifying the arch only
(e.g. changing the address format/re-organizing the address related field
nodes of the partner according to the company country).
To do so, all these overrides were doing `etree.fromstring` to parse the arch
which was sent in text to convert it to an `etree`,
then operations were done on the `etree`,
and then `etree.tostring` was called to convert back the arch to string.
With this change of signature to send the arch as an `etree`,
all these back and forth `etree.fromstring` -> `etree.tostring` are avoided,
allowing some performance gain and less code in the end.
- A cleanup of the keys returned in the dict of `fields_view_get`
has been performed in `get_view`:
- `fields` is removed, as explained above,
- `view_id` is renamed `id`,
- `name` is removed, it was unused by the web client,
- `type` is removed, it was unused by the web client,
- `field_parent` is removed, it was unused by the web client,
- `base_model` is removed, it was unused by the web client.
- `filters` is moved from the global dict returned by `load_views`
(now `get_views`) to the dict returned by `fields_view_get` (now `get_view`)
as it applies only to the `search` view type.
- Retro-compatible methods for the 3 methods
`fields_view_get`, `_fields_view_get` and `load_views` are provided,
with deprecation warnings in them.
- The web client could cache the model fields description
(as it already caches the views),
so it doesn't need to fetch them again if it asks for another view of a model
for which he already has the fields description.
If we do so, `get_views` could return only the list of models used by
the views, without the fields description as of now,
and the web client would then call `fields_get` independently only for
the models for which it doesn't have yet the fields description.
This would avoid the server to return the fields description
and to call `fields_get`, which is costly, for each `get_views`,
therefore gaining performances.
- Inject the views of the one2many and many2many fields all the way down,
unlimited depth level, as explained above.
- Cache with `ormcache` the architecture of back-end views.
This is already done for qweb views, it's not done for back-end views.
Therefore the postprocessing of the views is performed for each `get_views`,
which is costly, while the view architecture doesn't change for users
belonging to the same groups, according to the groups implied by the view.
This pull request is co-authored by
Aaron Bohy (aab) for the web client part and
Denis Ledoux (dle) for the server part.
Part-of: odoo/odoo#87522
This commit aims to fix multiple issues with the "Customer Account"
parameter in the backend config.
- Hide the parameter from general and sales settings if website is
installed.
- Properly compute the right value once website is installed, as it was
not using the website's value.
- Fix a traceback when clicking on "Default Access Rights".
TaskId-2825096
closesodoo/odoo#89806
X-original-commit: 8b162f507f881619061d61530cc03b4b4654c1fe
Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
Signed-off-by: William Braeckman (wbr) <wbr@odoo.com>
Prior to this commit there was no way for a `res.config.settings` field
using a `config_parameter` and remove the `config_parameter` aspect.
After this commit, the parameter is ignored if it is falsy.
TaskId-2825096
X-original-commit: b0b62ee3e302b1a1d08d1c8a32bf297380a4f27b
Part-of: odoo/odoo#89806
Purpose
=======
Several actions are done even if nothing has changed on the configuration.
Example:
Writing on a cron the same value makes a dummy write-lock on the table
...
Part-of: odoo/odoo#82999
* batch module data prefetch in res.config.settings flows.
* manipulate ir.module.module records instead of a strange list of tuples
* Only keep the missing module names logic where useful (useless for the
res.config.settings scope, modules must exists to be referenced by
a settings field).
* drop the support of module fields of type selection, they are not used anymore,
it's not even sure they still work and this feature doesn't bring much added value anyway.
Part-of: odoo/odoo#83104
Apparently a migration error in
0fd773a486, probably never noticed
because nobody ever tries to copy config objects since there's a
bespoke widget, and it's specifically forbidden.
Also fix the signature of the method itself to match the normal one.
closesodoo/odoo#82711
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
It used to be a tuple.
Cf: 1abe965b59
opw-2681777
closesodoo/odoo#81312
X-original-commit: aa74f51db7bf5a8ad1f4e309b6352df3c31037ec
Signed-off-by: Raphael Collet <rco@odoo.com>
When "Saving" a settings wizard, all its settings are written, even if
not modified.
This implies updating ir.default and ir.config.parameter models.
By verifying whether there were effective changes, we can
avoid:
1) the searches to get the corresponding records from database
2) the cache clear triggered by default/parameter updates/creation
This commit thus reduces the queries triggered when saving settings,
but also the queries of future operations, since we avoid clearing
the ORM cache if not needed.
Part-of: odoo/odoo#62249
The settings wizard provides the implied_group logic to add/remove
implied_groups to an existing group (by default base.group_user).
When verifying those special fields (onchange, default_get and execute
calls), ref is called once by group, by field.
E.g. a field
group_broll = fields.Boolean(implied_group="broll")
will trigger two refs ("broll" & "base.group_user") for each
onchange/default_get/execute call on res.config.settings.
This commit uses the cached method to fetch ir.model.data,
avoiding a lot of queries (depending on the fields defined on
res.config.settings model)
Part-of: odoo/odoo#62249
Following the API for ir.model records, the same logic is provided for
ir.module.module records.
This allows to avoid a bunch of queries when modifying/opening settings.
Part-of: odoo/odoo#62249
At create, the ORM fills the missing create values with the defaults,
calling default_get.
In the case of res.config.settings model, the default_get overrides triggers
a lot of operations to manage its custom field logic (config parameters,
defaults, modules installation, ...).
This slows down the creation (and application) of settings updates for "nothing".
This commit ensures the defaults are not recomputed for fields whose value
was provided to the create call, reducing the effective time of settings flow.
Part-of: odoo/odoo#62249
The profiling tools can be useful to profile a test of some execution
point but this is not convenient to identify a problem on a running
instance.
With this commit, an option available in the debug menu allows to add a
flag on the user sessions to enable profiling of all requests. Each
request will be saved in a different 'ir.profile' entry, but will be
grouped under the same session.
The profiling can be activated on all sessions, even for a public user,
but only if profiling is enabled on the database globally.
This commits also adds a speedscope view to visualize saved results in
the web client.
closesodoo/odoo#66590
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
User may use Settings menu just to click "Manage Users" buttons. Such simple
navigation sends ``create`` request, which may trigger a chain of
recomputations. To avoid that we redefine ``create`` method to check if a value
is really changed.
The previous explicit implementation lacks in v14 two fields at least:
* from module `account`
```
qr_code = fields.Boolean(string='Display SEPA QR-code', related='company_id.qr_code', readonly=False)
```
* from module `enterprise/account_reports`
```
account_tax_fiscal_country_id = fields.Many2one(string="Fiscal Country", related="company_id.account_tax_fiscal_country_id", readonly=False)
```
Performance Tests
=================
In this test we click "Manage users" and check stats for
``res.config.settings/create`` request.
Demo database with eCommerce and Accounting app installed:
```
| | Number of queries | Query time, sec | Remaining time, sec |
|--------+-------------------+-----------------+---------------------|
| Before | 707 | 0.325 | 0.215 |
| After | 382 | 0.283 | 0.174 |
```
The same, but with extra 1400 invoices:
```
| | Number of queries | Query time, sec | Remaining time, sec |
|--------+-------------------+-----------------+---------------------|
| Before | 715 | 0.459 | 0.349 |
| After | 382 | 0.176 | 0.107 |
```
---
opw-2489335
closesodoo/odoo#68620
X-original-commit: 5e3f37191a4687b305e2337780c7f10278f6a7aa
Signed-off-by: Ivan Yelizariev // IEL <yelizariev@users.noreply.github.com>
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Execute shouldn't really be overriden because it handles a very touchy
case: module (un)installs, if it is poorly overriden it can create
registry inconsistencies and can make databases crash in really dumb
ways, since the module operations *need* to be performed at the end of
the transaction (last).
Most of the time, an override of set_values() does the same job and is
much safer.
This commit updates the `res.config.settings.execute()` documentation to
reflect this.
closesodoo/odoo#56032
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Using a few regex like
\((_\(.*%s.*)(\) % )([\w\[\]][\w .\[\]\(\)'"]*)\)
($1, $3))
Old syntax is still compatible but starts the migration to the new
syntax that catches error.
This restricts the attributes of a BaseModel instance to `env`, `_ids`
and `_prefetch_ids`. This way, one can only assign fields on a record;
other assignments are programming errors.
This also reduces the memory footprint of records from 168 to 64 bytes
(-62%), and makes their instanciation faster.
closesodoo/odoo#51075
Related: odoo/enterprise#10529
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Execute the tests from ea574fe9ff644 and 9e9ac5ced80b30,
which are in a SavepointCase.
The second test fails on a cache_miss.
Whats happens is the following:
- the second test starts with the environment from the beginning of the
first test. However its envs has a reference to environments that
were created during the first test.
- when computing the field, the ORM finds the value in a zombie
environment, so does not recompute it
- when trying to get the value, the value is not in cache
The issue is that going through res.config.settings's execute resets the
envs.
One solution is to put:
self.addCleanup(lambda: setattr(self.env.envs, 'envs', envs))
in SavepointCase's setup.
However in that case the reset is not needed at all:
it's necessary only if there were some modules to install.
Unfortunately to_install and to_uninstall are not symmetric:
to_uninstall contains only modules that should be uninstalled, whereas
to_install contains everything, and only filters later what actions
really need to be performed.
In this case, we can rely on the result of the installation process.
closesodoo/odoo#41126
Signed-off-by: Nans Lefebvre (len) <len@odoo.com>
Because of f206714af0 and subsequent commits, adding groups may raise.
Thus, it is always safer to first remove groups and then add new groups.
The converse could raise, making settings save impossible.
Closes#37481
Forward-Port-Of: #37517
Go to Configuration > General Settings.
Before this commit:
if a setting is None, a stack trace appears.
After this commit:
a warning message is logged in this case, but there is no crash.
closesodoo/odoo#37271
Opw: 2075047
X-original-commit: ed64477d0a9fc58a577d9174a347268186eff70f
Signed-off-by: Nicolas Martinelli (nim) <nim@odoo.com>
Purpose
=======
When enabling/disabling a group, the modification is only applied
to the users from the enabled companies.
It should be applied to all the users.
closesodoo/odoo#36744
Signed-off-by: Yannick Tivisse (yti) <yti@odoo.com>
This branch is the combination of several optimizations in the ORM:
* store field values once in the cache: the cache reflects more
faithfully the database, only fields that explicitly depend on the
context have an extra indirection in the cache;
* delay recomputations by default: use method `recompute` to explicitly
flush out pending recomputations;
* delay updates in method `write`: updates are stored in a data
structure that can be flushed efficiently to the database with method
`flush` (which also flush out recomputations);
* make method `modified` take advantage of inverse fields to inverse
dependencies;
* filter records by evaluating a domain on records in Python;
* a computed field with `readonly=False` behaves like a normal field
with an onchange method;
* computed fields are computed in superuser mode by default.
Work done by Toufik Ben Jaa, Raphael Collet, Denis Ledoux and Fabien
Pinckaers.
closesodoo/odoo#35659
Signed-off-by: Denis Ledoux <beledouxdenis@users.noreply.github.com>
Multi is the default api for methods, it is not necessary to explicitly
decorate methods with it, adds clutter and most people use it because
they see that the rest of the code uses it.
Done with `find . -type f -name '*.py' | xargs sed -i '/@api.multi/d'`
Commit a0dd81b added 'magic' support for ir.config_parameter
to res.config.settings fields.
However for boolean fields, we have:
IrConfigParameter.get_param(icp, field.default(self) if field.default else False)
if value is False we do nothing.
If icp is defined we get a str.
Now if field.default(self) is truthy, it will be called with value.lower().
In particular if value is the boolean True, it will crash and thus settings are
rendered inaccessible.
Note that commit odoo/enterprise@39fb3be0ef gave a default '' value to a
boolean field, sidestepping the issue.
By convention, config_parameters encode booleans using bool(str),
i.e. '' encodes False, while anything else encodes True.
We follow this convention here;
which means that "False" would be be interpreted as True (to Tarski's dismay).
Note that passing a default True value would mean that the config_parameter
would be False before the first settings save, which could be avoided by putting
the value in the module data.
opw-2000718
Closesodoo/odoo#33517
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
Co-authored-by: Martin Trigaux <mat@odoo.com>