From 5d3d9f446836c375adb397468af09ba8cc316a77 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 2 Apr 2012 13:50:02 +0200 Subject: [PATCH 1/9] [CLEAN] mail.thread: cleaned mail.message, mail.thread bzr revid: tde@openerp.com-20120402115002-q8u8vlu49jjs8e5g --- addons/mail/mail_message.py | 14 ++--- addons/mail/mail_thread.py | 98 +++++++++++++++---------------- addons/mail/static/src/js/mail.js | 2 +- 3 files changed, 57 insertions(+), 57 deletions(-) diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 3b58a986782..5ac146066cf 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -81,7 +81,7 @@ class mail_message_common(osv.osv_memory): return result def search_body(self, cr, uid, obj, name, args, context=None): - """should have: + """will receive: - obj: mail.message object - name: 'body' - args: [('body', 'ilike', 'blah')]""" @@ -94,8 +94,7 @@ class mail_message_common(osv.osv_memory): for message in self.browse(cr, uid, ids, context=context): if not message.model or not message.res_id: continue - model = self.pool.get(message.model) - result[message.id] = model.name_get(cr, uid, [message.res_id], context=context)[0][1] + result[message.id] = self.pool.get(message.model).name_get(cr, uid, [message.res_id], context=context)[0][1] return result _name = 'mail.message.common' @@ -104,6 +103,8 @@ class mail_message_common(osv.osv_memory): 'subject': fields.char('Subject', size=512, required=True), 'model': fields.char('Related Document model', size=128, select=1), 'res_id': fields.integer('Related Document ID', select=1), + 'record_name': fields.function(get_record_name, type='string', string='Message record name', + help="Name of the record, matching the result of the name_get."), 'date': fields.datetime('Date'), 'email_from': fields.char('From', size=128, help='Message sender, taken from user preferences.'), 'email_to': fields.char('To', size=256, help='Message recipients'), @@ -120,13 +121,13 @@ class mail_message_common(osv.osv_memory): 'body_html': fields.text('Rich-text contents', help="Rich-text/HTML version of the message"), 'body': fields.function(get_body, fnct_search = search_body, string='Message content', type='text', help="Content of the message. This content equals the body_text field for plain-test messages, and body_html for rich-text/HTML messages. This allows having one field if we want to access the content matching the message subtype."), - 'parent_id': fields.many2one('mail.message', 'Parent message', help="Parent message, used for displaying as threads with hierarchy"), + 'parent_id': fields.many2one('mail.message', 'Parent message', help="Parent message, used for displaying as threads with hierarchy", + select=True, ondelete='set null',), 'type': fields.selection([ ('email', 'e-mail'), ('comment', 'Comment'), ('notification', 'System notification'), ], 'Type', help="Message type: e-mail for e-mail message, notification for system message, comment for other messages such as user replies"), - 'record_name': fields.function(get_record_name, type='string', string='Message record name', help="Name of the record, matching the result of the name_get."), } _defaults = { @@ -148,7 +149,7 @@ class mail_message(osv.osv): _name = 'mail.message' _inherit = 'mail.message.common' - _description = 'Mail Message (Email, Comment, Notification)' + _description = 'Mail Message (email, comment, notification)' _order = 'date desc' # XXX to review - how to determine action to use? @@ -219,7 +220,6 @@ class mail_message(osv.osv): ], 'State', readonly=True), 'auto_delete': fields.boolean('Auto Delete', help="Permanently delete this email after sending it, to save space"), 'original': fields.binary('Original', help="Original version of the message, as it was sent on the network", readonly=1), - } _defaults = { diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 5e4e6bbff56..0c310a3f8b4 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -65,11 +65,10 @@ class mail_thread(osv.osv): def _get_message_ids(self, cr, uid, ids, name, arg, context=None): res = {} for id in ids: - records = self.message_load(cr, uid, [id], context=context) - res[id] = [obj['id'] for obj in records] + res[id] = self.message_load_ids(cr, uid, [id], context=context) return res - # OpenSocial: message_ids_social is a dummy field that should not be used + # OpenChatter: message_ids_social is a dummy field that should not be used _columns = { 'message_ids_social': fields.function(_get_message_ids, method=True, type='one2many', obj='mail.message', string='Temp messages', _fields_id = 'res_id'), @@ -104,13 +103,12 @@ class mail_thread(osv.osv): """ if context is None: context = {} - subscr_obj = self.pool.get('mail.subscription') msg_obj = self.pool.get('mail.message') - + # delete subscriptions subscr_to_del_ids = subscr_obj.search(cr, uid, [('res_model', '=', self._name), ('res_id', 'in', ids)], context=context) subscr_obj.unlink(cr, uid, subscr_to_del_ids, context=context) - + # delete notifications msg_to_del_ids = msg_obj.search(cr, uid, [('model', '=', self._name), ('res_id', 'in', ids)], context=context) msg_obj.unlink(cr, uid, msg_to_del_ids, context=context) @@ -123,7 +121,7 @@ class mail_thread(osv.osv): def message_create(self, cr, uid, thread_id, vals, context=None): """OpenSocial: wrapper of mail.message create method - creates the mail.message - - automatically subscribe the message writer if not already done + - automatically subscribe the message writer - push the message to subscribed users """ if context is None: @@ -135,11 +133,11 @@ class mail_thread(osv.osv): # create message msg_id = self.pool.get('mail.message').create(cr, uid, vals, context=context) - # automatically subscribe the writer of the message if not subscribed - if vals['user_id'] and not self.message_is_subscriber(cr, vals['user_id'], [thread_id], context=context): + # automatically subscribe the writer of the message + if vals['user_id']: self.message_subscribe(cr, uid, [thread_id], [vals['user_id']], context=context) - # effectively push message to users + # push message to users user_to_push_ids = self.message_create_get_notification_user_ids(cr, uid, [thread_id], msg_id, vals, context=context) for id in user_to_push_ids: notification_obj.create(cr, uid, {'user_id': id, 'message_id': msg_id}, context=context) @@ -173,9 +171,10 @@ class mail_thread(osv.osv): def message_parse_users(self, cr, uid, ids, string, context=None): """Parse message content - - if find @login -(^|\s)@(\w*)-: returns the related ids + - if find @login -(^|\s)@((\w|@|\.)*)-: returns the related ids + this supports login that are emails (such as @admin@lapin.net) """ - regex = re.compile('(^|\s)@(\w*)') + regex = re.compile('(^|\s)@((\w|@|\.)*)') login_lst = [item[1] for item in regex.findall(string)] if not login_lst: return [] user_ids = self.pool.get('res.users').search(cr, uid, [('login', 'in', login_lst)], context=context) @@ -189,11 +188,11 @@ class mail_thread(osv.osv): ret_dict[model_name] = model._description return ret_dict - def message_append(self, cr, uid, threads, subject, parent_id=False, body_text=None, type='email', - email_to=False, email_from=False, email_cc=None, email_bcc=None, - reply_to=None, email_date=None, message_id=False, references=None, - attachments=None, body_html=None, subtype='plain', headers=None, - original=None, context=None): + def message_append(self, cr, uid, threads, subject, parent_id=False, body_text=None, + type='email', email_to=False, email_from=False, email_cc=None, + email_bcc=None, reply_to=None, email_date=None, message_id=False, + references=None, attachments=None, body_html=None, subtype=None, + headers=None, original=None, context=None): """Creates a new mail.message attached to the current mail.thread, containing all the details passed as parameters. All attachments will be attached to the thread record as well as to the actual @@ -334,50 +333,58 @@ class mail_thread(osv.osv): or msg_dict.get('in-reply-to'), attachments = msg_dict.get('attachments'), body_html= msg_dict.get('body_html'), - subtype = msg_dict.get('subtype'), + subtype = msg_dict.get('subtype', 'plain'), headers = msg_dict.get('headers'), original = msg_dict.get('original'), context = context) # Message loading - def _message_get_parent_ids(self, cr, uid, ids, child_ids, root_ids, context=None): + def _message_add_ancestor_ids(self, cr, uid, ids, child_ids, root_ids, context=None): + """ Given message child_ids + Find their ancestors until root ids""" if context is None: context = {} msg_obj = self.pool.get('mail.message') - msgs_tmp = msg_obj.read(cr, uid, child_ids, ['id', 'parent_id'], context=context) - parent_ids = [msg['parent_id'][0] for msg in msgs_tmp if msg['parent_id'] not in root_ids and msg['parent_id'][0] not in child_ids] + tmp_msgs = msg_obj.read(cr, uid, child_ids, ['id', 'parent_id'], context=context) + parent_ids = [msg['parent_id'][0] for msg in tmp_msgs if msg['parent_id'] and msg['parent_id'][0] not in root_ids and msg['parent_id'][0] not in child_ids] child_ids += parent_ids - cur_iter = 0; max_iter = 10; + cur_iter = 0; max_iter = 100; # avoid infinite loop while (parent_ids and (cur_iter < max_iter)): cur_iter += 1 - msgs_tmp = msg_obj.read(cr, uid, parent_ids, ['id', 'parent_id'], context=context) - parent_ids = [msg['parent_id'][0] for msg in msgs_tmp if msg['parent_id'] not in root_ids and msg['parent_id'][0] not in child_ids] + tmp_msgs = msg_obj.read(cr, uid, parent_ids, ['id', 'parent_id'], context=context) + parent_ids = [msg['parent_id'][0] for msg in tmp_msgs if msg['parent_id'] and msg['parent_id'][0] not in root_ids and msg['parent_id'][0] not in child_ids] child_ids += parent_ids + if (cur_iter > max_iter): + _logger.warning("Possible infinite loop in _message_add_ancestor_ids. Note that this algorithm is intended to check for cycle in message graph.") return child_ids - def message_load_ids(self, cr, uid, ids, limit=100, offset=0, domain=[], ascent=False, root_ids=[False], context=None): - """ OpenSocial feature: return thread messages ids (for web compatibility) - loading messages: search in mail.messages where res_id = ids, (res_)model = current model - see get_pushed_messages for parameters explanation + def message_load_ids(self, cr, uid, ids, limit=100, offset=0, domain=[], ascent=False, root_ids=[], context=None): + """ OpenChatter feature: return thread messages ids. It searches in + mail.messages where res_id = ids, (res_)model = current model. + :param domain: domain to add to the search; especially child_of + is interesting when dealing with threaded display + :param ascent: performs an ascended search; will add to fetched msgs + all their parents until root_ids + example: in combinaison with a child_of domain + ['id', 'child_of', [32, 33]], root_ids=[32,33] + :param root_ids: root_ids when performing an ascended search """ if context is None: context = {} msg_obj = self.pool.get('mail.message') msg_ids = msg_obj.search(cr, uid, ['&', ('res_id', 'in', ids), ('model', '=', self._name)] + domain, limit=limit, offset=offset, context=context) - if (ascent): msg_ids = self._message_get_parent_ids(cr, uid, ids, msg_ids, root_ids, context=context) + if (ascent): msg_ids = self._message_add_ancestor_ids(cr, uid, ids, msg_ids, root_ids, context=context) return msg_ids - def message_load(self, cr, uid, ids, limit=100, offset=0, domain=[], ascent=False, root_ids=[False], context=None): - """ OpenSocial feature: return thread messages - loading messages: search in mail.messages where res_id = ids, (res_)model = current model - see get_pushed_messages for parameters explanation + def message_load(self, cr, uid, ids, limit=100, offset=0, domain=[], ascent=False, root_ids=[], context=None): + """ OpenChatter feature: return thread messages """ msg_ids = self.message_load_ids(cr, uid, ids, limit, offset, domain, ascent, root_ids, context=context) return self.pool.get('mail.message').read(cr, uid, msg_ids, context=context) - def get_pushed_messages(self, cr, uid, ids, limit=100, offset=0, domain=[], ascent=False, root_ids=[False], context=None): - """OpenSocial: wall: get messages to display (=pushed notifications) + def get_pushed_messages(self, cr, uid, ids, limit=100, offset=0, domain=[], ascent=False, root_ids=[], context=None): + """ OpenChatter: wall: get messages to display (=pushed notifications) :param domain: domain to add to the search; especially child_of is interesting when dealing with threaded display :param deep: performs an ascended search; will add to fetched msgs all their parents until root_ids WARNING: must be used in combinaison with a child_of domain @@ -395,7 +402,7 @@ class mail_thread(osv.osv): # search messages: ids in notifications, add domain coming from wall search view search_domain = [('id', 'in', msg_ids)] + domain msg_ids = msg_obj.search(cr, uid, search_domain, limit=limit, offset=offset, context=context) - if (ascent): msg_ids = self._message_get_parent_ids(cr, uid, ids, msg_ids, root_ids, context=context) + if (ascent): msg_ids = self._message_add_ancestor_ids(cr, uid, ids, msg_ids, root_ids, context=context) msgs = msg_obj.read(cr, uid, msg_ids, context=context) #cr.execute( @@ -409,17 +416,6 @@ class mail_thread(osv.osv): #print res return msgs - - # Message tools - def message_get_discussions_nbr(self, cr, uid, ids, context=None): - message_obj = self.pool.get('mail.message') - count = message_obj.search(cr, uid, [('model', '=', self._name), ('res_id', '=', ids), ('parent_id', '=', False)], count=True, context=context) - return count - - def message_get_messages_nbr(self, cr, uid, ids, context=None): - message_obj = self.pool.get('mail.message') - count = message_obj.search(cr, uid, [('model', '=', self._name), ('res_id', 'in', ids)], count=True, context=context) - return count #------------------------------------------------------ # Email specific @@ -664,6 +660,10 @@ class mail_thread(osv.osv): # Note specific #------------------------------------------------------ + def log(self, cr, uid, id, message, secondary=False, context=None): + _logger.warning("log() is deprecated. Please use OpenChatter notification system instead of the res.log mechanism.") + self.message_append_note(cr, uid, [id], message, context=context) + def message_append_note(self, cr, uid, ids, subject, body, parent_id=False, type='notification', context=None): return self.message_append(cr, uid, ids, subject, body_text=body, parent_id=parent_id, type=type, context=context) @@ -679,7 +679,7 @@ class mail_thread(osv.osv): def message_get_subscribers(self, cr, uid, ids, context=None): user_ids = self.message_get_subscribers_ids(cr, uid, ids, context=context) - users = self.pool.get('res.users').read(cr, uid, user_ids, fields=['id', 'name', 'avatar_mini'], context=context) + users = self.pool.get('res.users').read(cr, uid, user_ids, fields=['id', 'name', 'avatar'], context=context) return users def message_is_subscriber(self, cr, uid, ids, user_id = None, context=None): @@ -713,7 +713,7 @@ class mail_thread(osv.osv): # Notification API #------------------------------------------------------ - def message_remove_pushed_notif(self, cr, uid, ids, msg_ids, remove_childs=True, context=None): + def message_remove_pushed_notifications(self, cr, uid, ids, msg_ids, remove_childs=True, context=None): if context is None: context = {} notif_obj = self.pool.get('mail.notification') diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index 432265dc3be..cfbb01013bb 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -115,7 +115,7 @@ openerp.mail = function(session) { var msg_id = event.srcElement.dataset.id; if (! msg_id) return false; //console.log(msg_id); - var call_defer = self.ds.call('message_remove_pushed_notif', [[self.params.res_id], [parseInt(msg_id)], true]); + var call_defer = self.ds.call('message_remove_pushed_notifications', [[self.params.res_id], [parseInt(msg_id)], true]); $(event.srcElement).parents('li.oe_mail_thread_msg').eq(0).hide(); if (self.params.thread_level > 0) { $(event.srcElement).parents('ul.oe_mail_thread').eq(0).hide(); From 713f86c8b9c9978948da55d2293696ca4b1febf2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 2 Apr 2012 14:59:26 +0200 Subject: [PATCH 2/9] [CLEAN] Cleaned comments. bzr revid: tde@openerp.com-20120402125926-xovqb64ryo6v70e3 --- addons/mail/mail_subscription.py | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/addons/mail/mail_subscription.py b/addons/mail/mail_subscription.py index 4caad289e28..fc82af879a9 100644 --- a/addons/mail/mail_subscription.py +++ b/addons/mail/mail_subscription.py @@ -26,8 +26,9 @@ class mail_subscription(osv.osv): """ mail_subscription holds the data related to the follow mechanism inside OpenERP. A subscription is characterized by: - - res_model: model of the followed objects - - res_id: ID of resource (may be 0 for every objects) + :param: res_model: model of the followed objects + :param: res_id: ID of resource (may be 0 for every objects) + :param: user_id: user_id of the follower """ _name = 'mail.subscription' _rec_name = 'id' @@ -35,16 +36,18 @@ class mail_subscription(osv.osv): _description = 'Mail subscription' _columns = { 'res_model': fields.char('Related Document Model', size=128, - select=1, required=True), - 'res_id': fields.integer('Related Document ID', select=1), - 'user_id': fields.many2one('res.users', string='Related User ID', + required=True, select=1, + help='Model of the followed resource'), + 'res_id': fields.integer('Related Document ID', select=1, + help='Id of the followed resource'), + 'user_id': fields.many2one('res.users', string='Related User', ondelete='cascade', required=True, select=1), } class mail_notification(osv.osv): """ mail_notification is a relational table modeling messages pushed to users. - - read: todo + :param: read: not used currently """ _name = 'mail.notification' _rec_name = 'id' @@ -56,7 +59,7 @@ class mail_notification(osv.osv): ondelete='cascade', required=True, select=1), 'message_id': fields.many2one('mail.message', string='Message', ondelete='cascade', required=True, select=1), - 'read': fields.boolean('Read'), + 'read': fields.boolean('Read', help="Not used currently",), # TODO: add a timestamp ? or use message date ? } _defaults = { From 1800d249df081033f0d8f6c16a225300c08f8b5d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 2 Apr 2012 14:59:49 +0200 Subject: [PATCH 3/9] [IMP] Wall: improved method to get pushed notifications bzr revid: tde@openerp.com-20120402125949-djqaasty1l78uhbj --- addons/mail/mail_thread.py | 50 ++++++++++++++++++-------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 0c310a3f8b4..6c62531ea52 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -127,11 +127,12 @@ class mail_thread(osv.osv): if context is None: context = {} user_to_push_ids = [] + message_obj = self.pool.get('mail.message') subscription_obj = self.pool.get('mail.subscription') notification_obj = self.pool.get('mail.notification') # create message - msg_id = self.pool.get('mail.message').create(cr, uid, vals, context=context) + msg_id = message_obj.create(cr, uid, vals, context=context) # automatically subscribe the writer of the message if vals['user_id']: @@ -365,8 +366,7 @@ class mail_thread(osv.osv): is interesting when dealing with threaded display :param ascent: performs an ascended search; will add to fetched msgs all their parents until root_ids - example: in combinaison with a child_of domain - ['id', 'child_of', [32, 33]], root_ids=[32,33] + :param root_ids: for ascent search :param root_ids: root_ids when performing an ascended search """ if context is None: @@ -383,38 +383,32 @@ class mail_thread(osv.osv): msg_ids = self.message_load_ids(cr, uid, ids, limit, offset, domain, ascent, root_ids, context=context) return self.pool.get('mail.message').read(cr, uid, msg_ids, context=context) - def get_pushed_messages(self, cr, uid, ids, limit=100, offset=0, domain=[], ascent=False, root_ids=[], context=None): + def get_pushed_messages(self, cr, uid, ids, limit=100, offset=0, notif_search_domain=[], msg_search_domain=[], ascent=False, root_ids=[], context=None): """ OpenChatter: wall: get messages to display (=pushed notifications) - :param domain: domain to add to the search; especially child_of is interesting when dealing with threaded display - :param deep: performs an ascended search; will add to fetched msgs all their parents until root_ids - WARNING: must be used in combinaison with a child_of domain - EXAMPLE: domain = ['id', 'child_of', [32, 33]], root_ids=[32,33] - :param root_ids: root_ids when performing an ascended search - :return: list of mail.messages sorted by date + :param domain: domain to add to the search; especially child_of + is interesting when dealing with threaded display + :param ascent: performs an ascended search; will add to fetched msgs + all their parents until root_ids + :param root_ids: for ascent search + :return list of mail.messages sorted by date """ if context is None: context = {} notification_obj = self.pool.get('mail.notification') msg_obj = self.pool.get('mail.message') - # get user notifications - notification_ids = notification_obj.search(cr, uid, [('user_id', '=', uid)], context=context) + # update message search + for arg in msg_search_domain: + if isinstance(arg, (tuple, list)): + arg[0] = 'message_id.' + arg[0] + # compose final domain + domain = [('user_id', '=', uid)] + notif_search_domain + msg_search_domain + # get notifications + notification_ids = notification_obj.search(cr, uid, domain, limit=limit, offset=offset, context=context) notifications = notification_obj.browse(cr, uid, notification_ids, context=context) msg_ids = [notification.message_id.id for notification in notifications] - # search messages: ids in notifications, add domain coming from wall search view - search_domain = [('id', 'in', msg_ids)] + domain - msg_ids = msg_obj.search(cr, uid, search_domain, limit=limit, offset=offset, context=context) + # get messages + msg_ids = msg_obj.search(cr, uid, [('id', 'in', msg_ids)], context=context) if (ascent): msg_ids = self._message_add_ancestor_ids(cr, uid, ids, msg_ids, root_ids, context=context) msgs = msg_obj.read(cr, uid, msg_ids, context=context) - - #cr.execute( - #''' - #select * from mail_notification notif - #left join mail_message mes - #on (notif.message_id=mes.id) - #where notif.user_id=%s - #''', - #(str(uid)),) - #print res - return msgs #------------------------------------------------------ @@ -664,6 +658,10 @@ class mail_thread(osv.osv): _logger.warning("log() is deprecated. Please use OpenChatter notification system instead of the res.log mechanism.") self.message_append_note(cr, uid, [id], message, context=context) + # tmp stuff + def message_add_note(self, cr, uid, ids, body, subject=_('System notification'), subtype='html', parent_id=False, type='notification', context=None): + return self.message_append(cr, uid, ids, subject, body_text=body, parent_id=parent_id, type=type, context=context) + def message_append_note(self, cr, uid, ids, subject, body, parent_id=False, type='notification', context=None): return self.message_append(cr, uid, ids, subject, body_text=body, parent_id=parent_id, type=type, context=context) From a2e5f0b6c1a2e16dd0c9e492965d62f36b730702 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 2 Apr 2012 15:00:31 +0200 Subject: [PATCH 4/9] [FIX] Wall: fixed error dur to small change in mail.thread API bzr revid: tde@openerp.com-20120402130031-j8oep0eoaw1lnd1t --- addons/mail/static/src/js/mail.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index cfbb01013bb..e616ebf4b4e 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -652,7 +652,7 @@ openerp.mail = function(session) { if (additional_context) var fetch_context = _.extend(this.params.search['context'], additional_context); else var fetch_context = this.params.search['context']; var load_res = this.ds_thread.call('get_pushed_messages', - [[this.session.uid], (limit || 0), (offset || 0), fetch_domain, true, [false], fetch_context]).then(function (records) { + [[this.session.uid], (limit || 0), (offset || 0), [], fetch_domain, true, [], fetch_context]).then(function (records) { self.do_update_show_more(records.length >= self.params.limit); self.display_comments(records); }); From 6a56c8e8e1c1ed6868657f853a1930eb15ee6917 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 2 Apr 2012 15:43:54 +0200 Subject: [PATCH 5/9] [CLEAN] Cleaned code. bzr revid: tde@openerp.com-20120402134354-v337jrlygvj2u2mw --- addons/mail/mail_group.py | 27 ++++++++++----------------- addons/mail/mail_group_view.xml | 15 +++++++-------- 2 files changed, 17 insertions(+), 25 deletions(-) diff --git a/addons/mail/mail_group.py b/addons/mail/mail_group.py index da53b3ae42e..9e918cf1c12 100644 --- a/addons/mail/mail_group.py +++ b/addons/mail/mail_group.py @@ -23,6 +23,7 @@ import datetime as DT import io import openerp import openerp.tools as tools +from operator import itemgetter from osv import osv from osv import fields from PIL import Image @@ -40,12 +41,6 @@ class mail_group(osv.osv): _description = 'Discussion group' _name = 'mail.group' _inherit = ['mail.thread'] - - def action_group_join(self, cr, uid, ids, context={}): - return self.message_subscribe(cr, uid, ids, context=context); - - def action_group_leave(self, cr, uid, ids, context={}): - return self.message_unsubscribe(cr, uid, ids, context=context); def onchange_photo(self, cr, uid, ids, value, context=None): if not value: @@ -80,8 +75,8 @@ class mail_group(osv.osv): for id in ids: result[id] = {} result[id]['member_ids'] = self.message_get_subscribers_ids(cr, uid, [id], context=context) - result[id]['member_nbr'] = len(result[id]['member_ids']) - result[id]['is_member'] = uid in result[id]['member_ids'] + result[id]['member_count'] = len(result[id]['member_ids']) + result[id]['is_subscriber'] = uid in result[id]['member_ids'] return result def search_member_ids(self, cr, uid, obj, name, args, context=None): @@ -90,8 +85,7 @@ class mail_group(osv.osv): sub_obj = self.pool.get('mail.subscription') sub_ids = sub_obj.search(cr, uid, ['&', ('res_model', '=', obj._name), ('user_id', '=', args[0][2])], context=context) subs = sub_obj.read(cr, uid, sub_ids, context=context) - obj_ids = [sub['res_id'] for sub in subs] - return [('id', 'in', obj_ids)] + return [('id', 'in', map(itemgetter('res_id'), subs))] def get_last_month_msg_nbr(self, cr, uid, ids, name, args, context=None): result = {} @@ -109,17 +103,18 @@ class mail_group(osv.osv): 'name': fields.char('Name', size=64, required=True), 'description': fields.text('Description'), 'responsible_id': fields.many2one('res.users', string='Responsible', - ondelete='set null', required=True, select=1), - 'public': fields.boolean('Public', help='This group is visible by non members'), + ondelete='set null', required=True, select=1, + help="Responsible of the group that has all rights on the record."), + 'public': fields.boolean('Public', help='This group is visible by non members. Invisible groups can add members through the invite button.'), 'photo_big': fields.binary('Full-size photo', help='Field holding the full-sized PIL-supported and base64 encoded version of the group image. The photo field is used as an interface for this field.'), 'photo': fields.function(_get_photo, fnct_inv=_set_photo, string='Photo', type="binary", store = { 'mail.group': (lambda self, cr, uid, ids, c={}: ids, ['photo_big'], 10), }, help='Field holding the automatically resized (128x128) PIL-supported and base64 encoded version of the group image.'), 'member_ids': fields.function(get_member_ids, fnct_search=search_member_ids, type='many2many', - relation='res.users', string='Members', multi='get_member_ids'), - 'member_nbr': fields.function(get_member_ids, type='integer', string='Member count', multi='get_member_ids'), - 'is_member': fields.function(get_member_ids, type='boolean', string='Joined', multi='get_member_ids'), + relation='res.users', string='Group members', multi='get_member_ids'), + 'member_count': fields.function(get_member_ids, type='integer', string='Member count', multi='get_member_ids'), + 'is_subscriber': fields.function(get_member_ids, type='boolean', string='Joined', multi='get_member_ids'), 'last_month_msg_nbr': fields.function(get_last_month_msg_nbr, type='integer', string='Messages count for last month'), } @@ -128,5 +123,3 @@ class mail_group(osv.osv): 'responsible_id': (lambda s, cr, uid, ctx: uid), 'photo': _get_default_photo, } - -mail_group() diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index 2366e33b6b1..243d2605027 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -17,18 +17,17 @@ -
+

