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