Commit Graph
448 Commits
Author SHA1 Message Date
Pierre Paridans eef262abf4 [FIX] *: adapt QUnit tests and tours
[FIX] *: selectors in tours

[FIX][TMP] account: CogMenu selector in tours

[FIX][TMP] web*: Breadcrumb targetting in tours

Adds a `o_breadcrumb` class to target the whole breadcrumb, no matter
how much elements it contains (collapsed parts, visible path, single
name...).

add classname on last breadcrumb item

[FIX][TMP] project: View buttons selector in tours (moved away from CP)

[FIX][TMP] project: Kanban selectors in tours (quick create)

[FIX][TMP] *: SearchBar selectors in tours (toggle menu)

[FIX][TMP] *: ButtonBox selector in tours

[WIP][IMP] web: add toggleSearchBarMenu in search helpers

adapt and unskip 3 list tests

adapt and unskip calendar tests

unskip web_tour test that actually pass

post rebase fix

allow to lose cell focus after multi edition (given to searchbar) - bug reported, to check later

post rebase fixes

fix

Part-of: odoo/odoo#116641
2023-05-12 22:59:22 +02:00
Raphael Collet 58bd33ccde [IMP] core: make onchange2() work with properties fields
The issue with properties fields is that the value in the record
snapshot is not correct.  This is caused by convert_to_record()
combining the values with the definition, and in the case of onchange(),
the values don't match the definition, which causes the method to return
the empty list [].

We fix the root cause by changing convert_to_record() to return the dict
itself.  The combination of the values with the definition is now only
done in convert_to_read().  Method convert_to_onchange() has only one
hack to retrieve the current definition record from the record snapshot,
as because of cache invalidation, its value is no longer available.

closes odoo/odoo#120457

Signed-off-by: Raphael Collet <rco@odoo.com>
2023-05-05 18:08:10 +02:00
std-odoo dc95819257 [IMP] base: do not write in database when we have invalid properties names
Purpose
=======
When we create a new record, we can change the definition on the definition
record. If the parent had no definition, in `_add_default_values`,
we just return the value. But in some weird cases, if we have
invalid properties name in the value, the will be written in database.

Now, in that particular case, we propagate the value only
if we try to change the definition.

Part-of: odoo/odoo#120457
2023-05-05 18:08:09 +02:00
Raphael Collet 7a5f655879 [FIX] test_new_api: introduce proper test mixin
Part-of: odoo/odoo#120457
2023-05-05 18:08:09 +02:00
Vincent Schippefilt 7d276aa941 [IMP] web: add reference fields to web_read
add support for fields of type `reference` and `many2one_reference` to `web_read` and `unity_web_search_read`

for both you can add a field_spec requesting fields of the "co-model":

request:
```python
{
    #reference
    'field_reference':
        {
            'fields': {'write_date': {}},
        }

    #many2one_reference
    'm2o_reference_id':
        {
            'fields': {'display_name': {}, 'write_date': {}},
        },
    'm2o_reference_model': {}
}
```
response:
```python
{
    'id': ...,
    #reference
    'field_reference': {
        'id': {'id': 3, 'model': 'comodel_name'},
        'write_date': '2004-11-23 11:30'
    }

    #many2one_reference
    'm2o_reference_id': {
        'id': 3,
        'display_name': "special first day",
        'write_date': '2004-11-23 11:30'
    },
    'm2o_reference_model': 'comodel_name',
}
```

closes odoo/odoo#119995

Task-id: 3284222
Signed-off-by: Raphael Collet <rco@odoo.com>
2023-05-04 00:46:53 +02:00
f5e6494da3 [IMP] web: introduce onchange2
The purpose of onchange2() is to adress two shortcomings of onchange():
 - reduce the payload of the RPC call by minimizing the diff
 - use the "unity" format for returning the data

Because of the dependency of onchange2() on web_read(), the new method
has been introduced in module web.

closes odoo/odoo#119510

Signed-off-by: Raphael Collet <rco@odoo.com>
Co-authored-by: Julien Castiaux <juc@odoo.com>
Co-authored-by: VincentSchippefilt <VincentSchippefilt@users.noreply.github.com>
2023-04-28 14:44:00 +02:00
Raphael Collet 664dc3f8fb [IMP] test_new_api: add test on first call to onchange()
Part-of: odoo/odoo#119510
2023-04-28 14:43:59 +02:00
Julien CastiauxandRaphaël Collet 5a998694a6 [IMP] core: merge subqueries WHERE clauses
Rationale
---------

Given the following domain:

    ['|',
        ('company_id.name', 'like', 'BE'),
        ('company_id.city', 'like', 'Brussels')]

The ORM would generate the following SQL query:

    SELECT "res_partner"."id"
    FROM "res_partner"
    WHERE "res_partner"."company_id" IN (
        SELECT "res_company"."id"
        FROM "res_company"
        WHERE "res_company"."name" like 'BE'
    ) OR "res_partner"."company_id" IN (
        SELECT "res_company"."id"
        FROM "res_company"
        WHERE "res_company"."email" like 'help@odoo.com'
    );