- +
@@ -97,8 +96,8 @@ - - + + From 995b99698df7512f56fd0e18a3db76dbc67909ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 2 Apr 2012 15:44:36 +0200 Subject: [PATCH 6/9] [TMP] Added temp message_add_note method, that will replace message_append_note to eliminate redundancy in subjects through the addons. bzr revid: tde@openerp.com-20120402134436-a6kgx7xvg2i0g8f1 --- addons/mail/mail_thread.py | 7 ++++++- addons/mail/static/src/js/mail.js | 4 ++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 6c62531ea52..0379955125a 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -659,7 +659,12 @@ class mail_thread(osv.osv): self.message_append_note(cr, uid, [id], message, context=context) # tmp stuff - def message_add_note(self, cr, uid, ids, body, subject=_('System notification'), subtype='html', parent_id=False, type='notification', context=None): + def message_add_note(self, cr, uid, ids, body, type='notification', parent_id=False, subject=False, subtype='html', context=None): + if not subject: + if type == 'notification': + subject = _('System notification on %s') % (self._name, fields.datetime.now()) + elif type == 'comment': + subject = _('Reply on %s at %s') % (self._name, fields.datetime.now()) return self.message_append(cr, uid, ids, subject, body_text=body, parent_id=parent_id, type=type, context=context) def message_append_note(self, cr, uid, ids, subject, body, parent_id=False, type='notification', context=None): diff --git a/addons/mail/static/src/js/mail.js b/addons/mail/static/src/js/mail.js index e616ebf4b4e..c736eadd85e 100644 --- a/addons/mail/static/src/js/mail.js +++ b/addons/mail/static/src/js/mail.js @@ -296,7 +296,7 @@ openerp.mail = function(session) { var comment_node = this.$element.find('textarea'); var body_text = comment_node.val(); comment_node.val(''); - return this.ds.call('message_append_note', [[this.params.res_id], 'Reply comment', body_text, this.params.parent_id, 'comment']).then( + return this.ds.call('message_add_note', [[this.params.res_id], body_text, 'comment', this.params.parent_id]).then( this.proxy('init_comments')); }, @@ -804,7 +804,7 @@ openerp.mail = function(session) { /** Action: Posts a comment */ do_comment: function () { var body_text = this.$element.find('textarea.oe_mail_wall_action_textarea').val(); - return this.ds_users.call('message_append_note', [[this.session.uid], 'Tweet', body_text, false, 'comment']).then( + return this.ds_users.call('message_add_note', [[this.session.uid], body_text, 'comment', false, 'Tweet', 'html']).then( this.init_and_fetch_comments(this.params.limit, 0)); }, }); From b131f0d5d316f147da714c660862b56395e97bdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 2 Apr 2012 16:09:58 +0200 Subject: [PATCH 7/9] [FIX] mail.thread: missin argument in log bzr revid: tde@openerp.com-20120402140958-r4qi3588q9x50h12 --- addons/mail/mail_thread.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 0379955125a..6d91e126400 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -656,7 +656,7 @@ class mail_thread(osv.osv): def log(self, cr, uid, id, message, secondary=False, context=None): _logger.warning("log() is deprecated. Please use OpenChatter notification system instead of the res.log mechanism.") - self.message_append_note(cr, uid, [id], message, context=context) + self.message_append_note(cr, uid, [id], 'res.log', message, context=context) # tmp stuff def message_add_note(self, cr, uid, ids, body, type='notification', parent_id=False, subject=False, subtype='html', context=None): From 2ff3c1eb1dfbace5e3c02215cd40c95eca79d5e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 2 Apr 2012 18:06:04 +0200 Subject: [PATCH 8/9] [IMP] mail.thread: Small improvement in message_append_note, to avoid adding subject everywhere in addons. Backward compatible with old formatting to ease the forthcoming merge process :) bzr revid: tde@openerp.com-20120402160604-i5ac9sxpuijyvc79 --- addons/mail/mail_thread.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/addons/mail/mail_thread.py b/addons/mail/mail_thread.py index 6d91e126400..03045eda15b 100644 --- a/addons/mail/mail_thread.py +++ b/addons/mail/mail_thread.py @@ -667,7 +667,14 @@ class mail_thread(osv.osv): subject = _('Reply on %s at %s') % (self._name, fields.datetime.now()) return self.message_append(cr, uid, ids, subject, body_text=body, parent_id=parent_id, type=type, context=context) - def message_append_note(self, cr, uid, ids, subject, body, parent_id=False, type='notification', context=None): + def message_append_note(self, cr, uid, ids, subject=None, body=None, parent_id=False, type='notification', subtype='html', context=None): + if subject is None: + if type == 'notification': + subject = _('System notification') + elif type == 'comment' and not parent_id: + subject = _('Comment') + elif type == 'comment' and parent_id: + subject = _('Reply') return self.message_append(cr, uid, ids, subject, body_text=body, parent_id=parent_id, type=type, context=context) #------------------------------------------------------ From 506fd1459b011f8178f09246cd13546d2a2f6e31 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Mon, 2 Apr 2012 18:24:25 +0200 Subject: [PATCH 9/9] [IMP] Type back to mail.message instead of mail.common bzr revid: tde@openerp.com-20120402162425-207jpzsz28nhrhou --- addons/mail/mail_message.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 5ac146066cf..371565872b2 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -123,15 +123,9 @@ class mail_message_common(osv.osv_memory): help="Content of the message. This content equals the body_text field for plain-test messages, and body_html for rich-text/HTML messages. This allows having one field if we want to access the content matching the message subtype."), 'parent_id': fields.many2one('mail.message', 'Parent message', help="Parent message, used for displaying as threads with hierarchy", select=True, ondelete='set null',), - 'type': fields.selection([ - ('email', 'e-mail'), - ('comment', 'Comment'), - ('notification', 'System notification'), - ], 'Type', help="Message type: e-mail for e-mail message, notification for system message, comment for other messages such as user replies"), } _defaults = { - 'type': 'comment', 'subtype': 'plain', 'date': (lambda *a: fields.datetime.now()), } @@ -206,6 +200,11 @@ class mail_message(osv.osv): return result _columns = { + 'type': fields.selection([ + ('email', 'e-mail'), + ('comment', 'Comment'), + ('notification', 'System notification'), + ], 'Type', help="Message type: e-mail for e-mail message, notification for system message, comment for other messages such as user replies"), 'partner_id': fields.many2one('res.partner', 'Related partner'), 'user_id': fields.many2one('res.users', 'Related user', readonly=1), 'attachment_ids': fields.many2many('ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id', 'Attachments'), @@ -223,6 +222,7 @@ class mail_message(osv.osv): } _defaults = { + 'type': 'comment', 'state': 'received', }