Bug
===
Since 69f911d994 , the body needs to be a
Markup object if we don't want to escape it. So, when we log an email
from the mail plugin, because we just log the string, it gets escaped.
Task-3387100
closesodoo/odoo#128984
X-original-commit: ef068b3b0d7df9f2e064889c62623b34f31e156b
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.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
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
Bug
===
Currently, we try to enrich the domains even if they are in the
`_MAIL_DOMAIN_BLACKLIST`. IAP always return a "missing data" error
because it can't enrich "gmail.com", etc except for "odoo.com". In that
case the enrichment is successful, but because the domain is
blacklisted, we use the entire email to find the company (and so it
will create a company for each odoo.com email addresses).
The test that was removed was wrong. It works because we mocked the
enrichment response, but in practice it will always return a missing
data error.
Task-3050230
closesodoo/odoo#107235
X-original-commit: 37503108cd878412474b5486877a861dad2efc1d
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Translated fields no longer use the model ir.translation. Instead they store
all their values as JSON, and store them into JSONB columns in the model's
table. The field's column value is either NULL or a JSON dict mapping language
codes to text (the field's value in the corresponding language), and must
contain an entry for key 'en_US' (as it is used as a fallback for all other
languages). Empty text is allowed in translation values, but not NULL.
Here are examples for a field with translate=True:
NULL
{"en_US": "Foo"}
{"en_US": "Foo", "fr_FR": "Bar", "nl_NL": "Baz"}
{"en_US": "Foo", "fr_FR": "", "nl_NL": "Baz"}
Like before, writing False to the field makes it NULL, i.e., False in all
languages. However, writing "" to the field makes its value empty in the
current language, but does not discard the values in the other languages.
Here are examples for a field with translate=xml_translate:
NULL
{"en_US": "<div>Foo<p>Bar</p></div>", "fr_FR": "<div>Fou<p>Barre</p></div>"}
Change for callable(translate) fields: one can now write any value in any
language on such a field. The new value will be adapted in all languages, based
on the mapping of terms between languages in the old values. Basically the
structure of the value must remain the same in all languages, like before.
Reading a translated field is now both simpler and faster than the former
implementation. We fetch the value of the field in the current language by
coalescing its value with the 'en_US' value of the field:
SELECT id, COALESCE(name->>'fr_FR', name->>'en_US') AS name ...
The raw cache of the field contains either None or a dict which is conceptually
a subset of the JSON value in database (except for missing languages). For the
sake of simplicity, most cache operations deal with the dict and return the text
value in the current language.
Trigram indexes have been adapted to the new storing strategy, and should enable
to search in any language. Before this change, only the source value of the
field ('en_US') could be indexed.
Computed stored translated fields are not supported by the framework, because of
the complexity of the computation itself: the field would need to be computed in
all active languages. We chose to not provide any hook to compute a field in
all languages at once, and the framework always invokes a compute method once to
recompute it.
Code translations are no longer stored into the database. They become static,
and are extracted from the PO files when needed. The worker simply uses a cache
with extracted code translations for performance. This is reasonable, since
fr_FR code translations for all modules takes around 2MB of memory, and the
cache can be shared among all registries in the worker. Changing code
translations requires to update the corresponding PO file and reloading the
worker(s).
Performance summary:
(+) reading 'model' translated fields is faster
(+) reading 'model_terms' translated fields is much faster (no need to inject
translations into the source value)
(+) searching translated fields with operator 'ilike' is much faster when the
field is indexed with 'trigram'
(+) updating translated fields requires less ORM flushing
(-) importing translations from PO files is 2x slower
Some extra fixes:
- make field 'name' of ir.actions.actions translated; because of the PG
inheritance, this is necessary to make the column definition consistent in
all models that inherit from ir.actions.actions.
- add some backend API for the web/website client for editing translations
- move methods get_field_string() to model ir.model.fields
- move _load_module_terms to model ir.module.module
- adapt tests in test_impex, test_new_api
- because env.lang is injected into SQL queries, its returned value is
now guaranteed to correspond to a valid active language or None
- remove wizard to insert missing translations (no longer makes sense)
task-id: 2081307
Co-authored-by: Fabien Pinckaers <fp@openerp.com>
Co-authored-by: Raphael Collet <rco@odoo.com>
Purpose
=======
Hide the "Create Partner" button if we do not have the "create" access
right.
Do not offer to create a project if the current user can't.
Do not try to enrich if we can't create a partner.
The write access on the partner is checked on the record itself because
of access rules.
Task-2826471
X-original-commit: b678a9bc1298e9a1973074740a8c8a1d471b6848
Part-of: odoo/odoo#93058
Bug
===
1. Open an email in Outlook, and create the contact
2. Go to Odoo and remove the partner
3. Without refreshing the browser tab, click on the "reload" icon of
the addin. A traceback will be raised on the Odoo side
Task-2601837
X-original-commit: bb2e5ce9cf149a5cfd68cf908184c823f882d97d
Part-of: odoo/odoo#89848
Purpose
=======
Improve the error message when the email
of the contact / company is not valid.
Task-2601837
closesodoo/odoo#86080
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Purpose
=======
If the partner was removed after the user open the email on the Gmail
side, return a clean error message instead of raising a traceback.
Add translations for the new strings in the plugin.
Links
=====
Task-2567566
Followup of odoo/odoo#73653
See odoo/mail-client-extensions#15closesodoo/odoo#75076
X-original-commit: e782c85b95aed30dd38bd30c29e57a9acc540a49
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Add an enrich and update endpoint allowing the user to update an existing
company if the company has no insights, as this can bring valuable information
for the user especially if the company has no infos.
Task-2563180
closesodoo/odoo#73658
X-original-commit: 72c35667d3e6f99cb4cfdbd1c93b877cc9fef750
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
This commit fixes the multi_company access error when the user is attempting to
see a record belonging to another company then the one he is logged in to from
the plugins, upon login, it returns all the company ids related to the user so
that the plugin redirects the user to the record with all companies ticked.
Task-2541205
closesodoo/odoo#72529
Plugin-pr: https://github.com/odoo/mail-client-extensions/pull/10
X-original-commit: 92972fa16920e070e533040439243a0257357aad
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Purpose
=======
Allow to upload the attachments of the email when logging it on the
partner / lead / ticket.
Technical
=========
The attachments posted on this new endpoint are base 64 encoded and
added in the JSON data in a list (name, encoded content).
Links
=====
Task 2545048
See odoo/mail-client-extensions/pull/11
closesodoo/odoo#72515
X-original-commit: 71626ad727fd573fd98e595e0ae964ce0559e547
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
In mail_plugin module, add a method which returns translatable modules,
this method will be overridden in the other modules to add their module names.
Translations are prepared via the _prepare_translations method which uses
the get_translations_for_webclient method, this way we can easily fetch
translations without having to write python code.
We also add xml files in "static/", these files contain terms to be translated,
for each plugin we create a separate xml file so that we can easily update each
plugin separately.
This implementation will allow having translations handled by Odoo, which has
several advantages:
- existing system, nothing to develop
- it will use transifex and the terms will be translated by the community
- forces that mail_client implementations to have the same logic (consistency)
- compared to other solutions which rely on python code to return translations,
this solution is more robust as it avoids having to type the string to
translate twice
Task-2480075
closesodoo/odoo#69118
Ent-pr: https://github.com/odoo/enterprise/pull/17626
Plugin-pr: https://github.com/odoo/mail-client-extensions/pull/6
Related: odoo/enterprise#17626
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Purpose
=======
Return the "is_company" field for the <res.partner>, so when the partner
has no image, we can display the appropriate placeholder image
(person for non-company and buildings image for company).
Task 2496443
closesodoo/odoo#69562
X-original-commit: 37766d3ef32816f332cd285cce8dbb1fa5e4b66a
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Purpose
=======
Avoid creating / enriching multiple time the same company.
It can occur in many situation; when IAP do not return an email address
the the company, when the domain is blacklisted...
We also want to remove the field "iap_enrich_info" from the res.partner
model because this field can be heavy (JSON field) and the res.partner
model is used a lot.
Technical
=========
For this purpose, we create a new model <res.partner.iap> which will
store the IAP response and the requested domain.
So we can retrieve the previously enriched company regardless of the
partner's values
Task 2466653
See odoo/odoo/pull/68286
See odoo/upgrade/pull/2301
closesodoo/odoo#68286
Related: odoo/upgrade#2301
Related: odoo/enterprise#17426
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>