Which is sub-optiomal as the WHERE clause of the two subqueries could be
regrouped inside of a single query like so:

    SELECT "res_partner"."id"
    FROM "res_partner"
    WHERE "res_partner"."company_id" IN (
        SELECT "res_company"."id"
        FROM "res_company" WHERE (
            "res_company"."name" like 'BE'
            OR "res_company"."email" like 'help@odoo.com'
        )
    );

Postgres-wise, it is faster to execute the latter query than the former
one. This commit is about optimizing the ORM so that it generates
queries where the WHERE clause of compatible subqueries are grouped
together.

Technical solution
------------------

The solution explored by this work is to replace the regular relational
field accesses (over a dotted path) by a new `any` operator that look as
follow:

    (relational_field, 'any', domain)

For instance, the above `('company_id.name', 'like', 'BE')` leaf becomes
`('company_id', 'any', [('name', 'like', 'BE')]` using `any`.

Having a domain as right-hand-side allow for the combination of the
domains of same compatible relations:

    [('company_id', 'any', ['|',
        ('name', 'like', 'BE'),
        ('city', 'like', 'Brussels')])

Having combined domains allows for generating better SQL queries with
minimal changes to the expression parsing algorithm, which can only
translate a single leaf at a time to SQL. With the new `any` operator,
it is still a single leaf but the right-hand-side contains the merged
domain, thus the combined SQL WHERE clause is immediately generated.

task-id-3234671

Part-of: odoo/odoo#118067
Co-authored-by: Raphaël Collet <rco@odoo.com>
2023-04-27 10:12:57 +02:00
Julien CastiauxandRaphaël Collet eee68139d5 [IMP] test_new_api: subqueries made by search() on relational fields
This commit hads a few tests that report the existing behavior (before
merging subqueries WHERE clauses).

task-id-3234671

Part-of: odoo/odoo#118067
Co-authored-by: Raphaël Collet <rco@odoo.com>
2023-04-27 10:12:57 +02:00
Rémy Voet (ryv) 70fd18ef67 [FIX] web: fix bad groupby as str instead of list
A mistake introduced in  234db70d86, the
`groupby` of  `_read_group` should be list/tuple of  `str`, not a `str`.

closes odoo/odoo#119400

Signed-off-by: Raphael Collet <rco@odoo.com>
2023-04-22 06:53:49 +02:00
Vincent Schippefilt 7d2baaa0c7 [IMP] web: project unity_read
Introduce an optimised way of reading a graph of data from the webclient.

Before this commit:
When reading data from the webclient it could at most read multiple ids of the same model in one RPC.
This mean that when reading x2many or specific information on many2one, that could only be done after the initial read (when the client knows the ids of the comodels) and model by model.

After this commit:
Introduce methods web_read and web_search_read_unity. Both method receive a specificiation for the fields instead of a list of fields. The specification can request fields from the model, as well as follow relations and request fields for each relations, recursively.

Example of web_read specification for account_move
```python
{'name': {}},
{'date': {}},
{'journal_id': {'fields': {'display_name':{}}}
},
...
{'invoice_line_ids' :
    {
        'fields': {
            'journal_id' : {'fields': {'display_name:{}}},
            'move_name' : {},
            ...
            'tax_ids' : {
                fields: {
                    'display_name':{},
                    ...
                }
            }
        }
    }
}
```

Result for this example with 2 invoice lines
```python
{
    'id': 1234,
    'name' : 'invoice name ABC',
    'journal_id: {
        'id': 999,
        'display_name': 'Customer Invoices'
    },
    ...
    'invoice_line_ids': [
        {
            'id': 666,
            'journal_id': {
                'id': 999,
                'display_name': 'Customer Invoices'
            },
            'move_name': 'a move name',
            'tax_ids': [
                {
                    'id': 333,
                    'display_name: "15% tax",
                    ...
                }
            ]
        },
        {
            'id': 667,
            'journal_id': {
                'id': 999,
                'display_name': 'Customer Invoices'
            },
            'move_name': 'another move name',
            'tax_ids': [
                {
                    'id': 334,
                    'display_name: "21% customer tax",
                    ...
                }
            ]
        }
    ]

}
```

closes odoo/odoo#119034

Signed-off-by: Vincent Schippefilt (vsc) <vsc@odoo.com>
2023-04-21 08:02:17 +02:00
Rémy Voet (ryv) 234db70d86 [IMP] *: Use the new API of _read_group for backend use
Part-of: odoo/odoo#110737
2023-04-19 21:58:27 +02:00
Ipsita Borisagar b2103b06f7 [FIX] base, web: allow reading property fields when no access to parent record
This commit fixes a use case where a user would not be able to access the
property field values of a record because he did not have access to that
record's parent (from the property field definition configuration).

In a concrete example:
- In the Knowledge App
- Marc Demo has access to the "Article B".
- The parent article of "Article B" is "Article A".
- Marc Demo does not have access to "Article A".
- Article B has some property fields values configured.
- If Marc Demo tries to open "Article B" -> crash

This is caused by the framework having to read the property definition from the
parent record, which we don't have access to.
A "sudo" was added to allow that use case (which is supported).

In addition, this commit also adds further checks on the web client side to
gracefully handle a special use case where the end-user could not write on the
parent record because of record rules.
(It only checked *access rules*).

To avoid making an extra RPC every time we load the record (to check if we can
write on the parent), we only make that check when the user tries to modify
(add/edit/remove) a property and show a proper error message.
(This also applies when creating new property field tags).

Task-3062064

closes odoo/odoo#118929

X-original-commit: bc538f6944461a642bac0f757ec96d7f8cc14c9a
Related: odoo/enterprise#39946
Signed-off-by: Warnon Aurélien (awa) <awa@odoo.com>
2023-04-18 19:29:03 +02:00
Michael (mcm) ff0d6dd580 [REF] *: replace odoo module by native one
This commit converts almost all odoo module by native module.
The goal is to deprecate odoo.define in favor of native module and then
simplify boot.js by removing the regexp that finds module dependencies.

task id: 3162300

closes odoo/odoo#117305

Related: odoo/enterprise#39118
Signed-off-by: Géry Debongnie <ged@odoo.com>
2023-04-03 17:07:24 +02:00
Julien Banken 88c256d8d8 [FIX] web: standardize behavior for int and float property fields
Currently, the property fields of type integer and decimal does not
behave like the standard fields. There are the following issues:

1. The property fields of type integer and decimal do not fallback to
   the value 0 or 0.0 when the field is emptied.
2. The user can not write the value 0 in the property field of type
   integer and decimal. The value gets discarded whenever the user
   unfocuses the input field.

This commit will fix those two issues and ensure that the property
fields have the same behavior as the standard fields.

task-3226202

closes odoo/odoo#117253

X-original-commit: 08c317743ba90802f471058a8f12d7211f9eb150
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
2023-03-31 09:48:46 +02:00
Joseph CaburnayandJulien Mougenot 3a798039d6 [REF] web_tour,*: convert web_tour to owl
* The tours are now run by the `MacroEngine` defined in `macro.js`.
  * This is accomplished by converting (at runtime) the user-defined tours to
    `Macro`s. See `tour_compilers.js` for the step (and tour-to-macro) compilation.
* API is kept the same as much as possible. Basically, declaring tours stayed
  the same with some exceptions:
  * `allowInvisible` can be provided in a step to allow consuming the trigger
    element even if it is invisible.
  * `isCheck` can now be used to replace the no operation `run` that is
    traditionally signals the runner to only perform a check.
  * Before, multiple `run`s can be called simultaneously. Now, each `run` method
    is awaited before proceeding to the next step.
* If the trigger element is `disabled`, the tour runner will *not* proceed on
  calling the `run` method and the runner will stay on current step until the
  trigger element becomes `enabled`.
  * However, the tour runner is okay with `disabled` trigger element if the step
    has `isCheck = true`. As long as the trigger element is found for `isCheck`
    step, the tour runner will happily move to the next step.
* Some tours are adjusted to properly run with this new tour runner.
* When the tour failed:
  * The dom string is not logged anymore.
  * However, a warning message containing the relative location of the step will
    be logged. This is better in helping the author in locating the failed step.

**Some guidelines learned during the development:**

* Each step may trigger a dom mutation. It's a good practice to insert an
  intermediate step that *checks* the existence of an element that result from
  the action of the previous step.
* Refrain from using the `run` method for assertions. `run`, in principle, is
  provided to perform actions that are not offered by the helper. Use the
  `trigger` for assertions.
* During dev, find `SHOW_POINTER_DURATION` and set it to `250`. This will show
  the pointer (pointing to the trigger element) for 250ms when watching the
  tour.

closes odoo/odoo#107618

Task-id: 3082036
Related: odoo/enterprise#37560
Signed-off-by: Géry Debongnie <ged@odoo.com>
Co-authored-by: Julien Mougenot <jum@odoo.com>
2023-03-15 13:19:45 +01:00
Louis Wicket (wil) 9afe7c74c9 [IMP] *: remove "French spacing" 👺
According to Wiktionary, French spacing is "the archaic practice (though
still current in French) of inserting a space around colons, semicolons,
question marks, and exclamation marks". This is not standard practice in
English and most languages of the world.

