The previous commit introduced an optimization to reduce the number of
queries and fields fetched when we call `name_search`. But it works much
better when the dependencies of `display_name` contain field names used
in the calculation (on the same record/model).
Then, to improve the performance and the cache coherency, add `depends`
and `depends_context` depending on the custom `_compute_display_name`.
Add only the first level of dependencies (never traverse relational
field) because only these have a positive impact on the previous
optimization and the cost is very low (see `modified`).
About `depends_context`, we don't include `lang` because (when `_` is
used by example) it is unlikely to get the same display_name in the same
request with two different lang.
closesodoo/odoo#122085
Related: odoo/documentation#4639
Related: odoo/enterprise#42599
Related: odoo/upgrade#4780
Signed-off-by: Raphael Collet <rco@odoo.com>
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
Adds `id` in the `mail.activity`'s order to force deterministic order in
case multiple activities have the same deadline.
Not having a deterministic order can cause issue when tests check
activities' values but don't ensure they are sorted also by id.
closesodoo/odoo#120034
X-original-commit: b0a99bde8efef287f3ed89afb9da2a67233d4bd8
Signed-off-by: Sébastien Theys (seb) <seb@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>
Lot of override of read_group reimplement partially custom security
rule of `_search` method. In order to simplify these security check
and have a consistent behavior between the search and read_group method,
_read_group now use _search to create the from and where clause.
Part-of: odoo/odoo#110737
Purpose
=======
Currently the on_delete='restrict' implicit constraint prevents
the user deletion in case it's linked to a mail.activity record.
Set the on_delete attribute to 'cascade' as the record is not
of any usage without the user anyway.
Taskid: 3222941
Part-of: odoo/odoo#114656
This is about the overrides of _search() on models mail.activity and
mail.message, which both make extra queries to implement their specific
access rights. We combine both queries made in _search() to retrieve
accessible records. This simply uses the API of the Query object to
retrieve the data that is necessary to restrict access to messages.
Move security check outside of _message_format() for performance. The
call to check_access_rule() inside _message_format() was redundant in
many cases and generated more SQL queries than necessary.
Also for performance, accessing fields from records should not actually
check permission. That's a bit freaky, but this reproduces the former
behavior of mail.message.
And finally, make method check_access_rule() on mail.message check
ir.rules, in order to make it consistent with method _search().
Part-of: odoo/odoo#112126
Goal: make _search() always return a Query object, in order to make
search_read() in a single query when possible
Adapt the overrides of _search() towards the given goal.
Part-of: odoo/odoo#112126
The parameter in search() is redundant with method search_count(), and
was making the calls less readable.
The method _search() is aimed at always returning a Query object. The
method can therefore never return an integer, hence the removal of the
parameter. This does not actually remove any functionality from the
method; counting result is simply given by using it differently.
Part-of: odoo/odoo#112126
RATIONALE
Purpose of this commit is to cleanup main post helpers and have a more easy
and understandable way of calling them.
SUMMARY
We now have two main API methods, based on business flow: either posting
on documents, either sending a mass mailing. Indeed those two flows are
different
* post: create message, then launch notification process by taking into
account subtype, followers, ...
* mail: create mails in batch with recipients being based on template or
given partners. No notifications is involved, only maybe traces if a
mass mailing is linked
Delegate QWeb rendering to the render mixin (i.e. _render_template_qweb_view)
in order to have a single point to forge evaluation context and re-use
existing rendering code.
SPECIFICATIONS
Main API helpers are now
* ``message_post_with_source``: (batch) post on records, using an ir.ui.view
(given a record or its xml id) or a mail.template record (given a record or
its xml id). When using a template, a composer is called to post on each
record (as batch post is not yet supported). When using a view, a direct
call to message_post using the rendered bodies is done, one record at a
time.
* ``message_mail_with_source``: send a mass mailing on records, acting like
invoking the mail composer in mass mode. Same arguments are valid, either
a reference to a view, either a reference to a mail template.
Other helpers are
* ``_message_log_with_view``: (batch) log on records, using an ir.ui.view
to render the body using QWeb (no notification process);
* ``_message_log(_batch)``: (batch) log on records (no notification process);
* ``message_notify``: notify partners on records (creating notifications
specifically for some people while message itself is not displayed in
chatter);
Code migration
* ``message_post_with_template`` in "mass mode": use ``message_mail_with_source``
and set the template record as source;
* ``message_post_with_template`` in "comment" mode: use ``message_post_with_source``
and set the template record as source;
* ``message_post_with_view``: its main usage was to post on a document, in which
case it generally can be replaced by ``message_mail_with_source`` using
the view reference as source;
Task-2710804 (Mail: Clean MailThread Posting API)
Part-of: odoo/odoo#99482
RATIONALE
Purpose of this commit is to be explicit in subtype chosen when invoking the
message composer / calling message_post. As default value may not always be
clear, better be explicit in case the composer default value changes.
SPECIFICATIONS
Add explicit references to subtype when it is not obvious what will be the
final subtype, notably when using helpers (post_with_view or template which
uses the composer that is not crystal clear in its subtype management).
In this commit we also add support of XMLID-based subtype when invoking the
composer. A ``default_subtype_xmlid`` context key is transformed into a
``default_subtype_id``, to be used notably in JS where we cannot easily
use a ``ref``-like statement. Post API now also supports 'subytpe_xmlid'
argument allowing to give the xml id and ease calling the methods.
Use ``_xmlid_to_res_id`` to get directly the ID of subtypes in order to
avoid useless queries from ``ref`` that does an exists.
Also remove useless values given to post API, notably author_id that is by
default the current users' partner.
Task-2710804 (Mail: Clean MailThread Posting API)
Part-of: odoo/odoo#99482
Ease the understanding of the notifications sent when users are assigned to an
activity or a model (task, lead, ...).
Technical note:
- the customization of data sent to the email layout template (here subtitles)
should be done by overriding
mail_thread._notify_by_email_prepare_rendering_context on the model.
But in this case, we send an activity (ex.: todo) for a model (ex.: crm.lead)
which involves 2 models. Data from both models must be sent to the template
layout. To solve this problem an optional parameter to
mail_thread.message_notify has been added: subtitles. This allows the
caller which knows about the 2 models to set the values for subtitles for
the template.
- mail_activity._render_notify_header has been added to render the subject and
subtitles using the language of the recipients through the context lang
variable.
- a generic mail notification template has been added and the specific
mail_notification_paynow has been derived from it as the only change is the
handling of the signature.
Task-2801600
Part-of: odoo/odoo#88466
Returning after first loop iteration has the sad side effect of
somehow breaking batch version of methods.
Oversight of odoo/odoo@0ea27f430cclosesodoo/odoo#99630
X-original-commit: 6d6dbe16d4570372fe5fd3d28ebe5c43b646d3bc
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
When assigning activities to people we check target user has the rights to
access to document. Otherwise they end up with notifications and activities
for records they can't see.
This code is currently a loop doing browse and access checks one record
at a time. We improve it by grouping activities by related record model
and target user, allowing to batch some calls.
Note that this somehow reverts odoo/odoo@c38a0d6768 and odoo/odoo@a98c15f443
as normally odoo/odoo@16351e4879 should be sufficient to handle MC use
cases. Lack of clear unit tests for those corner cases make it difficult to
clearly reproduce issue anyway.
Task-2883589 (Activity performance and cleaning)
Part-of: odoo/odoo#93682
MailActivity model has an ``_action_done`` method that is quite heavily
used and overridden. It notably posts messages, create next activities but
also has some specific behavior depending on category.
Purpose of this commit is to improve code of this method to avoid useless
queries, improve performance, and rethink the computation with batch in
mind.
Task-2883589 (Activity performance and cleaning)
Part-of: odoo/odoo#93682
Purpose of this commit is to improve batch creation of activities by trying
to group checks by user and/or model when possible.
Notably
* subscribe partners in batch when several activities are assigned to the
same user (use case: batch assign on leads, users may be assigned on
several records in a single udpate);
* check in batch access on partners;
Task-2883589 (Activity performance and cleaning)
Part-of: odoo/odoo#93682
Change some ``ref`` to low level method ``_xmlid_to_res_id``. The latter one
does not call exists, which allows to gain one query that we do not need
here.
Default methods on activity / activity mixin to find the default activity
type (todo, model-based, generic) are cleaned. Notably code was duplicated
between mixin and activity, it now always call the same code.
Remove an unnecessary ref, probably a leftover of new rendering methods on Qweb.
Remove an unnecessary sudo.
Task-2883589 (Activity performance and cleaning)
Part-of: odoo/odoo#93682
No need to send bus notifications one by one, we may use sendmany. Various
activities crud methods send notifications, better group them when possible.
Task-2883589 (Activity performance and cleaning)
Part-of: odoo/odoo#93682
Purpose is to add helpers on activity model, notably to ease batching based
on models. As activities are linked to records using a res_model / res_id
pair most code is not optimized (checking records one by one). Purpose of
this tool is to ease doing computation by batch of models.
Task-2883589 (Activity performance and cleaning)
Part-of: odoo/odoo#93682
We now return generated records when calling ``_action_send_mail`` on mail
composer. This allows to have access to generated emails (in mass mode) or
posted messages (in comment mode). Otherwise we have to access sub-fields
like activity_ids / message_ids, which may be inefficient or generate extra
ACLs checks.
Also replace some |= with += when usage of OrderedSet is not necessary. To
keep ordering, ordered sets are used when doing an or between record sets.
However in some cases we know we are simply adding records not already in
a previous record set, meaning we can just use +.
Task-2883589 (Activity performance and cleaning)
Part-of: odoo/odoo#93682
This commit aims at removing unuseful help message to:
1/ reduce translators work, to focus on more useful translations
2/ not sending unuseful information in load_views
3/ reduce help message to useful messages, so that we can mark
fields having a tooltip in the future UI.
4/ some cleanup of existing messages too
The main use cases:
- REMOVED: help redundant with the field name, providing no extra info
- MOVED TO COMMENT: technical help messages, that should not be in UX
closesodoo/odoo#97279
Signed-off-by: Fabien Pinckaers <fp@odoo.com>
Current behavior before PR: You have to find the right menu/view and then take
over the ID stored on the activity (through export) to find back the record.
This is annoying, painful and error prone.
Desired behavior after PR is merged: By adding a smartbutton the user can
quick-navigate to the related record in a second. This allows for quickly
finding and opening records which is usually handy when debugging things or
finding back related records.
Task-2868230
closesodoo/odoo#91230
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
There were inconsistencies in the calls to `_render`.
* the view context could contain information that misled developers.
Indeed, the context and value of the view are not supposed to be found
in the rendering. Thus by calling `ir.qweb` with the name of the
template, we ensure that there is no unwanted information and in
addition the cache key is that of the name of the template which saves
a query.
* the context used for rendering was modified by a method on
`ir.ui.view`, except this is not information used by this model. There
is now a `_prepare_environment` method residing on `ir.qweb`. This
method allows to modify the value dictionary as well as the context in
which the rendering will be done. This preparation of the data as well
as my security check is done only once per rendering. This also saves
some queries
* Freeze options for rendering were inconsistent. It could be that
options on which rendering depends were not part of the cache key. Thus,
depending on the user who generated the generation of the rendering
function, there was or was not information in the template. For example
for automatic branding. This is no longer possible, because it is the
context that is used. The options serving as a cache key are only
recorded for information (for the profiling system for example). A
simplification of the `ir.qweb.field` models could be made.
The report rendering and call `ir.qweb` instead of `ir.ui.view`.
Part-of: odoo/odoo#85110
Activity-level feedback method accepts attachment_ids but not its mixin-level
counterpart. This commit fixes that by adding the parameter. The activity-level
action_feedback_schedule_next method now also accepts attachments in addition
to the feedback, making the API coherent through all entry points.
At activity level ``action_done`` now goes through ``action_feedback``. This
means it now has two main methods
* ``action_feedback``;
* ``action_feedback_schedule_next``;
All methods finally end up calling ``_action_done`` and correctly propagate
feedback and attachments. We have a bit less entry points with possible API
changes.
Test mail models are updated to be able to use this small addition.
Task-2710804 (Mail: Clean MailThread API)
Part-of: odoo/odoo#86393
Activities and mailing trace are linked to documents through a model and
a many2one reference field. The latter one is required but is implemented like
an integer field, meaning writing 0 is actually a valid value for 'required'.
In this commit we add a constraint to ensure we never update activities with
a void res_id value. Same for mailing traces. This allows to remove the
required attribute on fields to avoid having redundant sql constraints.
Source: internal feedback about activities with 0 as res_id
Task-2694133
Part-of: odoo/odoo#81292
Accessing `valid_docs.ids` for each activity to check was costly, and in
my example the whole loop took 125 seconds to execute.
By turning it into a set, the same loop takes 0.2 seconds to execute.
When re-constructing the list based on ids to keep the order, using a
set is also faster, and takes another 0.2 seconds instead of 13.6.
closesodoo/odoo#79969
X-original-commit: f994db760b679c8acdaf4245315f89c1d31a9e1c
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Because activities_to_check was assigned in each loop, the result was
only containing the last chunk of 1000 records, instead of the whole
result.
This commit fixes the issue by concatenating into the list instead of
just assigning it.
X-original-commit: c06c96655b88cc4df59b8cdd5f05a2f600255c49
Part-of: odoo/odoo#79969
* = auth_signup, calendar, im_livechat, snailmail_account, survey, test_mail,
web_editor, website_crm_iap_reveal, website_livechat
The aim of this PR is to improve/fix various flaws and limitation of the current
API, to make it easier to use and more efficient.
Notification are now defined with 3 distinct parts:
- the channel determines which client(s) should receive it
- the type determines how it should be handled
- the payload determines any extra information helpful for handling it
Channel
=======
Business code
-------------
- Record channel is introduced for ease of subscribing to and sending
notifications to specific partners, channels, documents, ...
- String channel is still supported (but it is converted internally to the tuple
channel).
- Tuple channel is still supported without any change (but should be avoided
whenever possible due to its complex syntax).
The channel is no longer sent to the client. When the channel was used for
business purpose, the information it contained has been moved into either the
new type, or the payload itself.
Technical note
--------------
All channels are now internally converted to the tuple (db, ...) channel, which
is necessary for the platform code (saas/sh).
Internally, the bus.bus table is not changed, type and payload are grouped
together into what was (and still is) called message.
Type
====
Type is introduced to uniformize the way notifications are sent and handled.
All existing notifications already had some kind of manually-built type in them.
This is now officially supported at the bus API.
In client code this will allow (to be done in future commits) to register one
handler per specific type, instead of having to iterate and to filter all
received notifications on every handler.
Payload
=======
Payload (ex message) did not change, it can still be anything depending on
business needs.
Few adaptations:
- When the type was included on the payload, the type has been moved to the new
type parameter.
- When the channel was used in business code, its data has been copied into the
payload.
task-1891151
closesodoo/odoo#79201
X-original-commit: 543af27c7d6836ffac9e80ff8490b6ddbd849221
Related: odoo/enterprise#21998
Signed-off-by: Sébastien Theys (seb) <seb@odoo.com>
values for next activities are currently prepared inside the `mail_activity._action_done()` method which makes inheritance very difficult. This commit delegates the value computation to a sub-method and thereby improves the extensibility of the module.
required to support changes to enterprise documents odoo/enterprise#20769
Task-2627837
closesodoo/odoo#77004
X-original-commit: a26e6e954c5e6c773f37e9239138a7b94ded821f
Related: odoo/enterprise#21079
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Reorganize code to ease future additions understanding and setting code
at the right place.
Rename some compute methods to have understandable names.
Remove dead imports.
Fix pytz.utc usage.
No functional change comes with this commit. This is only code move.
Task-2631873
PR odoo/odoo#75571
As mail grows and will continue to grow, ordering imports and having right
files naming as well as right content in them is important to understand
module organization and content.
Containing
* reorder init file to give an overview of models;
* move ResGroups override in its own file, outside of res_users file;
* split file containing MailActivity model and MailActivityMixin so that
mixin is contained in its own file, easing followup;
* split Activity and ActivityType models into two files;
No functional change comes with this commit. This is only code move.
Task-2631873
PR odoo/odoo#75571
Following the removal of read access on ir.model (odoo/odoo#69120),
the mail.activity.type model was not accessible to non-admin users due
to the res_model_id many2one field.
Before this commit, a project user could not access the Activity Type
menu.
Convert it to a selection field with the selection values being
computed in sudo.
closesodoo/odoo#74981
Related: odoo/enterprise#20214
Related: odoo/upgrade#2734
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
When sending an email on an activity or a recovery email it is not necessary
to automatically include all recipients as follower. If they perform an action
on the record they will be added as follower. Same if they reply.
Task-2612911
PR odoo/odoo#60792
Purpose of this commit is to avoid forcing mail_post_autofollow to True when
it is set to False. It eases inheritance and custom behavior.
Task-2612911
PR odoo/odoo#60792
This commit fixes the performance issue in getting statistics for
``activity_state`` (colored clock icon for overdue/today/planned) in
CRM. The query has been tested for several years on a large database
(Odoo's own production database).
Performance test on 29 K crm.lead records (activity_state):
With a filter for 10 records:
```
| measurement | before | after |
|--------------------+--------+-------|
| number of queries | 25 | 5 |
| query time, ms | 12 | 95 | (*)
| remaining time, ms | 32 | 7 |
```
All records:
```
| measurement | before | after |
|--------------------+--------+-------|
| number of queries | 1326 | 5 |
| query time, ms | 1739 | 129 |
| remaining time, ms | 47934 | 17 |
```
As we can see in the last results, the time went from almost 50 seconds
(not responsive at all) to 150 milliseconds (responsive). The time
increase in (*) may be caused by imperfect measurements, which are raw
and not averaged measures.
---
opw-2346901
task-1915411
X-original-commit: 1088e73c9a897902f9d2d70df980fe2a5ed23492
Co-authored-by: Nicolas Seinlet <nse@odoo.com>
Before this commit, suppose we have a scenario like below
Task-A:
Activity-1:
name: Email ( Today )
Assigned to: User-1
Task-B:
Activity-1:
name: Email ( Today )
assigned to: User-2
Activity-2:
name: Call ( Due in 3 Days )
assigned to: User-1
When User-1 goes through the systray 'Today' filter shortcut he gets both
Task-A and Task-B in the list instead of only Task-A. Indeed currently
activities are not filtered based on current user with its deadlines.
However purpose of systray is to indicate activities current user has to
perform instead of global activities.
After this commit activities will be filtered based on deadlines as well as the
current user. In order to achieve this behavior we needed to pass a domain like
[
('activity_ids.date_deadline','=', fields.Date.today()),
('activity_ids.user_id','=', 1)
]
And for that purpose we introduced a non-stored compute field with a search
method.
Task ID-2438822
COM PR odoo/odoo#72219
X-original-commit: f4eaf4d8fb2f97240201104dcd4fc7e2674bce02
This commit adds some tests on mailing.activity to ensure read grouping is only
possible when the user has access to the underlying document.
Task-2272475
This commit adds some tests on mailing.activity to ensure _searching is only
possible when the user has access to the underlying document.
Query count for 'test_adv_activity_mixin' had to be slightly adapted (+1) since
calling 'action_close' in turn calls 'activity_search' that calls 'search' on
mail.activity that now runs an additional query (see '_search' override
docstring).
Task-2272475
* Reorganize and reword some of the fields for the activity form type view
* The fields `force_next` from `mail.activity.type` and its related
field from `mail.activity` are removed.
Instead, a new field `chaining_type`, which is a `selection` will
improve the readability of the activity_type form. (It is made more
obvious that the user has to choose between 2 modes :
- 'Trigger Next Activity': used when the user wants to specify the type of the
next activity, which will be triggered once the current activity is done
- 'Suggest Next Activity': used when the user wants to recommend the
next activity for the user to schedule once the current activity is done
* To be consistent with this change :
- The field `default_next_type_id` is renamed `triggered_next_type_id`
- The field `next_type_ids` is renamed `suggested_next_type_ids`
* The field `default_description` is renamed `default_note` to better match the
`note` field from `mail.activity`
* About the specific case of activity_type.category = 'upload_file' :
An activity which has this type's category is automatically marked as done as soon as
the file is uploaded. This prevents the user from choosing a "next activity type".
As such, an activity_type with this category can only make use of the
chaining_type = "trigger", to be part of an automated process.
An activity_type with this chaining_type should have the
triggered_next_type_id set (usually required in the Form).
But, since it does not make sense to set suggested_next_type_ids in this case :
- chaining_type will stay hidden in the Form
- triggered_next_type_id will always be shown and is not marked as required in the Form
- if triggered_next_type_id is not set, chaining_type will be "suggest"
Task ID : 2410217
PR : https://github.com/odoo/odoo/pull/63370
UPGRADE : https://github.com/odoo/upgrade/pull/2167
In case of bad translation that doesn't contain the placeholder
Context:
A bad Japanese translation was inserted
#. module: mail
#: code:addons/mail/models/mail_thread.py:0
#, python-format
msgid "Create new %(document)s"
msgstr "新しい%(ドキュメント)を作成する"
The translation has been corrected but use the 14.0 syntax of _ method
to include placeholders and fallback on the English source term in
case of bad translation
cf odoo/odoo#52155closesodoo/odoo#65586
X-original-commit: 48cc6b1f2b3208e8affd5f6a261751fe973c2091
Signed-off-by: Martin Trigaux (mat) <mat@odoo.com>
See merge commit for more details.
Note that mail.alias model will be done in a separate commit.
Task ID-2330149
COM PR odoo/odoo#61246
ENT PR odoo/enterprise#14561
Purpose
=======
Make the "activity_state" searchable on the "mail.activity" mixin.
This field is not stored as it depends on the current time.
Technical
=========
To make the search, we perform a SQL query.
The "activity_state" depends on the state of each activities on the
record. And this state also depends on the timezone of the user of
the activity. That's what made things tricky and we need to make the
conversion in SQL for performance purpose (we can not fetch all records
and compute them in python).
There's a special case, where there's less than 24 hours between the
deadline and the current time but one day of difference. In that case
the state should be "planned" and not "today". This case is handle by
the function "DATE_TRUNC" (e.g. 23h 01/01/2020 & 1h 02/02/2020).
Also for performance purpose, we compute the delay only once and we use
the function "SIGN" so we can use a switch/case instead of duplicating
3 times the expressions.
Task 2354754
closesodoo/odoo#60074
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>