[MERGE]merge with mail-cleaning-fp

bzr revid: sgo@tinyerp.com-20120905050803-qwrknvluqtkpwx6g
This commit is contained in:
Sanjay Gohel (Open ERP)
2012-09-05 10:38:03 +05:30
30 changed files with 332 additions and 552 deletions
@@ -123,64 +123,6 @@
</div>
</div>
]]></field>
<field name="body"><![CDATA[
Hello${object.partner_id.name and ' ' or ''}${object.partner_id.name or ''},
A new invoice is available for ${object.partner_id.name}:
| Invoice number: *${object.number}*
| Invoice total: *${object.amount_total} ${object.currency_id.name}*
| Invoice date: ${object.date_invoice}
% if object.origin:
| Order reference: ${object.origin}
% endif
| Your contact: ${object.user_id.name} ${object.user_id.email and '<%s>'%(object.user_id.email) or ''}
You can view the invoice document, download it and pay online using the following link:
${ctx.get('edi_web_url_view') or 'n/a'}
% if object.company_id.paypal_account and object.type in ('out_invoice', 'in_refund'):
<%
comp_name = quote(object.company_id.name)
inv_number = quote(object.number)
paypal_account = quote(object.company_id.paypal_account)
inv_amount = quote(str(object.amount_total))
cur_name = quote(object.currency_id.name)
paypal_url = "https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=%s&item_name=%s%%20Invoice%%20%s"\
"&invoice=%s&amount=%s&currency_code=%s&button_subtype=services&no_note=1&bn=OpenERP_Invoice_PayNow_%s" % \
(paypal_account,comp_name,inv_number,inv_number,inv_amount,cur_name,cur_name)
%>
It is also possible to directly pay with Paypal:
${paypal_url}
% endif
If you have any question, do not hesitate to contact us.
Thank you for choosing ${object.company_id.name}!
--
${object.user_id.name} ${object.user_id.email and '<%s>'%(object.user_id.email) or ''}
${object.company_id.name}
% if object.company_id.street:
${object.company_id.street or ''}
% endif
% if object.company_id.street2:
${object.company_id.street2}
% endif
% if object.company_id.city or object.company_id.zip:
${object.company_id.zip or ''} ${object.company_id.city or ''}
% endif
% if object.company_id.country_id:
${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}
% endif
% if object.company_id.phone:
Phone: ${object.company_id.phone}
% endif
% if object.company_id.website:
${object.company_id.website or ''}
% endif
]]></field>
</record>
</data>
</openerp>
@@ -213,8 +213,6 @@ class account_followup_print_all(osv.osv_memory):
mod_obj = self.pool.get('ir.model.data')
move_obj = self.pool.get('account.move.line')
user_obj = self.pool.get('res.users')
line_obj = self.pool.get('account_followup.stat')
mail_message = self.pool.get('mail.message')
if context is None:
context = {}
@@ -241,7 +239,6 @@ class account_followup_print_all(osv.osv_memory):
if (not dest) and partner.type=='default':
if partner.email:
dest = [partner.email]
src = tools.config.options['email_from']
if not data.partner_lang:
body = data.email_body
else:
@@ -281,7 +278,12 @@ class account_followup_print_all(osv.osv_memory):
msg = ''
if dest:
try:
mail_message.schedule_with_attach(cr, uid, src, dest, sub, body, context=context)
vals = {'state': 'outgoing',
'subject': sub,
'body_html': '<pre>%s</pre>' % body,
'email_to': dest,
'email_from': data_user.email or tools.config.options['email_from']}
self.pool.get('mail.mail').create(cr, uid, vals, context=context)
msg_sent += partner.name + '\n'
except Exception, e:
raise osv.except_osv('Error !', e )
@@ -9,16 +9,13 @@
<field name="email_from"><![CDATA[${object.company_id.name} <${object.company_id.email}>]]></field>
<field name="email_to" eval="False"><!--(set by reset_password module)--></field>
<field name="subject">Password reset</field>
<field name="body"><![CDATA[
A password reset was requested the OpenERP account linked to this email on ${object._auth_reset_password_host()}
<field name="body_html"><![CDATA[
<p>A password reset was requested the OpenERP account linked to this email on ${object._auth_reset_password_host()}</p>
You may change your password following this link:
<p>You may change your password following this <a href="${object._auth_reset_password_link()}">link</a>,
or by copy-pasting the following URL in your browser: ${object._auth_reset_password_link()}</p>
${object._auth_reset_password_link()}
If you don't have asked for password reset, you can safely ignore this email.
]]></field>
<p>Note: If you did not ask for a password reset, you can safely ignore this email.</p>]]></field>
</record>
<!-- TODO get own css -->
+15 -21
View File
@@ -302,33 +302,27 @@ the rule to mark CC(mail to any other person defined in actions)."),
return self.format_body(body % data)
def email_send(self, cr, uid, obj, emails, body, emailfrom=None, context=None):
""" send email
@param self: The object pointer
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param email: pass the emails
@param emailfrom: Pass name the email From else False
@param context: A standard dictionary for contextual values """
if not emailfrom:
emailfrom = tools.config.get('email_from', False)
if context is None:
context = {}
mail_message = self.pool.get('mail.message')
emailfrom = tools.config.get('email_from')
body = self.format_mail(obj, body)
if not emailfrom:
if hasattr(obj, 'user_id') and obj.user_id and obj.user_id.email:
emailfrom = obj.user_id.email
name = '[%d] %s' % (obj.id, tools.ustr(obj.name))
if not emailfrom and hasattr(obj, 'user_id') and obj.user_id and obj.user_id.email:
emailfrom = obj.user_id.email
emailfrom = tools.ustr(emailfrom)
reply_to = emailfrom
if not emailfrom:
raise osv.except_osv(_('Error!'),
_("No email ID found for your company address."))
return mail_message.schedule_with_attach(cr, uid, emailfrom, emails, name, body, model='base.action.rule', reply_to=reply_to, res_id=obj.id)
_("Missing default email address or missing email on responsible user"))
return self.pool.get('mail.mail').create(cr, uid,
{ 'email_from': emailfrom,
'email_to': emails.join(','),
'reply_to': reply_to,
'state': 'outgoing',
'subject': '[%d] %s' % (obj.id, tools.ustr(obj.name)),
'body_html': '<pre>%s</pre>' % body,
'res_id': obj.id,
'model': obj._table_name,
'auto_delete': True
}, context=context)
def do_check(self, cr, uid, action, obj, context=None):
+24 -57
View File
@@ -471,18 +471,10 @@ property or property parameter."),
def _send_mail(self, cr, uid, ids, mail_to, email_from=tools.config.get('email_from', False), context=None):
"""
Send mail for event invitation to event attendees.
@param cr: the current row, from the database cursor,
@param uid: the current user’s ID for security checks,
@param ids: List of attendee’s IDs.
@param email_from: Email address for user sending the mail
@param context: A standard dictionary for contextual values
@return: True
"""
if context is None:
context = {}
company = self.pool.get('res.users').browse(cr, uid, uid, context=context).company_id.name
mail_message = self.pool.get('mail.message')
for att in self.browse(cr, uid, ids, context=context):
sign = att.sent_by_uid and att.sent_by_uid.signature or ''
sign = '<br>'.join(sign and sign.split('\n') or [])
@@ -508,17 +500,18 @@ property or property parameter."),
}
body = html_invitation % body_vals
if mail_to and email_from:
attach = self.get_ics_file(cr, uid, res_obj, context=context)
mail_message.schedule_with_attach(cr, uid,
email_from,
mail_to,
sub,
body,
attachments=attach and {'invitation.ics': attach} or None,
content_subtype='html',
reply_to=email_from,
context=context
)
ics_file = self.get_ics_file(cr, uid, res_obj, context=context)
vals = {'email_from': email_from,
'email_to': mail_to,
'state': 'outgoing',
'subject': sub,
'body_html': body,
'auto_delete': True}
if ics_file:
vals['attachment_ids'] = [(0,0,{'name': 'invitation.ics',
'datas_fname': 'invitation.ics',
'datas': str(ics_file).encode('base64')})]
self.pool.get('mail.mail').create(cr, uid, vals, context=context)
return True
def onchange_user_id(self, cr, uid, ids, user_id, *args, **argv):
@@ -812,7 +805,6 @@ class calendar_alarm(osv.osv):
"""
if context is None:
context = {}
mail_message = self.pool.get('mail.message')
current_datetime = datetime.now()
alarm_ids = self.search(cr, uid, [('state', '!=', 'done')], context=context)
@@ -849,36 +841,10 @@ class calendar_alarm(osv.osv):
else:
re_dates = [alarm.trigger_date]
for r_date in re_dates:
ref = alarm.model_id.model + ',' + str(alarm.res_id)
# search for alreay sent requests
#if request_obj.search(cr, uid, [('trigger_date', '=', r_date), ('ref_doc1', '=', ref)], context=context):
#continue
# Deactivated because of the removing of res.request
# TODO: when cleaning calendar module, re-add this in a new mechanism
#if alarm.action == 'display':
#value = {
#'name': alarm.name,
#'act_from': alarm.user_id.id,
#'act_to': alarm.user_id.id,
#'body': alarm.description,
#'trigger_date': r_date,
#'ref_doc1': ref
#}
#request_id = request_obj.create(cr, uid, value)
#request_ids = [request_id]
#for attendee in res_obj.attendee_ids:
#if attendee.user_id:
#value['act_to'] = attendee.user_id.id
#request_id = request_obj.create(cr, uid, value)
#request_ids.append(request_id)
#request_obj.request_send(cr, uid, request_ids)
if re_dates:
if alarm.action == 'email':
sub = '[Openobject Reminder] %s' % (alarm.name)
body = """
sub = '[OpenERP Reminder] %s' % (alarm.name)
body = """<pre>
Event: %s
Event Date: %s
Description: %s
@@ -888,20 +854,21 @@ From:
----
%s
</pre>
""" % (alarm.name, alarm.trigger_date, alarm.description, \
alarm.user_id.name, alarm.user_id.signature)
mail_to = [alarm.user_id.email]
for att in alarm.attendee_ids:
mail_to.append(att.user_id.email)
if mail_to:
mail_message.schedule_with_attach(cr, uid,
tools.config.get('email_from', False),
mail_to,
sub,
body,
context=context
)
vals = {
'state': 'outgoing',
'subject': sub,
'body_html': body,
'email_to': mail_to,
'email_from': tools.config.get('email_from', mail_to),
}
self.pool.get('mail.mail').create(cr, uid, vals, context=context)
if next_trigger_date:
update_vals.update({'trigger_date': next_trigger_date})
else:
+25 -60
View File
@@ -297,55 +297,31 @@ class base_stage(object):
destination=False)
def remind_user(self, cr, uid, ids, context=None, attach=False, destination=True):
mail_message = self.pool.get('mail.message')
for case in self.browse(cr, uid, ids, context=context):
if not destination and not case.email_from:
return False
if not case.user_id.email:
return False
if destination and case.section_id.user_id:
case_email = case.section_id.user_id.email
else:
case_email = case.user_id.email
src = case_email
dest = case.user_id.email or ""
body = case.description or ""
for message in case.message_ids:
if message.email_from and message.body:
body = message.body
break
if not destination:
src, dest = dest, case.email_from
if body and case.user_id.signature:
if body:
body += '\n\n%s' % (case.user_id.signature)
else:
body = '\n\n%s' % (case.user_id.signature)
body = self.format_body(body)
attach_to_send = {}
if attach:
attach_ids = self.pool.get('ir.attachment').search(cr, uid, [('res_model', '=', self._name), ('res_id', '=', case.id)])
attach_to_send = self.pool.get('ir.attachment').read(cr, uid, attach_ids, ['datas_fname', 'datas'])
attach_to_send = dict(map(lambda x: (x['datas_fname'], base64.decodestring(x['datas'])), attach_to_send))
# Send an email
subject = "Reminder: [%s] %s" % (str(case.id), case.name, )
mail_message.schedule_with_attach(cr, uid,
src,
[dest],
subject,
body,
model=self._name,
reply_to=case.section_id.reply_to,
res_id=case.id,
attachments=attach_to_send,
context=context
)
if 'message_post' in self:
for case in self.browse(cr, uid, ids, context=context):
if destination:
recipient_id = case.user_id.partner_id.id
else:
if not case.email_from:
return False
recipient_id = self.pool.get('res.partner').find_or_create(cr, uid, case.email_from, context=context)
body = case.description or ""
for message in case.message_ids:
if message.type == 'email' and message.body:
body = message.body
break
body = self.format_body(body)
attach_to_send = {}
if attach:
attach_ids = self.pool.get('ir.attachment').search(cr, uid, [('res_model', '=', self._name), ('res_id', '=', case.id)])
attach_to_send = self.pool.get('ir.attachment').read(cr, uid, attach_ids, ['datas_fname', 'datas'])
attach_to_send = dict(map(lambda x: (x['datas_fname'], x['datas'].decode('base64')), attach_to_send))
subject = "Reminder: [%s] %s" % (case.id, case.name)
self.message_post(cr, uid, case.id, body=body,
subject=subject, attachments=attach_to_send,
partner_ids=[recipient_id], context=context)
return True
def _check(self, cr, uid, ids=False, context=None):
@@ -360,17 +336,6 @@ class base_stage(object):
def format_mail(self, obj, body):
return self.pool.get('base.action.rule').format_mail(obj, body)
def message_thread_followers(self, cr, uid, ids, context=None):
res = {}
for case in self.browse(cr, uid, ids, context=context):
l=[]
if case.email_cc:
l.append(case.email_cc)
if case.user_id and case.user_id.email:
l.append(case.user_id.email)
res[case.id] = l
return res
# ******************************
# Notifications
# ******************************
+4 -14
View File
@@ -46,21 +46,11 @@ class base_action_rule(osv.osv):
}
def email_send(self, cr, uid, obj, emails, body, emailfrom=tools.config.get('email_from', False), context=None):
mail_message = self.pool.get('mail.message')
body = self.format_mail(obj, body)
if not emailfrom:
if hasattr(obj, 'user_id') and obj.user_id and obj.user_id.email:
emailfrom = obj.user_id.email
name = '[%d] %s' % (obj.id, tools.ustr(obj.name))
emailfrom = tools.ustr(emailfrom)
if hasattr(obj, 'section_id') and obj.section_id and obj.section_id.alias_id:
mail_id = super(base_action_rule, self).email_send(cr, uid, obj, emails, body, emailfrom=emailfrom, context=context)
if mail_id and hasattr(obj, 'section_id') and obj.section_id and obj.section_id.alias_id:
reply_to = obj.section_id.alias_id.name_get()[0][1]
else:
reply_to = emailfrom
if not emailfrom:
raise osv.except_osv(_('Error!'), _("There is no email for your company address."))
return mail_message.schedule_with_attach(cr, uid, emailfrom, emails, name, body, model=obj._name, reply_to=reply_to, res_id=obj.id)
self.pool.get('mail.mail').write(cr, uid, [mail_id], {'reply_to': reply_to}, context=context)
return mail_id
def do_check(self, cr, uid, action, obj, context=None):
ok = super(base_action_rule, self).do_check(cr, uid, action, obj, context=context)
-18
View File
@@ -671,24 +671,6 @@ class crm_lead(base_stage, osv.osv):
partner_ids[lead.id] = partner_id
return partner_ids
def _send_mail_to_salesman(self, cr, uid, lead, context=None):
"""
Send mail to salesman with updated Lead details.
@ lead: browse record of 'crm.lead' object.
"""
#TOFIX: mail template should be used here instead of fix subject, body text.
message = self.pool.get('mail.message')
email_to = lead.user_id and lead.user_id.email
if not email_to:
return False
email_from = lead.section_id and lead.section_id.user_id and lead.section_id.user_id.email or email_to
partner = lead.partner_id and lead.partner_id.name or lead.partner_name
subject = "lead %s converted into opportunity" % lead.name
body = "Info \n Id : %s \n Subject: %s \n Partner: %s \n Description : %s " % (lead.id, lead.name, lead.partner_id.name, lead.description)
return message.schedule_with_attach(cr, uid, email_from, [email_to], subject, body)
def allocate_salesman(self, cr, uid, ids, user_ids, team_id=False, context=None):
index = 0
for lead_id in ids:
@@ -89,11 +89,6 @@ class crm_lead_forward_to_partner(osv.osv_memory):
lead = self.pool.get(model).browse(cr, uid, res_id, context=context)
body = self._get_message_body(cr, uid, lead, history_mode, context=context)
return {'value': {'body': body}}
def on_change_partner_ids(self, cr, uid, ids, partner_ids, context=None):
""" TDE-TODO: Keep void; maybe we could check that partner_ids have
email defined. """
return {}
def create(self, cr, uid, values, context=None):
""" TDE-HACK: remove 'type' from context, because when viewing an
@@ -106,9 +101,7 @@ class crm_lead_forward_to_partner(osv.osv_memory):
return new_id
def action_forward(self, cr, uid, ids, context=None):
"""
Forward the lead to a partner
"""
""" Forward the lead to a partner """
if context is None:
context = {}
res = {'type': 'ir.actions.act_window_close'}
@@ -126,7 +119,7 @@ class crm_lead_forward_to_partner(osv.osv_memory):
self.send_mail(cr, uid, ids, context=context)
# for case in lead.browse(cr, uid, lead_ids, context=context):
# TDE: WHAT TO DO WITH THAT ?
# TODO: WHAT TO DO WITH THAT ?
# if (this.send_to == 'partner' and this.partner_id):
# lead.assign_partner(cr, uid, [case.id], this.partner_id.id, context=context)
@@ -16,7 +16,7 @@
on_change="on_change_history_mode(history_mode, model, res_id)"/>
<field name="subject" colspan="4"/>
<field name="partner_ids" colspan="4" widget="many2many_tags"
on_change="on_change_partner_ids(partner_ids)"/>
on_change="onchange_partner_ids(partner_ids)"/>
<notebook colspan="4">
<page string="Body">
<field name="body"/>
+12 -18
View File
@@ -7,15 +7,12 @@
<field name="email_from" >${object.user_id.email or object.company_id.email or 'noreply@' + object.company_id.name + '.com'}</field>
<field name="email_to" >${object.email}</field>
<field name="subject">Your registration at ${object.event_id.name}</field>
<field name="body">
hello ${object.name},
The event ${object.event_id.name} that you registered for is confirmed and will be held from ${object.event_id.date_begin} to ${object.event_id.date_end}. For any further information please contact our event department.
we thank you for your participation
best regards
</field>
<field name="body_html"><![CDATA[
<p>Hello ${object.name},</p>
<p>The event ${object.event_id.name} that you registered for is confirmed and will be held from ${object.event_id.date_begin} to ${object.event_id.date_end}.
For any further information please contact our event department.</p>
<p>Thank you for your participation!</p>
<p>Best regards</p>]]></field>
</record>
</data>
@@ -27,15 +24,12 @@
<field name="email_from" >${object.user_id.email or object.company_id.email or 'noreply@' + object.company_id.name + '.com'}</field>
<field name="email_to" >${object.email}</field>
<field name="subject">Your registration at ${object.event_id.name}</field>
<field name="body">
hello ${object.name},
We confirm you that your registration to the event ${object.event_id.name} has been recorded. You will automatically receive an email providing you more practical information (such as the schedule, the plan...) as soon as the event will be confirmed to be held.
we thank you for your participation
best regards
</field>
<field name="body_html"><![CDATA[
<p>Hello ${object.name},</p>
<p>We confirm that your registration to the event ${object.event_id.name} has been recorded.
You will automatically receive an email providing you more practical information (such as the schedule, the agenda...) as soon as the event is confirmed.</p>
<p>Thank you for your participation!</p>
<p>Best regards</p>]]></field>
</record>
<!-- Default Values -->
+7 -3
View File
@@ -228,9 +228,13 @@ class hr_evaluation(osv.osv):
body = phase.mail_body % {'employee_name': child.name, 'user_signature': child.user_id.signature,
'eval_name': phase.survey_id.title, 'date': time.strftime('%Y-%m-%d'), 'time': time }
sub = phase.email_subject
dest = [child.work_email]
if dest:
mail_message.schedule_with_attach(cr, uid, evaluation.employee_id.work_email, dest, sub, body, context=context)
if child.work_email:
vals = {'state': 'outgoing',
'subject': sub,
'body_html': '<pre>%s</pre>' % body,
'email_to': child.work_email,
'email_from': evaluation.employee_id.work_email}
self.pool.get('mail.mail').create(cr, uid, vals, context=context)
self.write(cr, uid, ids, {'state':'wait'}, context=context)
return True
+20 -8
View File
@@ -267,16 +267,27 @@
<field name="arch" type="xml">
<form string="Interview Appraisal" version="7.0">
<header>
<button string="Cancel" name="survey_req_cancel" states="draft,waiting_answer" type="object" icon="gtk-cancel"/>
<button name="action_print_survey" string="Print Survey" type="object" states="draft" icon="gtk-print" context="{'survey_id': survey_id, 'response_id': [response], 'response_no':0}" attrs="{'readonly':[('survey_id','=',False)]}" class="oe_highlight"/>
<button string="Send Request" name="survey_req_waiting_answer" states="draft" type="object" icon="gtk-yes" class="oe_highlight"/>
<button name="%(survey.action_view_survey_question_message)d" string="Answer Survey" type="action" states="waiting_answer" context="{'survey_id': survey_id, 'response_id': [response], 'response_no':0, 'active' : response,'request' : True, 'object' : 'hr.evaluation.interview', 'cur_id' : active_id}" attrs="{'readonly':[('survey_id','=',False)]}"/>
<button string="Done" name="survey_req_done" states="waiting_answer" type="object" icon="gtk-jump-to"/>
<button string="Cancel" name="survey_req_cancel" type="object"
states="draft,waiting_answer"/>
<button string="Print Survey" name="action_print_survey" type="object"
states="draft" context="{'survey_id': survey_id, 'response_id': [response], 'response_no':0}"
attrs="{'readonly':[('survey_id','=',False)]}" class="oe_highlight"/>
<button string="Send Request" name="survey_req_waiting_answer" type="object"
states="draft" class="oe_highlight"/>
<button string="Answer Survey" name="%(survey.action_view_survey_question_message)d" type="action"
states="waiting_answer"
context="{'survey_id': survey_id, 'response_id': [response], 'response_no':0, 'active' : response,'request' : True, 'object' : 'hr.evaluation.interview', 'cur_id' : active_id}"
attrs="{'readonly':[('survey_id','=',False)]}"/>
<button string="Done" name="survey_req_done" type="object"
states="waiting_answer"/>
<field name="state" widget="statusbar" statusbar_visible="waiting_answer,done"/>
</header>
<sheet>
<div class="oe_right oe_button_box" name="button_box">
<button string="Send Reminder Email" name="%(mail.action_email_compose_message_wizard)d" icon="terp-mail-message-new" type="action" states="waiting_answer"/>
<button string="Send Reminder Email" name="%(mail.action_email_compose_message_wizard)d" type="action"
states="waiting_answer"
context="{'default_body_text': 'Hello,\n\nKindly post your response for the survey interview.\n\nThanks',
'default_subject': 'Reminder to fill up Survey' }"/>
</div>
<group>
<group col="3" colspan="1">
@@ -388,7 +399,6 @@
action="action_hr_evaluation_interview_tree"/>
<!-- Email Compose message Action-->
<!-- TDE TODO: add context values -->
<act_window
id="evaluation_reminders" name="Appraisal Reminders"
res_model="mail.compose.message"
@@ -396,7 +406,9 @@
view_type="form" view_mode="form"
target="new" multi="True"
key2="client_action_multi"
context="{'default_composition_mode': 'mass_mail'}"/>
context="{'default_composition_mode': 'mass_mail',
'default_body_text': 'Hello,\n\nKindly post your response for the survey interview.\n\nThanks',
'default_subject': 'Reminder to fill up Survey'}"/>
<!-- Appraisal Interviews Button on Employee Form -->
<act_window
+13 -4
View File
@@ -44,10 +44,6 @@ class mail_group(osv.Model):
def _set_image(self, cr, uid, id, name, value, args, context=None):
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
def _get_default_image(self, cr, uid, context=None):
image_path = openerp.modules.get_module_resource('mail', 'static/src/img', 'groupdefault.png')
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
_columns = {
'description': fields.text('Description'),
'menu_id': fields.many2one('ir.ui.menu', string='Related Menu', required=True, ondelete="cascade"),
@@ -89,6 +85,10 @@ class mail_group(osv.Model):
ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'base', 'group_user')
return ref and ref[1] or False
def _get_default_image(self, cr, uid, context=None):
image_path = openerp.modules.get_module_resource('mail', 'static/src/img', 'groupdefault.png')
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
def _get_menu_parent(self, cr, uid, context=None):
ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'mail_group_root')
return ref and ref[1] or False
@@ -156,3 +156,12 @@ class mail_group(osv.Model):
self._subscribe_users(cr, uid, ids, vals.get('group_ids'), context=context)
return result
def action_follow(self, cr, uid, ids, context=None):
""" Wrapper because message_subscribe_users take a user_ids=None
that receive the context without the wrapper. """
return self.message_subscribe_users(cr, uid, ids, context=context)
def action_unfollow(self, cr, uid, ids, context=None):
""" Wrapper because message_unsubscribe_users take a user_ids=None
that receive the context without the wrapper. """
return self.message_unsubscribe_users(cr, uid, ids, context=context)
+2 -3
View File
@@ -33,8 +33,8 @@
<h4><a type="open"><field name="name"/></a></h4>
<ul>
<li><t t-raw="record.message_summary.raw_value"/></li>
<li t-if="! record.message_is_follower.raw_value"><a name="message_subscribe_users" string="Join" type="object" class="oe_group_join">Not following</a></li>
<li t-if="record.message_is_follower.raw_value"><a name="message_unsubscribe_users" string="Leave" type="object" class="oe_group_leave">Following</a></li>
<li t-if="! record.message_is_follower.raw_value"><a name="action_follow" string="Join" type="object" class="oe_group_join">Not following</a></li>
<li t-if="record.message_is_follower.raw_value"><a name="action_unfollow" string="Leave" type="object" class="oe_group_leave">Following</a></li>
</ul>
</div>
</div>
@@ -81,7 +81,6 @@
</group>
</sheet>
<div class="oe_chatter">
<field name="message_is_follower" invisible="1"/>
<field name="message_ids" widget="mail_thread"
options='{"thread_level": 1}'/>
<field name="message_follower_ids" widget="mail_followers"/>
+2 -1
View File
@@ -136,7 +136,8 @@ class mail_message(osv.Model):
_defaults = {
'type': 'email',
'date': lambda *a: fields.datetime.now(),
'author_id': _get_default_author
'author_id': lambda self,cr,uid,ctx: self._get_default_author(cr, uid, ctx),
'body': '',
}
#------------------------------------------------------
+60 -66
View File
@@ -29,7 +29,6 @@ import time
import tools
import xmlrpclib
from email.utils import parsedate
from email.message import Message
from mail_message import decode
from osv import osv, fields
@@ -42,24 +41,20 @@ def decode_header(message, header, separator=' '):
return separator.join(map(decode,message.get_all(header, [])))
class many2many_reference(fields.many2many):
""" many2many_reference is an override of fields.many2many. It manages
many2many-like table where one id is given by two fields, res_model
and res_id.
"""
""" many2many_reference manages many2many fields where one id is found
by a reference-like key (a char column in addition to the foreign id).
The reference_column attribute on the many2many fields is used;
if not defined, ``res_model`` is used. """
def _get_query_and_where_params(self, cr, model, ids, values, where_params):
""" Add in where:
- ``mail_followers``.res_model = 'crm.lead'
"""
# reference column name: given by attribute or res_model
ref_col_name = self.ref_col_name if self.ref_col_name else 'res_model'
values.update({'ref_col_name': ref_col_name, 'ref_col_value': model._name})
""" Add in where condition like mail_followers.res_model = 'crm.lead' """
reference_column = self.reference_column if self.reference_column else 'res_model'
values.update(reference_column=reference_column, reference_value=model._name)
query = 'SELECT %(rel)s.%(id2)s, %(rel)s.%(id1)s \
FROM %(rel)s, %(from_c)s \
WHERE %(rel)s.%(id1)s IN %%s \
AND %(rel)s.%(id2)s = %(tbl)s.id \
AND %(rel)s.%(ref_col_name)s = \'%(ref_col_value)s\' \
AND %(rel)s.%(reference_column)s = \'%(reference_value)s\' \
%(where_c)s \
%(order_by)s \
%(limit)s \
@@ -68,41 +63,41 @@ class many2many_reference(fields.many2many):
return query, where_params
def set(self, cr, model, id, name, values, user=None, context=None):
""" Override to add the res_model field in queries. """
""" Override to add the reference field in queries. """
if not values: return
rel, id1, id2 = self._sql_names(model)
obj = model.pool.get(self._obj)
# reference column name: given by attribute or res_model
ref_col_name = self.ref_col_name if self.ref_col_name else 'res_model'
reference_column = self.reference_column if self.reference_column else 'res_model'
for act in values:
if not (isinstance(act, list) or isinstance(act, tuple)) or not act:
continue
if act[0] == 0:
idnew = obj.create(cr, user, act[2], context=context)
cr.execute('INSERT INTO '+rel+' ('+id1+','+id2+','+ref_col_name+') VALUES (%s,%s,%s)', (id, idnew, model._name))
cr.execute('INSERT INTO '+rel+' ('+id1+','+id2+','+reference_column+') VALUES (%s,%s,%s)', (id, idnew, model._name))
elif act[0] == 3:
cr.execute('DELETE FROM '+rel+' WHERE '+id1+'=%s AND '+id2+'=%s AND '+ref_col_name+'=%s', (id, act[1], model._name))
cr.execute('DELETE FROM '+rel+' WHERE '+id1+'=%s AND '+id2+'=%s AND '+reference_column+'=%s', (id, act[1], model._name))
elif act[0] == 4:
# following queries are in the same transaction - so should be relatively safe
cr.execute('SELECT 1 FROM '+rel+' WHERE '+id1+'=%s AND '+id2+'=%s AND '+ref_col_name+'=%s', (id, act[1], model._name))
cr.execute('SELECT 1 FROM '+rel+' WHERE '+id1+'=%s AND '+id2+'=%s AND '+reference_column+'=%s', (id, act[1], model._name))
if not cr.fetchone():
cr.execute('INSERT INTO '+rel+' ('+id1+','+id2+','+ref_col_name+') VALUES (%s,%s,%s)', (id, act[1], model._name))
cr.execute('INSERT INTO '+rel+' ('+id1+','+id2+','+reference_column+') VALUES (%s,%s,%s)', (id, act[1], model._name))
elif act[0] == 5:
cr.execute('delete from '+rel+' where '+id1+' = %s AND '+ref_col_name+'=%s', (id, model._name))
cr.execute('delete from '+rel+' where '+id1+' = %s AND '+reference_column+'=%s', (id, model._name))
elif act[0] == 6:
d1, d2,tables = obj.pool.get('ir.rule').domain_get(cr, user, obj._name, context=context)
if d1:
d1 = ' and ' + ' and '.join(d1)
else:
d1 = ''
cr.execute('DELETE FROM '+rel+' WHERE '+id1+'=%s AND '+ref_col_name+'=%s AND '+id2+' IN (SELECT '+rel+'.'+id2+' FROM '+rel+', '+','.join(tables)+' WHERE '+rel+'.'+id1+'=%s AND '+rel+'.'+id2+' = '+obj._table+'.id '+ d1 +')', [id, model._name, id]+d2)
cr.execute('DELETE FROM '+rel+' WHERE '+id1+'=%s AND '+reference_column+'=%s AND '+id2+' IN (SELECT '+rel+'.'+id2+' FROM '+rel+', '+','.join(tables)+' WHERE '+rel+'.'+id1+'=%s AND '+rel+'.'+id2+' = '+obj._table+'.id '+ d1 +')', [id, model._name, id]+d2)
for act_nbr in act[2]:
cr.execute('INSERT INTO '+rel+' ('+id1+','+id2+','+ref_col_name+') VALUES (%s,%s,%s)', (id, act_nbr, model._name))
cr.execute('INSERT INTO '+rel+' ('+id1+','+id2+','+reference_column+') VALUES (%s,%s,%s)', (id, act_nbr, model._name))
# cases 1, 2: performs write and unlink -> default implementation is ok
else:
return super(many2many_reference, self).set(cr, model, id, name, values, user, context)
class mail_thread(osv.Model):
class mail_thread(osv.AbstractModel):
''' mail_thread model is meant to be inherited by any model that needs to
act as a discussion topic on which messages can be attached. Public
methods are prefixed with ``message_`` in order to avoid name
@@ -161,19 +156,18 @@ class mail_thread(osv.Model):
type='boolean', string='Is a Follower', multi='_get_message_data'),
'message_follower_ids': many2many_reference('res.partner',
'mail_followers', 'res_id', 'partner_id',
ref_col_name='res_model', string='Followers'),
reference_column='res_model', string='Followers'),
'message_comment_ids': fields.one2many('mail.message', 'res_id',
domain=lambda self: [('model','=',self._name),('type','in',('comment','email'))],
string='Related Messages',
help="All messages related to the current document."),
domain=lambda self: [('model', '=', self._name), ('type', 'in', ('comment', 'email'))],
string='Comments and emails',
help="Comments and emails"),
'message_ids': fields.one2many('mail.message', 'res_id',
domain=lambda self: [('model','=',self._name)],
string='Related Messages',
help="All messages related to the current document."),
string='Messages',
help="Messages and communication history"),
'message_unread': fields.function(_get_message_data, fnct_search=_search_unread,
string='Has Unread Messages', type='boolean',
help="When checked, new messages require your attention.",
multi="_get_message_data"),
type='boolean', string='Unread Messages', multi="_get_message_data",
help="If checked new messages require your attention."),
'message_summary': fields.function(_get_message_data, method=True,
type='text', string='Summary', multi="_get_message_data",
help="Holds the Chatter summary (number of messages, ...). "\
@@ -186,7 +180,7 @@ class mail_thread(osv.Model):
#------------------------------------------------------
def create(self, cr, uid, vals, context=None):
""" Override of create to subscribe the current user. """
""" Override to subscribe the current user. """
thread_id = super(mail_thread, self).create(cr, uid, vals, context=context)
self.message_subscribe_users(cr, uid, [thread_id], [uid], context=context)
return thread_id
@@ -217,14 +211,20 @@ class mail_thread(osv.Model):
# Mail gateway
#------------------------------------------------------
def message_capable_models(self, cr, uid, context=None):
""" Used by the plugin addon, based for plugin_outlook and others. """
ret_dict = {}
for model_name in self.pool.obj_list():
model = self.pool.get(model_name)
if 'mail.thread' in getattr(model, '_inherit', []):
ret_dict[model_name] = model._description
return ret_dict
def _message_find_partners(self, cr, uid, message, header_fields=['From'], context=None):
""" Find partners related to some header fields of the message. """
s = ', '.join([decode(message.get(h)) for h in header_fields if message.get(h)])
mails = tools.email_split(s)
result = []
for email in mails:
result += self.pool.get('res.partner').search(cr, uid, [('email', 'ilike', email)], context=context)
return result
return [partner_id for email in tools.email_split(s)
for partner_id in self.pool.get('res.partner').search(cr, uid, [('email', 'ilike', email)], context=context)]
def _message_find_user_id(self, cr, uid, message, context=None):
from_local_part = tools.email_split(decode(message.get('From')))[0]
@@ -387,9 +387,7 @@ class mail_thread(osv.Model):
for a given thread model, if the message did not belong to
an existing thread.
The default behavior is to create a new record of the corresponding
model (based on some very basic info extracted from the message),
then attach the message to the newly created record
(by calling ``message_append_dict``).
model (based on some very basic info extracted from the message).
Additional behavior may be implemented by overriding this method.
:param dict msg_dict: a map containing the email details and
@@ -422,9 +420,8 @@ class mail_thread(osv.Model):
def message_update(self, cr, uid, ids, msg_dict, update_vals=None, context=None):
"""Called by ``message_process`` when a new message is received
for an existing thread. The default behavior is to create a
new mail.message in the given thread (by calling
``message_append_dict``)
for an existing thread. The default behavior is to update the record
with update_vals taken from the incoming email.
Additional behavior may be implemented by overriding this
method.
:param dict msg_dict: a map containing the email details and
@@ -556,23 +553,23 @@ class mail_thread(osv.Model):
#------------------------------------------------------
def log(self, cr, uid, id, message, secondary=False, context=None):
_logger.warning("log() is deprecated. As this module inherit from \
mail.thread, the message will be managed by this \
module instead of by the res.log mechanism. Please \
use the mail.thread OpenChatter API instead of the \
now deprecated res.log.")
_logger.warning("log() is deprecated. As this module inherit from "\
"mail.thread, the message will be managed by this "\
"module instead of by the res.log mechanism. Please "\
"use mail_thread.message_post() instead of the "\
"now deprecated res.log.")
self.message_post(cr, uid, [id], message, context=context)
def message_post(self, cr, uid, thread_id, body='', subject=False,
msg_type='notification', parent_id=False, attachments=None, subtype='other', context=None, **kwargs):
""" Post a new message in an existing message thread, returning the new
type='notification', parent_id=False, attachments=None, subtype='other', context=None, **kwargs):
""" Post a new message in an existing thread, returning the new
mail.message ID. Extra keyword arguments will be used as default
column values for the new mail.message record.
:param int thread_id: thread ID to post into, or list with one ID
:param str body: body of the message, usually raw HTML that will
be sanitized
:param str subject: optional subject
:param str msg_type: mail_message.type
:param str type: mail_message.type
:param int parent_id: optional ID of parent message in this thread
:param tuple(str,str) attachments: list of attachment tuples in the form
``(name,content)``, where content is NOT base64 encoded
@@ -608,11 +605,11 @@ class mail_thread(osv.Model):
if self._name in [model.model for model in subtype_browse.model_ids]:
values['subtype_id']=subtype_browse.id
values.update( {
'model': thread_id and context.get('thread_model', self._name) or False,
'model': context.get('thread_model', self._name) if thread_id else False,
'res_id': thread_id or False,
'body': body,
'subject': subject,
'type': msg_type,
'type': type,
'parent_id': parent_id,
'attachment_ids': attachment_ids,
})
@@ -626,16 +623,14 @@ class mail_thread(osv.Model):
def message_subscribe_users(self, cr, uid, ids, user_ids=None, context=None):
""" Wrapper on message_subscribe, using users. If user_ids is not
provided, subscribe uid instead. """
# isinstance: because using message_subscribe_users called in a view set the context as user_ids
if not user_ids or isinstance(user_ids, dict): user_ids = [uid]
if not user_ids: user_ids = [uid]
partner_ids = [user.partner_id.id for user in self.pool.get('res.users').browse(cr, uid, user_ids, context=context)]
return self.message_subscribe(cr, uid, ids, partner_ids, context=context)
def message_subscribe(self, cr, uid, ids, partner_ids,subtype_ids = None, context=None):
""" Add partners to the records followers.
:param partner_ids: a list of partner_ids to subscribe
:param return: new value of followers, for Chatter
:param return: new value of followers if read_back key in context
"""
self.write(cr, uid, ids, {'message_follower_ids': [(4, pid) for pid in partner_ids]}, context=context)
if not subtype_ids:
@@ -643,28 +638,27 @@ class mail_thread(osv.Model):
subtype_ids = subtype_obj.search(cr, uid, [('default', '=', 'true'),('model_ids.model', '=', self._name)])
if subtype_ids:
self.message_subscribe_udpate_subtypes(cr, uid, ids, partner_ids, subtype_ids, context=context)
# TDE: temp, must check followers widget
if context and context.get('read_back'):
return [follower.id for thread in self.browse(cr, uid, ids, context=context) for follower in thread.message_follower_ids]
return []
# return [follower.id for thread in self.browse(cr, uid, ids, context=context) for follower in thread.message_follower_ids]
def message_unsubscribe_users(self, cr, uid, ids, user_ids=None, context=None):
""" Wrapper on message_subscribe, using users. If user_ids is not
provided, unsubscribe uid instead. """
# isinstance: because using message_subscribe_users called in a view set the context as user_ids
if not user_ids or isinstance(user_ids, dict): user_ids = [uid]
if not user_ids: user_ids = [uid]
partner_ids = [user.partner_id.id for user in self.pool.get('res.users').browse(cr, uid, user_ids, context=context)]
return self.message_unsubscribe(cr, uid, ids, partner_ids, context=context)
def message_unsubscribe(self, cr, uid, ids, partner_ids, context=None):
""" Remove partners from the records followers.
:param partner_ids: a list of partner_ids to unsubscribe
:param return: new value of followers, for Chatter
:param return: new value of followers if read_back key in context
"""
self.write(cr, uid, ids, {'message_follower_ids': [(3, pid) for pid in partner_ids]}, context=context)
# TDE: temp, must check followers widget
if context and context.get('read_back'):
return [follower.id for thread in self.browse(cr, uid, ids, context=context) for follower in thread.message_follower_ids]
return []
# return [follower.id for thread in self.browse(cr, uid, ids, context=context) for follower in thread.message_follower_ids]
#------------------------------------------------------
# Thread state
+8 -14
View File
@@ -9,7 +9,7 @@ openerp_mail_followers = function(session, mail) {
* mail_followers Widget
* ------------------------------------------------------------
*
* This widget handles the display of a list of records as a vetical
* This widget handles the display of a list of records as a vertical
* list, with an image on the left. The widget itself is a floatting
* right-sided box.
* This widget is mainly used to display the followers of records
@@ -71,25 +71,17 @@ openerp_mail_followers = function(session, mail) {
this.$el.find('div.oe_mail_recthread_aside').hide();
return;
}
if (this.getParent().fields.message_is_follower === undefined) {
// TDE: TMP, need to change all form views
this.message_is_follower = false;
}
else {
this.message_is_follower = this.getParent().fields.message_is_follower.get_value();
}
return this.fetch_followers(value_);
},
fetch_followers: function (value_) {
return this.ds_follow.call('read', [value_ || this.get_value(), ['name']]).then(this.proxy('display_followers'));
return this.ds_follow.call('read', [value_ || this.get_value(), ['name', 'user_ids']]).then(this.proxy('display_followers'));
},
/**
* Display the followers.
* TODO: replace the is_follower check by fields read */
/** Display the followers, evaluate is_follower directly */
display_followers: function (records) {
var self = this;
this.message_is_follower = _.indexOf(_.flatten(_.pluck(records, 'user_ids')), this.session.uid) != -1;
var node_user_list = this.$el.find('ul.oe_mail_followers_display').empty();
this.$el.find('div.oe_mail_recthread_followers h4').html(this.options.title + ' (' + records.length + ')');
_(records).each(function (record) {
@@ -137,7 +129,8 @@ openerp_mail_followers = function(session, mail) {
},
do_follow: function () {
return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id]]).pipe(this.proxy('set_value'));
var context = new session.web.CompoundContext(this.build_context(), {'read_back': true});
return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], undefined, context]).pipe(this.proxy('set_value'));
},
//fetch subtype from subtype model
@@ -150,7 +143,8 @@ openerp_mail_followers = function(session, mail) {
},
do_unfollow: function () {
return this.ds_model.call('message_unsubscribe_users', [[this.view.datarecord.id]]).pipe(this.proxy('set_value'));
var context = new session.web.CompoundContext(this.build_context(), {'read_back': true});
return this.ds_model.call('message_unsubscribe_users', [[this.view.datarecord.id], undefined, context]).pipe(this.proxy('set_value'));
},
});
};
+2 -2
View File
@@ -251,7 +251,7 @@ class test_mail(common.TransactionCase):
_attachments = [('First', 'My first attachment'), ('Second', 'My second attachment')]
# CASE1: post comment, body and subject specified
msg_id = self.mail_group.message_post(cr, uid, self.group_pigs_id, body=_body1, subject=_subject, msg_type='comment')
msg_id = self.mail_group.message_post(cr, uid, self.group_pigs_id, body=_body1, subject=_subject, type='comment')
message = self.mail_message.browse(cr, uid, msg_id)
mail_ids = self.mail_mail.search(cr, uid, [], limit=1)
mail = self.mail_mail.browse(cr, uid, mail_ids[0])
@@ -281,7 +281,7 @@ class test_mail(common.TransactionCase):
# CASE2: post an email with attachments, parent_id, partner_ids
# TESTS: automatic subject, signature in body_html, attachments propagation
msg_id2 = self.mail_group.message_post(cr, uid, self.group_pigs_id, body=_body2, msg_type='email',
msg_id2 = self.mail_group.message_post(cr, uid, self.group_pigs_id, body=_body2, type='email',
partner_ids=[(6, 0, [p_d_id])], parent_id=msg_id, attachments=_attachments)
message = self.mail_message.browse(cr, uid, msg_id2)
mail_ids = self.mail_mail.search(cr, uid, [], limit=1)
+3 -3
View File
@@ -81,7 +81,7 @@ class mail_compose_message(osv.TransientModel):
elif composition_mode == 'comment' and model and res_id:
vals = self.get_record_data(cr, uid, model, res_id, context=context)
elif composition_mode == 'mass_mail' and model and active_ids:
vals = {'model': model, 'res_id': res_id, 'content_subtype': 'html'}
vals = {'model': model, 'res_id': res_id}
else:
vals = {'model': model, 'res_id': res_id}
if composition_mode:
@@ -106,7 +106,7 @@ class mail_compose_message(osv.TransientModel):
'mail_compose_message_ir_attachments_rel',
'wizard_id', 'attachment_id', 'Attachments'),
'filter_id': fields.many2one('ir.filters', 'Filters'),
'body_text': fields.text('Plain-text editor body'),
'body_text': fields.text('Plain-text Contents'),
'content_subtype': fields.char('Message content subtype', size=32, readonly=1,
help="Type of message, usually 'html' or 'plain', used to select "\
"plain-text or rich-text contents accordingly"),
@@ -269,7 +269,7 @@ class mail_compose_message(osv.TransientModel):
post_values['attachments'] += new_attachments
post_values.update(email_dict)
# post the message
active_model_pool.message_post(cr, uid, [res_id], msg_type='comment', context=context, **post_values)
active_model_pool.message_post(cr, uid, [res_id], type='comment', context=context, **post_values)
return {'type': 'ir.actions.act_window_close'}
@@ -6,34 +6,43 @@
<field name="model">mail.compose.message</field>
<field name="arch" type="xml">
<form string="Compose Email" version="7.0">
<field name="composition_mode" nolabel="1" invisible="1"/>
<field name="model" nolabel="1" invisible="1"/>
<field name="res_id" nolabel="1" invisible="1"/>
<field name="parent_id" nolabel="1" invisible="1"/>
<field name="content_subtype" nolabel="1" invisible="1"/>
<group>
<field name="composition_mode" invisible="1"/>
<field name="model" invisible="1"/>
<field name="res_id" invisible="1"/>
<field name="author_id"/>
<field name="partner_ids"/>
<field name="subject" widget="char" size="512"/>
<field name="message_id"/>
<field name="subject" placeholder="Subject..."/>
<field name="partner_ids" widget="many2many_tags" placeholder="Add contacts to notify..."
context="{'force_create':True}"
on_change="onchange_partner_ids(partner_ids)"/>
</group>
<notebook colspan="4">
<notebook>
<page string="Body">
<field name="body" colspan="4" nolabel="1" height="300" width="300"/>
<field name="body_text" nolabel="1"
attrs="{'invisible':[('content_subtype', '=', 'html')]}"/>
<field name="body" nolabel="1"
attrs="{'invisible':[('content_subtype', '=', 'plain')]}"/>
</page>
<page string="Attachments">
<field name="attachment_ids" colspan="4" nolabel="1"/>
</page>
</notebook>
<footer>
<button name="send_mail" string="Send" type="object" class="oe_highlight" />
<button string="Send" name="send_mail" type="object" class="oe_highlight" />
or
<button string="Cancel" class="oe_link" special="cancel" />
<div class="oe_right">
<button string="" name="toggle_content_subtype" type="object" icon="/mail/static/src/img/formatting.png"
help="Toggle advanced formatting mode"/>
</div>
</footer>
</form>
</field>
</record>
<record model="ir.ui.view" id="email_compose_message_wizard_form_chatter">
<field name="name">mail.compose.message.form</field>
<field name="name">mail.compose.message.form.chatter</field>
<field name="model">mail.compose.message</field>
<field name="priority">18</field>
<field name="arch" type="xml">
@@ -3,29 +3,29 @@
<data>
<!-- Email tempalte -->
<record id="email_template_1" model="email.template">
<field name="name">Template for New Partner</field>
<field name="name">welcome new partner</field>
<field name="email_from">info@openerp.com</field>
<field name="subject">Welcome in OpenERP Partner Channel!</field>
<field name="subject">Welcome to the OpenERP Partner Channel!</field>
<field name="email_to">${object.email or ''}</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="body">Hello, We are very happy to send Welcome message.</field>
<field name="body_html">Hello, you will receive your welcome pack via email shortly.</field>
</record>
<record id="email_template_2" model="email.template">
<field name="name">Template for Silver Partner</field>
<field name="name">congrats silver partner</field>
<field name="email_from">info@openerp.com</field>
<field name="subject">Congratulation! You become now our Silver Partner.</field>
<field name="subject">Congratulations! You are now a Silver Partner!</field>
<field name="email_to">${object.email or ''}</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="body">Hello, We are happy to announce that you now become our Silver Partner.</field>
<field name="body_html">Hi, we are delighted to welcome you among our Silver Partners as of today!</field>
</record>
<record id="email_template_3" model="email.template">
<field name="name">Template for Gold Partner</field>
<field name="name">congrats gold partner</field>
<field name="email_from">info@openerp.com</field>
<field name="subject">Congratulation! You become our Gold Partner.</field>
<field name="subject">Congratulations! You are now one of our Gold Partners!</field>
<field name="email_to">${object.email or ''}</field>
<field name="model_id" ref="base.model_res_partner"/>
<field name="body">Hello, We are happy to announce that you become our Gold Partner.</field>
<field name="body_html">Hi, we are delighted to let you know that you have entered the select circle of our Gold Partners</field>
</record>
@@ -40,7 +40,10 @@
<field model="ir.values" name="ref_ir_value" search="[('name', '=', u'Send Mail (For OpenERP OnDemand Free Trial 2010)')]"/>
<field name="model_id" ref="crm.model_crm_lead"/>
<field eval="0" name="user_signature"/>
<field name="body">Hello,Thanks for generous interest you have shown in the openERP.Regards,OpenERP Team,</field>
<field name="body_html"><![CDATA[<p>Hello,</p>
<p>Thanks for the genuine interest you have shown in OpenERP.</p>
<p>If any further information is required, do not hesitate to reply to this message.</p>
<p>Regards,OpenERP Team,</p>]]></field>
<field name="name">For OpenERP OnDemand Free Trial 2010</field>
</record>
<record id="email_template_2" model="email.template">
@@ -50,11 +53,11 @@
<field model="ir.values" name="ref_ir_value" search="[('name', '=', u'Send Mail (For OpenERP OnDemand Free Trial 2010)')]"/>
<field name="model_id" ref="crm.model_crm_lead"/>
<field eval="0" name="user_signature"/>
<field name="body">Hello,We have very good offer that might suit you.
We propose you to subscribe to the OpenERP Discovery Day on May 2010.
If any further information required kindly revert back.
We really appreciate your co-operation on this.
Regards,OpenERP Team,</field>
<field name="body_html"><![CDATA[<p>Hello,</p>
<p>We have very good offer that might suit you.
We suggest you subscribe to the OpenERP Discovery Day on May 2010.</p>
<p>If any further information is required, do not hesitate to reply to this message.</p>
<p>Regards,OpenERP Team,</p>]]></field>
<field name="name">For OpenERP Discovery Day on May 2010</field>
</record>
@@ -65,10 +68,10 @@
<field model="ir.values" name="ref_ir_value" search="[('name', '=', u'Send Mail (For OpenERP OnDemand Free Trial 2010)')]"/>
<field name="model_id" ref="crm.model_crm_lead"/>
<field eval="0" name="user_signature"/>
<field name="body">Hello,Thanks for showing intrest and for subscribing to the OpenERP Discovery Day.
If any further information required kindly revert back.
I really appreciate your co-operation on this.
Regards,OpenERP Team,</field>
<field name="body_html"><![CDATA[<p>Hello,</p>
<p>Thanks for showing interest and for subscribing to the OpenERP Discovery Day.</p>
<p>If any further information is required, do not hesitate to reply to this message.</p>
<p>Regards,OpenERP Team,</p>]]></field>
<field name="name">For OpenERP Discovery Day</field>
</record>
@@ -79,10 +82,10 @@
<field model="ir.values" name="ref_ir_value" search="[('name', '=', u'Send Mail (For OpenERP OnDemand Free Trial 2010)')]"/>
<field name="model_id" ref="crm.model_crm_lead"/>
<field eval="0" name="user_signature"/>
<field name="body">Hello,Thanks for showing intrest and buying the OpenERP book.
<field name="body_html"><![CDATA[<p>Hello,</p>
<p>Thanks for showing interest and buying the OpenERP book.</p>
If any further information required kindly revert back.
I really appreciate your co-operation on this.
Regards,OpenERP Team,</field>
<p>Regards,OpenERP Team,</p>]]></field>
<field name="name">For OpenERP book</field>
</record>
@@ -92,12 +95,12 @@
<field model="ir.actions.act_window" name="ref_ir_act_window" search="[('name', '=', u'For OpenERP OnDemand Free Trial 2010 Mail Form')]"/>
<field model="ir.values" name="ref_ir_value" search="[('name', '=', u'Send Mail (For OpenERP OnDemand Free Trial 2010)')]"/>
<field eval="0" name="user_signature"/>
<field name="body">Hello, We have very good offer that might suit you.
For our gold partners,We are arranging free technical training on june,2010.
If any further information required kindly revert back.
I really appreciate your co-operation on this.
Regards,OpenERP Team,</field>
<field name="name">For technical training to Gold partners</field>
<field name="body_html"><![CDATA[<p>Hello,</p>
<p>We have very good offer that might suit you.
For our gold partners,We are arranging free technical training on june,2010.</p>
<p>If any further information is required, do not hesitate to reply to this message.</p>
<p>Regards,OpenERP Team,</p>]]></field>
<field name="name">technical training to gold partners</field>
</record>
<record id="email_template_6" model="email.template">
@@ -107,12 +110,12 @@
<field model="ir.values" name="ref_ir_value" search="[('name', '=', u'Send Mail (For OpenERP OnDemand Free Trial 2010)')]"/>
<field name="model_id" ref="crm.model_crm_lead"/>
<field eval="0" name="user_signature"/>
<field name="body">Hello, We have very good offer that might suit you.
For our silver partners,We are paid technical training on june,2010.
If any further information required kindly revert back.
I really appreciate your co-operation on this.
Regards,OpenERP Team,</field>
<field name="name">For training to Silver partners</field>
<field name="body_html"><![CDATA[<p>Hello,</p>
<p>We have very good offer that might suit you.
For our silver partners,We are paid technical training on june,2010.</p>
<p>If any further information is required, do not hesitate to reply to this message.</p>
<p>Regards,OpenERP Team,</p>]]></field>
<field name="name">training to silver partners</field>
</record>
<record id="email_template_7" model="email.template">
@@ -122,12 +125,12 @@
<field model="ir.values" name="ref_ir_value" search="[('name', '=', u'Send Mail (For OpenERP OnDemand Free Trial 2010)')]"/>
<field name="model_id" ref="crm.model_crm_lead"/>
<field eval="0" name="user_signature"/>
<field name="body">Hello, We have very good offer that might suit you.
For our silver partners,We are offering Gold partnership.
If any further information required kindly revert back.
I really appreciate your co-operation on this.
Regards,OpenERP Team,</field>
<field name="name">For gold partnership to silver partners</field>
<field name="body_html"><![CDATA[<p>Hello,</p>
<p>We have very good offer that might suit you.
For our silver partners, we are offering Gold partnership.</p>
<p>If any further information is required, do not hesitate to reply to this message.</p>
<p>Regards,OpenERP Team,</p>]]></field>
<field name="name">gold partnership to silver partners</field>
</record>
<record id="email_template_8" model="email.template">
@@ -137,9 +140,12 @@
<field model="ir.values" name="ref_ir_value" search="[('name', '=', u'Send Mail (For OpenERP OnDemand Free Trial 2010)')]"/>
<field name="model_id" ref="crm.model_crm_lead"/>
<field eval="0" name="user_signature"/>
<field name="body">Hello, Thanks for showing intrest and for subscribing to technical training.If any further information required kindly revert back.I really appreciate your co-operation on this.
Regards,OpenERP Team,</field>
<field name="name">For subscribing to technical training</field>
<field name="body_html"><![CDATA[<p>Hello,</p>
<p>Thanks for showing interest and for subscribing to technical training.</p>
If any further information required kindly revert back.I really appreciate your co-operation on this.</p>
<p>If any further information is required, do not hesitate to reply to this message.</p>
<p>Regards,OpenERP Team,</p>]]></field>
<field name="name">subscribing to technical training</field>
</record>
<!-- Report -->
+7 -5
View File
@@ -171,7 +171,7 @@ class wizard(osv.osv_memory):
'url': wiz.portal_id.url or _("(missing url)"),
'db': cr.dbname,
}
mail_message_obj = self.pool.get('mail.message')
mail_mail_obj = self.pool.get('mail.mail')
dest_uids = user_obj.search(cr, ROOT_UID, login_cond)
dest_users = user_obj.browse(cr, ROOT_UID, dest_uids)
for dest_user in dest_users:
@@ -184,10 +184,12 @@ class wizard(osv.osv_memory):
email_to = dest_user.email
subject = _(WELCOME_EMAIL_SUBJECT) % data
body = _(WELCOME_EMAIL_BODY) % data
res = mail_message_obj.schedule_with_attach(cr, uid, email_from , [email_to], subject, body, context=context)
if not res:
_logger.warning(
'Failed to send email from %s to %s', email_from, email_to)
mail_id = mail_mail_obj.create(cr, uid, {
'email_from': email_from ,
'email_to': email_to,
'subject': subject,
'state': 'outgoing',
'body_html': '<pre>%s</pre>' % body}, context=context)
return {'type': 'ir.actions.act_window_close'}
-1
View File
@@ -363,7 +363,6 @@ class project_issue(base_stage, osv.osv):
return super(project_issue, self).write(cr, uid, ids, vals, context)
def onchange_task_id(self, cr, uid, ids, task_id, context=None):
result = {}
if not task_id:
return {'value':{}}
task = self.pool.get('project.task').browse(cr, uid, task_id, context=context)
@@ -108,51 +108,6 @@
</div>
</div>
]]></field>
<field name="body"><![CDATA[
Hello${object.partner_id.name and ' ' or ''}${object.partner_id.name or ''},
Here is a ${object.state in ('draft', 'sent') and 'request for quotation' or 'purchase order confirmation'} from ${object.company_id.name}:
| Order number: *${object.name}*
| Order total: *${object.amount_total} ${object.pricelist_id.currency_id.name}*
| Order date: ${object.date_order}
% if object.origin:
| Order reference: ${object.origin}
% endif
% if object.partner_ref:
| Your reference: ${object.partner_ref}<br />
% endif
| Your contact: ${object.validator.name} ${object.validator.email and '<%s>'%(object.validator.email) or ''}
You can view the ${object.state in ('draft', 'sent') and 'request for quotation' or 'order confirmation'} and download it using the following link:
${ctx.get('edi_web_url_view') or 'n/a'}
If you have any question, do not hesitate to contact us.
Thank you!
--
${object.validator.name} ${object.validator.email and '<%s>'%(object.validator.email) or ''}
${object.company_id.name}
% if object.company_id.street:
${object.company_id.street or ''}
% endif
% if object.company_id.street2:
${object.company_id.street2}
% endif
% if object.company_id.city or object.company_id.zip:
${object.company_id.zip or ''} ${object.company_id.city or ''}
% endif
% if object.company_id.country_id:
${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}
% endif
% if object.company_id.phone:
Phone: ${object.company_id.phone}
% endif
% if object.company_id.website:
${object.company_id.website or ''}
% endif
]]></field>
</record>
</data>
</openerp>
@@ -126,67 +126,6 @@
</div>
</div>
]]></field>
<field name="body"><![CDATA[
Hello${object.partner_id.name and ' ' or ''}${object.partner_id.name or ''},
Here is your ${object.state in ('draft', 'sent') and 'quotation' or 'order confirmation'} from ${object.company_id.name}:
| Order number: *${object.name}*
| Order total: *${object.amount_total} ${object.pricelist_id.currency_id.name}*
| Order date: ${object.date_order}
% if object.origin:
| Order reference: ${object.origin}
% endif
% if object.client_order_ref:
| Your reference: ${object.client_order_ref}<br />
% endif
| Your contact: ${object.user_id.name} ${object.user_id.email and '<%s>'%(object.user_id.email) or ''}
You can view the ${object.state in ('draft', 'sent') and 'quotation' or 'order confirmation'}, download it and even pay online using the following link:
${ctx.get('edi_web_url_view') or 'n/a'}
% if object.order_policy in ('prepaid','manual') and object.company_id.paypal_account and object.state not in ('draft', 'sent'):
<%
comp_name = quote(object.company_id.name)
order_name = quote(object.name)
paypal_account = quote(object.company_id.paypal_account)
order_amount = quote(str(object.amount_total))
cur_name = quote(object.pricelist_id.currency_id.name)
paypal_url = "https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=%s&item_name=%s%%20Order%%20%s&invoice=%s&amount=%s" \
"&currency_code=%s&button_subtype=services&no_note=1&bn=OpenERP_Order_PayNow_%s" % \
(paypal_account,comp_name,order_name,order_name,order_amount,cur_name,cur_name)
%>
It is also possible to directly pay with Paypal:
${paypal_url}
% endif
If you have any question, do not hesitate to contact us.
Thank you for choosing ${object.company_id.name}!
--
${object.user_id.name} ${object.user_id.email and '<%s>'%(object.user_id.email) or ''}
${object.company_id.name}
% if object.company_id.street:
${object.company_id.street or ''}
% endif
% if object.company_id.street2:
${object.company_id.street2}
% endif
% if object.company_id.city or object.company_id.zip:
${object.company_id.zip or ''} ${object.company_id.city or ''}
% endif
% if object.company_id.country_id:
${object.company_id.state_id and ('%s, ' % object.company_id.state_id.name) or ''} ${object.company_id.country_id.name or ''}
% endif
% if object.company_id.phone:
Phone: ${object.company_id.phone}
% endif
% if object.company_id.website:
${object.company_id.website or ''}
% endif
]]></field>
</record>
</data>
</openerp>
+13 -8
View File
@@ -775,8 +775,8 @@ class share_wizard(osv.TransientModel):
if res_id <= 0:
raise osv.except_osv(_('Record id not found'), _('The share engine has not been able to fetch a record_id for your invitation.'))
self.pool.get(model.model).message_subscribe(cr, uid, [res_id], new_ids + existing_ids, context=context)
self.send_invite_email(cr, uid, wizard_data, context=context)
self.send_invite_note(cr, uid, model.model, res_id, wizard_data, context=context)
# self.send_invite_email(cr, uid, wizard_data, context=context)
# self.send_invite_note(cr, uid, model.model, res_id, wizard_data, context=context)
# CLOSE
# A. Not invite: as before
@@ -820,9 +820,10 @@ class share_wizard(osv.TransientModel):
elif tmp_idx == len(wizard_data.result_line_ids)-2:
body += ' and'
body += '.'
return self.pool.get(model_name).message_post(cr, uid, [res_id], _('System Notification'), body, context=context)
return self.pool.get(model_name).message_post(cr, uid, [res_id], body=body, context=context)
def send_invite_email(self, cr, uid, wizard_data, context=None):
# TDE Note: not updated because will disappear
message_obj = self.pool.get('mail.message')
notification_obj = self.pool.get('mail.notification')
user = self.pool.get('res.users').browse(cr, UID_ROOT, uid)
@@ -855,13 +856,13 @@ class share_wizard(osv.TransientModel):
def send_emails(self, cr, uid, wizard_data, context=None):
_logger.info('Sending share notifications by email...')
mail_message = self.pool.get('mail.message')
mail_mail = self.pool.get('mail.mail')
user = self.pool.get('res.users').browse(cr, UID_ROOT, uid)
if not user.email:
raise osv.except_osv(_('Email required'), _('The current user must have an email address configured in User Preferences to be able to send outgoing emails.'))
# TODO: also send an HTML version of this mail
msg_ids = []
mail_ids = []
for result_line in wizard_data.result_line_ids:
email_to = result_line.user_id.email
if not email_to:
@@ -884,10 +885,14 @@ class share_wizard(osv.TransientModel):
body += "--\n"
body += _("OpenERP is a powerful and user-friendly suite of Business Applications (CRM, Sales, HR, etc.)\n"
"It is open source and can be found on http://www.openerp.com.")
msg_ids.append(mail_message.schedule_with_attach(cr, uid, user.email, [email_to], subject, body, model='share.wizard', context=context))
mail_ids.append(mail_mail.create(cr, uid, {
'email_from': user.email,
'email_to': email_to,
'subject': subject,
'body_html': '<pre>%s</pre>' % body}, context=context))
# force direct delivery, as users expect instant notification
mail_message.send(cr, uid, msg_ids, context=context)
_logger.info('%d share notification(s) sent.', len(msg_ids))
mail_mail.send(cr, uid, mail_ids, context=context)
_logger.info('%d share notification(s) sent.', len(mail_ids))
def onchange_embed_options(self, cr, uid, ids, opt_title, opt_search, context=None):
wizard = self.browse(cr, uid, ids[0], context)
+11 -1
View File
@@ -420,7 +420,17 @@ class survey_question_wiz(osv.osv_memory):
if user_email and resp_email:
user_name = user_obj.browse(cr, uid, uid, context=context).name
mail = "Hello " + survey_data.responsible_id.name + ",\n\n " + str(user_name) + " has given the Response Of " + survey_data.title + " Survey.\nThe Response has been attached herewith.\n\n Thanks."
mail_message.schedule_with_attach(cr, uid, user_email, [resp_email], "Survey Answer Of " + str(user_name) , mail, attachments=attachments, context=context)
vals = {'state': 'outgoing',
'subject': "Survey Answer Of " + user_name,
'body_html': '<pre>%s</pre>' % mail,
'email_to': [resp_email],
'email_from': user_email}
if attachments:
vals['attachment_ids'] = [(0,0,{'name': a_name,
'datas_fname': a_name,
'datas': str(a_content).encode('base64')})
for a_name, a_content in attachments]
self.pool.get('mail.mail').create(cr, uid, vals, context=context)
xml_form = etree.Element('form', {'string': _('Complete Survey Answer')})
etree.SubElement(xml_form, 'separator', {'string': 'Complete Survey', 'colspan': "4"})
+21 -5
View File
@@ -116,7 +116,6 @@ class survey_send_invitation(osv.osv_memory):
existing = ""
created = ""
error = ""
user_exists = False
new_user = []
attachments = {}
current_sur = survey_ref.browse(cr, uid, context.get('active_id'), context=context)
@@ -150,8 +149,14 @@ class survey_send_invitation(osv.osv_memory):
mail = record['mail']%{'login':partner.email, 'passwd':user.password, \
'name' : partner.name}
if record['send_mail_existing']:
mail_message.schedule_with_attach(cr, uid, record['mail_from'], [partner.email] , \
record['mail_subject_existing'] , mail, context=context)
vals = {
'state': 'outgoing',
'subject': record['mail_subject_existing'],
'body_html': '<pre>%s</pre>' % mail,
'email_to': partner.email,
'email_from': record['mail_from'],
}
self.pool.get('mail.mail').create(cr, uid, vals, context=context)
existing+= "- %s (Login: %s, Password: %s)\n" % (user.name, partner.email, \
user.password)
continue
@@ -160,8 +165,19 @@ class survey_send_invitation(osv.osv_memory):
out+= partner.email + ',' + passwd + '\n'
mail= record['mail'] % {'login' : partner.email, 'passwd' : passwd, 'name' : partner.name}
if record['send_mail']:
ans = mail_message.schedule_with_attach(cr, uid, record['mail_from'], [partner.email], \
record['mail_subject'], mail, attachments=attachments, context=context)
vals = {
'state': 'outgoing',
'subject': record['mail_subject'],
'body_html': '<pre>%s</pre>' % mail,
'email_to': partner.email,
'email_from': record['mail_from'],
}
if attachments:
vals['attachment_ids'] = [(0,0,{'name': a_name,
'datas_fname': a_name,
'datas': str(a_content).encode('base64')})
for a_name, a_content in attachments]
ans = self.pool.get('mail.mail').create(cr, uid, vals, context=context)
if ans:
res_data = {'name': partner.name or _('Unknown'),
'login': partner.email,