From f4551851fd7a3905782b4e81b81878d867cb2ff0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Tue, 31 Jan 2012 16:54:12 +0100 Subject: [PATCH] [IMP] Added group and subscription models. Added subscription mechanism when searching for tweets. Added views. bzr revid: tde@openerp.com-20120131155412-r16jr1nhwd9k4srv --- addons/mail/mail_group.py | 132 +++++++++++++++++++++++- addons/mail/mail_group_view.xml | 176 +++++++++++++++++++++++++++++++- addons/mail/mail_message.py | 81 ++++++++++++++- 3 files changed, 384 insertions(+), 5 deletions(-) diff --git a/addons/mail/mail_group.py b/addons/mail/mail_group.py index 5dfeb073de6..996f9f174ae 100644 --- a/addons/mail/mail_group.py +++ b/addons/mail/mail_group.py @@ -17,4 +17,134 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see # -############################################################################## \ No newline at end of file +############################################################################## + +import tools +from osv import osv +from osv import fields +from tools.translate import _ + +class mail_group(osv.osv): + """ + A mail group is a collection of users sharing messages. Mail groups are different from user groups + because they don't have a specific field holding users. Group users are users that follow + the mail group, using the subscription/follow mechanism of Chatter. + """ + + _name = 'mail.group' + _inherits = {'res.groups': 'group_id'} + + def action_group_join(self, cr, uid, ids, context={}): + sub_obj = self.pool.get('mail.subscription') + menu_values = {'res_model': 'mail.group', 'user_id': uid} + for id in ids: + menu_values['res_id'] = id + sub_id = sub_obj.create(cr, uid, menu_values, context=context) + + for group in self.browse(cr, uid, ids, context): + self.write(cr, uid, group.id, { + 'users': [(4, uid)] + }) + + return True + + _columns = { + 'group_id': fields.many2one('res.groups', required=True, ondelete='cascade', + string='Group', + help='The group extended by this portal'), + #'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), + 'public': fields.boolean('Public', help='This group is visible by non members') + } + + _defaults = { + 'public': True, + } + + + def create(self, cr, uid, values, context=None): + """ extend create() to automatically create a menu for the group """ + if context is None: context = {} + # create group + group_id = super(mail_group, self).create(cr, uid, values, context) + # create menu + self._create_menu(cr, uid, [group_id], context) + return group_id + + def _create_menu(self, cr, uid, ids, context=None): + """ create a menu for the given groups """ + menu_obj = self.pool.get('ir.ui.menu') + ir_data = self.pool.get('ir.model.data') + act_win_obj = self.pool.get('ir.actions.act_window') + menu_root = self._get_res_xml_id(cr, uid, 'mail', 'mg_groups') + + for group in self.browse(cr, uid, ids, context): + # create an ir.action.act_window action + act_values = { + 'name': '%s' % group.name, + 'res_model': 'mail.message', + 'domain': '["&", ("res_model", "=", "mail.group"), ("res_id", "=", %s)]' % group.id, + } + act_id = act_win_obj.create(cr, uid, act_values, context) + # create a menuitem under 'mail.mg_groups' + menu_values = { + 'name': _('%s') % group.name, + 'parent_id': menu_root, + 'action': 'ir.actions.act_window,%s' % (act_id), + 'groups_id': [(6, 0, [group.group_id.id])], + } + menu_id = menu_obj.create(cr, uid, menu_values, context) + # create data + data_values = { + 'name': _('%s') % group.name, + 'model': 'ir.ui.menu', + 'module': 'portal', + 'res_id': menu_id, + 'noupdate': 'True'} + data_id = ir_data.create(cr, uid, data_values, context) + return True + + def _assign_menu(self, cr, uid, ids, context=None): + """ assign groups (ids) menu to the users joigning the groups""" + user_obj = self.pool.get('res.users') + for p in self.browse(cr, uid, ids, context): + # user menu action = portal menu action if set in portal + if p.menu_action_id: + user_ids = [u.id for u in p.users if u.id != 1] + user_values = {'menu_id': p.menu_action_id.id} + user_obj.write(cr, uid, user_ids, user_values, context) + + def _get_res_xml_id(self, cr, uid, module, xml_id): + """ return the resource id associated to the given xml_id """ + data_obj = self.pool.get('ir.model.data') + data_id = data_obj._get_id(cr, uid, module, xml_id) + return data_obj.browse(cr, uid, data_id).res_id + + +mail_group() + + +class mail_subscription(osv.osv): + """ + mail_subscription holds the data related to the follow mechanism inside OpenERP. + A subscription can be of following: + - res_model: model of the followed objects + - res_id: ID of resource OR + - res_domain: a domain filtering followed objects + """ + + _name = 'mail.subscription' + _rec_name = 'id' + _columns = { + 'res_model': fields.char('Related Document model', size=128, select=1), + 'res_id': fields.integer('Related Document ID', select=1), + 'res_domain': fields.char('res_domain', size=256), + 'user_id': fields.integer('Related User ID', select=1), + } + + _defaults = { + } + +mail_subscription() diff --git a/addons/mail/mail_group_view.xml b/addons/mail/mail_group_view.xml index b2839b2cc0a..3532eed5871 100644 --- a/addons/mail/mail_group_view.xml +++ b/addons/mail/mail_group_view.xml @@ -1,4 +1,178 @@ + - + + + mail.message.tree_tweet + mail.message + tree + 15 + + + + + + + + + + + + mail.message.form_tweet + mail.message + form + 15 + +
+ + + + + + + + + + + + +
+ + + + mail.message.search_tweet + mail.message + search + + + + + + + + + + mail.group.kanban + mail.group + kanban + + + + + +
+
+ + prout +
+
+