The purpose of this commit is to start purging the code from this typo,
as it may reflect poorly on the software for some people.

closes odoo/odoo#114533

Related: odoo/enterprise#37853
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
2023-03-14 15:52:10 +01:00
Rémy Voet (ryv) 9b7c372602 [IMP] core: avoid queries when creating records with one2many values
When we create a new record X and its values contains an one2many field
with either a recordset Y or a Command.set(ids), the ORM generates extra
SQL queries to search and remove the existing lines of the new record.
The call chain is as follows:

    Model._create
        -> _RelationalMulti.create
            -> _RelationalMulti.write_batch
                -> One2many.write_real

But because record X is brand new, it has no lines to begin with.  The
fix consists in skipping the search and removal in that case.

Also remove any nondeterministic behavior of method write_real() using
an OrderedSet instead of a builtin set.

closes odoo/odoo#114726

X-original-commit: 428827e5213ee002a5b50d864f8ce1f24d1842b3
Signed-off-by: Raphael Collet <rco@odoo.com>
2023-03-09 15:54:53 +01:00
Raphael Collet be278780f7 [FIX] core: first onchange when adding a line in a one2many field
Consider a form view with a one2many field, which has no form subview.
Also the form view of the comodel (the one2many field's lines) contains
the inverse many2one field of the one2many field.  When adding a new
line on some existing record, the form view shows the many2one field as
empty, instead of being the main record.

Explanation: the form view of the line invokes onchange() with the main
record's values (dict) as the value of the many2one field.  Inside
onchange(), the field is actually set to a new record corresponding to
the main record.  Alas, when that value is sent back to the form, the
new record is serialized as False.

Solution: let onchange() serialize the new record as its origin record
instead.

closes odoo/odoo#114648

X-original-commit: d137ea4915da8d46909fcb082b5a88fd347874a4
Signed-off-by: Raphael Collet <rco@odoo.com>
2023-03-08 11:37:10 +01:00
Yolann Sabaux afe6f967cd [FIX] base: make country code required
Steps to reproduce:
- Go to Contact-Configuration-Countries
- Remove the code of a country
- Create a new contact
- Select the country from which you deleted the code
- Put any vat number starting with country code you deleted

Issue:
Traceback

Cause:
in `_run_vat_test` we want to `country.code.lower()` -> country code does not exist

Solution:
Prevent the user to delete a country code by making the field required.

sentry-3923412146

closes odoo/odoo#113207

Signed-off-by: William André (wan) <wan@odoo.com>
2023-03-07 11:11:42 +01:00
Nasreddin Boulif (bon) 8e299fb2ee [FIX] base: fix partner merge wizard
Steps to reproduce:

  - Install `Contacts` module
  - Create 3 contacts with the same name
  - Archive one of the contacts
  - Go to list view
  - Edit search filter to display archived and non archived contacts
  - Select the 3 created contacts
  - Open `Action` menu and click on `Merge`

Issues:

  - Archived partner is set by default as destination partner.
  - Archived partner is not displayed in the list of partners to merge.

Cause:

  - The default destination partner set is the last record of the record
    set returned by `_get_ordered_partner` (where `Archived` partners
    are the last ones in the record set).
  - The field `partner_ids` does not allow archived records.

Solution:

  - Sort the partners to have the archived ones on top (since we took
    the last one).
  - Set `active_test` to False in the context of the partner_ids field.

opw-3205577

closes odoo/odoo#114508

X-original-commit: 8d0cec6844b248d3787bd7d6b8868d930d25e38c
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Signed-off-by: Nasreddin Boulif (bon) <bon@odoo.com>
2023-03-07 02:57:02 +01:00
std-odoo 1c2f29fc56 [IMP] base: allow to order record by properties fields values
Purpose
=======
Allow to sort records by properties fields values.

Task-2980121

Part-of: odoo/odoo#101901
2023-03-07 01:59:05 +01:00
std-odoo 0583a5ddd0 [IMP] base: search on properties fields
Purpose
=======
Allow to search properties fields.

For now, the properties fields are meant to be used with the frontend
top bar filter on views in a later commit, and so everything as been
kept as simple as possible for that particular use case.

Technical
=========
Relational properties
---------------------
We can not search on relational properties using the rec name, or
using one of their fields.

The following domains do not work
```
[('properties.partner_id', 'ilike', 'alice')]
[('properties.partner_ids', 'ilike', 'alice')]
[('properties.user_id.name', 'ilike', 'bob')]
[('properties.user_ids.name', 'ilike', 'bob')]
```

Instead, we should give the ids
```
[('properties.partner_id', '=', 55)]
[('properties.partner_ids', 'in', 55)]
```

IN operator
-----------
The "in" operator is used to either search specific tags / many2many
values, either doing a "OR like" condition on "non-array" value.

It can be used if the left or the right side is not an array
```
[('properties.my_char', 'in', ['a', 'b'])]
[('properties.my_tags', 'in', 'a')]
```

But it can't be used if both side of the condition are array, because
it will require to check type in SQL (which is technically possible,
but add extra complexity, so for now we keep the feature as simple as
possible).

So the following domain is not supported.
```
[('properties.my_tags', 'in', ['a', 'b'])]
```

Instead we should use the "OR" operator
```
['|', ('properties.my_tags', 'in', 'a'), ('properties.my_tags', 'in', 'b')]
```

Tags / many2many - "=" operator
-------------------------------
Tags and many2many have to be searched using the "in" operator.

So the following domain will return unexpected results and raise a warning.
```
[('attributes.mytags', '=', ['a', 'b'])]
```

The reason is that we don't want to dynamically check the type in SQL,
and so we need the "in" domain operator to know what to do in SQL.

Task-2980121

Part-of: odoo/odoo#101901
2023-03-07 01:59:04 +01:00
std-odoo da48700b59 [IMP] base: do not modify the cache when reading properties fields in batch
Purpose
=======
Do not modify the cache in order to improve the performance when we
read in batch. Instead we create a new batched method "convert_to_read"
that check existence in batch, and generate a dict with the result.

Now, all the properties field checks (many2one existence, selection option
still exists, tag value stiff exist, etc) and done in "convert_to_read".

It means that doing `record.properties` won't do all those checks.

Having the batched field fetch at the convert_to_record required too
many changes for the scope of this task, so "record.properties" having
the cache values unchecked is an acceptable tradeoff currently, hence
we batch convert_to_read.

Task-2980121

Part-of: odoo/odoo#101901
2023-03-07 01:59:04 +01:00
Raphael Collet e962860c6f [IMP] core: introduce search_fetch() and fetch()
This fulfills the goal of searching and fetching fields in a single SQL
query.  We introduce the new method search_fetch() for that purpose.
Also introduce method fetch() to fetch some fields for a recordset if
they are not in cache yet.

The call graph is as follows:

    search()        calls   search_fetch()
    search_read()   calls   search_fetch() and _read_format()
    read()          calls   fetch() and _read_format()

    search_count()  calls   _search()
    search_fetch()  calls   _search() and _fetch_query()
    fetch()         calls   _search() and _fetch_query()

The methods _search() and _fetch_query() are usually the ones to
override to implement business-specific logic.  The method _search()
returns a Query object to retrieve the records that satisfy the given
domain and are accessible for reading.  The method _fetch_query() uses a
Query object to retrieve fields from the database and store them in
cache.

Also use search_fetch() to save one query in search_read() and the
reading of one2many fields.

Part-of: odoo/odoo#112126
2023-03-05 15:12:55 +01:00
Raphael Collet 537a60ffd1 [IMP] core: quote field "id" in SQL queries
Part-of: odoo/odoo#112126
2023-03-05 15:12:53 +01:00
Raphael Collet 637cdc8ffa [IMP] test_performance: more tests and adapt query counts
Part-of: odoo/odoo#112126
2023-03-05 15:12:53 +01:00
Jorge Pinna Puissant 4a8876b550 [IMP] web: oh-snappisation
The aim of this commit is to make more warning and error dialogs behave
like the "oh snap" dialog of form views.

task-id=3126594

closes odoo/odoo#112276

Related: odoo/enterprise#37593
Signed-off-by: Aaron Bohy (aab) <aab@odoo.com>
2023-02-28 13:01:36 +01:00
Raphael Collet 80ad999475 [FIX] core: cache consistency of field parent_path
The field is updated in SQL but not in cache.  Also remove hacks in the
business code to prevent potential issues from this behavior.

closes odoo/odoo#113119

X-original-commit: 8bb660c985c7a1349cae1bf58dc5bf7981bd9058
Signed-off-by: Rémy Voet <ryv@odoo.com>
Signed-off-by: Raphael Collet <rco@odoo.com>
2023-02-20 13:44:36 +01:00
Raphael Collet 206525658b [IMP] core: add a class for trigger trees
The class is a simple extension of dict, and adds an explicit attribute
for the content of the root node of a tree.  It makes the code much more
readable with very small performance overhead.

closes odoo/odoo#111946

X-original-commit: 8a01d74e5f7d035cfd05bc02596f075270e0fcf8
Signed-off-by: Raphael Collet <rco@odoo.com>
2023-02-04 22:39:45 +01:00
Raphael Collet 161e5fad3b [REF] core: make APIs on registry for computation triggers
Those APIs are aimed at hiding the implementation of trigger trees,
dependent fields and fields modifying relations.  Explicit APIs simplify
the profiling of executions and comparison of implementations for
building trigger trees.

X-original-commit: d12b9270375634e738f5288d0c523ac0eec2fa18
Part-of: odoo/odoo#111946
2023-02-04 22:39:45 +01:00
Raphael Collet ed762a3cef [FIX] core: field recomputed on more records than expected
The issue occurs when a computed field depends on a many2many field with
a corresponding inverse field on its comodel.  Consider two models like

class User(models.Model):
    _name = _description = 'test_new_api.user'

    group_ids = fields.Many2many('test_new_api.group')
    group_count = fields.Integer(compute='_compute_group_count', store=True)

    @api.depends('group_ids')
    def _compute_group_count(self):
        for user in self:
            user.group_count = len(user.group_ids)

class Group(models.Model):
    _name = _description = 'test_new_api.group'

    user_ids = fields.Many2many('test_new_api.user')

When a user is added to a group with

    group.write({'user_ids': [Command.link(user.id)]})

we expect the field `group_count` to be recomputed on `user` only, but
it is actually triggered on *all* the records in `group.user_ids`.  This
is a real performance issue when there are many records in the relation.

The explanation comes from the fact that
 - the framework considers the field `user_ids` is modified on `group`;
 - the field `group_count` implicitly depends on `group_ids.user_ids`,
   which makes it triggered on the users `u` such that `u.group_ids`
   intersects `group`.

The solution consists in handling the dependencies on inverse many2many
field in the field itself.  The field no longer adds the implicit
dependency on its inverse field in the trigger tree, but instead
determines which records in the comodel are actually impacted by the
relation change in the method field.write().

closes odoo/odoo#111943

X-original-commit: bb3a6e378b5f6b2e14b74ce4efb6d749ad54cb1e
Signed-off-by: Raphael Collet <rco@odoo.com>
2023-02-04 18:48:07 +01:00
Martin Trigaux a349b0a89b [IMP] test_new_api: move logger to top level
closes odoo/odoo#111764

X-original-commit: ca83a7879aed132ad2ff216405f745b5bd2ebb80
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
2023-02-03 09:28:38 +01:00
Géry Debongnie b53f78e224 [REF] web_tour,*: use the registry in collecting the tours
This is a step closer to a goal of avoiding dependence on asynchronous
modules. Starting from this commit, new tour definition should be
registered to `registry.category("web_tour.tours")` registry.

So, instead of the following:

```js
import tour from "web_tour.tour";
tour.register(name, options, steps);
```

We now do:

```js
import { registry } from "@web/core/registry";
registry.category("web_tour.tours").add(name, optionsWithSteps);
```

Notice the `options` and `steps` params are merged when registering
the tour definition. It should look something like so:

```js
registry.category("web_tour.tours").add("account_tour", {
  test: true,
  steps: [ ... ],
});
```

And if the `TourManager` instance is needed, one can get it from the
registry like so `registry.get("tourManager")`. Note however that
this instance is only available when the `TourManager` has been
instantiated -- so it's not available at top level of the module.

closes odoo/odoo#111103

Related: odoo/enterprise#36335
Signed-off-by: Géry Debongnie <ged@odoo.com>
2023-01-27 23:17:35 +01:00
Romain Derie fff31b316f [FIX] core: extract normalize from HTML sanitizer
Since [1], it's possible to conditionnally bypass the HTML sanitizer in field
definition with the `sanitize_overridable` attribute.
In a nutshell, when someone is part of the required group(s), it won't go
through the sanitizer, while the people not part of the group(s) will.

A behavior was thus introcuded to prevent a "restricted" user to wipe the
changes done previously by an "elevated" user (which bypassed the sanitizer).
But that behavior was not correct as there was unforeseen cases which led to
raise this error which are not due to the sanitizer but to normalization.

Indeed, while named `html_sanitize()`, it also does some normalize stuff on top
of the real sanitize part.
For instance, there is also (not exhaustive):
- some MAKO compatibility, replacing some chars
- special case for quotes, related to mail clients, which will add data
  attributes, add nodes in dom etc. This happen when the following are found:
  - `<blockquote/>` tag
  - text-based quotes (>, >>) and signatures (-- Signature)
  - html signature (-- <br />blah)
- some editor compatibility which removed the wrapping `<div/>` element
- `nbsp` handling..

See commit list below for detail about how/when/why those normalize cases where
introduced.

At the end, the issue was that the normalize part should not prevent a
"restricted" user to modify the content of an "elevated" user. Only the sanitize
part should.

For instance, the `Quotes` snippet dropped by an "elevated" user was preventing
further edition by a "restricted" user because there was a "false positive"
raised when checking if the save would wipe the existing changes.
Indeed, when the "elevated" user droped the snippet, it was saved as:
```html
<blockquote class=".." data-name="Blockquote">
```
But when the "restricted" user then wanted to do some changes, it would become:
```html
<blockquote class=".." data-name="Blockquote" data-o-mail-quote-node="1" data-o-mail-quote="1">
```

Same for `Share` snippet:
```html
<a href="https://www.facebook.com/sharer/sharer.php?u={url}">
<a href="https://www.facebook.com/sharer/sharer.php?u=%7Burl%7D">
```

[1]: https://github.com/odoo/odoo/commit/cf844e34dd0ce4830eb99fd0fa5b6b9cb58c867c

Normalize commit list:
https://github.com/odoo/odoo/commit/5f1ec49ecdac6d72cd42755c41fbe75d6a1f3587
https://github.com/odoo/odoo/commit/69af79ff3d705d19a71ba3ba7851b981cb301077
https://github.com/odoo/odoo/commit/2bcf4cca79a57dfba84d1f3e3fa7b8908bfe66e8
https://github.com/odoo/odoo/commit/f5688cd8fd515d1b668e8eb1d74de68faa681a01
https://github.com/odoo/odoo/commit/cb8c2d2b7e15c7c16e02d078767e27a07e5012c6
https://github.com/odoo/odoo/commit/275ee5825d38841a3eb21bb195722f3ceed09005
https://github.com/odoo/odoo/commit/b51d21c5b83b88e8d56dbbbb7600bcbe554d1b07

closes odoo/odoo#110903

X-original-commit: 3a2e82cf40f3265650b4f79f9ad5fe309906311d
Signed-off-by: Romain Derie (rde) <rde@odoo.com>
2023-01-25 05:06:02 +01:00
Thibault Delavallée 04a6b74d09 [FIX] mail, various: update query counters
Update counters according to latest runbot counters. It allows to better spot
side effects of upcoming changes.

Task-2710804 (Mail: Clean MailThread Posting API)

Part-of: odoo/odoo#99482
2023-01-17 20:58:30 +01:00
Raphael Collet f2115ba0f2 [FIX] core: don't fail when reading recordset with ids [None]
The revision 65a012c2bba0ed81d9b525a7779c726043b17707 changed the
behavior of method _read() when invoked on a record with id None.
Before the change, the method would consider that no records have been
fetched because the id is falsy.  After the change, it keeps the id None
in the fetched records, and attempts to make subsequent SQL queries like
"column IN ()", which is syntactically incorrect.

OPW 3104957

closes odoo/odoo#108785

X-original-commit: 712d03cb2ee5f2fde0e80619be5db38aa09ed1ac
Signed-off-by: Rémy Voet <ryv@odoo.com>
Signed-off-by: Raphael Collet <rco@odoo.com>
2022-12-29 11:55:57 +01:00
Rémy Voet (ryv) c6c79473dd [FIX] core: unexpected MissingError when prefetching record
This is a rare case where method _read() raises a MissingError instead
of just ignoring it.

The issue is triggered by several conditions on a model M:
 - at least one ir.rule on M with a domain using a column field on M;
 - one deleted record Y which is in the prefetch set of a record X;
 - one reads a non-column field on record X.

Fix method _read() to manage that case.  It adds an extra call to
exists() in that case, but adds no overhead in the general case.

closes odoo/odoo#108050

X-original-commit: 1876dc87e5c88c711c9b3882c39be704ffc46532
Signed-off-by: Raphael Collet <rco@odoo.com>
Signed-off-by: Rémy Voet <ryv@odoo.com>
2022-12-15 14:43:57 +01:00
Chong Wang (cwg) a0bd7d0d72 [IMP] core: improve translation import speed
this commit improves the performance of importing translations by
1. groupup udpating data for different languages and different modules
2. read model_terms translations data directly with xmlid to get rid of fetching
   data from ir_model_data

for modules:sale_management, point_of_sale, industry_fsm, helpdesk, mrp, mrp_plm
(62 installed modules)
time for test_language_install is 45.14% less

for all modules:
time for test_language_install is 68.03% less

closes odoo/odoo#107332

X-original-commit: 727ef9e0a2ca93089b472eb1313117fee8dc876d
Signed-off-by: Raphael Collet <rco@odoo.com>
2022-12-06 17:12:21 +01:00
Adrien Widart (awt) e762362ef0 [FIX] core: find currency when writing monetary field
When creating a record, if a value is related to a monetary field and if
the currency field is a non-stored related one, the value will not be
rounding: when writing the monetary value in the database, we first call
`convert_to_column`. In the parameter, `record` is empty (it is not yet
created) and `values` only contains the stored values (so the currency
value is not present). As a result, `currency` will not be defined and
the value will not be rounded.

OPW-2955202

closes odoo/odoo#106283

X-original-commit: 28196693b50b9d424887391ad13db69c5f5dfe4f
Related: odoo/enterprise#34265
Signed-off-by: Raphael Collet <rco@odoo.com>
Signed-off-by: Adrien Widart <awt@odoo.com>
2022-11-23 11:26:28 +01:00
Rémy Voet (ryv) 29e9d99364 [FIX] core: field indexed by trigram cannot become translated
Field indexed by trigram cannot become translated because the
`convert_column_translatable` is based on the old index naming convention
(changed in https://github.com/odoo/odoo/pull/100736).
Then it generates a PostgreSQL error:
`psycopg2.errors.DatatypeMismatch: operator class "gin_trgm_ops" does not accept data type jsonb`

closes odoo/odoo#105295

Signed-off-by: Raphael Collet <rco@odoo.com>
2022-11-08 13:36:05 +01:00
Chong Wang (cwg) d57d8534bb [FIX] core: fix search with accent
For a trigram indexed translated field field_x,
domain leaf ('field_x', '=', value) and ('field_x', 'ilike', pattern)
will miss records if the pattern contains accent characters

This commit set ensure_ascii=False for json.dumps to avoid escaping special
characters

opw-3048182

closes odoo/odoo#105240

X-original-commit: 26b5c8c2baeaee9fcd5384aafa5f9b39543d6903
Signed-off-by: Raphael Collet <rco@odoo.com>
Signed-off-by: Wang Chong (cwg) <cwg@odoo.com>
2022-11-07 21:37:44 +01:00
Rémy Voet (ryv) 0787f150b1 [FIX] core: make index naming without conflicts
There are two issues with the index naming convention used by the ORM:

Problem 1: it is possible to have naming conflict for indexes.  For
instance, the name 'slide_channel_tag_group_sequence_index' is used for
both fields slide.channel.tag.group.sequence and
slide.channel.tag.group_sequence.  Only the first index will be created.

Solution 1: we separate the model and field names with a double
underscore instead of a single one, which is the same strategy as with
LEFT JOIN aliases.  This is correct because model names don't contain
such double underscores or underscores as prefix or suffix (it is not
forbiden but model name should follow the 'dot notation'.)

Problem 2: index names can be longer than 63 chars, but PostgreSQL
silently truncates it.  This doesn't actually break anything (PostgreSQL
also truncates values when we check the existence of indexes) but it can
lead to using the same name twice.  There is hopefully not any example
in our code.

Solution 2: if the name is too large, we truncate it and pad it with a
hash of the complete name to match 63 characters, which is also the
strategy used for LEFT JOIN aliases.

task-2984730

closes odoo/odoo#100736

Related: odoo/upgrade#3957
Signed-off-by: Raphael Collet <rco@odoo.com>
2022-11-07 15:57:28 +01:00
Rémy Voet (ryv) 1cfc896f2c [IMP] core: add Json field
To be able to create easily a jsonb column in database,
we create a Json type Field. Currently, it is quite limited
field:

- We cannot modified the value in-place, we need to always set
the entire jsonify value.
- No domain operator is done to work with jsonb. Now, it works as a
text field.

closes odoo/odoo#103097

X-original-commit: 7eeba9d205d2dace571b5d0895ddba6290a512db
Related: odoo/enterprise#32729
Signed-off-by: Quentin De Paoli <qdp@odoo.com>
2022-10-17 10:11:09 +02:00
Chong Wang (cwg) 25e4a53753 [FIX] core: fix search domain containing empty False None
For non-translated field, when search(['name', 'in', list_right])
The behavior of False and the behavior of None in list_right should be the same.

Translated fields need customized process for 'in' operator

X-original-commit: a9a3c666f08c5612432dba40a69c7cfdc54ba96e
Part-of: odoo/odoo#103031
2022-10-11 14:10:16 +02:00
Chong Wang (cwg) 105e0b9ef2 [FIX] core: search translated fields with characters needed to be escaped
The trigram index function jsonb_path_query_array("column_name", '$.*')::text
uses all translations' representations to build the indexed text. So the
original text needs to be JSON-escaped correctly to match it.

X-original-commit: 7547df664945dddcb839e4903068f7f25ecfc08c
Part-of: odoo/odoo#103031
2022-10-11 14:10:16 +02:00
std-odoo 6823aa5f99 [IMP] base: improve the performance of properties when used in batch
Purpose
=======
Check the existence of the relational properties (many2one / many2many)
in batch and prefetch the values in batch as well to reduce the number
of SQL queries.

Technical
=========
The existence is checked in the read method of the properties field,
because we have the entire recordset. Then, the non-existing ids are
remove from the properties values and the cache is updated.

Task-2965523

X-original-commit: dba9b684d29c0041a32a5508284573851b8dd097
Part-of: odoo/odoo#102243
2022-10-06 00:37:09 +02:00
std-odoo 608bffff59 [FIX] base: fix the default properties value
Bug
===
If we re-write the same definition record, the default values were
applied again (even if the definition record didn't change).

This is because the compute on the properties is called even if the
definition record didn't change.

Task-2965523

X-original-commit: 70d80771f2430f83c91e7ef46eeebde8de70c3fe
Part-of: odoo/odoo#101487
2022-09-28 19:31:53 +02:00
std-odoo 50abdbe9d9 [FIX] base: fix the property onchange
Bug
===
- create a new helpdesk ticket without properties
- create a new property
- change the customer
=> The added property is removed

The fix in the onchange of models.py needs to be more specific, and
should be used only when the definition record is changed.

Task-2965523

X-original-commit: 909ee004183068d9ffa94abe0d1472a8f0534f34
Part-of: odoo/odoo#101487
2022-09-28 19:31:52 +02:00
std-odoo 1b4c5e92ff [IMP] base: log a message each time a definition is modified
Purpose
=======
Log a message each time a user change a properties definition
by writing on the record properties values.

Task-2965523

X-original-commit: 6fa6fcd13e248d4bdf1febb0d8399cfe634037f5
Part-of: odoo/odoo#101487
2022-09-28 19:31:52 +02:00