[REF] mail, various: cleanup input/output of generation methods on template and composer
Purpose of this commit is to prepare further improvements in template and
composer rendering methods. First step is to
* make them private;
* correctly name parameters (notably rename fields to render_fields to avoid
collision with odoo.fields);
* remove the "single / multi" mode. This is a relic of old implementation
when rendering was done mainly record by record and sometimes by batch.
Now everything should be batched;
* split some lines to ease future diff in upcoming commits;
* improve some docstrings;
Next commits will rewrite and split parts of ``_generate_email``.
Task-2710804 (Mail: Clean MailThread Posting API)
Prepares Task-2088884 (Mail: Use editable computed stored fields in composer)
Part-of: odoo/odoo#99482
This commit is contained in:
@@ -191,7 +191,7 @@ class MailTemplate(models.Model):
|
||||
# MESSAGE/EMAIL VALUES GENERATION
|
||||
# ------------------------------------------------------------
|
||||
|
||||
def generate_recipients(self, results, res_ids):
|
||||
def _generate_recipients(self, results, res_ids):
|
||||
"""Generates the recipients of the template. Default values can ben generated
|
||||
instead of the template values if requested by template or context.
|
||||
Emails (email_to, email_cc) can be transformed into partners if requested
|
||||
@@ -228,24 +228,24 @@ class MailTemplate(models.Model):
|
||||
results[res_id]['partner_ids'] = partner_ids
|
||||
return results
|
||||
|
||||
def generate_email(self, res_ids, render_fields):
|
||||
"""Generates an email from the template for given the given model based on
|
||||
records given by res_ids.
|
||||
def _generate_template(self, res_ids, render_fields):
|
||||
""" Render values from template 'self' on records given by 'res_ids'.
|
||||
Those values are generally used to create a mail.mail or a mail.message.
|
||||
Model of records is the one defined on template.
|
||||
|
||||
:param res_id: id of the record to use for rendering the template (model
|
||||
is taken from template definition)
|
||||
:returns: a dict containing all relevant fields for creating a new
|
||||
mail.mail entry, with one extra key ``attachments``, in the
|
||||
format [(report_name, data)] where data is base64 encoded.
|
||||
:param list res_ids: list of record IDs on which template is rendered;
|
||||
:param list render_fields: list of fields to render on template;
|
||||
|
||||
:returns: a dict of (res_ids, values) where values contains all rendered
|
||||
fields asked in ``render_fields``. Asking for attachments adds an
|
||||
'attachments' key using the format [(report_name, data)] where data
|
||||
is base64 encoded. Asking for recipients adds a 'partner_ids' key.
|
||||
Note that 2many fields contain a list of IDs, not commands.
|
||||
"""
|
||||
self.ensure_one()
|
||||
multi_mode = True
|
||||
if isinstance(res_ids, int):
|
||||
res_ids = [res_ids]
|
||||
multi_mode = False
|
||||
|
||||
results = dict()
|
||||
for lang, (template, template_res_ids) in self._classify_per_lang(res_ids).items():
|
||||
for _lang, (template, template_res_ids) in self._classify_per_lang(res_ids).items():
|
||||
for field in render_fields:
|
||||
generated_field_values = template._render_field(
|
||||
field, template_res_ids
|
||||
@@ -254,7 +254,7 @@ class MailTemplate(models.Model):
|
||||
results.setdefault(res_id, dict())[field] = field_value
|
||||
# compute recipients
|
||||
if any(field in render_fields for field in ['email_to', 'partner_to', 'email_cc']):
|
||||
results = template.generate_recipients(results, template_res_ids)
|
||||
results = template._generate_recipients(results, template_res_ids)
|
||||
# update values for all res_ids
|
||||
for res_id in template_res_ids:
|
||||
values = results[res_id]
|
||||
@@ -291,7 +291,7 @@ class MailTemplate(models.Model):
|
||||
raise UserError(_('Unsupported report type %s found.', report.report_type))
|
||||
result, report_format = res
|
||||
|
||||
# TODO in trunk, change return format to binary to match message_post expected format
|
||||
# TODO in trunk, change return report_format to binary to match message_post expected format
|
||||
result = base64.b64encode(result)
|
||||
if not report_name:
|
||||
report_name = 'report.' + report_service
|
||||
@@ -310,7 +310,7 @@ class MailTemplate(models.Model):
|
||||
results[res_id]['attachment_ids'] += additional_attachments.get('attachment_ids', [])
|
||||
results[res_id]['attachments'] += additional_attachments.get('attachments', [])
|
||||
|
||||
return multi_mode and results or results[res_ids[0]]
|
||||
return results
|
||||
|
||||
# ------------------------------------------------------------
|
||||
# EMAIL
|
||||
@@ -342,7 +342,7 @@ class MailTemplate(models.Model):
|
||||
Attachment = self.env['ir.attachment'] # TDE FIXME: should remove default_type from context
|
||||
|
||||
# create a mail_mail based on values, without attachments
|
||||
values = self.generate_email(
|
||||
values = self._generate_template(
|
||||
res_id,
|
||||
('auto_delete',
|
||||
'body_html',
|
||||
@@ -354,7 +354,7 @@ class MailTemplate(models.Model):
|
||||
'scheduled_date',
|
||||
'subject',
|
||||
)
|
||||
)
|
||||
)[res_id]
|
||||
values['recipient_ids'] = [Command.link(pid) for pid in values.get('partner_ids', list())]
|
||||
values['attachment_ids'] = [Command.link(aid) for aid in values.get('attachment_ids', list())]
|
||||
values.update(email_values or {})
|
||||
|
||||
@@ -390,7 +390,7 @@ class MailComposer(models.TransientModel):
|
||||
|
||||
# render all template-based value at once
|
||||
if mass_mail_mode and self.model:
|
||||
rendered_values = self.render_message(res_ids)
|
||||
rendered_values = self._render_message(res_ids)
|
||||
# compute alias-based reply-to in batch
|
||||
reply_to_value = dict.fromkeys(res_ids, None)
|
||||
if mass_mail_mode and not self.reply_to_force_new:
|
||||
@@ -585,7 +585,7 @@ class MailComposer(models.TransientModel):
|
||||
if template.mail_server_id:
|
||||
values['mail_server_id'] = template.mail_server_id.id
|
||||
elif template_id:
|
||||
values = self.generate_email_for_composer(
|
||||
values = self._generate_email_for_composer(
|
||||
template_id, [res_id],
|
||||
('attachment_ids',
|
||||
'body_html',
|
||||
@@ -649,7 +649,7 @@ class MailComposer(models.TransientModel):
|
||||
|
||||
return {'value': values}
|
||||
|
||||
def render_message(self, res_ids):
|
||||
def _render_message(self, res_ids):
|
||||
"""Generate template-based values of wizard, for the document records given
|
||||
by res_ids. This method is meant to be inherited by email_template that
|
||||
will produce a more complete dictionary, using qweb templates.
|
||||
@@ -669,10 +669,6 @@ class MailComposer(models.TransientModel):
|
||||
subject, body, email_from and reply_to
|
||||
"""
|
||||
self.ensure_one()
|
||||
multi_mode = True
|
||||
if isinstance(res_ids, int):
|
||||
multi_mode = False
|
||||
res_ids = [res_ids]
|
||||
|
||||
subjects = self._render_field('subject', res_ids)
|
||||
# We want to preserve comments in emails so as to keep mso conditionals
|
||||
@@ -696,7 +692,7 @@ class MailComposer(models.TransientModel):
|
||||
|
||||
# generate template-based values
|
||||
if self.template_id:
|
||||
template_values = self.generate_email_for_composer(
|
||||
template_values = self._generate_email_for_composer(
|
||||
self.template_id.id, res_ids,
|
||||
('attachment_ids',
|
||||
'email_to',
|
||||
@@ -721,24 +717,19 @@ class MailComposer(models.TransientModel):
|
||||
# update template values by composer values
|
||||
template_values[res_id].update(results[res_id])
|
||||
|
||||
return multi_mode and template_values or template_values[res_ids[0]]
|
||||
return template_values
|
||||
|
||||
@api.model
|
||||
def generate_email_for_composer(self, template_id, res_ids, fields):
|
||||
""" Call email_template.generate_email(), get fields relevant for
|
||||
def _generate_email_for_composer(self, template_id, res_ids, render_fields):
|
||||
""" Call email_template._generate_template(), get fields relevant for
|
||||
mail.compose.message, transform email_cc and email_to into partner_ids """
|
||||
multi_mode = True
|
||||
if isinstance(res_ids, int):
|
||||
multi_mode = False
|
||||
res_ids = [res_ids]
|
||||
|
||||
returned_fields = list(fields) + ['partner_ids', 'attachments']
|
||||
returned_fields = list(render_fields) + ['partner_ids', 'attachments']
|
||||
values = dict.fromkeys(res_ids, False)
|
||||
|
||||
template_values = self.env['mail.template'].with_context(tpl_partners_only=True).browse(template_id).generate_email(res_ids, fields)
|
||||
template_values = self.env['mail.template'].with_context(tpl_partners_only=True).browse(template_id)._generate_template(res_ids, render_fields)
|
||||
for res_id in res_ids:
|
||||
res_id_values = dict((field, template_values[res_id][field]) for field in returned_fields if template_values[res_id].get(field))
|
||||
res_id_values['body'] = res_id_values.pop('body_html', '')
|
||||
values[res_id] = res_id_values
|
||||
|
||||
return multi_mode and values or values[res_ids[0]]
|
||||
return values
|
||||
|
||||
@@ -55,7 +55,7 @@ class MailTemplatePreview(models.TransientModel):
|
||||
help="The queue manager will send the email after the date")
|
||||
body_html = fields.Html('Body', compute='_compute_mail_template_fields', sanitize=False)
|
||||
attachment_ids = fields.Many2many('ir.attachment', 'Attachments', compute='_compute_mail_template_fields')
|
||||
# Extra fields info generated by generate_email
|
||||
# Extra fields info generated by _generate_template
|
||||
partner_ids = fields.Many2many('res.partner', string='Recipients', compute='_compute_mail_template_fields')
|
||||
|
||||
@api.depends('model_id')
|
||||
@@ -76,10 +76,10 @@ class MailTemplatePreview(models.TransientModel):
|
||||
self._set_mail_attributes()
|
||||
else:
|
||||
copy_depends_values['resource_ref'] = '%s,%s' % (self.resource_ref._name, self.resource_ref.id)
|
||||
mail_values = mail_template.with_context(template_preview_lang=self.lang).generate_email(
|
||||
self.resource_ref.id,
|
||||
mail_values = mail_template.with_context(template_preview_lang=self.lang)._generate_template(
|
||||
[self.resource_ref.id],
|
||||
self._MAIL_TEMPLATE_FIELDS
|
||||
)
|
||||
)[self.resource_ref.id]
|
||||
self._set_mail_attributes(values=mail_values)
|
||||
self.error_msg = False
|
||||
except (ValueError, UserError) as user_error:
|
||||
|
||||
@@ -135,7 +135,7 @@ class ChannelUsersRelation(models.Model):
|
||||
record_email_values = dict()
|
||||
for template, records in template_to_records.items():
|
||||
record_email_values.update(
|
||||
template.generate_email(
|
||||
template._generate_template(
|
||||
records.ids,
|
||||
['body_html',
|
||||
'email_from',
|
||||
@@ -148,6 +148,9 @@ class ChannelUsersRelation(models.Model):
|
||||
mail_mail_values = []
|
||||
for record in self:
|
||||
email_values = record_email_values.get(record.id)
|
||||
# attachments specific not supported currently, only attachment_ids
|
||||
email_values.pop('attachments', False)
|
||||
|
||||
if not email_values or not email_values.get('partner_ids'):
|
||||
continue
|
||||
|
||||
|
||||
Reference in New Issue
Block a user