+
    +
  • +
  • Join
  • +
  • Joined
  • +
+
+ +
+
+
+
+
+
+ + + + mail.group.form + mail.group + form + + +
+ + + + + + + + + + + + + +
+ + + + Groups + mail.group + form + kanban,tree,form + + + + Messages + mail.message + form + tree,form + {'filter_search': True, 'tree_view_ref': 'mail.view_tweet_tree', 'form_view_ref': 'mail.view_tweet_form'} + + + + + Messages + mail.message + form + tree,form + {'filter_search': True, 'tree_view_ref': 'mail.view_tweet_tree', 'form_view_ref': 'mail.view_tweet_form'} + + [('user_id', '=', uid)] + + + + Subscriptions + mail.subscription + form + tree,form + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/addons/mail/mail_message.py b/addons/mail/mail_message.py index 1693397f6fa..825e3f3c7c6 100644 --- a/addons/mail/mail_message.py +++ b/addons/mail/mail_message.py @@ -71,8 +71,8 @@ class mail_message_common(osv.osv_memory): _rec_name = 'subject' _columns = { 'subject': fields.char('Subject', size=512, required=True), - 'model': fields.char('Related Document model', size=128, select=1, readonly=1), - 'res_id': fields.integer('Related Document ID', select=1, readonly=1), + 'model': fields.char('Related Document model', size=128, select=1), # was rfeadonly + 'res_id': fields.integer('Related Document ID', select=1), # was rfeadonly 'date': fields.datetime('Date'), 'email_from': fields.char('From', size=128, help='Message sender, taken from user preferences. If empty, this is not a mail but a message.'), 'email_to': fields.char('To', size=256, help='Message recipients'), @@ -163,7 +163,7 @@ class mail_message(osv.osv): _columns = { 'partner_id': fields.many2one('res.partner', 'Related partner'), - 'user_id': fields.many2one('res.users', 'Related user', readonly=1), + #'user_id': fields.many2one('res.users', 'Related user', readonly=1), 'attachment_ids': fields.many2many('ir.attachment', 'message_attachment_rel', 'message_id', 'attachment_id', 'Attachments'), 'display_text': fields.function(_get_display_text, method=True, type='text', size="512", string='Display Text'), 'mail_server_id': fields.many2one('ir.mail_server', 'Outgoing mail server', readonly=1), @@ -176,12 +176,87 @@ 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), + # tde add/modif + 'user_id': fields.many2one('res.users', 'Related user', readonly=1), + 'type': fields.selection([ + ('tweet', 'Tweet'), + ('status', 'Status'), + ], 'Type'), + 'need_action': fields.boolean('Need action'), } _defaults = { 'state': 'received', } + # thib add + def create(self, cr, uid, vals, context=None): + print vals + return super(mail_message, self).create(cr, uid, vals, context) + + def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False): + if not context or not context.has_key('filter_search'): + return super(mail_message, self).search(cr, uid, args, offset=offset, limit=limit, order=order, context=context, count=count) + + # get subscriptions + sub_obj = self.pool.get('mail.subscription') + sub_ids = sub_obj.search(cr, uid, [('user_id', '=', uid)]) + subs = sub_obj.browse(cr, uid, sub_ids) + + # stock tweets to find + res_model_ids_dict = {} + res_model_all_list = [] + + # check all subscriptions + for sub in subs: + if sub.res_model and sub.res_id == 0 and sub.res_domain == False: + print "s-1" + if sub.res_model not in res_model_all_list: + res_model_all_list.append(sub.res_model) + elif sub.res_model and sub.res_id: + print "s-2" + if res_model_ids_dict.has_key(sub.res_model): + res_model_ids_dict[sub.res_model].append(sub.res_id) + else: + res_model_ids_dict[sub.res_model] = [sub.res_id] + elif sub.res_model and sub.res_domain: + print "s-3" + res_obj = self.pool.get(sub.res_model) + print sub.res_domain + #res_ids = res_obj.search(cr, uid, [('id', 'in', [1,2])]) + res_ids = res_obj.search(cr, uid, eval(sub.res_domain)) + if res_model_ids_dict.has_key(sub.res_model): + res_model_ids_dict[sub.res_model] += res_ids + else: + res_model_ids_dict[sub.res_model] = res_ids + print 'cacaprout' + else: + print 'erreur !!!' + print sub + + # add fully-followed domains + args.append('|') + args.append(['model', 'in', res_model_all_list]) + + # add partially-followed domains + for x in range(0, len(res_model_ids_dict.keys())-1): + args.append('|') + + for res_model in res_model_ids_dict.keys(): + if res_model not in res_model_all_list: + args.append('&') + args.append(['model', '=', res_model]) + args.append(['res_id', 'in', res_model_ids_dict[res_model]]) + + if context and context.has_key('filter_search'): + pass + else: + args = [] + print args + return super(mail_message, self).search(cr, uid, args, offset=offset, limit=limit,order=order, context=context, count=count) + + # end thib add + def init(self, cr): cr.execute("""SELECT indexname FROM pg_indexes WHERE indexname = 'mail_message_model_res_id_idx'""") if not cr.fetchone():