diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index 6b04be2244d..924326c7c02 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -27,13 +27,15 @@ 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, osv.osv): +class crm_lead(base_stage, format_address, osv.osv): """ CRM Lead Case """ _name = "crm.lead" _description = "Lead/Opportunity" @@ -105,6 +107,12 @@ class crm_lead(base_stage, 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 } diff --git a/addons/mail/__openerp__.py b/addons/mail/__openerp__.py index fa7a929a543..e7348acb675 100644 --- a/addons/mail/__openerp__.py +++ b/addons/mail/__openerp__.py @@ -61,6 +61,7 @@ The main features of the module are: 'website': 'http://www.openerp.com', 'depends': ['base', 'base_tools', 'base_setup'], 'data': [ + 'wizard/invite_view.xml', 'wizard/mail_compose_message_view.xml', 'mail_message_subtype.xml', 'res_config_view.xml', diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 8e40ae37546..d5cdc9fcfc3 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -20,11 +20,13 @@ ############################################################################## 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__) @@ -35,6 +37,7 @@ 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. """ @@ -57,7 +60,10 @@ 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 - result[message.id] = self._shorten_name(self.pool.get(message.model).name_get(cr, uid, [message.res_id], context=context)[0][1]) + 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 return result def _get_unread(self, cr, uid, ids, name, arg, context=None): @@ -351,3 +357,25 @@ 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, + } + } diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 23c038ce692..3f034b8875a 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -629,20 +629,14 @@ 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,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) + def message_subscribe(self, cr, uid, ids, partner_ids, context=None): + """ Add partners to the records followers. """ if not subtype_ids: subtype_obj = self.pool.get('mail.message.subtype') 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) - 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 self.write(cr, uid, ids, {'message_follower_ids': [(4, pid) for pid in partner_ids]}, context=context) def message_unsubscribe_users(self, cr, uid, ids, user_ids=None, context=None): """ Wrapper on message_subscribe, using users. If user_ids is not @@ -652,14 +646,8 @@ 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. - :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 [] + """ Remove partners from the records followers. """ + return self.write(cr, uid, ids, {'message_follower_ids': [(3, pid) for pid in partner_ids]}, context=context) #------------------------------------------------------ # Thread state diff --git a/addons/mail/static/src/css/mail.css b/addons/mail/static/src/css/mail.css index 92ead6f2432..48a178732b0 100644 --- a/addons/mail/static/src/css/mail.css +++ b/addons/mail/static/src/css/mail.css @@ -96,10 +96,6 @@ width: 120px; } -.openerp button.oe_mail_button_followers { - display: inline; -} - .openerp button.oe_mail_button_mouseout { color: white; background-color: #8a89ba; diff --git a/addons/mail/static/src/js/mail_followers.js b/addons/mail/static/src/js/mail_followers.js index 9a823df0369..f4710580d81 100644 --- a/addons/mail/static/src/js/mail_followers.js +++ b/addons/mail/static/src/js/mail_followers.js @@ -33,20 +33,12 @@ openerp_mail_followers = function(session, mail) { }, start: function() { - 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 + // use actual_mode property on view 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() { @@ -54,14 +46,40 @@ 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(); - // this.$el.find('ul.oe_mail_recthread_subtype').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')); }, set_value: function(value_) { @@ -71,11 +89,11 @@ openerp_mail_followers = function(session, mail) { this.$el.find('div.oe_mail_recthread_aside').hide(); return; } - return this.fetch_followers(value_); + return this.fetch_followers(value_ || this.get_value()); }, fetch_followers: function (value_) { - return this.ds_follow.call('read', [value_ || this.get_value(), ['name', 'user_ids']]).then(this.proxy('display_followers')); + return this.ds_follow.call('read', [value_, ['name', 'user_ids']]).pipe(this.proxy('display_followers')); }, /** Display the followers, evaluate is_follower directly */ @@ -131,8 +149,8 @@ openerp_mail_followers = function(session, mail) { }, do_follow: function () { - 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')); + 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')); }, //fetch subtype from subtype model @@ -145,8 +163,8 @@ openerp_mail_followers = function(session, mail) { }, do_unfollow: function () { - 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')); + 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')); }, }); }; diff --git a/addons/mail/static/src/xml/mail.xml b/addons/mail/static/src/xml/mail.xml index 4d3b56cf62f..bf339f21f1c 100644 --- a/addons/mail/static/src/xml/mail.xml +++ b/addons/mail/static/src/xml/mail.xml @@ -114,7 +114,7 @@