diff --git a/addons/mail/models/mail_render_mixin.py b/addons/mail/models/mail_render_mixin.py index a0d633538dc..ddd32659a03 100644 --- a/addons/mail/models/mail_render_mixin.py +++ b/addons/mail/models/mail_render_mixin.py @@ -183,10 +183,74 @@ class MailRenderMixin(models.AbstractModel): return html + @api.model + def _render_encapsulate(self, layout_xmlid, html, add_context=None, context_record=None): + try: + template = self.env.ref(layout_xmlid, raise_if_not_found=True) + except ValueError: + _logger.warning('QWeb template %s not found when rendering encapsulation template.' % (layout_xmlid)) + else: + record_name = context_record.display_name if context_record else '' + model_description = self.env['ir.model']._get(context_record._name).display_name if context_record else False + template_ctx = { + 'body': html, + 'record_name': record_name, + 'model_description': model_description, + 'company': context_record['company_id'] if (context_record and 'company_id' in context_record) else self.env.company, + 'record': context_record, + } + if add_context: + template_ctx.update(**add_context) + + html = template._render(template_ctx, engine='ir.qweb', minimal_qcontext=True) + html = self.env['mail.render.mixin']._replace_local_links(html) + return html + # ------------------------------------------------------------ # RENDERING # ------------------------------------------------------------ + @api.model + def _render_qweb_eval_context(self): + """ Prepare qweb evaluation context, containing for all rendering + + * ``user``: current user browse record; + * ``ctx```: current context; + * various formatting tools; + """ + render_context = { + 'format_date': lambda date, date_format=False, lang_code=False: format_date(self.env, date, date_format, lang_code), + 'format_datetime': lambda dt, tz=False, dt_format=False, lang_code=False: format_datetime(self.env, dt, tz, dt_format, lang_code), + 'format_amount': lambda amount, currency, lang_code=False: tools.format_amount(self.env, amount, currency, lang_code), + 'format_duration': lambda value: tools.format_duration(value), + 'user': self.env.user, + 'ctx': self._context, + } + return render_context + + @api.model + def _render_template_qweb(self, template_src, model, res_ids, add_context=None): + view = self.env.ref(template_src, raise_if_not_found=False) or self.env['ir.ui.view'] + results = dict.fromkeys(res_ids, u"") + if not view: + return results + + # prepare template variables + variables = self._render_qweb_eval_context() + if add_context: + variables.update(**add_context) + + for record in self.env[model].browse(res_ids): + variables['object'] = record + try: + render_result = view._render(variables, engine='ir.qweb', minimal_qcontext=True) + except Exception as e: + _logger.info("Failed to render template : %s (%d)" % (template_src, view.id), exc_info=True) + raise UserError(_("Failed to render template : %s (%d)") % (template_src, view.id)) + results[record.id] = render_result + + return results + @api.model def _render_jinja_eval_context(self): """ Prepare jinja evaluation context, containing for all rendering @@ -207,7 +271,7 @@ class MailRenderMixin(models.AbstractModel): return render_context @api.model - def _render_template_jinja(self, template_txt, model, res_ids): + def _render_template_jinja(self, template_txt, model, res_ids, add_context=None): """ Render a string-based template on records given by a model and a list of IDs, using jinja. @@ -238,6 +302,9 @@ class MailRenderMixin(models.AbstractModel): # prepare template variables variables = self._render_jinja_eval_context() + if add_context: + variables.update(**add_context) + # TDE CHECKME # records = self.env[model].browse(it for it in res_ids if it) # filter to avoid browsing [None] if any(r is None for r in res_ids): @@ -271,11 +338,12 @@ class MailRenderMixin(models.AbstractModel): return rendered @api.model - def _render_template(self, template_txt, model, res_ids, engine='jinja', post_process=False): + def _render_template(self, template_src, model, res_ids, engine='jinja', add_context=None, post_process=False): """ Render the given string on records designed by model / res_ids using the given rendering engine. Currently only jinja is supported. - :param str template_txt: template text to render + :param str template_src: template text to render (jinja) or xml id of view (qweb) + this could be cleaned but hey, we are in a rush :param str model: model name of records on which we want to perform rendering :param list res_ids: list of ids of records (all belonging to same model) :param string engine: jinja @@ -286,10 +354,13 @@ class MailRenderMixin(models.AbstractModel): """ if not isinstance(res_ids, (list, tuple)): raise ValueError(_('Template rendering should be called only using on a list of IDs.')) - if engine != 'jinja': - raise ValueError(_('Template rendering supports only jinja.')) + if engine not in ('jinja', 'qweb'): + raise ValueError(_('Template rendering supports only jinja or qweb.')) - rendered = self._render_template_jinja(template_txt, model, res_ids) + if engine == 'qweb': + rendered = self._render_template_qweb(template_src, model, res_ids, add_context=add_context) + else: + rendered = self._render_template_jinja(template_src, model, res_ids, add_context=add_context) if post_process: rendered = self._render_template_postprocess(rendered)