[MRG]merge with lp:~openerp-dev/openobject-addons/trunk-mail-alias-jam
[odoo/odoo.git] / addons / mail / mail_group.py
1 # -*- coding: utf-8 -*-
2 ##############################################################################
3 #
4 #    OpenERP, Open Source Management Solution
5 #    Copyright (C) 2010-today OpenERP SA (<http://www.openerp.com>)
6 #
7 #    This program is free software: you can redistribute it and/or modify
8 #    it under the terms of the GNU Affero General Public License as
9 #    published by the Free Software Foundation, either version 3 of the
10 #    License, or (at your option) any later version
11 #
12 #    This program is distributed in the hope that it will be useful,
13 #    but WITHOUT ANY WARRANTY; without even the implied warranty of
14 #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 #    GNU Affero General Public License for more details
16 #
17 #    You should have received a copy of the GNU Affero General Public License
18 #    along with this program.  If not, see <http://www.gnu.org/licenses/>
19 #
20 ##############################################################################
21
22 import datetime as DT
23 import io
24 import openerp
25 import openerp.tools as tools
26 from operator import itemgetter
27 from osv import osv
28 from osv import fields
29 from PIL import Image
30 import StringIO
31 import tools
32 from tools.translate import _
33 from lxml import etree
34
35 class mail_group(osv.osv):
36     """
37     A mail_group is a collection of users sharing messages in a discussion
38     group. Group users are users that follow the mail group, using the
39     subscription/follow mechanism of OpenSocial. A mail group has nothing
40     in common wih res.users.group.
41     Additional information on fields:
42         - ``member_ids``: user member of the groups are calculated with
43           ``message_get_subscribers`` method from mail.thread
44         - ``member_count``: calculated with member_ids
45         - ``is_subscriber``: calculated with member_ids
46         
47     """
48     
49     _description = 'Discussion group'
50     _name = 'mail.group'
51     _inherit = ['mail.thread']
52     _inherits = {'mail.alias': 'alias_id'}
53     def action_group_join(self, cr, uid, ids, context={}):
54         return self.message_subscribe(cr, uid, ids, context=context);
55     
56     def action_group_leave(self, cr, uid, ids, context={}):
57         return self.message_unsubscribe(cr, uid, ids, context=context);
58
59     def onchange_photo(self, cr, uid, ids, value, context=None):
60         if not value:
61             return {'value': {'avatar_big': value, 'avatar': value} }
62         return {'value': {'photo_big': value, 'photo': self._photo_resize(cr, uid, value) } }
63     
64     def _set_photo(self, cr, uid, id, name, value, args, context=None):
65         if value:
66             return self.write(cr, uid, [id], {'photo_big': value}, context=context)
67         else:
68             return self.write(cr, uid, [id], {'photo_big': value}, context=context)
69     
70     def _photo_resize(self, cr, uid, photo, width=128, height=128, context=None):
71         image_stream = io.BytesIO(photo.decode('base64'))
72         img = Image.open(image_stream)
73         img.thumbnail((width, height), Image.ANTIALIAS)
74         img_stream = StringIO.StringIO()
75         img.save(img_stream, "JPEG")
76         return img_stream.getvalue().encode('base64')
77         
78     def _get_photo(self, cr, uid, ids, name, args, context=None):
79         result = dict.fromkeys(ids, False)
80         for group in self.browse(cr, uid, ids, context=context):
81             if group.photo_big:
82                 result[group.id] = self._photo_resize(cr, uid, group.photo_big, context=context)
83         return result
84     
85     def get_member_ids(self, cr, uid, ids, field_names, args, context=None):
86         if context is None:
87             context = {}
88         result = dict.fromkeys(ids)
89         for id in ids:
90             result[id] = {}
91             result[id]['member_ids'] = self.message_get_subscribers_ids(cr, uid, [id], context=context)
92             result[id]['member_count'] = len(result[id]['member_ids'])
93             result[id]['is_subscriber'] = uid in result[id]['member_ids']
94         return result
95     
96     def search_member_ids(self, cr, uid, obj, name, args, context=None):
97         if context is None:
98             context = {}
99         sub_obj = self.pool.get('mail.subscription')
100         sub_ids = sub_obj.search(cr, uid, ['&', ('res_model', '=', obj._name), ('user_id', '=', args[0][2])], context=context)
101         subs = sub_obj.read(cr, uid, sub_ids, context=context)
102         return [('id', 'in', map(itemgetter('res_id'), subs))]
103     
104     def get_last_month_msg_nbr(self, cr, uid, ids, name, args, context=None):
105         result = {}
106         message_obj = self.pool.get('mail.message')
107         for id in ids:
108             lower_date = (DT.datetime.now() - DT.timedelta(days=30)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
109             result[id] = message_obj.search(cr, uid, ['&', '&', ('model', '=', self._name), ('res_id', 'in', ids), ('date', '>=', lower_date)], count=True, context=context)
110         return result
111     
112     def _get_default_photo(self, cr, uid, context=None):
113         avatar_path = openerp.modules.get_module_resource('mail', 'static/src/img', 'groupdefault.png')
114         return self._photo_resize(cr, uid, open(avatar_path, 'rb').read().encode('base64'), context=context)
115     
116     _columns = {
117         'name': fields.char('Name', size=64, required=True),
118         'description': fields.text('Description'),
119         'responsible_id': fields.many2one('res.users', string='Responsible',
120                             ondelete='set null', required=True, select=1,
121                             help="Responsible of the group that has all rights on the record."),
122         'public': fields.boolean('Public', help='This group is visible by non members. Invisible groups can add members through the invite button.'),
123         '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.'),
124         'photo': fields.function(_get_photo, fnct_inv=_set_photo, string='Photo', type="binary",
125             store = {
126                 'mail.group': (lambda self, cr, uid, ids, c={}: ids, ['photo_big'], 10),
127             }, help='Field holding the automatically resized (128x128) PIL-supported and base64 encoded version of the group image.'),
128         'member_ids': fields.function(get_member_ids, fnct_search=search_member_ids, type='many2many',
129                         relation='res.users', string='Group members', multi='get_member_ids'),
130         'member_count': fields.function(get_member_ids, type='integer', string='Member count', multi='get_member_ids'),
131         'is_subscriber': fields.function(get_member_ids, type='boolean', string='Joined', multi='get_member_ids'),
132         'last_month_msg_nbr': fields.function(get_last_month_msg_nbr, type='integer', string='Messages count for last month'),
133         'alias_id': fields.many2one('mail.alias', 'Mail Alias', ondelete="cascade", required=True, 
134                                     help="This Unique Mail Box Alias of the Group allows to manage the Seamless email communication between Mail Box and OpenERP,"
135                                          "This Alias MailBox manage the Group email communication.")
136     }
137
138     _defaults = {
139         'public': True,
140         'responsible_id': (lambda s, cr, uid, ctx: uid),
141         'photo': _get_default_photo,
142     }
143     
144     def fields_view_get(self, cr, uid, view_id=None, view_type='form', context=None, toolbar=False, submenu=False):
145         res = super(mail_group,self).fields_view_get(cr, uid, view_id, view_type, context, toolbar=toolbar, submenu=submenu)
146         if view_type == 'form':
147             domain = self.pool.get("ir.config_parameter").get_param(cr, uid, "mail.catchall.domain", context=context)
148             if not domain:
149                 doc = etree.XML(res['arch'])
150                 alias_node = doc.xpath("//field[@name='alias_id']")[0]
151                 parent = alias_node.getparent()
152                 parent.remove(alias_node)
153                 res['arch'] = etree.tostring(doc)
154         return res
155     
156     def create(self, cr, uid, vals, context=None):
157         alias_pool = self.pool.get('mail.alias')
158         if not vals.get('alias_id'):
159             alias_id = alias_pool.create_unique_alias(cr, uid, {'alias_name': "mail_group."+vals['name'], 'alias_model_id': self._name}, context=context)
160             vals.update({'alias_id': alias_id})
161         res = super(mail_group, self).create(cr, uid, vals, context)
162         alias_pool.write(cr, uid, [vals['alias_id']], {"alias_force_thread_id": res}, context)
163         return res
164