[MERGE] Merged OpenChatter-3-5 followers refactoring. Followers is now a modified many2many field, using reference (res_model, res_id) to access one of the relationship. Added message_followers_ids and message_is_follower fields. Refactored subscribers management, because it is now managed through classic reads and writes in the field.
Web-side: the followers display is now a separated widget. It has been moved out of mail.js, into mail_followers.js. Modified views accordingly, because mail_followers is a widget on message_follower_ids field. This is more clean with other OpenERP aspects. Misc: updated all views using Chatter in addons, to use mail_followers widget. Cleaned some issues. Also renamed mail.subscription into mail.followers, and propagated that change through the code. bzr revid: tde@openerp.com-20120816003157-f2820hibc17f0j5q
This commit is contained in:
commit
f4f7de1369
|
@ -273,6 +273,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -426,6 +427,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -111,6 +111,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -240,6 +240,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -408,6 +409,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -147,6 +147,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -301,6 +302,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -297,7 +297,6 @@ class account_analytic_account(osv.osv):
|
|||
|
||||
def create_send_note(self, cr, uid, ids, context=None):
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
self.message_subscribe(cr, uid, [obj.id], [obj.user_id.id], context=context)
|
||||
self.message_append_note(cr, uid, [obj.id], body=_("Contract for <em>%s</em> has been <b>created</b>.") % (obj.partner_id.name), context=context)
|
||||
|
||||
account_analytic_account()
|
||||
|
|
|
@ -45,6 +45,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -233,6 +233,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -859,13 +859,10 @@ class crm_lead(base_stage, osv.osv):
|
|||
# OpenChatter methods and notifications
|
||||
# ----------------------------------------
|
||||
|
||||
def message_get_subscribers(self, cr, uid, ids, context=None):
|
||||
""" Override to add the salesman. """
|
||||
user_ids = super(crm_lead, self).message_get_subscribers(cr, uid, ids, context=context)
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
if obj.user_id and not obj.user_id.id in user_ids:
|
||||
user_ids.append(obj.user_id.id)
|
||||
return user_ids
|
||||
def message_get_monitored_follower_fields(self, cr, uid, ids, context=None):
|
||||
""" Add 'user_id' to the monitored fields """
|
||||
res = super(crm_lead, self).message_get_monitored_follower_fields(cr, uid, ids, context=context)
|
||||
return res + ['user_id']
|
||||
|
||||
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
|
||||
""" Override of the (void) default notification method. """
|
||||
|
|
|
@ -222,6 +222,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -532,6 +533,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -271,7 +271,6 @@ class crm_phonecall(base_state, osv.osv):
|
|||
def case_open_send_note(self, cr, uid, ids, context=None):
|
||||
lead_obj = self.pool.get('crm.lead')
|
||||
for phonecall in self.browse(cr, uid, ids, context=context):
|
||||
phonecall.message_subscribe([phonecall.user_id.id], context=context)
|
||||
if phonecall.opportunity_id:
|
||||
lead = phonecall.opportunity_id
|
||||
# convert datetime field to a datetime, using server format, then
|
||||
|
|
|
@ -154,6 +154,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -182,6 +182,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -100,6 +100,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -196,6 +196,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -477,6 +478,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -120,6 +120,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -366,15 +366,11 @@ class hr_holidays(osv.osv):
|
|||
result[obj.id] = hr_manager_group['users']
|
||||
return result
|
||||
|
||||
def message_get_subscribers(self, cr, uid, ids, context=None):
|
||||
""" Override to add employee and its manager. """
|
||||
user_ids = super(hr_holidays, self).message_get_subscribers(cr, uid, ids, context=context)
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
if obj.user_id and not obj.user_id.id in user_ids:
|
||||
user_ids.append(obj.user_id.id)
|
||||
if obj.employee_id.parent_id and not obj.employee_id.parent_id.user_id.id in user_ids:
|
||||
user_ids.append(obj.employee_id.parent_id.user_id.id)
|
||||
return user_ids
|
||||
def message_get_monitored_follower_fields(self, cr, uid, ids, context=None):
|
||||
""" Add 'user_id' and 'manager' to the monitored fields """
|
||||
res = super(hr_holidays, self).message_get_monitored_follower_fields(cr, uid, ids, context=context)
|
||||
# TODO: add manager
|
||||
return res + ['user_id']
|
||||
|
||||
def create_notificate(self, cr, uid, ids, context=None):
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
|
|
|
@ -137,6 +137,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -183,6 +184,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -461,13 +461,10 @@ class hr_applicant(base_stage, osv.Model):
|
|||
# OpenChatter methods and notifications
|
||||
# -------------------------------------------------------
|
||||
|
||||
def message_get_subscribers(self, cr, uid, ids, context=None):
|
||||
""" Override to add responsible user. """
|
||||
user_ids = super(hr_applicant, self).message_get_subscribers(cr, uid, ids, context=context)
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
if obj.user_id and not obj.user_id.id in user_ids:
|
||||
user_ids.append(obj.user_id.id)
|
||||
return user_ids
|
||||
def message_get_monitored_follower_fields(self, cr, uid, ids, context=None):
|
||||
""" Add 'user_id' to the monitored fields """
|
||||
res = super(hr_applicant, self).message_get_monitored_follower_fields(cr, uid, ids, context=context)
|
||||
return res + ['user_id']
|
||||
|
||||
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
|
||||
""" Override of the (void) default notification method. """
|
||||
|
|
|
@ -181,6 +181,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -78,6 +78,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -21,9 +21,9 @@
|
|||
|
||||
import mail_alias
|
||||
import mail_message
|
||||
import mail_followers
|
||||
import mail_thread
|
||||
import mail_group
|
||||
import mail_subscription
|
||||
import ir_needaction
|
||||
import res_partner
|
||||
import res_users
|
||||
|
|
|
@ -64,7 +64,7 @@ The main features of the module are:
|
|||
'wizard/mail_compose_message_view.xml',
|
||||
'res_config_view.xml',
|
||||
'mail_message_view.xml',
|
||||
'mail_subscription_view.xml',
|
||||
'mail_followers_view.xml',
|
||||
'mail_thread_view.xml',
|
||||
'mail_group_view.xml',
|
||||
'res_partner_view.xml',
|
||||
|
@ -102,9 +102,11 @@ The main features of the module are:
|
|||
'js': [
|
||||
'static/lib/jquery.expander/jquery.expander.js',
|
||||
'static/src/js/mail.js',
|
||||
'static/src/js/mail_followers.js',
|
||||
],
|
||||
'qweb': [
|
||||
'static/src/xml/mail.xml',
|
||||
'static/src/xml/mail_followers.xml',
|
||||
],
|
||||
}
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -22,18 +22,21 @@
|
|||
from osv import osv
|
||||
from osv import fields
|
||||
|
||||
class mail_subscription(osv.osv):
|
||||
"""
|
||||
mail_subscription holds the data related to the follow mechanism inside OpenERP.
|
||||
class mail_followers(osv.Model):
|
||||
""" mail_followers holds the data related to the follow mechanism inside
|
||||
OpenERP. Users can choose to follow documents (records) of any kind that
|
||||
inherits from mail.thread. Following documents allow to receive
|
||||
notifications for new messages.
|
||||
A subscription is characterized by:
|
||||
: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'
|
||||
_name = 'mail.followers'
|
||||
_rec_name = 'id'
|
||||
_log_access = False
|
||||
_order = 'res_model asc'
|
||||
_description = 'Mail subscription'
|
||||
_description = 'Mail Document Followers'
|
||||
_columns = {
|
||||
'res_model': fields.char('Related Document Model', size=128,
|
||||
required=True, select=1,
|
||||
|
@ -44,10 +47,8 @@ class mail_subscription(osv.osv):
|
|||
ondelete='cascade', required=True, select=1),
|
||||
}
|
||||
|
||||
class mail_notification(osv.osv):
|
||||
"""
|
||||
mail_notification is a relational table modeling messages pushed to users.
|
||||
:param: read: not used currently
|
||||
class mail_notification(osv.Model):
|
||||
""" mail_notification is a relational table modeling messages pushed to users.
|
||||
"""
|
||||
_name = 'mail.notification'
|
||||
_rec_name = 'id'
|
||||
|
@ -59,9 +60,4 @@ 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', help="Not used currently",),
|
||||
# TODO: add a timestamp ? or use message date ?
|
||||
}
|
||||
_defaults = {
|
||||
'read': False,
|
||||
}
|
|
@ -2,16 +2,14 @@
|
|||
<openerp>
|
||||
<data>
|
||||
|
||||
<!--
|
||||
SUBSCRIPTION
|
||||
!-->
|
||||
|
||||
<record model="ir.ui.view" id="view_subscription_tree">
|
||||
<field name="name">mail.subscription.tree</field>
|
||||
<field name="model">mail.subscription</field>
|
||||
<!-- FOLLOWERS !-->
|
||||
<record model="ir.ui.view" id="view_followers_tree">
|
||||
<field name="name">mail.followers.tree</field>
|
||||
<field name="model">mail.followers</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="priority">10</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Subscription">
|
||||
<tree string="Followers">
|
||||
<field name="res_model"/>
|
||||
<field name="res_id"/>
|
||||
<field name="user_id"/>
|
||||
|
@ -19,26 +17,22 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<!--
|
||||
NOTIFICATION
|
||||
!-->
|
||||
|
||||
<!-- NOTIFICATION !-->
|
||||
<record model="ir.ui.view" id="view_notification_tree">
|
||||
<field name="name">mail.notification.tree</field>
|
||||
<field name="model">mail.notification</field>
|
||||
<field name="priority">10</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Subscription">
|
||||
<tree string="Notifications">
|
||||
<field name="user_id"/>
|
||||
<field name="message_id"/>
|
||||
<field name="read"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_view_subscriptions" model="ir.actions.act_window">
|
||||
<field name="name">Subscriptions</field>
|
||||
<field name="res_model">mail.subscription</field>
|
||||
<record id="action_view_followers" model="ir.actions.act_window">
|
||||
<field name="name">Followers</field>
|
||||
<field name="res_model">mail.followers</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
@ -50,9 +44,9 @@
|
|||
<field name="view_mode">tree,form</field>
|
||||
</record>
|
||||
|
||||
<!-- Add subscriptions related menu entries in Settings/Email -->
|
||||
<menuitem name="Subscriptions" id="menu_email_subscriptions" parent="base.menu_email"
|
||||
action="action_view_subscriptions" sequence="30" groups="base.group_no_one"/> -->
|
||||
<!-- Add followers related menu entries in Settings/Email -->
|
||||
<menuitem name="Followers" id="menu_email_followers" parent="base.menu_email"
|
||||
action="action_view_followers" sequence="30" groups="base.group_no_one"/> -->
|
||||
|
||||
<!-- Add notifications related menu entry in Settings/Email -->
|
||||
<menuitem name="Notifications" id="menu_email_notifications" parent="base.menu_email"
|
|
@ -27,18 +27,12 @@ from osv import osv
|
|||
from osv import fields
|
||||
from tools.translate import _
|
||||
|
||||
class mail_group(osv.osv):
|
||||
class mail_group(osv.Model):
|
||||
"""
|
||||
A mail_group is a collection of users sharing messages in a discussion
|
||||
group. Group users are users that follow the mail group, using the
|
||||
subscription/follow mechanism of OpenSocial. A mail group has nothing
|
||||
in common with res.users.group.
|
||||
Additional information on fields:
|
||||
- ``member_ids``: user member of the groups are calculated with
|
||||
``message_get_subscribers`` method from mail.thread
|
||||
- ``member_count``: calculated with member_ids
|
||||
- ``is_subscriber``: calculated with member_ids
|
||||
|
||||
"""
|
||||
|
||||
_description = 'Discussion group'
|
||||
|
@ -55,26 +49,7 @@ class mail_group(osv.osv):
|
|||
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):
|
||||
def _get_last_month_msg_nbr(self, cr, uid, ids, name, args, context=None):
|
||||
result = {}
|
||||
for id in ids:
|
||||
lower_date = (DT.datetime.now() - DT.timedelta(days=30)).strftime(tools.DEFAULT_SERVER_DATE_FORMAT)
|
||||
|
@ -86,21 +61,21 @@ class mail_group(osv.osv):
|
|||
return tools.image_resize_image_big(open(image_path, 'rb').read().encode('base64'))
|
||||
|
||||
_columns = {
|
||||
#'name': fields.char('Group Name', size=64, required=True),
|
||||
'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',
|
||||
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'),('groups','Selected Group Only')], 'Privacy', required=True,
|
||||
help='This group is visible by non members. \
|
||||
Invisible groups can add members through the invite button.'),
|
||||
'public': fields.selection([('public', 'Public'), ('private', 'Private'), ('groups', 'Selected Group Only')],
|
||||
string='Privacy', required=True,
|
||||
help='This group is visible by non members. '\
|
||||
'Invisible groups can add members through the invite button.'),
|
||||
'group_public_id': fields.many2one('res.groups', string='Authorized Group'),
|
||||
'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."),
|
||||
"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. "\
|
||||
|
@ -121,15 +96,7 @@ class mail_group(osv.osv):
|
|||
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',
|
||||
deprecated='This field will be deleted in a few hours or days, so please do not use it.'),
|
||||
'member_count': fields.function(get_member_ids, type='integer',
|
||||
string='Member count', multi='get_member_ids',
|
||||
deprecated='This field will be deleted in a few hours or days, so please do not use it.'),
|
||||
'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',
|
||||
'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",
|
||||
help="The email address associated with this group. New emails received will automatically "
|
||||
|
@ -218,3 +185,12 @@ class mail_group(osv.osv):
|
|||
|
||||
def action_group_leave(self, cr, uid, ids, context=None):
|
||||
return self.message_unsubscribe(cr, uid, ids, context=context)
|
||||
|
||||
# ----------------------------------------
|
||||
# OpenChatter methods and notifications
|
||||
# ----------------------------------------
|
||||
|
||||
def message_get_monitored_follower_fields(self, cr, uid, ids, context=None):
|
||||
""" Add 'responsible_id' to the monitored fields """
|
||||
res = super(mail_group, self).message_get_monitored_follower_fields(cr, uid, ids, context=context)
|
||||
return res + ['responsible_id']
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
##############################################################################
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2010-today OpenERP SA (<http://www.openerp.com>)
|
||||
# Copyright (C) 2012-today OpenERP SA (<http://www.openerp.com>)
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU Affero General Public License as
|
||||
|
@ -24,21 +24,29 @@ from osv import fields
|
|||
from tools.translate import _
|
||||
|
||||
class ir_ui_menu(osv.osv):
|
||||
""" Override of ir.ui.menu class. When adding mail_thread module, each
|
||||
new mail.group will create a menu entry. This overrides checks that
|
||||
the current user is in the mail.group followers. If not, the menu
|
||||
entry is taken off the list of menu ids. This way the user will see
|
||||
menu entries for the mail.group he is following.
|
||||
"""
|
||||
_inherit = 'ir.ui.menu'
|
||||
|
||||
_columns = {
|
||||
'mail_group_id': fields.many2one('mail.group', 'Mail Group')
|
||||
}
|
||||
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)
|
||||
|
||||
subs = self.pool.get('mail.subscription')
|
||||
def search(self, cr, uid, args, offset=0, limit=None, order=None, context=None, count=False):
|
||||
""" Override to take off menu entries (mail.group) the user is not
|
||||
following. """
|
||||
ids = super(ir_ui_menu, self).search(cr, uid, args, offset=0, limit=None, order=order, context=context, count=False)
|
||||
follower_obj = self.pool.get('mail.followers')
|
||||
for menu in self.browse(cr, uid, ids, context=context):
|
||||
if menu.mail_group_id:
|
||||
sub_ids = subs.search(cr, uid, [
|
||||
('user_id','=',uid),('res_model','=','mail.group'),
|
||||
('res_id','=',menu.mail_group_id.id)
|
||||
sub_ids = follower_obj.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
|
||||
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
<field name="priority" eval="10"/>
|
||||
<field name="arch" type="xml">
|
||||
<kanban>
|
||||
<field name="message_follower_ids"/>
|
||||
<field name="message_is_follower"/>
|
||||
<templates>
|
||||
<t t-name="kanban-description">
|
||||
<div class="oe_group_description" t-if="record.description.raw_value">
|
||||
|
@ -21,17 +23,19 @@
|
|||
</div>
|
||||
</t>
|
||||
<t t-name="kanban-box">
|
||||
<div t-attf-class="{record.is_subscriber.raw_value} oe_group_vignette">
|
||||
<div t-attf-class="{record.message_is_follower.raw_value} oe_group_vignette">
|
||||
<div class="oe_group_image">
|
||||
<a type="edit"><img t-att-src="kanban_image('mail.group', 'image_medium', record.id.value)" class="oe_group_photo" tooltip="kanban-description"/></a>
|
||||
</div>
|
||||
<div class="oe_group_details">
|
||||
<h4><a type="edit"><field name="name"/></a></h4>
|
||||
<span style="display: none;"><field name="is_subscriber"/></span>
|
||||
<ul>
|
||||
<li><field name="member_count"/> members</li>
|
||||
<li t-if="! record.is_subscriber.raw_value"><a name="action_group_join" string="Join" type="object" class="oe_group_join">Not following</a></li>
|
||||
<li t-if="record.is_subscriber.raw_value"><a name="action_group_leave" string="Join" type="object" class="oe_group_leave">Following</a></li>
|
||||
<!-- <li><field name="message_follower_count"/> member(s)</li> -->
|
||||
<li>
|
||||
<t t-raw="record.message_follower_ids.raw_value.length"/> member(s)
|
||||
</li>
|
||||
<li t-if="! record.message_is_follower.raw_value"><a name="action_group_join" string="Join" type="object" class="oe_group_join">Not following</a></li>
|
||||
<li t-if="record.message_is_follower.raw_value"><a name="action_group_leave" string="Join" type="object" class="oe_group_leave">Following</a></li>
|
||||
<li><field name="last_month_msg_nbr"/> messages last month</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
@ -84,6 +88,8 @@
|
|||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"
|
||||
options='{"thread_level": 1}'/>
|
||||
<field name="message_follower_ids" widget="mail_followers"
|
||||
context="{'lapin': 'nouille'}" image="image_small"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -36,10 +36,61 @@ from tools.safe_eval import safe_eval as eval
|
|||
|
||||
_logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def decode_header(message, header, separator=' '):
|
||||
return separator.join(map(decode,message.get_all(header, [])))
|
||||
|
||||
class many2many_reference(fields.many2many):
|
||||
""" many2many_reference is an override of fields.many2many. It manages
|
||||
many2many-like table where one id is given by two fields, res_model
|
||||
and res_id.
|
||||
"""
|
||||
|
||||
def _get_query_and_where_params(self, cr, model, ids, values, where_params):
|
||||
""" Add in where:
|
||||
- mail_followers.res_model = 'crm.lead'
|
||||
"""
|
||||
query = 'SELECT %(rel)s.%(id2)s, %(rel)s.%(id1)s \
|
||||
FROM %(rel)s, %(from_c)s \
|
||||
WHERE %(rel)s.%(id1)s IN %%s \
|
||||
AND %(rel)s.%(id2)s = %(tbl)s.id \
|
||||
AND %(rel)s.res_model = %%s \
|
||||
%(where_c)s \
|
||||
%(order_by)s \
|
||||
%(limit)s \
|
||||
OFFSET %(offset)d' \
|
||||
% values
|
||||
where_params = [model._name] + where_params
|
||||
return query, where_params
|
||||
|
||||
def set(self, cr, model, id, name, values, user=None, context=None):
|
||||
""" Override to add the res_model field in queries. """
|
||||
if not values: return
|
||||
rel, id1, id2 = self._sql_names(model)
|
||||
obj = model.pool.get(self._obj)
|
||||
for act in values:
|
||||
if not (isinstance(act, list) or isinstance(act, tuple)) or not act:
|
||||
continue
|
||||
if act[0] == 0:
|
||||
idnew = obj.create(cr, user, act[2], context=context)
|
||||
cr.execute('INSERT INTO '+rel+' ('+id1+','+id2+',res_model) VALUES (%s,%s,%s)', (id, idnew, model._name))
|
||||
elif act[0] == 3:
|
||||
cr.execute('DELETE FROM '+rel+' WHERE '+id1+'=%s AND '+id2+'=%s AND res_model=%s', (id, act[1], model._name))
|
||||
elif act[0] == 4:
|
||||
# following queries are in the same transaction - so should be relatively safe
|
||||
cr.execute('SELECT 1 FROM '+rel+' WHERE '+id1+'=%s AND '+id2+'=%s AND res_model=%s', (id, act[1], model._name))
|
||||
if not cr.fetchone():
|
||||
cr.execute('INSERT INTO '+rel+' ('+id1+','+id2+',res_model) VALUES (%s,%s,%s)', (id, act[1], model._name))
|
||||
elif act[0] == 6:
|
||||
d1, d2,tables = obj.pool.get('ir.rule').domain_get(cr, user, obj._name, context=context)
|
||||
if d1:
|
||||
d1 = ' and ' + ' and '.join(d1)
|
||||
else:
|
||||
d1 = ''
|
||||
cr.execute('DELETE FROM '+rel+' WHERE '+id1+'=%s AND res_model=%s AND '+id2+' IN (SELECT '+rel+'.'+id2+' FROM '+rel+', '+','.join(tables)+' WHERE '+rel+'.'+id1+'=%s AND '+rel+'.'+id2+' = '+obj._table+'.id '+ d1 +')', [id, model._name, id]+d2)
|
||||
for act_nbr in act[2]:
|
||||
cr.execute('INSERT INTO '+rel+' ('+id1+','+id2+',res_model) VALUES (%s,%s,%s)', (id, act_nbr, model._name))
|
||||
else:
|
||||
return super(many2many_reference, self).set(cr, model, id, name, values, user, context)
|
||||
|
||||
class mail_thread(osv.Model):
|
||||
'''Mixin model, meant to be inherited by any model that needs to
|
||||
|
@ -62,22 +113,24 @@ class mail_thread(osv.Model):
|
|||
default implementation will work for any model. However it is common
|
||||
to override at least the ``message_new`` and ``message_update``
|
||||
methods (calling ``super``) to add model-specific behavior at
|
||||
creation and update of a thread; and ``message_get_subscribers``
|
||||
to manage more precisely the social aspect of the thread through
|
||||
the followers.
|
||||
creation and update of a thread.
|
||||
|
||||
#TODO: UPDATE WITH SUBTYPE / NEW FOLLOW MECHANISM
|
||||
'''
|
||||
_name = 'mail.thread'
|
||||
_description = 'Email Thread'
|
||||
|
||||
def _get_message_ids(self, cr, uid, ids, name, args, context=None):
|
||||
res = {}
|
||||
def _get_message_data(self, cr, uid, ids, field_names, args, context=None):
|
||||
res = dict.fromkeys(ids)
|
||||
for id in ids:
|
||||
message_ids = self.message_search(cr, uid, [id], context=context)
|
||||
subscriber_ids = self.message_get_subscribers(cr, uid, [id], context=context)
|
||||
res[id] = {
|
||||
'message_ids': message_ids,
|
||||
'message_summary': "<span><span class='oe_e'>9</span> %d</span> <span><span class='oe_e'>+</span> %d</span>" % (len(message_ids), len(subscriber_ids)),
|
||||
}
|
||||
res[id] = {'message_ids': self.message_search(cr, uid, [id], context=context)}
|
||||
for thread in self.browse(cr, uid, ids, context=context):
|
||||
message_follower_ids = [follower.id for follower in thread.message_follower_ids]
|
||||
res[thread.id].update({
|
||||
'message_is_follower': uid in message_follower_ids,
|
||||
'message_summary': "<span><span class='oe_e'>9</span> %d</span> <span><span class='oe_e'>+</span> %d</span>" %
|
||||
(len(res[thread.id]['message_ids']), len(thread.message_follower_ids))
|
||||
})
|
||||
return res
|
||||
|
||||
def _search_message_ids(self, cr, uid, obj, name, args, context=None):
|
||||
|
@ -86,15 +139,22 @@ class mail_thread(osv.Model):
|
|||
return [('id', 'in', msg_ids)]
|
||||
|
||||
_columns = {
|
||||
'message_ids': fields.function(_get_message_ids,
|
||||
'message_ids': fields.function(_get_message_data,
|
||||
fnct_search=_search_message_ids,
|
||||
type='one2many', obj='mail.message', _fields_id = 'res_id',
|
||||
string='Temp messages', multi="_get_message_ids",
|
||||
help="Functional field holding messages related to the current document."),
|
||||
string='Messages', multi="_get_message_data",
|
||||
help="Field holding discussion about the current document."),
|
||||
'message_follower_ids': many2many_reference('res.users',
|
||||
rel='mail_followers', id1='res_id', id2='user_id', string="Followers",
|
||||
help="Followers of the document. The followers have full access to " \
|
||||
"the document details, as well as the conversation."),
|
||||
'message_is_follower': fields.function(_get_message_data, method=True,
|
||||
type='boolean', string='I am Follower', multi='_get_message_data',
|
||||
help='True if the current user is following the current document.'),
|
||||
'message_state': fields.boolean('Read',
|
||||
help="When checked, new messages require your attention."),
|
||||
'message_summary': fields.function(_get_message_ids, method=True,
|
||||
type='text', string='Summary', multi="_get_message_ids",
|
||||
'message_summary': fields.function(_get_message_data, method=True,
|
||||
type='text', string='Summary', multi='_get_message_data',
|
||||
help="Holds the Chatter summary (number of messages, ...). "\
|
||||
"This summary is directly in html format in order to "\
|
||||
"be inserted in kanban views."),
|
||||
|
@ -109,40 +169,93 @@ class mail_thread(osv.Model):
|
|||
#------------------------------------------------------
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
"""Automatically subscribe the creator """
|
||||
""" Override of create to subscribe :
|
||||
- the writer
|
||||
- followers given by the monitored fields
|
||||
"""
|
||||
thread_id = super(mail_thread, self).create(cr, uid, vals, context=context)
|
||||
if thread_id:
|
||||
self.message_subscribe(cr, uid, [thread_id], [uid], context=context)
|
||||
followers_command = self.message_get_automatic_followers(cr, uid, thread_id, vals, fetch_missing=False, context=context)
|
||||
if followers_command:
|
||||
self.write(cr, uid, [thread_id], {'message_follower_ids': followers_command}, context=context)
|
||||
return thread_id
|
||||
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
"""Automatically subscribe the writer"""
|
||||
""" Override of write to subscribe :
|
||||
- the writer
|
||||
- followers given by the monitored fields
|
||||
"""
|
||||
if isinstance(ids, (int, long)):
|
||||
ids = [ids]
|
||||
write_res = super(mail_thread, self).write(cr, uid, ids, vals, context=context);
|
||||
if write_res:
|
||||
self.message_subscribe(cr, uid, ids, [uid], context=context)
|
||||
return write_res;
|
||||
for id in ids:
|
||||
# copy original vals because we are going to modify it
|
||||
specific_vals = dict(vals)
|
||||
# we modify followers: do not subscribe the uid
|
||||
if specific_vals.get('message_follower_ids'):
|
||||
followers_command = self.message_get_automatic_followers(cr, uid, id, specific_vals, add_uid=False, context=context)
|
||||
specific_vals['message_follower_ids'] += followers_command
|
||||
else:
|
||||
followers_command = self.message_get_automatic_followers(cr, uid, id, specific_vals, context=context)
|
||||
specific_vals['message_follower_ids'] = followers_command
|
||||
write_res = super(mail_thread, self).write(cr, uid, ids, specific_vals, context=context)
|
||||
return True
|
||||
|
||||
def unlink(self, cr, uid, ids, context=None):
|
||||
"""Override unlink, to automatically delete
|
||||
- subscriptions
|
||||
- messages
|
||||
"""Override unlink, to automatically delete messages
|
||||
that are linked with res_model and res_id, not through
|
||||
a foreign key with a 'cascade' ondelete attribute.
|
||||
Notifications will be deleted with messages
|
||||
"""
|
||||
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 messages and 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)
|
||||
|
||||
return super(mail_thread, self).unlink(cr, uid, ids, context=context)
|
||||
|
||||
def message_get_automatic_followers(self, cr, uid, id, record_vals, add_uid=True, fetch_missing=False, context=None):
|
||||
""" Return the command for the many2many follower_ids field to manage
|
||||
subscribers. Behavior :
|
||||
- get the monitored fields (ex: ['user_id', 'responsible_id']); those
|
||||
fields should be relationships to res.users (#TODO: res.partner)
|
||||
- if this field is in the record_vals: it means it has been modified
|
||||
thus add its value to the followers
|
||||
- if this fields is not in record_vals, but fetch_missing paramter
|
||||
is set to True: fetch the value in the record (use: at creation
|
||||
for default values, not present in record_vals)
|
||||
- if add_uid: add the current user (for example: writer is subscriber)
|
||||
- generate the command and return it
|
||||
This method has to be used on 1 id, because otherwise it would imply
|
||||
to track which user.id is used for which record.id.
|
||||
|
||||
:param record_vals: values given to the create method of the new
|
||||
record, or values updated in a write.
|
||||
:param monitored_fields: a list of fields that are monitored. Those
|
||||
fields must be many2one fields to the res.users model.
|
||||
:param fetch_missing: is set to True, the method will read the
|
||||
record to find values that are not present in record_vals.
|
||||
|
||||
#TODO : UPDATE WHEN MERGING TO PARTNERS
|
||||
"""
|
||||
# get monitored fields
|
||||
monitored_fields = self.message_get_monitored_follower_fields(cr, uid, [id], context=context)
|
||||
modified_fields = [field for field in monitored_fields if field in record_vals.iterkeys()]
|
||||
other_fields = [field for field in monitored_fields if field not in record_vals.iterkeys()] if fetch_missing else []
|
||||
# for each monitored field: if in record_vals, it has been modified/added
|
||||
follower_ids = []
|
||||
for field in modified_fields:
|
||||
# do not add 'False'
|
||||
if record_vals.get(fields):
|
||||
follower_ids.append(record_vals.get(field))
|
||||
# for other fields: read in record if fetch_missing (otherwise list is void)
|
||||
for field in other_fields:
|
||||
record = self.browse(cr, uid, id, context=context)
|
||||
value = getattr(record, field)
|
||||
if value:
|
||||
follower_ids.append(value)
|
||||
# add uid if asked and not already present
|
||||
if add_uid and uid not in follower_ids:
|
||||
follower_ids.append(uid)
|
||||
return self.message_subscribe_get_command(cr, uid, follower_ids, context=context)
|
||||
|
||||
#------------------------------------------------------
|
||||
# mail.message wrappers and tools
|
||||
#------------------------------------------------------
|
||||
|
@ -151,20 +264,20 @@ class mail_thread(osv.Model):
|
|||
""" OpenChatter: wrapper of mail.message create method
|
||||
- creates the mail.message
|
||||
- automatically subscribe the message writer
|
||||
- push the message to subscribed users
|
||||
- push the message to followers
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
message_obj = self.pool.get('mail.message')
|
||||
notification_obj = self.pool.get('mail.notification')
|
||||
# create message
|
||||
msg_id = self.pool.get('mail.message').create(cr, uid, vals, context=context)
|
||||
|
||||
# automatically subscribe the writer of the message
|
||||
if vals.get('user_id'):
|
||||
self.message_subscribe(cr, uid, [thread_id], [vals['user_id']], context=context)
|
||||
|
||||
# create message
|
||||
msg_id = message_obj.create(cr, uid, vals, context=context)
|
||||
record = self.browse(cr, uid, thread_id, context=context)
|
||||
follower_ids = [follower.id for follower in record.message_follower_ids]
|
||||
if vals.get('user_id') not in follower_ids:
|
||||
self.message_subscribe(cr, uid, [thread_id], [vals.get('user_id')], context=context)
|
||||
|
||||
# Set as unread if writer is not the document responsible
|
||||
self.message_create_set_unread(cr, uid, [thread_id], context=context)
|
||||
|
@ -174,6 +287,7 @@ class mail_thread(osv.Model):
|
|||
return msg_id
|
||||
|
||||
# get users that will get a notification pushed
|
||||
notification_obj = self.pool.get('mail.notification')
|
||||
user_to_push_ids = self.message_get_user_ids_to_notify(cr, uid, [thread_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)
|
||||
|
@ -188,10 +302,9 @@ class mail_thread(osv.Model):
|
|||
body = new_msg_vals.get('body_html', '') if new_msg_vals.get('content_subtype') == 'html' else new_msg_vals.get('body_text', '')
|
||||
|
||||
# get subscribers
|
||||
notif_user_ids = self.message_get_subscribers(cr, uid, thread_ids, context=context)
|
||||
|
||||
# add users requested via parsing message (@login)
|
||||
notif_user_ids += self.message_parse_users(cr, uid, body, context=context)
|
||||
subscr_obj = self.pool.get('mail.followers')
|
||||
subscr_ids = subscr_obj.search(cr, uid, ['&', ('res_model', '=', self._name), ('res_id', 'in', thread_ids)], context=context)
|
||||
notif_user_ids = [sub['user_id'][0] for sub in subscr_obj.read(cr, uid, subscr_ids, ['user_id'], context=context)]
|
||||
|
||||
# add users requested to perform an action (need_action mechanism)
|
||||
if hasattr(self, 'get_needaction_user_ids') and self._columns.get('user_id'):
|
||||
|
@ -210,17 +323,6 @@ class mail_thread(osv.Model):
|
|||
notif_user_ids = list(set(notif_user_ids))
|
||||
return notif_user_ids
|
||||
|
||||
def message_parse_users(self, cr, uid, string, context=None):
|
||||
"""Parse message content
|
||||
- if find @login -(^|\s)@((\w|@|\.)*)-: returns the related ids
|
||||
this supports login that are emails (such as @raoul@grobedon.net)
|
||||
"""
|
||||
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)
|
||||
return user_ids
|
||||
|
||||
#------------------------------------------------------
|
||||
# Generic message api
|
||||
#------------------------------------------------------
|
||||
|
@ -903,70 +1005,41 @@ class mail_thread(osv.Model):
|
|||
# Subscription mechanism
|
||||
#------------------------------------------------------
|
||||
|
||||
def message_get_subscribers(self, cr, uid, ids, context=None):
|
||||
""" Returns the current document followers. Basically this method
|
||||
checks in mail.subscription for entries with matching res_model,
|
||||
res_id.
|
||||
This method can be overriden to add implicit subscribers, such
|
||||
as project managers, by adding their user_id to the list of
|
||||
ids returned by this method.
|
||||
def message_get_monitored_follower_fields(self, cr, uid, ids, context=None):
|
||||
""" Returns a list of fields containing a res.user.id. Those fields
|
||||
will be checked to automatically subscribe those users.
|
||||
"""
|
||||
subscr_obj = self.pool.get('mail.subscription')
|
||||
subscr_ids = subscr_obj.search(cr, uid, ['&', ('res_model', '=', self._name), ('res_id', 'in', ids)], context=context)
|
||||
return [sub['user_id'][0] for sub in subscr_obj.read(cr, uid, subscr_ids, ['user_id'], context=context)]
|
||||
|
||||
def message_read_subscribers(self, cr, uid, ids, fields=['id', 'name', 'image_small'], context=None):
|
||||
""" Returns the current document followers as a read result. Used
|
||||
mainly for Chatter having only one method to call to have
|
||||
details about users.
|
||||
"""
|
||||
user_ids = self.message_get_subscribers(cr, uid, ids, context=context)
|
||||
return self.pool.get('res.users').read(cr, uid, user_ids, fields=fields, context=context)
|
||||
|
||||
def message_is_subscriber(self, cr, uid, ids, user_id = None, context=None):
|
||||
""" Check if uid or user_id (if set) is a subscriber to the current
|
||||
document.
|
||||
|
||||
:param user_id: if set, check is done on user_id; if not set
|
||||
check is done on uid
|
||||
"""
|
||||
sub_user_id = uid if user_id is None else user_id
|
||||
if sub_user_id in self.message_get_subscribers(cr, uid, ids, context=context):
|
||||
return True
|
||||
return False
|
||||
return []
|
||||
|
||||
def message_subscribe(self, cr, uid, ids, user_ids = None, context=None):
|
||||
""" Subscribe the user (or user_ids) to the current document.
|
||||
|
||||
:param user_ids: a list of user_ids; if not set, subscribe
|
||||
uid instead
|
||||
:param return: new value of followers, for Chatter
|
||||
"""
|
||||
subscription_obj = self.pool.get('mail.subscription')
|
||||
to_subscribe_uids = [uid] if user_ids is None else user_ids
|
||||
create_ids = []
|
||||
for id in ids:
|
||||
already_subscribed_user_ids = self.message_get_subscribers(cr, uid, [id], context=context)
|
||||
for user_id in to_subscribe_uids:
|
||||
if user_id in already_subscribed_user_ids: continue
|
||||
create_ids.append(subscription_obj.create(cr, uid, {'res_model': self._name, 'res_id': id, 'user_id': user_id}, context=context))
|
||||
return create_ids
|
||||
write_res = self.write(cr, uid, ids, {'message_follower_ids': self.message_subscribe_get_command(cr, uid, to_subscribe_uids, context)}, context=context)
|
||||
return [follower.id for thread in self.browse(cr, uid, ids, context=context) for follower in thread.message_follower_ids]
|
||||
|
||||
def message_subscribe_get_command(self, cr, uid, follower_ids, context=None):
|
||||
""" Generate the many2many command to add followers. """
|
||||
return [(4, id) for id in follower_ids]
|
||||
|
||||
def message_unsubscribe(self, cr, uid, ids, user_ids = None, context=None):
|
||||
""" Unsubscribe the user (or user_ids) from the current document.
|
||||
|
||||
:param user_ids: a list of user_ids; if not set, subscribe
|
||||
uid instead
|
||||
:param return: new value of followers, for Chatter
|
||||
"""
|
||||
# Trying to unsubscribe somebody not in subscribers: returns False
|
||||
# if special management is needed; allows to know that an automatically
|
||||
# subscribed user tries to unsubscribe and allows to warn him
|
||||
to_unsubscribe_uids = [uid] if user_ids is None else user_ids
|
||||
subscription_obj = self.pool.get('mail.subscription')
|
||||
to_delete_sub_ids = subscription_obj.search(cr, uid,
|
||||
['&', '&', ('res_model', '=', self._name), ('res_id', 'in', ids), ('user_id', 'in', to_unsubscribe_uids)], context=context)
|
||||
if not to_delete_sub_ids:
|
||||
return False
|
||||
return subscription_obj.unlink(cr, uid, to_delete_sub_ids, context=context)
|
||||
write_res = self.write(cr, uid, ids, {'message_follower_ids': self.message_unsubscribe_get_command(cr, uid, to_unsubscribe_uids, context)}, context=context)
|
||||
return [follower.id for thread in self.browse(cr, uid, ids, context=context) for follower in thread.message_follower_ids]
|
||||
|
||||
def message_unsubscribe_get_command(self, cr, uid, follower_ids, context=None):
|
||||
""" Generate the many2many command to remove followers. """
|
||||
return [(3, id) for id in follower_ids]
|
||||
|
||||
#------------------------------------------------------
|
||||
# Notification API
|
||||
|
@ -998,14 +1071,11 @@ class mail_thread(osv.Model):
|
|||
if user_to_notify_ids.count(new_msg_values.get('user_id')) > 0:
|
||||
user_to_notify_ids.remove(new_msg_values.get('user_id'))
|
||||
|
||||
# get user_ids directly asked
|
||||
user_to_push_from_parse_ids = self.message_parse_users(cr, uid, body, context=context)
|
||||
|
||||
# try to find an email_to
|
||||
email_to = ''
|
||||
for user in res_users_obj.browse(cr, uid, user_to_notify_ids, context=context):
|
||||
if not user.notification_email_pref == 'all' and \
|
||||
not (user.notification_email_pref == 'to_me' and user.id in user_to_push_from_parse_ids):
|
||||
# TO BE REFACTORED BY FP, JUSTE REMOVED TO_ME, NOT SURE WHAT S NEW BEHAVIOR
|
||||
if not user.notification_email_pref == 'all':
|
||||
continue
|
||||
if not user.email:
|
||||
continue
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"
|
||||
options='{"thread_level": 1}'/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</field>
|
||||
|
|
|
@ -159,10 +159,6 @@ class res_users(osv.Model):
|
|||
for user in self.browse(cr, uid, ids, context=context):
|
||||
return user.partner_id.message_read(fetch_ancestors, ancestor_ids, limit, offset, domain)
|
||||
|
||||
def message_read_subscribers(self, cr, uid, ids, fields=['id', 'name', 'image_small'], context=None):
|
||||
for user in self.browse(cr, uid, ids, context=context):
|
||||
return user.partner_id.message_read_subscribers(fields)
|
||||
|
||||
def message_search(self, cr, uid, ids, fetch_ancestors=False, ancestor_ids=None,
|
||||
limit=100, offset=0, domain=None, count=False, context=None):
|
||||
for user in self.browse(cr, uid, ids, context=context):
|
||||
|
|
|
@ -2,7 +2,7 @@ id,name,model_id:id,group_id:id,perm_read,perm_write,perm_create,perm_unlink
|
|||
access_mail_message_all,mail.message.all,model_mail_message,,1,0,0,0
|
||||
access_mail_message_group_user,mail.message.group.user,model_mail_message,base.group_user,1,1,1,1
|
||||
access_mail_thread,mail.thread,model_mail_thread,base.group_user,1,1,1,0
|
||||
access_mail_subscription_all,mail.subscription.all,model_mail_subscription,,1,1,1,1
|
||||
access_mail_followers_all,mail.followers.all,model_mail_followers,,1,1,1,1
|
||||
access_mail_notification_all,mail.notification.all,model_mail_notification,,1,1,1,1
|
||||
access_mail_group,mail.group,model_mail_group,base.group_user,1,1,1,1
|
||||
access_mail_alias_user,mail.alias,model_mail_alias,base.group_user,1,1,1,0
|
||||
|
|
|
|
@ -21,7 +21,7 @@
|
|||
<field name="name">Mail.group: access only public and joined groups</field>
|
||||
<field name="model_id" ref="model_mail_group"/>
|
||||
<!-- This rule has to be improved for employee only groups -->
|
||||
<field name="domain_force">['|', '|', ('public', '=', 'public'), ('member_ids', 'in', [user.id]), '&', ('public','=','groups'), ('group_public_id','in', [x.id for x in user.groups_id])]</field>
|
||||
<field name="domain_force">['|', '|', ('public', '=', 'public'), ('message_follower_ids', 'in', [user.id]), '&', ('public','=','groups'), ('group_public_id','in', [x.id for x in user.groups_id])]</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
|
|
|
@ -89,10 +89,14 @@
|
|||
/* RecordThread
|
||||
/* ------------------------------------------------------------ */
|
||||
|
||||
.openerp div.oe_mail_recthread {
|
||||
.openerp .oe_form div.oe_chatter {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.openerp div.oe_mail_recthread {
|
||||
/*overflow: auto;*/
|
||||
}
|
||||
|
||||
.openerp div.oe_mail_recthread_main {
|
||||
float: left;
|
||||
width: 560px;
|
||||
|
|
|
@ -4,6 +4,8 @@ openerp.mail = function(session) {
|
|||
|
||||
var mail = session.mail = {};
|
||||
|
||||
openerp_mail_followers(session, mail); // import mail_followers.js
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------
|
||||
* FormView
|
||||
|
@ -838,32 +840,17 @@ openerp.mail = function(session) {
|
|||
this._super.apply(this, arguments);
|
||||
this.params = this.get_definition_options();
|
||||
this.params.thread_level = this.params.thread_level || 0;
|
||||
this.params.see_subscribers = true;
|
||||
this.params.see_subscribers_options = this.params.see_subscribers_options || false;
|
||||
this.thread = null;
|
||||
this.ds = new session.web.DataSet(this, this.view.model);
|
||||
this.ds_users = new session.web.DataSet(this, 'res.users');
|
||||
},
|
||||
|
||||
start: function() {
|
||||
var self = this;
|
||||
|
||||
// NB: all the widget should be modified to check the actual_mode property on view, not use
|
||||
// any other method to know if the view is in create mode anymore
|
||||
this.view.on("change:actual_mode", this, this._check_visibility);
|
||||
this._check_visibility();
|
||||
|
||||
mail.ChatterUtils.bind_events(this);
|
||||
this.$element.find('button.oe_mail_button_followers').click(function () { self.do_toggle_followers(); });
|
||||
if (! this.params.see_subscribers_options) {
|
||||
this.$element.find('button.oe_mail_button_followers').hide(); }
|
||||
this.$element.find('button.oe_mail_button_follow').click(function () { self.do_follow(); })
|
||||
.mouseover(function () { $(this).html('Follow').removeClass('oe_mail_button_mouseout').addClass('oe_mail_button_mouseover'); })
|
||||
.mouseleave(function () { $(this).html('Not following').removeClass('oe_mail_button_mouseover').addClass('oe_mail_button_mouseout'); });
|
||||
this.$element.find('button.oe_mail_button_unfollow').click(function () { self.do_unfollow(); })
|
||||
.mouseover(function () { $(this).html('Unfollow').removeClass('oe_mail_button_mouseout').addClass('oe_mail_button_mouseover'); })
|
||||
.mouseleave(function () { $(this).html('Following').removeClass('oe_mail_button_mouseover').addClass('oe_mail_button_mouseout'); });
|
||||
this.reinit();
|
||||
},
|
||||
|
||||
_check_visibility: function() {
|
||||
|
@ -874,72 +861,20 @@ openerp.mail = function(session) {
|
|||
this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
reinit: function() {
|
||||
this.params.see_subscribers = true;
|
||||
this.params.see_subscribers_options = this.params.see_subscribers_options || false;
|
||||
this.$element.find('button.oe_mail_button_followers').html('Hide followers')
|
||||
this.$element.find('button.oe_mail_button_follow').hide();
|
||||
this.$element.find('button.oe_mail_button_unfollow').hide();
|
||||
},
|
||||
|
||||
set_value: function() {
|
||||
this._super.apply(this, arguments);
|
||||
var self = this;
|
||||
this.reinit();
|
||||
if (! this.view.datarecord.id ||
|
||||
session.web.BufferedDataSet.virtual_id_regex.test(this.view.datarecord.id)) {
|
||||
this.$element.find('.oe_mail_thread').hide();
|
||||
return;
|
||||
}
|
||||
// fetch followers
|
||||
var fetch_sub_done = this.fetch_subscribers();
|
||||
// create and render Thread widget
|
||||
this.$element.find('div.oe_mail_recthread_main').empty();
|
||||
if (this.thread) this.thread.destroy();
|
||||
this.thread = new mail.Thread(this, {'res_model': this.view.model, 'res_id': this.view.datarecord.id, 'uid': this.session.uid,
|
||||
'thread_level': this.params.thread_level, 'show_post_comment': true, 'limit': 15});
|
||||
var thread_done = this.thread.appendTo(this.$element.find('div.oe_mail_recthread_main'));
|
||||
return fetch_sub_done && thread_done;
|
||||
},
|
||||
|
||||
fetch_subscribers: function () {
|
||||
return this.ds.call('message_read_subscribers', [[this.view.datarecord.id]]).then(this.proxy('display_subscribers'));
|
||||
},
|
||||
|
||||
display_subscribers: function (records) {
|
||||
var self = this;
|
||||
this.is_subscriber = false;
|
||||
var user_list = this.$element.find('ul.oe_mail_followers_display').empty();
|
||||
this.$element.find('div.oe_mail_recthread_followers h4').html('Followers (' + records.length + ')');
|
||||
_(records).each(function (record) {
|
||||
if (record.id == self.session.uid) { self.is_subscriber = true; }
|
||||
record.avatar_url = mail.ChatterUtils.get_image(self.session.prefix, self.session.session_id, 'res.users', 'image_small', record.id);
|
||||
$(session.web.qweb.render('mail.record_thread.subscriber', {'record': record})).appendTo(user_list);
|
||||
});
|
||||
if (self.is_subscriber) {
|
||||
self.$element.find('button.oe_mail_button_follow').hide();
|
||||
self.$element.find('button.oe_mail_button_unfollow').show(); }
|
||||
else {
|
||||
self.$element.find('button.oe_mail_button_follow').show();
|
||||
self.$element.find('button.oe_mail_button_unfollow').hide(); }
|
||||
},
|
||||
|
||||
do_follow: function () {
|
||||
return this.ds.call('message_subscribe', [[this.view.datarecord.id]]).pipe(this.proxy('fetch_subscribers'));
|
||||
},
|
||||
|
||||
do_unfollow: function () {
|
||||
var self = this;
|
||||
return this.ds.call('message_unsubscribe', [[this.view.datarecord.id]]).then(function (record) {
|
||||
if (record == false) self.do_notify("Impossible to unsubscribe", "You are automatically subscribed to this record. You cannot unsubscribe.");
|
||||
}).pipe(this.proxy('fetch_subscribers'));
|
||||
},
|
||||
|
||||
do_toggle_followers: function () {
|
||||
this.params.see_subscribers = ! this.params.see_subscribers;
|
||||
if (this.params.see_subscribers) { this.$element.find('button.oe_mail_button_followers').html('Hide followers'); }
|
||||
else { this.$element.find('button.oe_mail_button_followers').html('Show followers'); }
|
||||
this.$element.find('div.oe_mail_recthread_followers').toggle();
|
||||
return thread_done;
|
||||
},
|
||||
});
|
||||
|
||||
|
@ -976,7 +911,6 @@ openerp.mail = function(session) {
|
|||
this.params.res_id = params.res_id || false;
|
||||
this.params.search_view_id = params.search_view_id || false;
|
||||
this.params.thread_level = params.thread_level || 1;
|
||||
this.params.title = params.title || false;
|
||||
this.comments_structure = {'root_ids': [], 'new_root_ids': [], 'msgs': {}, 'tree_struct': {}, 'model_to_root_ids': {}};
|
||||
this.display_show_more = true;
|
||||
this.thread_list = [];
|
||||
|
|
|
@ -0,0 +1,122 @@
|
|||
openerp_mail_followers = function(session, mail) {
|
||||
var _t = session.web._t,
|
||||
_lt = session.web._lt;
|
||||
|
||||
var mail_followers = session.mail_followers = {};
|
||||
|
||||
/**
|
||||
* ------------------------------------------------------------
|
||||
* mail_followers Widget
|
||||
* ------------------------------------------------------------
|
||||
*
|
||||
* This widget handles the display of a list of records as a vetical
|
||||
* list, with an image on the left. The widget itself is a floatting
|
||||
* right-sided box.
|
||||
* This widget is mainly used to display the followers of records
|
||||
* in OpenChatter.
|
||||
*/
|
||||
|
||||
/* Add the widget to registry */
|
||||
session.web.form.widgets.add('mail_followers', 'openerp.mail_followers.Followers');
|
||||
|
||||
mail_followers.Followers = session.web.form.AbstractField.extend({
|
||||
template: 'mail.followers',
|
||||
|
||||
init: function() {
|
||||
this._super.apply(this, arguments);
|
||||
this.params = {};
|
||||
this.params.image = this.node.attrs.image || 'image_small';
|
||||
this.params.title = this.node.attrs.title || 'Followers';
|
||||
this.params.display_followers = true;
|
||||
this.params.display_control = this.node.attrs.display_control || false;
|
||||
this.params.display_actions = this.node.attrs.display_actions || false;
|
||||
this.ds_model = new session.web.DataSetSearch(this, this.view.model);
|
||||
this.ds_follow = new session.web.DataSetSearch(this, this.field.relation);
|
||||
},
|
||||
|
||||
start: function() {
|
||||
var self = this;
|
||||
// NB: all the widget should be modified to check the actual_mode property on view, not use
|
||||
// any other method to know if the view is in create mode anymore
|
||||
this.view.on("change:actual_mode", this, this._check_visibility);
|
||||
this._check_visibility();
|
||||
this.$element.find('button.oe_mail_button_followers').click(function () { self.do_toggle_followers(); });
|
||||
if (! this.params.display_control) {
|
||||
this.$element.find('button.oe_mail_button_followers').hide(); }
|
||||
this.$element.find('button.oe_mail_button_follow').click(function () { self.do_follow(); })
|
||||
.mouseover(function () { $(this).html('Follow').removeClass('oe_mail_button_mouseout').addClass('oe_mail_button_mouseover'); })
|
||||
.mouseleave(function () { $(this).html('Not following').removeClass('oe_mail_button_mouseover').addClass('oe_mail_button_mouseout'); });
|
||||
this.$element.find('button.oe_mail_button_unfollow').click(function () { self.do_unfollow(); })
|
||||
.mouseover(function () { $(this).html('Unfollow').removeClass('oe_mail_button_mouseout').addClass('oe_mail_button_mouseover'); })
|
||||
.mouseleave(function () { $(this).html('Following').removeClass('oe_mail_button_mouseover').addClass('oe_mail_button_mouseout'); });
|
||||
this.reinit();
|
||||
},
|
||||
|
||||
_check_visibility: function() {
|
||||
this.$element.toggle(this.view.get("actual_mode") !== "create");
|
||||
},
|
||||
|
||||
destroy: function () {
|
||||
this._super.apply(this, arguments);
|
||||
},
|
||||
|
||||
reinit: function() {
|
||||
this.params.display_followers = true;
|
||||
this.params.display_control = this.node.attrs.display_control || false;
|
||||
this.params.display_actions = this.node.attrs.display_actions || false;
|
||||
this.$element.find('button.oe_mail_button_followers').html('Hide followers')
|
||||
this.$element.find('button.oe_mail_button_follow').hide();
|
||||
this.$element.find('button.oe_mail_button_unfollow').hide();
|
||||
},
|
||||
|
||||
set_value: function(value_) {
|
||||
this.reinit();
|
||||
if (! this.view.datarecord.id ||
|
||||
session.web.BufferedDataSet.virtual_id_regex.test(this.view.datarecord.id)) {
|
||||
this.$element.find('div.oe_mail_recthread_aside').hide();
|
||||
return;
|
||||
}
|
||||
return this.fetch_subscribers(value_);
|
||||
},
|
||||
|
||||
fetch_subscribers: function (value_) {
|
||||
return this.ds_follow.call('read', [value_ || this.get_value(), ['name', this.params.image]]).then(this.proxy('display_subscribers'));
|
||||
},
|
||||
|
||||
/**
|
||||
* Display the followers.
|
||||
* TODO: replace the is_subscriber check by fields read */
|
||||
display_subscribers: function (records) {
|
||||
var self = this;
|
||||
this.is_subscriber = false;
|
||||
var user_list = this.$element.find('ul.oe_mail_followers_display').empty();
|
||||
this.$element.find('div.oe_mail_recthread_followers h4').html(this.params.title + ' (' + records.length + ')');
|
||||
_(records).each(function (record) {
|
||||
if (record.id == self.session.uid) { self.is_subscriber = true; }
|
||||
record.avatar_url = mail.ChatterUtils.get_image(self.session.prefix, self.session.session_id, 'res.users', 'image_small', record.id);
|
||||
$(session.web.qweb.render('mail.followers.partner', {'record': record})).appendTo(user_list);
|
||||
});
|
||||
if (this.is_subscriber) {
|
||||
this.$element.find('button.oe_mail_button_follow').hide();
|
||||
this.$element.find('button.oe_mail_button_unfollow').show(); }
|
||||
else {
|
||||
this.$element.find('button.oe_mail_button_follow').show();
|
||||
this.$element.find('button.oe_mail_button_unfollow').hide(); }
|
||||
},
|
||||
|
||||
do_follow: function () {
|
||||
return this.ds_model.call('message_subscribe', [[this.view.datarecord.id]]).pipe(this.proxy('set_value'));
|
||||
},
|
||||
|
||||
do_unfollow: function () {
|
||||
return this.ds_model.call('message_unsubscribe', [[this.view.datarecord.id]]).pipe(this.proxy('set_value'));
|
||||
},
|
||||
|
||||
do_toggle_followers: function () {
|
||||
this.params.see_subscribers = ! this.params.see_subscribers;
|
||||
if (this.params.see_subscribers) { this.$element.find('button.oe_mail_button_followers').html('Hide followers'); }
|
||||
else { this.$element.find('button.oe_mail_button_followers').html('Show followers'); }
|
||||
this.$element.find('div.oe_mail_recthread_followers').toggle();
|
||||
},
|
||||
});
|
||||
};
|
|
@ -61,28 +61,8 @@
|
|||
<div class="oe_mail_recthread_main">
|
||||
<!-- contains the document thread -->
|
||||
</div>
|
||||
<div class="oe_mail_recthread_aside">
|
||||
<div class="oe_mail_recthread_actions">
|
||||
<button type="button" class="oe_mail_button_follow oe_mail_button_mouseout">Not following</button>
|
||||
<button type="button" class="oe_mail_button_unfollow oe_mail_button_mouseout">Following</button>
|
||||
<button type="button" class="oe_mail_button_followers">Show followers</button>
|
||||
</div>
|
||||
<div class="oe_mail_recthread_followers">
|
||||
<h4>Followers</h4>
|
||||
<ul class="oe_mail_followers_display"></ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
record_thread.subscriber template
|
||||
Template used to display a subscriber.
|
||||
-->
|
||||
<li t-name="mail.record_thread.subscriber">
|
||||
<img class="oe_mail_thumbnail oe_mail_frame" t-attf-src="{record.avatar_url}"/>
|
||||
<a t-attf-href="#model=res.users&id=#{record.id}"><t t-raw="record.name"/></a>
|
||||
</li>
|
||||
|
||||
<!--
|
||||
mail.compose_message template
|
||||
This template holds the composition form to write a note or send
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<template>
|
||||
|
||||
<!--
|
||||
followers main template
|
||||
Template used to display the followers and the actions in a record.
|
||||
-->
|
||||
<div t-name="mail.followers" class="oe_mail_recthread_aside">
|
||||
<div class="oe_mail_recthread_actions">
|
||||
<button type="button" class="oe_mail_button_follow oe_mail_button_mouseout">Not following</button>
|
||||
<button type="button" class="oe_mail_button_unfollow oe_mail_button_mouseout">Following</button>
|
||||
<button type="button" class="oe_mail_button_followers">Show followers</button>
|
||||
</div>
|
||||
<div class="oe_mail_recthread_followers">
|
||||
<t t-if="widget.params.title">
|
||||
<h4><t t-raw="widget.params.title"/></h4>
|
||||
</t>
|
||||
<ul class="oe_mail_followers_display"></ul>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!--
|
||||
followers.partner template
|
||||
Template used to display a partner following the record
|
||||
-->
|
||||
<li t-name="mail.followers.partner">
|
||||
<img class="oe_mail_thumbnail oe_mail_frame" t-attf-src="{record.avatar_url}"/>
|
||||
<a t-attf-href="#model=res.users&id=#{record.id}"><t t-raw="record.name"/></a>
|
||||
</li>
|
||||
|
||||
</template>
|
|
@ -1046,13 +1046,10 @@ class mrp_production(osv.osv):
|
|||
# OpenChatter methods and notifications
|
||||
# ---------------------------------------------------
|
||||
|
||||
def message_get_subscribers(self, cr, uid, ids, context=None):
|
||||
""" Override to add responsible user. """
|
||||
user_ids = super(mrp_production, self).message_get_subscribers(cr, uid, ids, context=context)
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
if obj.user_id and not obj.user_id.id in user_ids:
|
||||
user_ids.append(obj.user_id.id)
|
||||
return user_ids
|
||||
def message_get_monitored_follower_fields(self, cr, uid, ids, context=None):
|
||||
""" Add 'user_id' to the monitored fields """
|
||||
res = super(mrp_production, self).message_get_monitored_follower_fields(cr, uid, ids, context=context)
|
||||
return res + ['user_id']
|
||||
|
||||
def create_send_note(self, cr, uid, ids, context=None):
|
||||
self.message_append_note(cr, uid, ids, body=_("Manufacturing order has been <b>created</b>."), context=context)
|
||||
|
|
|
@ -818,6 +818,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -108,6 +108,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -190,6 +190,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -6,7 +6,7 @@ access_widget_manager,access.portal.widget.manager,model_res_portal_widget,group
|
|||
access_mail_message,mail.message,mail.model_mail_message,group_portal_member,1,0,1,1
|
||||
access_mail_message_all,mail.message.all,mail.model_mail_message,group_portal_member,1,0,0,0
|
||||
access_mail_thread,mail.thread,mail.model_mail_thread,group_portal_member,1,0,0,0
|
||||
access_mail_subscription,mail.subscription,mail.model_mail_subscription,group_portal_member,1,0,1,1
|
||||
access_mail_followers,mail.followers,mail.model_mail_followers,group_portal_member,1,0,1,1
|
||||
access_mail_notification,mail.notification,mail.model_mail_notification,group_portal_member,1,0,1,0
|
||||
access_mail_group,mail.group,mail.model_mail_group,group_portal_member,1,0,0,0
|
||||
access_mail_alias,mail.alias,mail.model_mail_alias,group_portal_member,1,0,0,0
|
||||
|
|
|
|
@ -104,6 +104,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -176,6 +176,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -514,13 +514,10 @@ def Project():
|
|||
# OpenChatter methods and notifications
|
||||
# ------------------------------------------------
|
||||
|
||||
def message_get_subscribers(self, cr, uid, ids, context=None):
|
||||
""" Override to add responsible user. """
|
||||
user_ids = super(project, self).message_get_subscribers(cr, uid, ids, context=context)
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
if obj.user_id and not obj.user_id.id in user_ids:
|
||||
user_ids.append(obj.user_id.id)
|
||||
return user_ids
|
||||
def message_get_monitored_follower_fields(self, cr, uid, ids, context=None):
|
||||
""" Add 'user_id' to the monitored fields """
|
||||
res = super(project, self).message_get_monitored_follower_fields(cr, uid, ids, context=context)
|
||||
return res + ['user_id']
|
||||
|
||||
def create(self, cr, uid, vals, context=None):
|
||||
if context is None: context = {}
|
||||
|
@ -1204,15 +1201,10 @@ class task(base_stage, osv.osv):
|
|||
result[obj.id].append(obj.user_id.id)
|
||||
return result
|
||||
|
||||
def message_get_subscribers(self, cr, uid, ids, context=None):
|
||||
""" Override to add responsible user and project manager. """
|
||||
user_ids = super(task, self).message_get_subscribers(cr, uid, ids, context=context)
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
if obj.user_id and not obj.user_id.id in user_ids:
|
||||
user_ids.append(obj.user_id.id)
|
||||
if obj.manager_id and not obj.manager_id.id in user_ids:
|
||||
user_ids.append(obj.manager_id.id)
|
||||
return user_ids
|
||||
def message_get_monitored_follower_fields(self, cr, uid, ids, context=None):
|
||||
""" Add 'user_id' and 'manager_id' to the monitored fields """
|
||||
res = super(task, self).message_get_monitored_follower_fields(cr, uid, ids, context=context)
|
||||
return res + ['user_id', 'manager_id']
|
||||
|
||||
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
|
||||
""" Override of the (void) default notification method. """
|
||||
|
|
|
@ -148,6 +148,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
@ -481,6 +482,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -499,13 +499,10 @@ class project_issue(base_stage, osv.osv):
|
|||
# OpenChatter methods and notifications
|
||||
# -------------------------------------------------------
|
||||
|
||||
def message_get_subscribers(self, cr, uid, ids, context=None):
|
||||
""" Override to add responsible user. """
|
||||
user_ids = super(project_issue, self).message_get_subscribers(cr, uid, ids, context=context)
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
if obj.user_id and not obj.user_id.id in user_ids:
|
||||
user_ids.append(obj.user_id.id)
|
||||
return user_ids
|
||||
def message_get_monitored_follower_fields(self, cr, uid, ids, context=None):
|
||||
""" Add 'user_id' to the monitored fields """
|
||||
res = super(project_issue, self).message_get_monitored_follower_fields(cr, uid, ids, context=context)
|
||||
return res + ['user_id']
|
||||
|
||||
def stage_set_send_note(self, cr, uid, ids, stage_id, context=None):
|
||||
""" Override of the (void) default notification method. """
|
||||
|
|
|
@ -160,6 +160,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -738,12 +738,16 @@ class purchase_order(osv.osv):
|
|||
result[obj.id].append(obj.validator.id)
|
||||
return result
|
||||
|
||||
def message_get_monitored_follower_fields(self, cr, uid, ids, context=None):
|
||||
""" Add 'validator' to the monitored fields """
|
||||
res = super(purchase_order, self).message_get_monitored_follower_fields(cr, uid, ids, context=context)
|
||||
return res + ['validator']
|
||||
|
||||
def create_send_note(self, cr, uid, ids, context=None):
|
||||
return self.message_append_note(cr, uid, ids, body=_("Request for quotation <b>created</b>."), context=context)
|
||||
|
||||
def confirm_send_note(self, cr, uid, ids, context=None):
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
self.message_subscribe(cr, uid, [obj.id], [obj.validator.id], context=context)
|
||||
self.message_append_note(cr, uid, [obj.id], body=_("Quotation for <em>%s</em> <b>converted</b> to a Purchase Order of %s %s.") % (obj.partner_id.name, obj.amount_total, obj.pricelist_id.currency_id.symbol), context=context)
|
||||
|
||||
def shipment_send_note(self, cr, uid, ids, picking_id, context=None):
|
||||
|
|
|
@ -261,6 +261,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -103,6 +103,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -1031,7 +1031,6 @@ class sale_order(osv.osv):
|
|||
|
||||
def create_send_note(self, cr, uid, ids, context=None):
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
self.message_subscribe(cr, uid, [obj.id], [obj.user_id.id], context=context)
|
||||
self.message_append_note(cr, uid, [obj.id], body=_("Quotation for <em>%s</em> has been <b>created</b>.") % (obj.partner_id.name), context=context)
|
||||
|
||||
def confirm_send_note(self, cr, uid, ids, context=None):
|
||||
|
|
|
@ -351,6 +351,7 @@
|
|||
</sheet>
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" widget="mail_thread"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</form>
|
||||
</field>
|
||||
|
|
|
@ -1011,6 +1011,7 @@
|
|||
<xpath expr="/form/sheet" position="after">
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</data>
|
||||
|
@ -1133,6 +1134,7 @@
|
|||
<xpath expr="/form/sheet" position="after">
|
||||
<div class="oe_chatter">
|
||||
<field name="message_ids" colspan="4" widget="mail_thread" nolabel="1"/>
|
||||
<field name="message_follower_ids" widget="mail_followers"/>
|
||||
</div>
|
||||
</xpath>
|
||||
</data>
|
||||
|
|
Loading…
Reference in New Issue