[IMP] Added group and subscription models. Added subscription mechanism when searching for tweets. Added views.
bzr revid: tde@openerp.com-20120131155412-r16jr1nhwd9k4srv
This commit is contained in:
+131
-1
@@ -17,4 +17,134 @@
|
||||
# You should have received a copy of the GNU Affero General Public License
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
#
|
||||
##############################################################################
|
||||
##############################################################################
|
||||
|
||||
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()
|
||||
|
||||
@@ -1,4 +1,178 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
</openerp>
|
||||
<!-- mail.message tree: tweet-type view !-->
|
||||
<record model="ir.ui.view" id="view_tweet_tree">
|
||||
<field name="name">mail.message.tree_tweet</field>
|
||||
<field name="model">mail.message</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="sequence">15</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Tweets">
|
||||
<field name="date"/>
|
||||
<field name="subject"/>
|
||||
<field name="user_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- mail.message form: tweet-type view !-->
|
||||
<record model="ir.ui.view" id="view_tweet_form">
|
||||
<field name="name">mail.message.form_tweet</field>
|
||||
<field name="model">mail.message</field>
|
||||
<field name="type">form</field>
|
||||
<field name="sequence">15</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Tweet">
|
||||
<group colspan="4" col="6">
|
||||
<field name="subject" colspan="4"/>
|
||||
<field name="date"/>
|
||||
<field name="user_id" string="User" readonly="0"/>
|
||||
<field name="partner_id" readonly="1" attrs="{'invisible':[('partner_id', '=', False)]}"/>
|
||||
</group>
|
||||
<field name="type"/>
|
||||
<field name="need_action"/>
|
||||
<field name="model"/>
|
||||
<field name="res_id" groups="base.group_extended"/>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- mail.message search: tweet-type view !-->
|
||||
<record model="ir.ui.view" id="view_tweet_search">
|
||||
<field name="name">mail.message.search_tweet</field>
|
||||
<field name="model">mail.message</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Tweet Search">
|
||||
<field name="user_id" string="User"/>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Group Kanban View !-->
|
||||
<record model="ir.ui.view" id="view_group_kanban">
|
||||
<field name="name">mail.group.kanban</field>
|
||||
<field name="model">mail.group</field>
|
||||
<field name="type">kanban</field>
|
||||
<field name="priority" eval="10"/>
|
||||
<field name="arch" type="xml">
|
||||
<kanban>
|
||||
<templates>
|
||||
<t t-name="kanban-box">
|
||||
<div class="oe_group_vignette">
|
||||
<div class="oe_group_image">
|
||||
<!-- <a type="edit"><img t-att-src="kanban_image('hr.employee', 'photo', record.id.value)" class="oe_employee_picture"/></a> -->
|
||||
prout
|
||||
</div>
|
||||
<div class="oe_group_details">
|
||||
<h4><a type="edit"><field name="name"/></a></h4>
|
||||
<ul>
|
||||
<li t-if="record.name.raw_value"><field name="name"/></li>
|
||||
<li><a name="action_group_join" string="Join" type="object">Join</a></li>
|
||||
<li>Joined</li>
|
||||
</ul>
|
||||
</div>
|
||||
<script>
|
||||
$('.oe_employee_picture').load(function() { if($(this).width() > $(this).height()) { $(this).addClass('oe_employee_picture_wide') } });
|
||||
</script>
|
||||
</div>
|
||||
</t>
|
||||
</templates>
|
||||
</kanban>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Group Form View !-->
|
||||
<record model="ir.ui.view" id="view_group_form">
|
||||
<field name="name">mail.group.form</field>
|
||||
<field name="model">mail.group</field>
|
||||
<field name="type">form</field>
|
||||
<field name="priority" eval="10"/>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Group">
|
||||
<field name="name" colspan="2"/>
|
||||
<field name="responsible_id" colspan="2"/>
|
||||
<newline/>
|
||||
<field name="description" colspan="4"/>
|
||||
<newline/>
|
||||
<separator string="Privacy settings" colspan="4"/>
|
||||
<group colspan="2" col="4">
|
||||
<field name="public" nolabel="1" colspan="1"/>
|
||||
<label string="This group is visible by non members" colspan="2"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<!-- <button name="action_follow" type="object" context="{}"
|
||||
string="Follow" icon="gtk-go-forward" colspan="1"/>
|
||||
<button name="action_unfollow" type="object" context="{}"
|
||||
string="Unfollow" icon="gtk-go-forward" colspan="1"/>
|
||||
<button name="action_see_followers" type="object" context="{}"
|
||||
string="See followers" icon="gtk-go-forward" colspan="1"/>-->
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- group record !-->
|
||||
<record id="action_view_group" model="ir.actions.act_window">
|
||||
<field name="name">Groups</field>
|
||||
<field name="res_model">mail.group</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">kanban,tree,form</field>
|
||||
</record>
|
||||
|
||||
<record id="action_view_tweets" model="ir.actions.act_window">
|
||||
<field name="name">Messages</field>
|
||||
<field name="res_model">mail.message</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'filter_search': True, 'tree_view_ref': 'mail.view_tweet_tree', 'form_view_ref': 'mail.view_tweet_form'}</field>
|
||||
<field name="search_view_id" ref="view_tweet_search"/>
|
||||
</record>
|
||||
|
||||
<record id="action_view_mytweets" model="ir.actions.act_window">
|
||||
<field name="name">Messages</field>
|
||||
<field name="res_model">mail.message</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
<field name="context">{'filter_search': True, 'tree_view_ref': 'mail.view_tweet_tree', 'form_view_ref': 'mail.view_tweet_form'}</field>
|
||||
<field name="search_view_id" ref="view_tweet_search"/>
|
||||
<field name="domain">[('user_id', '=', uid)]</field>
|
||||
</record>
|
||||
|
||||
<record id="action_view_subscriptions" model="ir.actions.act_window">
|
||||
<field name="name">Subscriptions</field>
|
||||
<field name="res_model">mail.subscription</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<!-- toplevel menu -->
|
||||
<menuitem id="mail_group" name="Feeds" action="action_view_group"/>
|
||||
|
||||
<!-- left-side menu: Feeds !-->
|
||||
<menuitem id="mg_feeds" name="Feeds" parent="mail_group" action="action_view_group"/>
|
||||
<!-- left-side Tmp: temporary Messages link to create a message !-->
|
||||
<menuitem id="mg_feeds_my" name="My feeds" parent="mg_feeds" action="action_view_mytweets"/>
|
||||
<!-- left-side Tmp: temporary Messages link to create a message !-->
|
||||
<menuitem id="mg_feeds_all" name="All feeds" parent="mg_feeds" action="action_view_tweets"/>
|
||||
<!-- left-side menu: Groups !-->
|
||||
<menuitem id="mg_groups" name="Groups" parent="mail_group" action="action_view_group"/>
|
||||
<!-- left-side menu: Tmp !-->
|
||||
<menuitem id="mg_tmp" name="Tmp" parent="mail_group" action="action_view_mail_message"/>
|
||||
<!-- left-side Tmp: temporary Messages link to create a message !-->
|
||||
<menuitem id="mg_msg" name="Messages" parent="mg_tmp" action="action_view_mail_message"/>
|
||||
<!-- left-side Tmp: temporary Subscriptions link to see subscriptions !-->
|
||||
<menuitem id="mg_sub" name="Subscriptions" parent="mg_tmp" action="action_view_subscriptions"/>
|
||||
|
||||
<!-- <act_window
|
||||
context="{'search_default__id': [active_id], 'default_project_id': active_id}"
|
||||
id="act_project_project_2_project_task_all"
|
||||
name="Tasks"
|
||||
res_model="project.task"
|
||||
src_model="project.project"
|
||||
view_mode="tree,form,calendar,graph"
|
||||
view_type="form"/>-->
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -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():
|
||||
|
||||
Reference in New Issue
Block a user