[IMP] mail group in menu

bzr revid: fp@openerp.com-20120814090719-7dals8fzupv9cx4j
This commit is contained in:
Fabien Pinckaers 2012-08-14 11:07:19 +02:00
parent 29eb174ce5
commit 6f7b789f7a
3 changed files with 44 additions and 220 deletions

View File

@ -46,7 +46,7 @@ class mail_group(osv.osv):
_description = 'Discussion group' _description = 'Discussion group'
_name = 'mail.group' _name = 'mail.group'
_inherit = ['mail.thread'] _inherit = ['mail.thread']
_inherits = {'mail.alias': 'alias_id'} _inherits = {'mail.alias': 'alias_id', 'ir.ui.menu': 'menu_id'}
def _get_image(self, cr, uid, ids, name, args, context=None): def _get_image(self, cr, uid, ids, name, args, context=None):
result = dict.fromkeys(ids, False) result = dict.fromkeys(ids, False)
@ -89,8 +89,9 @@ class mail_group(osv.osv):
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64')) return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
_columns = { _columns = {
'name': fields.char('Group Name', size=64, required=True), #'name': fields.char('Group Name', size=64, required=True),
'description': fields.text('Description'), 'description': fields.text('Description'),
'menu_id': fields.many2one('ir.ui.menu', string='Related Menu', required=True, ondelete="cascade"),
'responsible_id': fields.many2one('res.users', string='Responsible', 'responsible_id': fields.many2one('res.users', string='Responsible',
ondelete='set null', required=True, select=1, ondelete='set null', required=True, select=1,
help="Responsible of the group that has all rights on the record."), help="Responsible of the group that has all rights on the record."),
@ -130,15 +131,20 @@ class mail_group(osv.osv):
string='Joined', multi='get_member_ids'), string='Joined', multi='get_member_ids'),
'last_month_msg_nbr': fields.function(get_last_month_msg_nbr, type='integer', 'last_month_msg_nbr': fields.function(get_last_month_msg_nbr, type='integer',
string='Messages count for last month'), string='Messages count for last month'),
'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="cascade", required=True, 'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="cascade",
help="The email address associated with this group. New emails received will automatically " help="The email address associated with this group. New emails received will automatically "
"create new topics."), "create new topics."),
} }
def _get_menu_parent(self, cr, uid, context=None):
ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'mail_group_root')
return ref and ref[1] or False
_defaults = { _defaults = {
'public': 'employee', 'public': 'employee',
'responsible_id': (lambda s, cr, uid, ctx: uid), 'responsible_id': (lambda s, cr, uid, ctx: uid),
'image': _get_default_image, 'image': _get_default_image,
'parent_id': _get_menu_parent,
} }
def _subscribe_user_with_group_m2m_command(self, cr, uid, ids, group_ids_command, context=None): def _subscribe_user_with_group_m2m_command(self, cr, uid, ids, group_ids_command, context=None):
@ -161,9 +167,23 @@ class mail_group(osv.osv):
{'alias_name': "group_"+name}, {'alias_name': "group_"+name},
model_name=self._name, context=context) model_name=self._name, context=context)
vals['alias_id'] = alias_id vals['alias_id'] = alias_id
mail_group_id = super(mail_group, self).create(cr, uid, vals, context)
alias_pool.write(cr, uid, [vals['alias_id']], {"alias_force_thread_id": mail_group_id}, context)
mail_group_id = super(mail_group, self).create(cr, uid, vals, context)
# Create client action for this group and link the menu to it
ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'action_mail_group_feeds')
if ref:
search_ref = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'view_message_search_wall')
params = {
'search_view_id': search_ref and search_ref[1] or False,
'domain': [('model','=','mail.group'),('res_id','=',mail_group_id)],
'thread_level': 2
}
cobj = self.pool.get('ir.actions.client')
newref = cobj.copy(cr, uid, ref[1], default={'params': str(params), 'name': vals['name']}, context=context)
self.write(cr, uid, [mail_group_id], {'action': 'ir.actions.client,'+str(newref), 'mail_group_id': mail_group_id}, context=context)
alias_pool.write(cr, uid, [vals['alias_id']], {"alias_force_thread_id": mail_group_id}, context)
if vals.get('group_ids'): if vals.get('group_ids'):
self._subscribe_user_with_group_m2m_command(cr, uid, [mail_group_id], vals.get('group_ids'), context=context) self._subscribe_user_with_group_m2m_command(cr, uid, [mail_group_id], vals.get('group_ids'), context=context)

