[FIX] mail: fix composer default values computation

As default is called numerous times with sometimes all fields, sometimes
only one field we have to ensure we avoid computing and setting unnecessary
or wrong values. We suspect this comes from default_get being called more
often at creation time since Odoo v14.

Default values for some fields in mail composer are dependent on each other.
Especially composition mode and model / res_id(s) are important for some
fields as behavior is not the same in comment or mass mail mode (subject
set / not set, template values rendered / displayed raw, ...).

Especially subject is wrongly computed in mass mail mode. For example use a
mass mail composer action on leads without template. Indeed a default_get
is called on subject alone. As web client adds active_model / active_id
automatically default returns a value for subject while it should not as
other values (model, res_id) are not asked and therefore not correctly
computed. It makes composer compute values in comment mode while it should
stay in mass mode.

In this commit we fix that behavior by

  * computing only requested values (better match returned values and asked
    fields);
  * avoid computing values if context values are not given (model, res_id or
    res_ids, composition_mode);

Task ID-2390314
PR odoo/odoo#62061

X-original-commit: 1c8ca358d75c9fe00631731d5061674c0a3a040b
This commit is contained in:
Thibault Delavallée
2020-11-26 10:43:08 +00:00
parent 1e53dd9adb
commit 7ca9cdd392
2 changed files with 14 additions and 18 deletions
+13 -16
View File
@@ -63,25 +63,22 @@ class MailComposer(models.TransientModel):
if missing_author:
result['author_id'] = author_id
result['composition_mode'] = result.get('composition_mode', 'comment')
result['model'] = result.get('model', self._context.get('active_model'))
result['res_id'] = result.get('res_id', self._context.get('active_id'))
if 'no_auto_thread' not in result and (result['model'] not in self.env or not hasattr(self.env[result['model']], 'message_post')):
result['no_auto_thread'] = True
if 'model' in fields and 'model' not in result:
result['model'] = self._context.get('active_model')
if 'res_id' in fields and 'res_id' not in result:
result['res_id'] = self._context.get('active_id')
if 'no_auto_thread' in fields and 'no_auto_thread' not in result and result.get('model'):
# doesn't support threading
if result['model'] not in self.env or not hasattr(self.env[result['model']], 'message_post'):
result['no_auto_thread'] = True
vals = {}
if 'active_domain' in self._context: # not context.get() because we want to keep global [] domains
vals['active_domain'] = '%s' % self._context.get('active_domain')
if result['composition_mode'] == 'comment':
vals.update(self.get_record_data(result))
result['active_domain'] = '%s' % self._context.get('active_domain')
if result.get('composition_mode') == 'comment' and (set(fields) & set(['model', 'res_id', 'partner_ids', 'record_name', 'subject'])):
result.update(self.get_record_data(result))
for field in vals:
if field in fields:
result[field] = vals[field]
if fields is not None:
[result.pop(field, None) for field in list(result) if field not in fields]
return result
filtered_result = dict((fname, result[fname]) for fname in result if fname in fields)
return filtered_result
# content
subject = fields.Char('Subject')
+1 -2
View File
@@ -107,8 +107,7 @@ class TestComposerForm(TestMailComposer):
@users('employee')
def test_mail_composer_mass(self):
composer_form = Form(self.env['mail.compose.message'].with_context(self._get_web_context(self.test_records, add_web=True)))
# TDE FIXME: currently failing
# self.assertFalse(composer_form.subject, 'MailComposer: mass mode should have void default subject if no template')
self.assertFalse(composer_form.subject, 'MailComposer: mass mode should have void default subject if no template')
# record name not displayed currently in view
# self.assertFalse(composer_form.record_name, 'MailComposer: mass mode should have void record name')
self.assertFalse(composer_form.no_auto_thread)