7c02334a9fbc6f6d268c5e99b637f9f0f2f91fa3
[odoo/odoo.git] / addons / email_template / email_template.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2009 Sharoon Thomas
6 #    Copyright (C) 2010-2010 OpenERP SA (<http://www.openerp.com>)
7 #
8 #    This program is free software: you can redistribute it and/or modify
9 #    it under the terms of the GNU General Public License as published by
10 #    the Free Software Foundation, either version 3 of the License, or
11 #    (at your option) any later version.
12 #
13 #    This program is distributed in the hope that it will be useful,
14 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
15 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 #    GNU General Public License for more details.
17 #
18 #    You should have received a copy of the GNU General Public License
19 #    along with this program.  If not, see <http://www.gnu.org/licenses/>
20 #
21 ##############################################################################
22
23 import base64
24 import random
25 import netsvc
26 import re
27
28 LOGGER = netsvc.Logger()
29
30 TEMPLATE_ENGINES = []
31
32 from osv import osv, fields
33 from tools.translate import _
34
35 try:
36     from mako.template import Template as MakoTemplate
37     TEMPLATE_ENGINES.append(('mako', 'Mako Templates'))
38 except:
39     LOGGER.notifyChannel(
40          _("Email Template"),
41          netsvc.LOG_WARNING,
42          _("Mako templates not installed")
43     )
44 try:
45     from django.template import Context, Template as DjangoTemplate
46     #Workaround for bug:
47     #http://code.google.com/p/django-tagging/issues/detail?id=110
48     from django.conf import settings
49     settings.configure()
50     #Workaround ends
51     TEMPLATE_ENGINES.append(('django', 'Django Template'))
52 except:
53     LOGGER.notifyChannel(
54          _("Email Template"),
55          netsvc.LOG_WARNING,
56          _("Django templates not installed")
57     )
58
59 import tools
60 import pooler
61 import logging
62
63 def get_value(cursor, user, recid, message=None, template=None, context=None):
64     """
65     Evaluates an expression and returns its value
66     @param cursor: Database Cursor
67     @param user: ID of current user
68     @param recid: ID of the target record under evaluation
69     @param message: The expression to be evaluated
70     @param template: BrowseRecord object of the current template
71     @param context: OpenERP Context
72     @return: Computed message (unicode) or u""
73     """
74     pool = pooler.get_pool(cursor.dbname)
75     if message is None:
76         message = {}
77     #Returns the computed expression
78     if message:
79         try:
80             message = tools.ustr(message)
81             object = pool.get(template.model_int_name).browse(cursor, user, recid, context)
82             env = {
83                 'user':pool.get('res.users').browse(cursor, user, user, context),
84                 'db':cursor.dbname
85                    }
86             if template.template_language == 'mako':
87                 templ = MakoTemplate(message, input_encoding='utf-8')
88                 reply = MakoTemplate(message).render_unicode(object=object,
89                                                              peobject=object,
90                                                              env=env,
91                                                              format_exceptions=True)
92             elif template.template_language == 'django':
93                 templ = DjangoTemplate(message)
94                 env['object'] = object
95                 env['peobject'] = object
96                 reply = templ.render(Context(env))
97             return reply or False
98         except Exception:
99             logging.exception("can't render %r", message)
100             return u""
101     else:
102         return message
103
104 class email_template(osv.osv):
105     "Templates for sending Email"
106     
107     _name = "email.template"
108     _description = 'Email Templates for Models'
109
110     def change_model(self, cursor, user, ids, object_name, context=None):
111         if object_name:
112             mod_name = self.pool.get('ir.model').read(
113                                               cursor,
114                                               user,
115                                               object_name,
116                                               ['model'], context)['model']
117         else:
118             mod_name = False
119         return {
120                 'value':{'model_int_name':mod_name}
121                 }
122
123     _columns = {
124         'name' : fields.char('Name', size=100, required=True),
125         'object_name':fields.many2one('ir.model', 'Resource'),
126         'model_int_name':fields.char('Model Internal Name', size=200,),
127         'from_account':fields.many2one(
128                    'email_template.account',
129                    string="Email Account",
130                    help="Emails will be sent from this approved account."),
131         'def_to':fields.char(
132                  'Recipient (To)',
133                  size=250,
134                  help="The Recipient of email. " 
135                  "Placeholders can be used here. "
136                  "e.g. ${object.email_to}"),
137         'def_cc':fields.char(
138                  'CC',
139                  size=250,
140                  help="Carbon Copy address(es), comma-separated."
141                     " Placeholders can be used here. "
142                     "e.g. ${object.email_cc}"),
143         'def_bcc':fields.char(
144                   'BCC',
145                   size=250,
146                   help="Blind Carbon Copy address(es), comma-separated."
147                     " Placeholders can be used here. "
148                     "e.g. ${object.email_bcc}"),
149         'reply_to':fields.char('Reply-To', 
150                     size=250, 
151                     help="The address recipients should reply to,"
152                     " if different from the From address."
153                     " Placeholders can be used here. "
154                     "e.g. ${object.email_reply_to}"),
155         'message_id':fields.char('Message-ID', 
156                     size=250, 
157                     help="Specify the Message-ID SMTP header to use in outgoing emails. Please note that this overrides the Resource tracking option! Placeholders can be used here."),
158         'track_campaign_item':fields.boolean('Resource Tracking',
159                                 help="Enable this is you wish to include a special \
160 tracking marker in outgoing emails so you can identify replies and link \
161 them back to the corresponding resource record. \
162 This is useful for CRM leads for example"), 
163         'lang':fields.char(
164                    'Language',
165                    size=250,
166                    help="The default language for the email."
167                    " Placeholders can be used here. "
168                    "eg. ${object.partner_id.lang}"),
169         'def_subject':fields.char(
170                   'Subject',
171                   size=200,
172                   help="The subject of email."
173                   " Placeholders can be used here.",
174                   translate=True),
175         'def_body_text':fields.text(
176                     'Standard Body (Text)',
177                     help="The text version of the mail",
178                     translate=True),
179         'def_body_html':fields.text(
180                     'Body (Text-Web Client Only)',
181                     help="The text version of the mail",
182                     translate=True),
183         'use_sign':fields.boolean(
184                   'Signature',
185                   help="the signature from the User details" 
186                   " will be appended to the mail"),
187         'file_name':fields.char(
188                 'Report Filename',
189                 size=200,
190                 help="Name of the generated report file. Placeholders can be used in the filename. eg: 2009_SO003.pdf",
191                 translate=True),
192         'report_template':fields.many2one(
193                   'ir.actions.report.xml',
194                   'Report to send'),
195         'attachment_ids': fields.many2many(
196                     'ir.attachment',
197                     'email_template_attachment_rel',
198                     'email_template_id',
199                     'attachment_id',
200                     'Attached Files',
201                     help="You may attach existing files to this template, "
202                          "so they will be added in all emails created from this template"), 
203         'ref_ir_act_window':fields.many2one(
204                     'ir.actions.act_window',
205                     'Window Action',
206                     help="Action that will open this email template on Resource records", 
207                     readonly=True),
208         'ref_ir_value':fields.many2one(
209                    'ir.values',
210                    'Wizard Button',
211                    help="Button in the side bar of the form view of this Resource that will invoke the Window Action", 
212                    readonly=True),
213         'allowed_groups':fields.many2many(
214                   'res.groups',
215                   'template_group_rel',
216                   'templ_id', 'group_id',
217                   string="Allowed User Groups",
218                   help="Only users from these groups will be"
219                   " allowed to send mails from this Template"),
220         'model_object_field':fields.many2one(
221                  'ir.model.fields',
222                  string="Field",
223                  help="Select the field from the model you want to use."
224                  "\nIf it is a relationship field you will be able to "
225                  "choose the nested values in the box below\n(Note:If "
226                  "there are no values make sure you have selected the"
227                  " correct model)",
228                  store=False),
229         'sub_object':fields.many2one(
230                  'ir.model',
231                  'Sub-model',
232                  help='When a relation field is used this field'
233                  ' will show you the type of field you have selected',
234                  store=False),
235         'sub_model_object_field':fields.many2one(
236                  'ir.model.fields',
237                  'Sub Field',
238                  help="When you choose relationship fields "
239                  "this field will specify the sub value you can use.",
240                  store=False),
241         'null_value':fields.char(
242                  'Null Value',
243                  help="This Value is used if the field is empty",
244                  size=50, store=False),
245         'copyvalue':fields.char(
246                 'Expression',
247                 size=100,
248                 help="Copy and paste the value in the "
249                 "location you want to use a system value.",
250                 store=False),
251         'table_html':fields.text(
252              'HTML code',
253              help="Copy this html code to your HTML message"
254              " body for displaying the info in your mail.",
255              store=False),
256         #Template language(engine eg.Mako) specifics
257         'template_language':fields.selection(
258                 TEMPLATE_ENGINES,
259                 'Templating Language',
260                 required=True
261                 )
262     }
263
264     _defaults = {
265         'template_language' : lambda *a:'mako',
266
267     }
268     
269     _sql_constraints = [
270         ('name', 'unique (name)', _('The template name must be unique !'))
271     ]
272
273     def create_action(self, cr, uid, ids, context):
274         vals = {}
275         template_obj = self.browse(cr, uid, ids)[0]
276         src_obj = template_obj.object_name.model
277         vals['ref_ir_act_window'] = self.pool.get('ir.actions.act_window').create(cr, uid, {
278              'name': template_obj.name,
279              'type': 'ir.actions.act_window',
280              'res_model': 'email_template.send.wizard',
281              'src_model': src_obj,
282              'view_type': 'form',
283              'context': "{'src_model':'%s','template_id':'%d','src_rec_id':active_id,'src_rec_ids':active_ids}" % (src_obj, template_obj.id),
284              'view_mode':'form,tree',
285              'view_id': self.pool.get('ir.ui.view').search(cr, uid, [('name', '=', 'email_template.send.wizard.form')], context=context)[0],
286              'target': 'new',
287              'auto_refresh':1
288         }, context)
289         vals['ref_ir_value'] = self.pool.get('ir.values').create(cr, uid, {
290              'name': _('Send Mail (%s)') % template_obj.name,
291              'model': src_obj,
292              'key2': 'client_action_multi',
293              'value': "ir.actions.act_window," + str(vals['ref_ir_act_window']),
294              'object': True,
295          }, context)
296         self.write(cr, uid, ids, {
297             'ref_ir_act_window': vals['ref_ir_act_window'],
298             'ref_ir_value': vals['ref_ir_value'],
299         }, context)
300         return True
301
302     def unlink_action(self, cr, uid, ids, context):
303         for template in self.browse(cr, uid, ids, context):
304             try:
305                 if template.ref_ir_act_window:
306                     self.pool.get('ir.actions.act_window').unlink(cr, uid, template.ref_ir_act_window.id, context)
307                 if template.ref_ir_value:
308                     self.pool.get('ir.values').unlink(cr, uid, template.ref_ir_value.id, context)
309             except:
310                 raise osv.except_osv(_("Warning"), _("Deletion of Record failed"))
311
312     def delete_action(self, cr, uid, ids, context):
313         self.unlink_action(cr, uid, ids, context)
314         return True
315         
316     def unlink(self, cr, uid, ids, context=None):
317         self.unlink_action(cr, uid, ids, context)
318         return super(email_template, self).unlink(cr, uid, ids, context)
319     
320     def copy(self, cr, uid, id, default=None, context=None):
321         if default is None:
322             default = {}
323         default = default.copy()
324         old = self.read(cr, uid, id, ['name'], context=context)
325         new_name = _("Copy of template ") + old.get('name', 'No Name')
326         check = self.search(cr, uid, [('name', '=', new_name)], context=context)
327         if check:
328             new_name = new_name + '_' + random.choice('abcdefghij') + random.choice('lmnopqrs') + random.choice('tuvwzyz')
329         default.update({'name':new_name})
330         return super(email_template, self).copy(cr, uid, id, default, context)
331     
332     def build_expression(self, field_name, sub_field_name, null_value, template_language='mako'):
333         """
334         Returns a template expression based on data provided
335         @param field_name: field name
336         @param sub_field_name: sub field name (M2O)
337         @param null_value: default value if the target value is empty
338         @param template_language: name of template engine
339         @return: computed expression
340         """
341
342         expression = ''
343         if template_language == 'mako':
344             if field_name:
345                 expression = "${object." + field_name
346                 if sub_field_name:
347                     expression += "." + sub_field_name
348                 if null_value:
349                     expression += " or '''%s'''" % null_value
350                 expression += "}"
351         elif template_language == 'django':
352             if field_name:
353                 expression = "{{object." + field_name
354                 if sub_field_name:
355                     expression += "." + sub_field_name
356                 if null_value:
357                     expression += "|default: '''%s'''" % null_value  
358                 expression += "}}"
359         return expression 
360             
361     def onchange_model_object_field(self, cr, uid, ids, model_object_field, template_language, context=None):
362         if not model_object_field:
363             return {}
364         result = {}
365         field_obj = self.pool.get('ir.model.fields').browse(cr, uid, model_object_field, context)
366         #Check if field is relational
367         if field_obj.ttype in ['many2one', 'one2many', 'many2many']:
368             res_ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', field_obj.relation)], context=context)
369             if res_ids:
370                 result['sub_object'] = res_ids[0]
371                 result['copyvalue'] = self.build_expression(False,
372                                                       False,
373                                                       False,
374                                                       template_language)
375                 result['sub_model_object_field'] = False
376                 result['null_value'] = False
377         else:
378             #Its a simple field... just compute placeholder
379             result['sub_object'] = False
380             result['copyvalue'] = self.build_expression(field_obj.name,
381                                                   False,
382                                                   False,
383                                                   template_language
384                                                   )
385             result['sub_model_object_field'] = False
386             result['null_value'] = False
387         return {'value':result}
388         
389     def onchange_sub_model_object_field(self, cr, uid, ids, model_object_field, sub_model_object_field, template_language, context=None):
390         if not model_object_field or not sub_model_object_field:
391             return {}
392         result = {}
393         field_obj = self.pool.get('ir.model.fields').browse(cr, uid, model_object_field, context)
394         if field_obj.ttype in ['many2one', 'one2many', 'many2many']:
395             res_ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', field_obj.relation)], context=context)
396             sub_field_obj = self.pool.get('ir.model.fields').browse(cr, uid, sub_model_object_field, context)
397             if res_ids:
398                 result['sub_object'] = res_ids[0]
399                 result['copyvalue'] = self.build_expression(field_obj.name,
400                                                       sub_field_obj.name,
401                                                       False,
402                                                       template_language
403                                                       )
404                 result['sub_model_object_field'] = sub_model_object_field
405                 result['null_value'] = False
406         else:
407             #Its a simple field... just compute placeholder
408             result['sub_object'] = False
409             result['copyvalue'] = self.build_expression(field_obj.name,
410                                                   False,
411                                                   False,
412                                                   template_language
413                                                   )
414             result['sub_model_object_field'] = False
415             result['null_value'] = False
416         return {'value':result}
417
418     def onchange_null_value(self, cr, uid, ids, model_object_field, sub_model_object_field, null_value, template_language, context=None):
419         if not model_object_field and not null_value:
420             return {}
421         result = {}
422         field_obj = self.pool.get('ir.model.fields').browse(cr, uid, model_object_field, context)
423         if field_obj.ttype in ['many2one', 'one2many', 'many2many']:
424             res_ids = self.pool.get('ir.model').search(cr, uid, [('model', '=', field_obj.relation)], context=context)
425             sub_field_obj = self.pool.get('ir.model.fields').browse(cr, uid, sub_model_object_field, context)
426             if res_ids:
427                 result['sub_object'] = res_ids[0]
428                 result['copyvalue'] = self.build_expression(field_obj.name,
429                                                       sub_field_obj.name,
430                                                       null_value,
431                                                       template_language
432                                                       )
433                 result['sub_model_object_field'] = sub_model_object_field
434                 result['null_value'] = null_value
435         else:
436             #Its a simple field... just compute placeholder
437             result['sub_object'] = False
438             result['copyvalue'] = self.build_expression(field_obj.name,
439                                                   False,
440                                                   null_value,
441                                                   template_language
442                                                   )
443             result['sub_model_object_field'] = False
444             result['null_value'] = null_value
445         return {'value':result}
446
447     def _add_attachment(self, cursor, user, mailbox_id, name, data, filename, context=None):
448         """
449         Add an attachment to a given mailbox entry.
450         
451         :param data: base64 encoded attachment data to store
452         """
453         attachment_obj = self.pool.get('ir.attachment')
454         attachment_data = {
455             'name':  (name or '') + _(' (Email Attachment)'),
456             'datas': data,
457             'datas_fname': filename,
458             'description': name or _('No Description'),
459             'res_model':'email_template.mailbox',
460             'res_id': mailbox_id,
461         }
462         attachment_id = attachment_obj.create(cursor,
463                                               user,
464                                               attachment_data,
465                                               context)
466         if attachment_id:
467             self.pool.get('email_template.mailbox').write(
468                               cursor,
469                               user,
470                               mailbox_id,
471                               {
472                                'attachments_ids':[(4, attachment_id)],
473                                'mail_type':'multipart/mixed'
474                               },
475                               context)
476
477     def generate_attach_reports(self,
478                                  cursor,
479                                  user,
480                                  template,
481                                  record_id,
482                                  mail,
483                                  context=None):
484         """
485         Generate report to be attached and attach it
486         to the email, and add any directly attached files as well.
487         
488         @param cursor: Database Cursor
489         @param user: ID of User
490         @param template: Browse record of
491                          template
492         @param record_id: ID of the target model
493                           for which this mail has
494                           to be generated
495         @param mail: Browse record of email object 
496         @return: True 
497         """
498         if template.report_template:
499             reportname = 'report.' + \
500                 self.pool.get('ir.actions.report.xml').read(
501                                              cursor,
502                                              user,
503                                              template.report_template.id,
504                                              ['report_name'],
505                                              context)['report_name']
506             service = netsvc.LocalService(reportname)
507             data = {}
508             data['model'] = template.model_int_name
509             (result, format) = service.create(cursor,
510                                               user,
511                                               [record_id],
512                                               data,
513                                               context)   
514             fname = tools.ustr(get_value(cursor, user, record_id,
515                                          template.file_name, template, context)
516                                or 'Report')
517             ext = '.' + format
518             if not fname.endswith(ext):
519                 fname += ext
520             self._add_attachment(cursor, user, mail.id, mail.subject, base64.b64encode(result), fname, context)
521
522         if template.attachment_ids:
523             for attachment in template.attachment_ids:
524                 self._add_attachment(cursor, user, mail.id, attachment.name, attachment.datas, attachment.datas_fname, context)
525
526         return True
527     
528     def _generate_mailbox_item_from_template(self,
529                                       cursor,
530                                       user,
531                                       template,
532                                       record_id,
533                                       context=None):
534         """
535         Generates an email from the template for
536         record record_id of target object
537         
538         @param cursor: Database Cursor
539         @param user: ID of User
540         @param template: Browse record of
541                          template
542         @param record_id: ID of the target model
543                           for which this mail has
544                           to be generated
545         @return: ID of created object 
546         """
547         if context is None:
548             context = {}
549         #If account to send from is in context select it, else use enforced account
550         if 'account_id' in context.keys():
551             from_account = self.pool.get('email_template.account').read(
552                                                     cursor,
553                                                     user,
554                                                     context.get('account_id'),
555                                                     ['name', 'email_id'],
556                                                     context
557                                                     )
558         else:
559             from_account = {
560                             'id':template.from_account.id,
561                             'name':template.from_account.name,
562                             'email_id':template.from_account.email_id
563                             }
564         lang = get_value(cursor,
565                          user,
566                          record_id,
567                          template.lang,
568                          template,
569                          context)
570         if lang:
571             ctx = context.copy()
572             ctx.update({'lang':lang})
573             template = self.browse(cursor, user, template.id, context=ctx)
574         
575         # determine name of sender, either it is specified in email_id or we 
576         # use the account name 
577         email_id = from_account['email_id'].strip()
578         email_from = re.findall(r'([^ ,<@]+@[^> ,]+)', email_id)[0]
579         if email_from != email_id:
580             # we should keep it all, name is probably specified in the address
581             email_from = from_account['email_id']
582         else:
583             email_from = tools.ustr(from_account['name']) + "<" + tools.ustr('email_id') + ">",
584
585         # FIXME: should do this in a loop and rename template fields to the corresponding
586         # mailbox fields. (makes no sense to have different names I think.
587         mailbox_values = {
588             'email_from': email_from,
589             'email_to':get_value(cursor,
590                                user,
591                                record_id,
592                                template.def_to,
593                                template,
594                                context),
595             'email_cc':get_value(cursor,
596                                user,
597                                record_id,
598                                template.def_cc,
599                                template,
600                                context),
601             'email_bcc':get_value(cursor,
602                                 user,
603                                 record_id,
604                                 template.def_bcc,
605                                 template,
606                                 context),
607             'reply_to':get_value(cursor,
608                                 user,
609                                 record_id,
610                                 template.reply_to,
611                                 template,
612                                 context),
613             'subject':get_value(cursor,
614                                     user,
615                                     record_id,
616                                     template.def_subject,
617                                     template,
618                                     context),
619             'body_text':get_value(cursor,
620                                       user,
621                                       record_id,
622                                       template.def_body_text,
623                                       template,
624                                       context),
625             'body_html':get_value(cursor,
626                                       user,
627                                       record_id,
628                                       template.def_body_html,
629                                       template,
630                                       context),
631             'account_id' :from_account['id'],
632             #This is a mandatory field when automatic emails are sent
633             'state':'na',
634             'folder':'drafts',
635             'mail_type':'multipart/alternative',
636         }
637
638         if template['message_id']:
639             # use provided message_id with placeholders
640             mailbox_values.update({'message_id': get_value(cursor, user, record_id, template['message_id'], template, context)})
641
642         elif template['track_campaign_item']:
643             # get appropriate message-id
644             mailbox_values.update({'message_id': tools.misc.generate_tracking_message_id(record_id)})
645
646         if not mailbox_values['account_id']:
647             raise Exception("Unable to send the mail. No account linked to the template.")
648         #Use signatures if allowed
649         if template.use_sign:
650             sign = self.pool.get('res.users').read(cursor,
651                                                    user,
652                                                    user,
653                                                    ['signature'],
654                                                    context)['signature']
655             if mailbox_values['body_text']:
656                 mailbox_values['body_text'] += sign
657             if mailbox_values['body_html']:
658                 mailbox_values['body_html'] += sign
659         mailbox_id = self.pool.get('email_template.mailbox').create(
660                                                              cursor,
661                                                              user,
662                                                              mailbox_values,
663                                                              context)
664
665         return mailbox_id
666         
667
668     def generate_mail(self,
669                       cursor,
670                       user,
671                       template_id,
672                       record_ids,
673                       context=None):
674         if context is None:
675             context = {}
676         template = self.browse(cursor, user, template_id, context=context)
677         if not template:
678             raise Exception("The requested template could not be loaded")
679         result = True
680         mailbox_obj = self.pool.get('email_template.mailbox')
681         for record_id in record_ids:
682             mailbox_id = self._generate_mailbox_item_from_template(
683                                                                 cursor,
684                                                                 user,
685                                                                 template,
686                                                                 record_id,
687                                                                 context)
688             mail = mailbox_obj.browse(
689                                         cursor,
690                                         user,
691                                         mailbox_id,
692                                         context=context
693                                               )
694             if template.report_template or template.attachment_ids:
695                 self.generate_attach_reports(
696                                               cursor,
697                                               user,
698                                               template,
699                                               record_id,
700                                               mail,
701                                               context
702                                               )
703
704             self.pool.get('email_template.mailbox').write(
705                                                 cursor,
706                                                 user,
707                                                 mailbox_id,
708                                                 {'folder':'outbox'},
709                                                 context=context
710             )
711             # TODO : manage return value of all the records
712             result = self.pool.get('email_template.mailbox').send_this_mail(cursor, user, [mailbox_id], context)
713         return result
714
715 email_template()
716
717
718 ## FIXME: this class duplicates a lot of features of the email template send wizard,
719 ##        one of the 2 should inherit from the other!
720
721 class email_template_preview(osv.osv_memory):
722     _name = "email_template.preview"
723     _description = "Email Template Preview"
724     
725     def _get_model_recs(self, cr, uid, context=None):
726         if context is None:
727             context = {}
728             #Fills up the selection box which allows records from the selected object to be displayed
729         self.context = context
730         if 'template_id' in context:
731             ref_obj_id = self.pool.get('email.template').read(cr, uid, context['template_id'], ['object_name'], context)
732             ref_obj_name = self.pool.get('ir.model').read(cr, uid, ref_obj_id['object_name'][0], ['model'], context)['model']
733             model_obj = self.pool.get(ref_obj_name)
734             ref_obj_ids = model_obj.search(cr, uid, [], 0, 20, 'id desc', context=context)
735             if not ref_obj_ids:
736                 ref_obj_ids = []
737
738             # also add the default one if requested, otherwise it won't be available for selection:
739             default_id = context.get('default_rel_model_ref')
740             if default_id and default_id not in ref_obj_ids:
741                 ref_obj_ids.insert(0, default_id)
742             return model_obj.name_get(cr, uid, ref_obj_ids, context)
743         else:
744             return []
745
746     def default_get(self, cr, uid, fields, context=None):
747         if context is None:
748             context = {}
749         result = super(email_template_preview, self).default_get(cr, uid, fields, context=context)
750         if (not fields or 'rel_model_ref' in fields) and 'template_id' in context \
751            and not result.get('rel_model_ref'):
752             selectables = self._get_model_recs(cr, uid, context=context)
753             result['rel_model_ref'] = selectables and selectables[0][0] or False
754         return result
755
756     def _default_model(self, cursor, user, context=None):
757         """
758         Returns the default value for model field
759         @param cursor: Database Cursor
760         @param user: ID of current user
761         @param context: OpenERP Context
762         """
763         return self.pool.get('email.template').read(
764                                                    cursor,
765                                                    user,
766                                                    context['template_id'],
767                                                    ['object_name'],
768                                                    context)['object_name'] or False
769         
770     _columns = {
771         'ref_template':fields.many2one(
772                                        'email.template',
773                                        'Template', readonly=True),
774         'rel_model':fields.many2one('ir.model', 'Model', readonly=True),
775         'rel_model_ref':fields.selection(_get_model_recs, 'Referred Document'),
776         'to':fields.char('To', size=250, readonly=True),
777         'cc':fields.char('CC', size=250, readonly=True),
778         'bcc':fields.char('BCC', size=250, readonly=True),
779         'reply_to':fields.char('Reply-To', 
780                     size=250, 
781                     help="The address recipients should reply to,"
782                          " if different from the From address."
783                          " Placeholders can be used here."),
784         'message_id':fields.char('Message-ID', 
785                     size=250, 
786                     help="The Message-ID header value, if you need to"
787                          "specify it, for example to automatically recognize the replies later."
788                         " Placeholders can be used here."),
789         'subject':fields.char('Subject', size=200, readonly=True),
790         'body_text':fields.text('Body', readonly=True),
791         'body_html':fields.text('Body', readonly=True),
792         'report':fields.char('Report Name', size=100, readonly=True),
793     }
794     _defaults = {
795         'ref_template': lambda self, cr, uid, ctx:ctx['template_id'] or False,
796         'rel_model': _default_model,
797     }
798     def on_change_ref(self, cr, uid, ids, rel_model_ref, context=None):
799         if context is None:
800             context = {}
801         if not rel_model_ref:
802             return {}
803         vals = {}
804         if context == {}:
805             context = self.context
806         template = self.pool.get('email.template').browse(cr, uid, context['template_id'], context)
807         #Search translated template
808         lang = get_value(cr, uid, rel_model_ref, template.lang, template, context)
809         if lang:
810             ctx = context.copy()
811             ctx.update({'lang':lang})
812             template = self.pool.get('email.template').browse(cr, uid, context['template_id'], ctx)
813         vals['to'] = get_value(cr, uid, rel_model_ref, template.def_to, template, context)
814         vals['cc'] = get_value(cr, uid, rel_model_ref, template.def_cc, template, context)
815         vals['bcc'] = get_value(cr, uid, rel_model_ref, template.def_bcc, template, context)
816         vals['reply_to'] = get_value(cr, uid, rel_model_ref, template.reply_to, template, context)
817         if template.message_id:
818             vals['message_id'] = get_value(cr, uid, rel_model_ref, template.message_id, template, context)
819         elif template.track_campaign_item:
820             vals['message_id'] = tools.misc.generate_tracking_message_id(rel_model_ref)
821         vals['subject'] = get_value(cr, uid, rel_model_ref, template.def_subject, template, context)
822         vals['body_text'] = get_value(cr, uid, rel_model_ref, template.def_body_text, template, context)
823         vals['body_html'] = get_value(cr, uid, rel_model_ref, template.def_body_html, template, context)
824         vals['report'] = get_value(cr, uid, rel_model_ref, template.file_name, template, context)
825         return {'value':vals}
826         
827 email_template_preview()
828
829 # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: