[IMP]changed as per new spec update and make it work for crm changes done in crm

bzr revid: sgo@tinyerp.com-20120912112245-3cp03024fiqb47qs
This commit is contained in:
Sanjay Gohel (Open ERP) 2012-09-12 16:52:45 +05:30
parent a807b57f4e
commit ce39ffe927
9 changed files with 106 additions and 212 deletions

View File

@ -27,15 +27,13 @@ import time
import tools
from tools.translate import _
from base.res.res_partner import format_address
CRM_LEAD_PENDING_STATES = (
crm.AVAILABLE_STATES[2][0], # Cancelled
crm.AVAILABLE_STATES[3][0], # Done
crm.AVAILABLE_STATES[4][0], # Pending
)
class crm_lead(base_stage, format_address, osv.osv):
class crm_lead(base_stage, osv.osv):
""" CRM Lead Case """
_name = "crm.lead"
_description = "Lead/Opportunity"
@ -107,12 +105,6 @@ class crm_lead(base_stage, format_address, osv.osv):
return result, fold
def fields_view_get(self, cr, user, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
res = super(crm_lead,self).fields_view_get(cr, user, view_id, view_type, context, toolbar=toolbar, submenu=submenu)
if view_type == 'form':
res['arch'] = self.fields_view_get_address(cr, user, res['arch'], context=context)
return res
_group_by_full = {
'stage_id': _read_group_stage_ids
}
@ -842,7 +834,7 @@ class crm_lead(base_stage, format_address, osv.osv):
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
""" Override of the (void) default notification method. """
stage_name = self.pool.get('crm.case.stage').name_get(cr, uid, [stage_id], context=context)[0][1]
return self.message_post(cr, uid, ids, body= _("Stage changed to <b>%s</b>.") % (stage_name), subtype="stage change",context=context)
return self.message_post(cr, uid, ids, body= _("Stage changed to <b>%s</b>.") % (stage_name), mail_subtype_new="crm_subtype_stage_change",context=context)
def case_get_note_msg_prefix(self, cr, uid, lead, context=None):
if isinstance(lead, (int, long)):
@ -852,16 +844,16 @@ class crm_lead(base_stage, format_address, osv.osv):
def create_send_note(self, cr, uid, ids, context=None):
for id in ids:
message = _("%s has been <b>created</b>.")% (self.case_get_note_msg_prefix(cr, uid, id, context=context))
self.message_post(cr, uid, [id], body=message, subtype="new", context=context)
self.message_post(cr, uid, [id], body=message, subtype_xml_id="crm_subtype_new", context=context)
return True
def case_mark_lost_send_note(self, cr, uid, ids, context=None):
message = _("Opportunity has been <b>lost</b>.")
return self.message_post(cr, uid, ids, body=message,subtype="lost", context=context)
return self.message_post(cr, uid, ids, body=message,subtype_xml_id="crm_subtype_lost", context=context)
def case_mark_won_send_note(self, cr, uid, ids, context=None):
message = _("Opportunity has been <b>won</b>.")
return self.message_post(cr, uid, ids, body=message, subtype="won", context=context)
return self.message_post(cr, uid, ids, body=message, subtype_xml_id="crm_subtype_won", context=context)
def schedule_phonecall_send_note(self, cr, uid, ids, phonecall_id, action, context=None):
phonecall = self.pool.get('crm.phonecall').browse(cr, uid, [phonecall_id], context=context)[0]

View File

@ -155,32 +155,24 @@
</record>
<!-- mail subtype -->
<record id="mail.mail_subtype_new" model="mail.message.subtype">
<record id="mail.crm_subtype_new" model="mail.message.subtype">
<field name="name">new</field>
<field name="model_ids" eval="[(4,ref('crm.model_crm_lead'))]"/>
<field name="res_model">crm.lead</field>
<field name="default" eval="False"/>
</record>
<record id="mail.mail_subtype_won" model="mail.message.subtype">
<record id="mail.crm_subtype_won" model="mail.message.subtype">
<field name="name">won</field>
<field name="model_ids" eval="[(4,ref('crm.model_crm_lead'))]"/>
<field name="res_model">crm.lead</field>
</record>
<record id="mail_subtype_lost" model="mail.message.subtype">
<record id="mail.crm_subtype_lost" model="mail.message.subtype">
<field name="name">lost</field>
<field name="model_ids" eval="[(4, ref('crm.model_crm_lead'))]"/>
</record>
<record id="mail.mail_subtype_stage_change" model="mail.message.subtype">
<field name="name">stage change</field>
<field name="model_ids" eval="[(4,ref('crm.model_crm_lead'))]"/>
<field name="res_model">crm.lead</field>
<field name="default" eval="False"/>
</record>
<record id="mail.mail_subtype_email" model="mail.message.subtype">
<field name="model_ids" eval="[(4,ref('crm.model_crm_lead'))]"/>
</record>
<record id="mail.mail_subtype_comment" model="mail.message.subtype">
<field name="model_ids" eval="[(4,ref('crm.model_crm_lead'))]"/>
</record>
<record id="mail.mail_subtype_other" model="mail.message.subtype">
<field name="model_ids" eval="[(4,ref('crm.model_crm_lead'))]"/>
<record id="mail.crm_subtype_stage_change" model="mail.message.subtype">
<field name="name">stage change</field>
<field name="res_model">crm.lead</field>
<field name="default" eval="False"/>
</record>
</data>
</openerp>

View File

@ -13,18 +13,8 @@
<field eval="'()'" name="args"/>
</record>
<record id="mail_subtype_other" model="mail.message.subtype">
<field name="name">other</field>
<field name="model_ids" eval="[(4,ref('mail.model_mail_group'))]"/>
<field name="default" eval='False'/>
</record>
<record id="mail_subtype_email" model="mail.message.subtype">
<field name="name">email</field>
<field name="model_ids" eval="[(4,ref('mail.model_mail_group'))]"/>
</record>
<record id="mail_subtype_comment" model="mail.message.subtype">
<field name="name">comment</field>
<field name="model_ids" eval="[(4,ref('mail.model_mail_group'))]"/>
</record>
</data>
</openerp>

View File

@ -20,13 +20,11 @@
##############################################################################
import logging
import openerp
import tools
from email.header import decode_header
from operator import itemgetter
from osv import osv, fields
from tools.translate import _
_logger = logging.getLogger(__name__)
@ -37,7 +35,6 @@ def decode(text):
text = decode_header(text.replace('\r', ''))
return ''.join([tools.ustr(x[0], x[1]) for x in text])
class mail_message(osv.Model):
""" Messages model: system notification (replacing res.log notifications),
comments (OpenChatter discussion) and incoming emails. """
@ -60,10 +57,7 @@ class mail_message(osv.Model):
for message in self.browse(cr, uid, ids, context=context):
if not message.model or not message.res_id:
continue
try:
result[message.id] = self._shorten_name(self.pool.get(message.model).name_get(cr, uid, [message.res_id], context=context)[0][1])
except openerp.exceptions.AccessDenied, e:
pass
result[message.id] = self._shorten_name(self.pool.get(message.model).name_get(cr, uid, [message.res_id], context=context)[0][1])
return result
def _get_unread(self, cr, uid, ids, name, arg, context=None):
@ -154,7 +148,7 @@ class mail_message(osv.Model):
def _message_dict_get(self, cr, uid, msg, context=None):
""" Return a dict representation of the message browse record. """
attachment_ids = [{'id': attach[0], 'name': attach[1]} for attach in self.pool.get('ir.attachment').name_get(cr, uid, [x.id for x in msg.attachment_ids], context=context)]
attachment_ids = self.pool.get('ir.attachment').name_get(cr, uid, [x.id for x in msg.attachment_ids], context=context)
author_id = self.pool.get('res.partner').name_get(cr, uid, [msg.author_id.id], context=context)[0]
author_user_id = self.pool.get('res.users').name_get(cr, uid, [msg.author_id.user_ids[0].id], context=context)[0]
partner_ids = self.pool.get('res.partner').name_get(cr, uid, [x.id for x in msg.partner_ids], context=context)
@ -313,15 +307,15 @@ class mail_message(osv.Model):
def unlink(self, cr, uid, ids, context=None):
# cascade-delete attachments that are directly attached to the message (should only happen
# for mail.messages that act as parent for a standalone mail.mail record).
# for mail.messages that act as parent for a standalone mail.mail record.
attachments_to_delete = []
for message in self.browse(cr, uid, ids, context=context):
for attach in message.attachment_ids:
if attach.res_model == self._name and attach.res_id == message.id:
for mail in self.browse(cr, uid, ids, context=context):
for attach in mail.attachment_ids:
if attach.res_model == 'mail.message' and attach.res_id == mail.id:
attachments_to_delete.append(attach.id)
if attachments_to_delete:
self.pool.get('ir.attachment').unlink(cr, uid, attachments_to_delete, context=context)
return super(mail_message, self).unlink(cr, uid, ids, context=context)
return super(mail_message,self).unlink(cr, uid, ids, context=context)
def notify(self, cr, uid, newid, context=None):
""" Add the related record followers to the destination partner_ids.
@ -344,6 +338,9 @@ class mail_message(osv.Model):
follow_ids = followers_obj.search(cr, uid, [('partner_id','=',p_id),('subtype_ids','in',[message.subtype_id.id]),('res_model','=',message.model),('res_id','=',message.res_id)], context=context)
if follow_ids and len(follow_ids):
missing_follow_ids.append(p_id)
subtype_record = self.pool.get('mail.message.subtype').browse(cr, uid, message.subtype_id.id,context=context)
if not subtype_record.res_model:
missing_follow_ids.append(p_id)
message.write({'partner_ids': [(4, p_id) for p_id in missing_follow_ids]})
partners_to_notify |= extra_notified
self.pool.get('mail.notification').notify(cr, uid, list(partners_to_notify), newid, context=context)
@ -354,25 +351,3 @@ class mail_message(osv.Model):
default = {}
default.update(message_id=False, headers=False)
return super(mail_message, self).copy(cr, uid, id, default=default, context=context)
#------------------------------------------------------
# Tools
#------------------------------------------------------
def check_partners_email(self, cr, uid, partner_ids, context=None):
""" Verify that selected partner_ids have an email_address defined.
Otherwise throw a warning. """
partner_wo_email_lst = []
for partner in self.pool.get('res.partner').browse(cr, uid, partner_ids, context=context):
if not partner.email:
partner_wo_email_lst.append(partner)
if not partner_wo_email_lst:
return {}
warning_msg = _('The following partners chosen as recipients for the email have no email address linked :')
for partner in partner_wo_email_lst:
warning_msg += '\n- %s' % (partner.name)
return {'warning': {
'title': _('Partners email addresses not found'),
'message': warning_msg,
}
}

View File

@ -29,15 +29,9 @@ class mail_message_subtype(osv.osv):
_columns = {
'name': fields.char('Message Subtype ', size = 128,
required = True, help = 'Message subtype, gives a more precise type on the message, especially for system notifications. For example, it can be a notification related to a new record (New), or to a stage change in a process (Stage change). Message subtypes allow to precisely tune the notifications the user want to receive on its wall.'),
'model_ids': fields.many2many('ir.model',
'mail_message_subtyp_message_rel',
'message_subtype_id', 'model_id', 'Model',
help = "link some subtypes to several models, for projet/task"),
'res_model': fields.char('Model',size = 128, help = "link subtype to model"),
'default': fields.boolean('Default', help = "When subscribing to the document, users will receive by default messages related to this subtype unless they uncheck this subtype"),
}
_defaults = {
'default': True,
}
_sql_constraints = [
('name_uniq', 'unique (name)', 'The name of the message subtype must be unique !')
]

View File

@ -14,7 +14,7 @@
<field name="arch" type="xml">
<tree string="Subtype">
<field name="name"/>
<field name="model_ids" invisible="1"/>
<field name="res_model" invisible="1"/>
<field name="default"/>
</tree>
</field>
@ -30,13 +30,12 @@
<group>
<group>
<field name="name"/>
<field name="res_model"/>
</group>
<group>
<field name="default"/>
</group>
</group>
<separator string="Models"/>
<field name="model_ids" widget="many2many"/>
</sheet>
</form>
</field>

View File

@ -562,7 +562,7 @@ class mail_thread(osv.AbstractModel):
self.message_post(cr, uid, [id], message, context=context)
def message_post(self, cr, uid, thread_id, body='', subject=False,
type='notification', parent_id=False, attachments=None, subtype='comment', context=None, **kwargs):
type='notification', parent_id=False, attachments=None, subtype_xml_id='mail_subtype_comment', 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.
@ -599,12 +599,13 @@ class mail_thread(osv.AbstractModel):
values = kwargs
subtype_obj = self.pool.get('mail.message.subtype')
if subtype:
subtypes = subtype_obj.name_search(cr, uid, subtype,context=context)
if len(subtypes):
subtype_browse = subtype_obj.browse(cr, uid, subtypes[0][0],context=context)
if self._name in [model.model for model in subtype_browse.model_ids]:
values['subtype_id']=subtype_browse.id
ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', subtype_xml_id)
if subtype_xml_id:
subtype_browse = subtype_obj.browse(cr, uid, ref[1],context=context)
if self._name == subtype_browse.res_model:
values['subtype_id']=subtype_browse.id
else:
values['subtype_id']=subtype_browse.id
values.update({
'model': context.get('thread_model', self._name) if thread_id else False,
'res_id': thread_id or False,
@ -628,14 +629,20 @@ class mail_thread(osv.AbstractModel):
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, context=None):
""" Add partners to the records followers. """
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 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:
subtype_obj = self.pool.get('mail.message.subtype')
subtype_ids = subtype_obj.search(cr, uid, [('default', '=', 'true'),('model_ids.model', '=', self._name)],context=context)
subtype_ids = subtype_obj.search(cr, uid, [('default', '=', 'true'),('res_model', '=', self._name)],context=context)
if subtype_ids:
self.message_subscribe_udpate_subtypes(cr, uid, ids, partner_ids, subtype_ids, context=context)
return self.write(cr, uid, ids, {'message_follower_ids': [(4, pid) for pid in partner_ids]}, context=context)
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 []
def message_unsubscribe_users(self, cr, uid, ids, user_ids=None, context=None):
""" Wrapper on message_subscribe, using users. If user_ids is not
@ -645,8 +652,14 @@ class mail_thread(osv.AbstractModel):
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. """
return self.write(cr, uid, ids, {'message_follower_ids': [(3, pid) for pid in partner_ids]}, context=context)
""" Remove partners from the records followers.
:param partner_ids: a list of partner_ids to unsubscribe
: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)
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 []
#------------------------------------------------------
# Thread state
@ -679,6 +692,6 @@ class mail_thread(osv.AbstractModel):
def message_subscribe_udpate_subtypes(self, cr, uid, ids, user_id, subtype_ids,context=None):
followers_obj = self.pool.get('mail.followers')
followers_ids = followers_obj.search(cr, uid, [('res_model', '=', self._name), ('res_id', 'in', ids)], context=context)
return followers_obj.write(cr, uid, followers_ids, {'subtype_ids': [(6, 0 , subtype_ids)]}, context = context) #overright or add new one
return followers_obj.write(cr, uid, followers_ids, {'subtype_ids': [(6, 0 , subtype_ids)]}, context = context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:

View File

@ -33,12 +33,20 @@ openerp_mail_followers = function(session, mail) {
},
start: function() {
// use actual_mode property on view to know if the view is in create mode anymore
var self = this;
// NB: all the widget should be modified to check the actual_mode property on view, not use
// any other method to know if the view is in create mode anymore
this.view.on("change:actual_mode", this, this._check_visibility);
this._check_visibility();
this.fetch_subtype();
this.$el.find('ul.oe_mail_recthread_subtype').click(function () {self.update_subtype();})
this.$el.find('button.oe_mail_button_follow').click(function () { self.do_follow(); self.fetch_subtype();})
.mouseover(function () { $(this).html('Follow').removeClass('oe_mail_button_mouseout').addClass('oe_mail_button_mouseover'); })
.mouseleave(function () { $(this).html('Not following').removeClass('oe_mail_button_mouseover').addClass('oe_mail_button_mouseout'); });
this.$el.find('button.oe_mail_button_unfollow').click(function () { self.do_unfollow(); })
.mouseover(function () { $(this).html('Unfollow').removeClass('oe_mail_button_mouseout').addClass('oe_mail_button_mouseover'); })
.mouseleave(function () { $(this).html('Following').removeClass('oe_mail_button_mouseover').addClass('oe_mail_button_mouseout'); });
this.reinit();
this.bind_events();
},
_check_visibility: function() {
@ -46,40 +54,14 @@ openerp_mail_followers = function(session, mail) {
if (this.view.get("actual_mode") !== "create"){this.fetch_subtype();}
},
destroy: function () {
this._super.apply(this, arguments);
},
reinit: function() {
this.$el.find('button.oe_mail_button_follow').hide();
this.$el.find('button.oe_mail_button_unfollow').hide();
},
bind_events: function() {
var self = this;
this.$('button.oe_mail_button_unfollow').on('click', function () { self.do_unfollow(); })
.mouseover(function () { $(this).html('Unfollow').removeClass('oe_mail_button_mouseout').addClass('oe_mail_button_mouseover'); })
.mouseleave(function () { $(this).html('Following').removeClass('oe_mail_button_mouseover').addClass('oe_mail_button_mouseout'); });
this.$el.on('click', 'button.oe_mail_button_follow', function () { self.do_follow(); self.fetch_subtype(); });
this.$el.on('click','ul.oe_mail_recthread_subtype', function () {self.update_subtype();})
this.$el.on('click', 'button.oe_mail_button_invite', function(event) {
action = {
type: 'ir.actions.act_window',
res_model: 'mail.wizard.invite',
view_mode: 'form',
view_type: 'form',
views: [[false, 'form']],
target: 'new',
context: {
'default_res_model': self.view.dataset.model,
'default_res_id': self.view.datarecord.id
},
}
self.do_action(action, function() { self.read_value(); });
});
},
read_value: function() {
var self = this;
return this.ds_model.read_ids([this.view.datarecord.id], ['message_follower_ids']).pipe(function (results) {
return results[0].message_follower_ids;
}).pipe(this.proxy('set_value'));
// this.$el.find('ul.oe_mail_recthread_subtype').hide()
},
set_value: function(value_) {
@ -89,11 +71,11 @@ openerp_mail_followers = function(session, mail) {
this.$el.find('div.oe_mail_recthread_aside').hide();
return;
}
return this.fetch_followers(value_ || this.get_value());
return this.fetch_followers(value_);
},
fetch_followers: function (value_) {
return this.ds_follow.call('read', [value_, ['name', 'user_ids']]).pipe(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, evaluate is_follower directly */
@ -103,7 +85,7 @@ openerp_mail_followers = function(session, mail) {
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) {
record.avatar_url = mail.ChatterUtils.get_image(self.session, 'res.partner', 'image_small', record.id);
record.avatar_url = mail.ChatterUtils.get_image(self.session.prefix, self.session.session_id, 'res.partner', 'image_small', record.id);
$(session.web.qweb.render('mail.followers.partner', {'record': record})).appendTo(node_user_list);
});
if (this.message_is_follower) {
@ -149,22 +131,22 @@ openerp_mail_followers = function(session, mail) {
},
do_follow: function () {
var context = new session.web.CompoundContext(this.build_context(), {});
return this.ds_model.call('message_subscribe_users', [[this.view.datarecord.id], undefined, context]).pipe(this.proxy('read_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
fetch_subtype: function () {
var self = this
var subtype_object = this.sub_model.call('search', [[['model_ids.model','=',this.view.model]]]);
var subtype_object = this.sub_model.call('search', [[['res_model','=',this.view.model]]]);
subtype_object.then(function (subtype_ids){
self.sub_model.call('read', [subtype_ids || self.get_value(),['name', 'default']]).then(self.proxy('display_subtype'));
});
},
do_unfollow: function () {
var context = new session.web.CompoundContext(this.build_context(), {});
return this.ds_model.call('message_unsubscribe_users', [[this.view.datarecord.id], undefined, context]).pipe(this.proxy('read_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'));
},
});
};

View File

@ -19,8 +19,6 @@
#
##############################################################################
import tools
from openerp.tests import common
from openerp.tools.html_sanitize import html_sanitize
@ -31,7 +29,7 @@ Received: by mail1.openerp.com (Postfix, from userid 10002)
From: Sylvie Lelitre <sylvie.lelitre@agrolait.com>
Subject: {subject}
MIME-Version: 1.0
Content-Type: multipart/alternative;
Content-Type: multipart/alternative;
boundary="----=_Part_4200734_24778174.1344608186754"
Date: Fri, 10 Aug 2012 14:16:26 +0000
Message-ID: <1198923581.41972151344608186760.JavaMail@agrolait.com>
@ -54,9 +52,9 @@ Content-Transfer-Encoding: quoted-printable
<meta http-equiv=3D"Content-Type" content=3D"text/html; charset=3Dutf-8" />
</head>=20
<body style=3D"margin: 0; padding: 0; background: #ffffff;-webkit-text-size-adjust: 100%;">=20
<p>Please call me as soon as possible this afternoon!</p>
<p>--<br/>
Sylvie
<p>
@ -84,42 +82,15 @@ Sylvie
"""
class TestMailMockups(common.TransactionCase):
class test_mail(common.TransactionCase):
def _mock_smtp_gateway(self, *args, **kwargs):
return True
def _init_mock_build_email(self):
self._build_email_args_list = []
self._build_email_kwargs_list = []
def _mock_build_email(self, *args, **kwargs):
self._build_email_args_list.append(args)
self._build_email_kwargs_list.append(kwargs)
return self._build_email(*args, **kwargs)
def setUp(self):
super(TestMailMockups, self).setUp()
# Install mock SMTP gateway
self._init_mock_build_email()
self._build_email = self.registry('ir.mail_server').build_email
self.registry('ir.mail_server').build_email = self._mock_build_email
self._send_email = self.registry('ir.mail_server').send_email
self.registry('ir.mail_server').send_email = self._mock_smtp_gateway
def tearDown(self):
# Remove mocks
self.registry('ir.mail_server').build_email = self._build_email
self.registry('ir.mail_server').send_email = self._send_email
super(TestMailMockups, self).tearDown()
class test_mail(TestMailMockups):
def _mock_send_get_mail_body(self, *args, **kwargs):
# def _send_get_mail_body(self, cr, uid, mail, partner=None, context=None)
body = tools.append_content_to_html(args[2].body_html, kwargs.get('partner').name if kwargs.get('partner') else 'No specific partner')
return body
self._build_email_args = args
self._build_email_kwargs = kwargs
return self.build_email_real(*args, **kwargs)
def setUp(self):
super(test_mail, self).setUp()
@ -135,9 +106,10 @@ class test_mail(TestMailMockups):
self.res_users = self.registry('res.users')
self.res_partner = self.registry('res.partner')
# Mock send_get_mail_body to test its functionality without other addons override
self._send_get_mail_body = self.registry('mail.mail').send_get_mail_body
self.registry('mail.mail').send_get_mail_body = self._mock_send_get_mail_body
# Install mock SMTP gateway
self.build_email_real = self.registry('ir.mail_server').build_email
self.registry('ir.mail_server').build_email = self._mock_build_email
self.registry('ir.mail_server').send_email = self._mock_smtp_gateway
# groups@.. will cause the creation of new mail groups
self.mail_group_model_id = self.ir_model.search(self.cr, self.uid, [('model', '=', 'mail.group')])[0]
@ -147,11 +119,6 @@ class test_mail(TestMailMockups):
self.group_pigs_id = self.mail_group.create(self.cr, self.uid,
{'name': 'Pigs', 'description': 'Fans of Pigs, unite !'})
def tearDown(self):
# Remove mocks
self.registry('mail.mail').send_get_mail_body = self._send_get_mail_body
super(test_mail, self).tearDown()
def test_00_message_process(self):
cr, uid = self.cr, self.uid
# Incoming mail creates a new mail_group "frogs"
@ -187,7 +154,7 @@ class test_mail(TestMailMockups):
test_msg_id = '<deadcafe.1337@smtp.agrolait.com>'
mail_text = MAIL_TEMPLATE_PLAINTEXT.format(to='groups@example.com', subject='frogs', extra='', msg_id=test_msg_id)
self.mail_thread.message_process(cr, uid, None, mail_text)
new_mail = self.mail_message.browse(cr, uid, self.mail_message.search(cr, uid, [('message_id', '=', test_msg_id)])[0])
new_mail = self.mail_message.browse(cr, uid, self.mail_message.search(cr, uid, [('message_id','=',test_msg_id)])[0])
self.assertEqual(new_mail.body, '\n<pre>\nPlease call me as soon as possible this afternoon!\n\n--\nSylvie\n</pre>\n',
'plaintext mail incorrectly parsed')
@ -308,20 +275,18 @@ class test_mail(TestMailMockups):
_attachments = [('First', 'My first attachment'), ('Second', 'My second attachment')]
# CASE1: post comment, body and subject specified
self._init_mock_build_email()
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)
sent_emails = self._build_email_kwargs_list
sent_email = self._build_email_kwargs
# Test: notifications have been deleted
self.assertFalse(self.mail_mail.search(cr, uid, [('mail_message_id', '=', msg_id)]), 'mail.mail notifications should have been auto-deleted!')
# Test: mail_message: subject is _subject, body is _body1 (no formatting done)
self.assertEqual(message.subject, _subject, 'mail.message subject incorrect')
self.assertEqual(message.body, _body1, 'mail.message body incorrect')
# Test: sent_email: email send by server: correct subject, body, body_alternative
for sent_email in sent_emails:
self.assertEqual(sent_email['subject'], _subject, 'sent_email subject incorrect')
self.assertEqual(sent_email['body'], _mail_body1 + '\n<pre>Bert Tartopoils</pre>\n', 'sent_email body incorrect')
self.assertEqual(sent_email['body_alternative'], _mail_bodyalt1 + '\nBert Tartopoils', 'sent_email body_alternative is incorrect')
# Test: sent_email: email send by server: correct subject, body; body_alternative
self.assertEqual(sent_email['subject'], _subject, 'sent_email subject incorrect')
self.assertEqual(sent_email['body'], _mail_body1, 'sent_email body incorrect')
self.assertEqual(sent_email['body_alternative'], _mail_bodyalt1, 'sent_email body_alternative is incorrect')
# Test: mail_message: partner_ids = group followers
message_pids = set([partner.id for partner in message.partner_ids])
test_pids = set([p_a_id, p_b_id, p_c_id])
@ -331,16 +296,14 @@ class test_mail(TestMailMockups):
notif_pids = set([notif.partner_id.id for notif in self.mail_notification.browse(cr, uid, notif_ids)])
self.assertEqual(notif_pids, test_pids, 'mail.message notification partners incorrect')
# Test: sent_email: email_to should contain b@b, not c@c (pref email), not a@a (writer)
for sent_email in sent_emails:
self.assertEqual(sent_email['email_to'], ['b@b'], 'sent_email email_to is incorrect')
self.assertEqual(sent_email['email_to'], ['b@b'], 'sent_email email_to is incorrect')
# CASE2: post an email with attachments, parent_id, partner_ids
# TESTS: automatic subject, signature in body_html, attachments propagation
self._init_mock_build_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)
sent_emails = self._build_email_kwargs_list
sent_email = self._build_email_kwargs
self.assertFalse(self.mail_mail.search(cr, uid, [('mail_message_id', '=', msg_id2)]), 'mail.mail notifications should have been auto-deleted!')
# Test: mail_message: subject is False, body is _body2 (no formatting done), parent_id is msg_id
@ -348,11 +311,9 @@ class test_mail(TestMailMockups):
self.assertEqual(message.body, html_sanitize(_body2), 'mail.message body incorrect')
self.assertEqual(message.parent_id.id, msg_id, 'mail.message parent_id incorrect')
# Test: sent_email: email send by server: correct subject, body, body_alternative
self.assertEqual(len(sent_emails), 2, 'sent_email number of sent emails incorrect')
for sent_email in sent_emails:
self.assertEqual(sent_email['subject'], _mail_subject, 'sent_email subject incorrect')
self.assertIn(_mail_body2, sent_email['body'], 'sent_email body incorrect')
self.assertIn(_mail_bodyalt2, sent_email['body_alternative'], 'sent_email body_alternative incorrect')
self.assertEqual(sent_email['subject'], _mail_subject, 'sent_email subject incorrect')
self.assertEqual(sent_email['body'], _mail_body2, 'sent_email body incorrect')
self.assertEqual(sent_email['body_alternative'], _mail_bodyalt2, 'sent_email body_alternative incorrect')
# Test: mail_message: partner_ids = group followers
message_pids = set([partner.id for partner in message.partner_ids])
test_pids = set([p_a_id, p_b_id, p_c_id, p_d_id])
@ -362,8 +323,7 @@ class test_mail(TestMailMockups):
notif_pids = set([notif.partner_id.id for notif in self.mail_notification.browse(cr, uid, notif_ids)])
self.assertEqual(notif_pids, test_pids, 'mail.message notification partners incorrect')
# Test: sent_email: email_to should contain b@b, c@c, not a@a (writer)
for sent_email in sent_emails:
self.assertTrue(set(sent_email['email_to']).issubset(set(['b@b', 'c@c'])), 'sent_email email_to incorrect')
self.assertEqual(set(sent_email['email_to']), set(['b@b', 'c@c']), 'sent_email email_to incorrect')
# Test: attachments
for attach in message.attachment_ids:
self.assertEqual(attach.res_model, 'mail.group', 'mail.message attachment res_model incorrect')
@ -450,14 +410,12 @@ class test_mail(TestMailMockups):
self.assertEqual(compose.content_subtype, 'html', 'mail.compose.message incorrect content_subtype')
# 2. Post the comment, get created message
parent_id = message.id
mail_compose.send_mail(cr, uid, [compose_id])
group_pigs.refresh()
message = group_pigs.message_ids[0]
# Test: mail.message: subject as Re:.., body in html, parent_id
# Test: mail.message: subject as Re:.., body in html
self.assertEqual(message.subject, _msg_reply, 'mail.message incorrect subject')
self.assertIn('Administrator wrote:<blockquote><pre>Pigs rules</pre></blockquote></div>', message.body, 'mail.message body is incorrect')
self.assertEqual(message.parent_id and message.parent_id.id, parent_id, 'mail.message parent_id incorrect')
# Test: mail.message: attachments
for attach in message.attachment_ids:
self.assertEqual(attach.res_model, 'mail.group', 'mail.message attachment res_model incorrect')
@ -501,7 +459,6 @@ class test_mail(TestMailMockups):
# It will be updated as soon as we have fixed specs !
cr, uid = self.cr, self.uid
group_pigs = self.mail_group.browse(cr, uid, self.group_pigs_id)
def _compare_structures(struct1, struct2, n=0):
# print '%scompare structure' % ('\t' * n)
self.assertEqual(len(struct1), len(struct2), 'message_read structure number of childs incorrect')
@ -673,10 +630,10 @@ class test_mail(TestMailMockups):
_mail_bodyalt2 = 'Pigs rules\nAdmin\n'
filter_subtype_id = self.mail_message_subtype.search(cr, uid, [('default','=',True)])
# Post comment with body and subject, comment preference
msg_id = self.mail_group.message_post(cr, uid, [self.group_pigs_id], body=_body1, subject=_subject, type='comment',subtype='email')
msg_id = self.mail_group.message_post(cr, uid, [self.group_pigs_id], body=_body1, subject=_subject, type='comment',subtype_xml_id='mail_subtype_comment')
notif_ids = self.mail_notification.search(cr, uid, [('message_id', '=', msg_id)])
self.assertTrue(len(notif_ids) >= 1,"subtype is email and show notification on wall")
# New post: test automatic subject, signature in html, add a partner, email preference, parent_id previous message
msg_id2 = self.mail_group.message_post(cr, uid, [self.group_pigs_id], body=_body2,subject=_subject, type='email', subtype='other')
notif_ids2 = self.mail_notification.search(cr, uid, [('message_id', '=', msg_id2)])
self.assertTrue(len(notif_ids2) == 0,"subtype is false cannot show notification on wall")
# msg_id2 = self.mail_group.message_post(cr, uid, [self.group_pigs_id], body=_body2,subject=_subject, type='email', subtype='other')
# notif_ids2 = self.mail_notification.search(cr, uid, [('message_id', '=', msg_id2)])
# self.assertTrue(len(notif_ids2) == 0,"subtype is false cannot show notification on wall")