View File

@ -19,222 +19,26 @@
# #
############################################################################## ##############################################################################
import datetime as DT
import openerp
import openerp.tools as tools
from operator import itemgetter
from osv import osv from osv import osv
from osv import fields from osv import fields
import tools
from tools.translate import _ from tools.translate import _
from lxml import etree
class ir_ui_menu(osv.osv): class ir_ui_menu(osv.osv):
_inherit = 'ir.ui.menu' _inherit = 'ir.ui.menu'
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
context = context or {}
ids = super(ir_ui_menu, self).search(cr, uid, args, offset=0,
limit=None, order=order, context=context, count=False)
if context.get('ir.ui.menu.full_list'):
return ids
root_group = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'mail_group_root')
if not root_group:
return ids
root_group = root_group[1]
print 'Root Group', root_group, ids, args
for a in args:
if a[0]=='id':
return ids
if a[0]=='parent_id':
if (a[1] == 'child_of'):
if root_group not in ids:
return ids
elif (a[1] == 'in'):
if root_group not in a[2]:
return ids
elif (a[1] <> '='):
if a[2] <> root_group:
return ids
print 'Got IT'
subs = self.pool.get('mail.subscription')
sub_ids = subs.search(cr, uid, [('user_id','=',uid),('res_model','=','mail.group')], context=context)
result = ids + map(lambda x: 'group-'+str(x.res_id), subs.browse(cr, uid, sub_ids, context=context))
print 'END SEARCH', result
return result
def _read_flat(self, cr, uid, ids, fields=None, context=None, load='_classic_read'):
group_ids = filter(lambda x: type(x)==str and x.startswith('group-'), ids)
nongroup_ids = filter(lambda x: x not in group_ids, ids)
print 'READ ***', ids, nongroup_ids, group_ids
result = super(ir_ui_menu, self)._read_flat(cr, uid, nongroup_ids, fields, context, load)
group_ids = map(lambda x: int(x[6:]), group_ids)
root_group = self.pool.get('ir.model.data').get_object_reference(cr, uid, 'mail', 'mail_group_root')
if not root_group:
return result
root_group = root_group[1]
for group in self.pool.get('mail.group').browse(cr, uid, group_ids, context=context):
data = {
'id': 'group-'+str(group.id),
'name': group.name,
'child_id': [],
'parent_id': root_group,
'complete_name': group.name,
'needaction_enabled': 1,
'needaction_counter': 1, # to compute
'action': 'ir.actions.client,1'
}
for key in fields or []:
data.setdefault(key, False)
for key in data.keys():
if fields and key not in fields:
del data[key]
result.append(data)
print result
return result
def _get_image(self, cr, uid, ids, name, args, context=None):
result = dict.fromkeys(ids, False)
for obj in self.browse(cr, uid, ids, context=context):
result[obj.id] = tools.image_get_resized_images(obj.image)
return result
def _set_image(self, cr, uid, id, name, value, args, context=None):
return self.write(cr, uid, [id], {'image': tools.image_resize_image_big(value)}, context=context)
def get_member_ids(self, cr, uid, ids, field_names, args, context=None):
if context is None:
context = {}
result = dict.fromkeys(ids)
for id in ids:
result[id] = {}
result[id]['member_ids'] = self.message_get_subscribers(cr, uid, [id], context=context)
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):
if context is None:
context = {}
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)
return [('id', 'in', map(itemgetter('res_id'), subs))]
def get_last_month_msg_nbr(self, cr, uid, ids, name, args, context=None):
result = {}
message_obj = self.pool.get('mail.message')
for id in ids:
lower_date = (DT.datetime.now() - DT.timedelta(days=30)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
result[id] = self.message_search(cr, uid, [id], limit=None, domain=[('date', '>=', lower_date)], count=True, context=context)
return result
def _get_default_image(self, cr, uid, context=None):
image_path = openerp.modules.get_module_resource('mail', 'static/src/img', 'groupdefault.png')
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
_columns = { _columns = {
'name': fields.char('Group Name', size=64, required=True), 'mail_group_id': fields.many2one('mail.group', 'Mail Group')
'description': fields.text('Description'),
'responsible_id': fields.many2one('res.users', string='Responsible',
ondelete='set null', required=True, select=1,
help="Responsible of the group that has all rights on the record."),
'public': fields.selection([('public','Public'),('private','Private'),('employee','Employees Only')], 'Privacy', required=True,
help='This group is visible by non members. \
Invisible groups can add members through the invite button.'),
'group_ids': fields.many2many('res.groups', rel='mail_group_res_group_rel',
id1='mail_group_id', id2='groups_id', string='Auto Subscription',
help="Members of those groups will automatically added as followers. "\
"Note that they will be able to manage their subscription manually "\
"if necessary."),
'image': fields.binary("Photo",
help="This field holds the image used as photo for the "\
"user. The image is base64 encoded, and PIL-supported. "\
"It is limited to a 12024x1024 px image."),
'image_medium': fields.function(_get_image, fnct_inv=_set_image,
string="Medium-sized photo", type="binary", multi="_get_image",
store = {
'mail.group': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
},
help="Medium-sized photo of the group. It is automatically "\
"resized as a 180x180px image, with aspect ratio preserved. "\
"Use this field in form views or some kanban views."),
'image_small': fields.function(_get_image, fnct_inv=_set_image,
string="Small-sized photo", type="binary", multi="_get_image",
store = {
'mail.group': (lambda self, cr, uid, ids, c={}: ids, ['image'], 10),
},
help="Small-sized photo of the group. It is automatically "\
"resized as a 50x50px image, with aspect ratio preserved. "\
"Use this field anywhere a small image is required."),
'member_ids': fields.function(get_member_ids, fnct_search=search_member_ids,
type='many2many', 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'),
'alias_id': fields.many2one('mail.alias', 'Alias', ondelete="cascade", required=True,
help="The email address associated with this group. New emails received will automatically "
"create new topics."),
} }
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
ids = super(ir_ui_menu, self).search(cr, uid, args, offset=0, limit=None, order=order, context=context, count=False)
_defaults = { subs = self.pool.get('mail.subscription')
'public': 'employee', for menu in self.browse(cr, uid, ids, context=context):
'responsible_id': (lambda s, cr, uid, ctx: uid), if menu.mail_group_id:
'image': _get_default_image, sub_ids = subs.search(cr, uid, [
} ('user_id','=',uid),('res_model','=','mail.group'),
('res_id','=',menu.mail_group_id.id)
], context=context)
if not sub_ids:
ids.remove(menu.id)
return ids
def _subscribe_user_with_group_m2m_command(self, cr, uid, ids, group_ids_command, context=None):
# form: {'group_ids': [(3, 10), (3, 3), (4, 10), (4, 3)]} or {'group_ids': [(6, 0, [ids]}
user_group_ids = [command[1] for command in group_ids_command if command[0] == 4]
user_group_ids += [id for command in group_ids_command if command[0] == 6 for id in command[2]]
# retrieve the user member of those groups
user_ids = []
res_groups_obj = self.pool.get('res.groups')
for group in res_groups_obj.browse(cr, uid, user_group_ids, context=context):
user_ids += [user.id for user in group.users]
# subscribe the users
return self.message_subscribe(cr, uid, ids, user_ids, context=context)
def create(self, cr, uid, vals, context=None):
alias_pool = self.pool.get('mail.alias')
if not vals.get('alias_id'):
name = vals.get('alias_name') or vals['name']
alias_id = alias_pool.create_unique_alias(cr, uid,
{'alias_name': "group_"+name},
model_name=self._name, context=context)
vals['alias_id'] = alias_id
mail_group_id = super(mail_group, self).create(cr, uid, vals, context)
alias_pool.write(cr, uid, [vals['alias_id']], {"alias_force_thread_id": mail_group_id}, context)
if vals.get('group_ids'):
self._subscribe_user_with_group_m2m_command(cr, uid, [mail_group_id], vals.get('group_ids'), context=context)
return mail_group_id
def unlink(self, cr, uid, ids, context=None):
# Cascade-delete mail aliases as well, as they should not exist without the mail group.
mail_alias = self.pool.get('mail.alias')
alias_ids = [group.alias_id.id for group in self.browse(cr, uid, ids, context=context) if group.alias_id]
res = super(mail_group, self).unlink(cr, uid, ids, context=context)
mail_alias.unlink(cr, uid, alias_ids, context=context)
return res
def write(self, cr, uid, ids, vals, context=None):
if vals.get('group_ids'):
self._subscribe_user_with_group_m2m_command(cr, uid, ids, vals.get('group_ids'), context=context)
return super(mail_group, self).write(cr, uid, ids, vals, context=context)
def action_group_join(self, cr, uid, ids, context=None):
return self.message_subscribe(cr, uid, ids, context=context)
def action_group_leave(self, cr, uid, ids, context=None):
return self.message_unsubscribe(cr, uid, ids, context=context)

View File

@ -1,6 +1,11 @@
<?xml version="1.0"?> <?xml version="1.0"?>
<openerp> <openerp>
<data> <data>
<record id="action_mail_group_feeds" model="ir.actions.client">
<field name="name">Discussion Group</field>
<field name="tag">mail.wall</field>
<field name="params" eval="{'search_view_id': ref('view_message_search_wall')}"/>
</record>
<!-- Group Kanban View !--> <!-- Group Kanban View !-->
<record model="ir.ui.view" id="view_group_kanban"> <record model="ir.ui.view" id="view_group_kanban">
@ -54,7 +59,7 @@
<field name="image_small" widget='image' class="oe_avatar oe_left"/> <field name="image_small" widget='image' class="oe_avatar oe_left"/>
<div class="oe_title"> <div class="oe_title">
<div class="oe_edit_only"> <div class="oe_edit_only">
<label for="name"/> <label for="name" string="Group Name"/>
</div> </div>
<h1><field name="name"/></h1> <h1><field name="name"/></h1>
<field name="description" placeholder="Topics discussed in this group..."/> <field name="description" placeholder="Topics discussed in this group..."/>
@ -63,11 +68,6 @@
<group> <group>
<group class="oe_edit_only"> <group class="oe_edit_only">
<field name="responsible_id" class="oe_inline"/> <field name="responsible_id" class="oe_inline"/>
<label for="alias_name" attrs="{'invisible': [('alias_domain', '=', False)]}"/>
<div name="alias_box" attrs="{'invisible': [('alias_domain', '=', False)]}">
<field name="alias_name" class="oe_inline" attrs="{'required': [('alias_id', '!=', False)]}"/>@<field name="alias_domain" class="oe_inline"/>
<field name="alias_id" invisible="1"/>
</div>
</group> </group>
<group class="oe_edit_only"> <group class="oe_edit_only">
<field name="public" class="oe_inline"/> <field name="public" class="oe_inline"/>
@ -91,7 +91,7 @@
<field name="priority" eval="10"/> <field name="priority" eval="10"/>
<field name="arch" type="xml"> <field name="arch" type="xml">
<tree string="Groups"> <tree string="Groups">
<field name="name"/> <field name="name" string="Group Name"/>
<field name="responsible_id"/> <field name="responsible_id"/>
</tree> </tree>
</field> </field>