def send(self, recipients, sender=None, record=None, record_name=None): recipient_partners = [] for recipient in recipients: recipient_partners.append((4, recipient.sudo().partner_id.id)) subtype = None if not sender: sender = self.env.ref('message_template.user_messages') subtype = self.env.ref('message_template.subtype_system_message') base_url = self.env['ir.config_parameter'].get_param('web.base.url') def link_to(record): """ Create an absolute link to the given record. """ path = '/web#id={}&model={}'.format(record.id, record._name) return urljoin(base_url, path) # Enable resolution of ${variables} inside body template_context = { 'record': record, 'context': self.env.context, 'base_url': base_url, 'link_to': link_to, 'site_name': self.env.user.company_id.name, 'bleach': filters.bleach, } body_template = mako_template_env.from_string(tools.ustr(self.body)) body_rendered = body_template.render(template_context) subject_template = mako_template_env.from_string( tools.ustr(self.subject)) subject_rendered = subject_template.render(template_context) self.env['mail.message'].sudo().create({ 'type': 'comment', 'author_id': sender.sudo().partner_id.id, 'partner_ids': recipient_partners, 'model': self.model, 'res_id': record and record.id, 'record_name': record_name or (record and record.display_name), 'subject': subject_rendered, 'body': body_rendered, 'template': self.id, 'subtype_id': subtype and subtype.id })
def render_signature_id(self): if not self.signature_id: return mako = mako_template_env.from_string(tools.ustr(self.signature_id.template)) html = mako.render({'user': self}) if html != self.signature: self.signature = html
def render_signature_id(self): if not self.signature_id: return mako = mako_template_env.from_string(tools.ustr(self.signature_id.template)) html = mako.render({'user':self}) if html != self.signature: self.signature = html
def render_template(self, cr, uid, template, model, res_id, context=None): result = '' try: mako_template_env.autoescape = False result = super(email_template, self).render_template(cr, uid, template, model, res_id, context) finally: mako_template_env.autoescape = True if (model == 'newsletter.newsletter' and res_id and context.get('newsletter_res_id')): newsletter = self.pool.get(model).browse(cr, uid, res_id, context=context) user = self.pool.get('res.users').browse(cr, uid, uid, context=context) result = mako_template_env.from_string(result).render({ 'object': self.pool.get(newsletter.type_id.model.model).browse( cr, uid, context.get('newsletter_res_id'), context), 'user': user, 'ctx': context }) return result
def send(self, recipients, sender=None, record=None, record_name=None): recipient_partners = [] for recipient in recipients: recipient_partners.append( (4, recipient.partner_id.id) ) subtype = None if not sender: sender = self.env.ref('message_template.user_messages') subtype = self.env.ref('message_template.subtype_system_message') # Enable resolution of ${variables} inside body body_template = mako_template_env.from_string(tools.ustr(self.body)) body_rendered = body_template.render({'record': record}) self.env['mail.message'].sudo().create({ 'type': 'comment', 'author_id': sender.partner_id.id, 'partner_ids': recipient_partners, 'model': self.model, 'res_id': record and record.id, 'record_name': record_name or (record and record.name), 'subject': self.subject, 'body': body_rendered, 'template': self.id, 'subtype_id': subtype and subtype.id })
def render_template_batch(self, cr, uid, template, model, res_ids, context=None, post_process=False): result = {} try: if model == 'newsletter.newsletter': mako_template_env.autoescape = False post_process = False result = super(email_template, self).render_template_batch( cr, uid, template, model, res_ids, context=context, post_process=post_process) finally: if model == 'newsletter.newsletter': mako_template_env.autoescape = True if model == 'newsletter.newsletter' and res_ids and result and\ context.get('newsletter_res_id'): for res_id, rendered in result.iteritems(): newsletter = self.pool[model].browse( cr, uid, res_id, context=context) user = self.pool['res.users'].browse( cr, uid, uid, context=context) template = mako_template_env.from_string(rendered) result[res_id] = template.render({ 'object': self.pool[newsletter.type_id.model.model].browse( cr, uid, context.get('newsletter_res_id'), context), 'user': user, 'ctx': context, 'format_tz': lambda dt, tz=False, fmt=False: format_tz(self.pool, cr, uid, dt, tz, fmt, context), }) return result
def send(self, recipients, sender=None, record=None, record_name=None): recipient_partners = [] for recipient in recipients: recipient_partners.append( (4, recipient.sudo().partner_id.id) ) subtype = None if not sender: sender = self.env.ref('message_template.user_messages') subtype = self.env.ref('message_template.subtype_system_message') base_url = self.env['ir.config_parameter'].get_param('web.base.url') def link_to(record): """ Create an absolute link to the given record. """ path = '/web#id={}&model={}'.format(record.id, record._name) return urljoin(base_url, path) # Enable resolution of ${variables} inside body template_context = { 'record': record, 'context': self.env.context, 'base_url': base_url, 'link_to': link_to, 'site_name': self.env.user.company_id.name, 'bleach': filters.bleach, } body_template = mako_template_env.from_string(tools.ustr(self.body)) body_rendered = body_template.render(template_context) subject_template = mako_template_env.from_string(tools.ustr(self.subject)) subject_rendered = subject_template.render(template_context) self.env['mail.message'].sudo().create({ 'type': 'comment', 'author_id': sender.sudo().partner_id.id, 'partner_ids': recipient_partners, 'model': self.model, 'res_id': record and record.id, 'record_name': record_name or (record and record.display_name), 'subject': subject_rendered, 'body': body_rendered, 'template': self.id, 'subtype_id': subtype and subtype.id })
def render_mako_template_string(self, template_string, template_values=None, user=None): template_string = template_string if template_string else u'' template_values = template_values if template_values else dict() assert isinstance(template_values, dict), "values must be a dictionary!" # Load the mako template environment # ---------------------------------- try: template = mako_template_env.from_string( tools.ustr(template_string)) except Exception as e: _logger.error( "Could not render e-mail template! Initialization of mako template failed!\n%s" % repr(e)) return u'' # Prepare the template_vars # ------------------------- req = request pool, cr, uid, ctx = req.env[ 'email.template'].pool, req.cr, req.uid, req.context # HINT: This 1.) creates a named tuple object with all attributes from the dict and then # 2.) assigns the values of the dict to the named_tuple arguments # *values.values() means we unpack the dict (e.g.: {'key1': '3'} will be key1='3') # ATTENTION: A NamedTuple will genereate an ._fields just like a regular odoo record! # therefore you could use this in the mako template if you want to show all fields of the record! tvalues_object = namedtuple( "TemplateValueObject", template_values.keys())(*template_values.values()) # HINT: These variables should be available to all templates (specified in the addon email_template) template_vars = { 'format_tz': lambda dt, tz=False, format=False, context=ctx: format_tz( pool, cr, uid, dt, tz, format, context), 'user': user if user else req.env.user, 'ctx': ctx, 'object': tvalues_object } # Render the mako template # ------------------------ try: output = template.render(template_vars) output = u'' if (not output or output == u'False') else output except Exception as e: _logger.error('Could not render email template!\n%s' % repr(e)) return u'' return output
def create(self, cr, uid, vals, context=None): record = self.pool.get(vals.get('res_model')).browse(cr, uid, vals.get('res_id')) mako = mako_template_env.from_string(tools.ustr(vals.get('website_description'))) website_description = mako.render({'record':record}) website_description = website_description.replace('template-only-', '') vals['website_description'] = website_description new_id = super(website_proposal, self).create(cr, uid, vals, context=context) return new_id
def render_template_batch(self, cr, uid, template, model, res_ids, context=None, post_process=False): result = {} try: if model == 'newsletter.newsletter': mako_template_env.autoescape = False post_process = False result = super(email_template, self).render_template_batch( cr, uid, template, model, res_ids, context=context, post_process=post_process) finally: if model == 'newsletter.newsletter': mako_template_env.autoescape = True if model == 'newsletter.newsletter' and res_ids and result and\ context.get('newsletter_res_id'): for res_id, rendered in result.iteritems(): newsletter = self.pool[model].browse(cr, uid, res_id, context=context) user = self.pool['res.users'].browse(cr, uid, uid, context=context) template = mako_template_env.from_string(rendered) result[res_id] = template.render({ 'object': self.pool[newsletter.type_id.model.model].browse( cr, uid, context.get('newsletter_res_id'), context), 'user': user, 'ctx': context, 'format_tz': lambda dt, tz=False, fmt=False: format_tz( self.pool, cr, uid, dt, tz, fmt, context), }) return result
def create(self, cr, uid, vals, context=None): record = self.pool.get(vals.get('res_model')).browse( cr, uid, vals.get('res_id')) mako = mako_template_env.from_string( tools.ustr(vals.get('website_description'))) website_description = mako.render({'record': record}) website_description = website_description.replace('template-only-', '') vals['website_description'] = website_description new_id = super(website_proposal, self).create(cr, uid, vals, context=context) return new_id
def render_template(self, cr, uid, template, model, res_id, context=None): result = '' try: mako_template_env.autoescape = False result = super(email_template, self).render_template( cr, uid, template, model, res_id, context) finally: mako_template_env.autoescape = True if (model == 'newsletter.newsletter' and res_id and context.get('newsletter_res_id')): newsletter = self.pool.get(model).browse(cr, uid, res_id, context=context) user = self.pool.get('res.users').browse(cr, uid, uid, context=context) result = mako_template_env.from_string(result).render({ 'object': self.pool.get(newsletter.type_id.model.model).browse( cr, uid, context.get('newsletter_res_id'), context), 'user': user, 'ctx': context}) return result
def send(self, recipients, sender=None, record=None, record_name=None): recipient_partners = [] for recipient in recipients: recipient_partners.append((4, recipient.partner_id.id)) subtype = None if not sender: sender = self.env.ref('message_template.user_messages') subtype = self.env.ref('message_template.subtype_system_message') # Enable resolution of ${variables} inside body body_template = mako_template_env.from_string(tools.ustr(self.body)) body_rendered = body_template.render({'record': record}) self.env['mail.message'].sudo().create({ 'type': 'comment', 'author_id': sender.partner_id.id, 'partner_ids': recipient_partners, 'model': self.model, 'res_id': record and record.id, 'record_name': record_name or (record and record.name), 'subject': self.subject, 'body': body_rendered, 'template': self.id, 'subtype_id': subtype and subtype.id })
def get_data(self, user): domain = safe_eval(self.domain, {'user': user}) won_domain = safe_eval(self.won_domain or '[]', {'user': user}) field_date_name = self.field_date_id and self.field_date_id.name if self.start_date and field_date_name: domain.append((field_date_name, '>=', self.start_date)) if self.end_date and field_date_name: domain.append((field_date_name, '<=', self.end_date)) res = { 'name': self.name, 'type': self.type, 'model': self.model_id.model, 'domain': str(domain), 'precision': self.precision, } obj = self.env[self.model_id.model] if self.type == 'list': total_count = obj.search_count(domain) groups = [{'test': lambda r: True}] if self.agenda: today = date.today() tomorrow = today + timedelta(days=1) def r2date(r): d = getattr(r, field_date_name) if d: d = datetime.strptime( d, self.field_date_id.ttype == 'date' and DEFAULT_SERVER_DATE_FORMAT or DEFAULT_SERVER_DATETIME_FORMAT) d = d.date() else: d = date.today() return d groups = [ { 'label': _('Overdue'), 'class': 'overdue', 'test': lambda r: r2date(r) < today, 'mandatory': False, }, { 'label': _('Today'), 'class': 'today', 'test': lambda r: r2date(r) == today, 'mandatory': True, }, { 'label': _('Tomorrow'), 'class': 'tomorrow', 'test': lambda r: r2date(r) == tomorrow, 'mandatory': False, }, { 'label': _('Later'), 'class': 'later', 'test': lambda r: r2date(r) > tomorrow, 'mandatory': False, }, ] for g in groups: g['lines'] = [] res.update({ 'more': self.limit and self.limit < total_count, 'total_count': total_count, 'agenda': self.agenda, 'groups': groups, }) for r in obj.search(domain, limit=self.limit, order=self.order): mako = mako_template_env.from_string(tools.ustr(self.content)) content = mako.render({'record': r}) r_json = { 'id': r.id, #'fields': dict( (f,getattr(r,f)) for f in fields), 'display_mode': 'progress', 'state': 'inprogress', 'completeness': 0, 'name': content, 'description': '', } if self.value_field_id: r_json['current'] = getattr(r, self.value_field_id.name) if self.value_field_monetary: r_json['monetary'] = 1 for g in groups: if g['test'](r): g['lines'].append(r_json) break for g in groups: del g['test'] elif self.type == 'funnel': stage_ids = [] # [key] for group in obj.read_group(domain, [], [self.stage_field_id.name]): key = group[self.stage_field_id.name] if isinstance(key, (list, tuple)): key = key[0] stage_ids.append(key) stages = [] # [{'name':Name, 'id': key}] if self.stage_field_id.ttype == 'selection': d = dict(self.stage_field_id.selection) stages = [{'id': id, 'name': d[id]} for id in stage_ids] else: # many2one stage_model = self.stage_field_id.relation for r in self.env[stage_model].browse(stage_ids): stages.append({'id': r.id, 'name': r.name_get()[0][1]}) value_field_name = self.value_field_id.name for stage in stages: d = copy.copy(domain) d.append((self.stage_field_id.name, '=', stage['id'])) result = obj.read_group(d, [value_field_name], []) stage['closed_value'] = result and result[0][ value_field_name] or 0.0 stage['domain'] = str(d) # won value d = domain + won_domain result = obj.read_group(domain, [value_field_name], []) won = { 'name': _('Won'), 'id': '__won__', 'closed_value': result and result[0][value_field_name] or 0.0 } stages.append(won) cur = 0 for stage in reversed(stages): cur += stage['closed_value'] stage['abs_value'] = cur total_value = stages[0]['abs_value'] precision = self.precision for s in stages: s['rel_value'] = round( 100 * s['abs_value'] / total_value / precision) * precision if total_value else 100 # dummy fields s['display_mode'] = 'progress' s['monetary'] = 1 res['stages'] = stages res['won'] = won res['conversion_rate'] = stages[-1]['rel_value'] elif self.type == 'slice': value_field_name = self.value_field_id.name for f, d in [('total', domain), ('won', won_domain)]: result = obj.read_group(d, [value_field_name], []) res[f] = result and result[0][value_field_name] or 0.0 res['domain'] = str(domain) res['won_domain'] = str(won_domain) precision = self.precision total_value = res['total'] res['slice'] = round( 100 * res['won'] / res['total'] / precision) * precision if res['total'] else 100 # dummy fields res['display_mode'] = 'progress' res['monetary'] = self.value_field_monetary return res
def render_template(self, cr, uid, template, model, res_id, context=None): """Render the given template text, replace mako expressions ``${expr}`` with the result of evaluating these expressions with an evaluation context containing: * ``user``: browse_record of the current user * ``object``: browse_record of the document record this mail is related to * ``context``: the context passed to the mail composition wizard :param str template: the template text to render :param str model: model name of the document record this mail is related to. :param int res_id: id of the document record this mail is related to. """ if not template: return u"" if context is None: context = {} try: template = tools.ustr(template) record = None if res_id: record = self.pool.get(model).browse(cr, uid, res_id, context=context) user = self.pool.get('res.users').browse(cr, uid, uid, context=context) variables = { 'object': record, 'user': user, 'ctx': context, # context kw would clash with mako internals } result = mako_template_env.from_string(template).render(variables) if result == u"False": result = u"" return result except Exception as e: logger.exception("failed to render mako template value %r", template) logger.exception(e) issue_obj = self.pool.get('project.issue') for issue_id in issue_obj.find_resource_issues( cr, uid, model, res_id, tags=['email.template', 'error'], create=True, reopen=True, context=context): # A message is trigger in a new/open issue issue_obj.message_post( cr, uid, issue_id, _('Exception on email.template<br/><b>{0}</b>:<br/>{1}<br/>{2}' ).format( e, traceback.format_exc(limit=10).replace( '\n', '<br/>'), template.replace('<', '<').replace('\n', '<br/>')), context=context) return u""
def get_data(self, user): domain = safe_eval(self.domain, {'user': user}) won_domain = safe_eval(self.won_domain or '[]', {'user': user}) field_date_name = self.field_date_id and self.field_date_id.name if self.start_date and field_date_name: domain.append((field_date_name, '>=', self.start_date)) if self.end_date and field_date_name: domain.append((field_date_name, '<=', self.end_date)) res = { 'name': self.name, 'type': self.type, 'model': self.model_id.model, 'domain': str(domain), 'precision': self.precision, } obj = self.env[self.model_id.model] if self.type == 'list': total_count = obj.search_count(domain) groups = [{'test': lambda r: True}] if self.agenda: today = date.today() tomorrow = today + timedelta(days=1) def r2date(r): d = getattr(r, field_date_name) if d: d = datetime.strptime(d, self.field_date_id.ttype=='date' and DEFAULT_SERVER_DATE_FORMAT or DEFAULT_SERVER_DATETIME_FORMAT) d = d.date() else: d = date.today() return d groups = [ { 'label': _('Overdue'), 'class': 'overdue', 'test': lambda r: r2date(r) < today, 'mandatory': False, }, { 'label': _('Today'), 'class': 'today', 'test': lambda r: r2date(r) == today, 'mandatory': True, }, { 'label': _('Tomorrow'), 'class': 'tomorrow', 'test': lambda r: r2date(r) == tomorrow, 'mandatory': False, }, { 'label': _('Later'), 'class': 'later', 'test': lambda r: r2date(r) > tomorrow, 'mandatory': False, }, ] for g in groups: g['lines'] = [] res.update({ 'more': self.limit and self.limit < total_count, 'total_count': total_count, 'agenda': self.agenda, 'groups': groups, }) for r in obj.search(domain, limit=self.limit, order=self.order): mako = mako_template_env.from_string(tools.ustr(self.content)) content = mako.render({'record':r}) r_json = { 'id': r.id, #'fields': dict( (f,getattr(r,f)) for f in fields), 'display_mode': 'progress', 'state': 'inprogress', 'completeness': 0, 'name': content, 'description': '', } if self.value_field_id: r_json['current'] = getattr(r, self.value_field_id.name) if self.value_field_monetary: r_json['monetary'] = 1 for g in groups: if g['test'](r): g['lines'].append(r_json) break for g in groups: del g['test'] elif self.type == 'funnel': stage_ids = [] # [key] for group in obj.read_group(domain, [], [self.stage_field_id.name]): key = group[self.stage_field_id.name] if isinstance(key, (list, tuple)): key = key[0] stage_ids.append(key) stages = [] # [{'name':Name, 'id': key}] if self.stage_field_id.ttype == 'selection': d = dict (self.stage_field_id.selection) stages = [ {'id':id, 'name':d[id]} for id in stage_ids ] else: # many2one stage_model = self.stage_field_id.relation for r in self.env[stage_model].browse(stage_ids): stages.append({'id': r.id, 'name':r.name_get()[0][1]}) value_field_name = self.value_field_id.name for stage in stages: d = copy.copy(domain) d.append( (self.stage_field_id.name, '=', stage['id']) ) result = obj.read_group(d, [value_field_name], []) stage['closed_value'] = result and result[0][value_field_name] or 0.0 stage['domain'] = str(d) # won value d = domain + won_domain result = obj.read_group(domain, [value_field_name], []) won = {'name': _('Won'), 'id':'__won__', 'closed_value': result and result[0][value_field_name] or 0.0 } stages.append(won) cur = 0 for stage in reversed(stages): cur += stage['closed_value'] stage['abs_value'] = cur total_value = stages[0]['abs_value'] precision = self.precision for s in stages: s['rel_value'] = round(100*s['abs_value']/total_value/precision)*precision if total_value else 100 # dummy fields s['display_mode'] = 'progress' s['monetary'] = 1 res['stages'] = stages res['won'] = won res['conversion_rate'] = stages[-1]['rel_value'] elif self.type == 'slice': value_field_name = self.value_field_id.name for f,d in [('total', domain), ('won', won_domain)]: result = obj.read_group(d, [value_field_name], []) res[f] = result and result[0][value_field_name] or 0.0 res['domain'] = str(domain) res['won_domain'] = str(won_domain) precision = self.precision total_value = res['total'] res['slice'] = round(100*res['won']/res['total']/precision)*precision if res['total'] else 100 # dummy fields res['display_mode'] = 'progress' res['monetary'] = self.value_field_monetary return res