[REF] mail: mail_thread: followers update
Followers can now be partners or channels. Partners following a document will receive needaction, as previously. However people can follow documents through channels. Members of a channel are able to listen to a stream of messages using the channel. Those messages do not create needaction messages. It is therefore possible to follow documents without receiving too much notifications. For interesting documents subscribing with its partner will create notification. message_follower_ids fields is udpated. It is now a many2many to mail.followers, not to res.partner anymore. A subscription can be either a partner (partner_id) or a channel (channel_id). Some access rules have been updated accordingly.
This commit is contained in:
@@ -30,5 +30,5 @@ class lead_test(osv.Model):
|
||||
def message_post(self, cr, uid, thread_id, body='', subject=None, message_type='notification', subtype=None, parent_id=False, attachments=None, context=None, **kwargs):
|
||||
pass
|
||||
|
||||
def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None):
|
||||
def message_subscribe(self, cr, uid, ids, partner_ids=None, channel_ids=None, subtype_ids=None, force=True, context=None):
|
||||
pass
|
||||
|
||||
@@ -1395,11 +1395,17 @@ class calendar_event(osv.Model):
|
||||
del context['default_date']
|
||||
return super(calendar_event, self).message_post(cr, uid, thread_id, context=context, **kwargs)
|
||||
|
||||
def message_subscribe(self, cr, uid, ids, partner_ids, subtype_ids=None, context=None):
|
||||
return super(calendar_event, self).message_subscribe(cr, uid, get_real_ids(ids), partner_ids, subtype_ids=subtype_ids, context=context)
|
||||
def message_subscribe(self, cr, uid, ids, partner_ids=None, channel_ids=None, subtype_ids=None, force=True, context=None):
|
||||
return super(calendar_event, self).message_subscribe(
|
||||
cr, uid, get_real_ids(ids),
|
||||
partner_ids=partner_ids,
|
||||
channel_ids=channel_ids,
|
||||
subtype_ids=subtype_ids,
|
||||
force=force,
|
||||
context=context)
|
||||
|
||||
def message_unsubscribe(self, cr, uid, ids, partner_ids, context=None):
|
||||
return super(calendar_event, self).message_unsubscribe(cr, uid, get_real_ids(ids), partner_ids, context=context)
|
||||
def message_unsubscribe(self, cr, uid, ids, partner_ids=None, channel_ids=None, context=None):
|
||||
return super(calendar_event, self).message_unsubscribe(cr, uid, get_real_ids(ids), partner_ids=partner_ids, channel_ids=channel_ids, context=context)
|
||||
|
||||
def do_sendmail(self, cr, uid, ids, context=None):
|
||||
for event in self.browse(cr, uid, ids, context):
|
||||
|
||||
@@ -240,8 +240,11 @@ class hr_evaluation(osv.Model):
|
||||
def write(self, cr, uid, ids, vals, context=None):
|
||||
if vals.get('employee_id'):
|
||||
employee_id = self.pool.get('hr.employee').browse(cr, uid, vals.get('employee_id'), context=context)
|
||||
# TDE FIXME: use add_command
|
||||
if employee_id.parent_id and employee_id.parent_id.user_id:
|
||||
vals['message_follower_ids'] = [(4, employee_id.parent_id.user_id.partner_id.id)]
|
||||
message_follower_ids = vals.get('message_follower_ids') or [] # webclient can send None or False
|
||||
message_follower_ids += self.env['mail.followers']._add_follower_command(self._name, ids, {employee_id.parent_id.user_id.partner_id.id: None}, {}, force=True)[0]
|
||||
vals['message_follower_ids'] = message_follower_ids
|
||||
if 'date' in vals:
|
||||
new_vals = {'deadline': vals.get('date')}
|
||||
obj_hr_eval_iterview = self.pool.get('hr.evaluation.interview')
|
||||
|
||||
@@ -48,12 +48,14 @@ class MailController(http.Controller):
|
||||
def read_followers(self, follower_ids):
|
||||
result = []
|
||||
is_editable = request.env.user.has_group('base.group_no_one')
|
||||
for follower in request.env['res.partner'].browse(follower_ids):
|
||||
for follower in request.env['mail.followers'].browse(follower_ids):
|
||||
result.append({
|
||||
'id': follower.id,
|
||||
'name': follower.name,
|
||||
'name': follower.partner_id.name or follower.channel_id.name,
|
||||
'res_model': 'res.partner' if follower.partner_id else 'mail.channel',
|
||||
'res_id': follower.partner_id.id or follower.channel_id.id,
|
||||
'is_editable': is_editable,
|
||||
'is_uid': request.env.user.partner_id == follower,
|
||||
'is_uid': request.env.user.partner_id == follower.partner_id,
|
||||
})
|
||||
return result
|
||||
|
||||
|
||||
@@ -7,23 +7,14 @@
|
||||
<field name="name">Best Sales Practices</field>
|
||||
<field name="description">Discussion about best sales practices and deals.</field>
|
||||
</record>
|
||||
<record model="mail.channel" id="channel_1">
|
||||
<field name="message_follower_ids" eval="[(6, 0, [ref('base.partner_demo')])]"/>
|
||||
</record>
|
||||
<record model="mail.channel" id="channel_2">
|
||||
<field name="name">Board meetings</field>
|
||||
<field name="description">Board meetings, budgets, strategic plans</field>
|
||||
</record>
|
||||
<record model="mail.channel" id="channel_2">
|
||||
<field name="message_follower_ids" eval="[(6, 0, [])]"/>
|
||||
</record>
|
||||
<record model="mail.channel" id="channel_3">
|
||||
<field name="name">R&D</field>
|
||||
<field name="description">Research and development discussion group</field>
|
||||
</record>
|
||||
<record model="mail.channel" id="channel_3">
|
||||
<field name="message_follower_ids" eval="[(6, 0, [])]"/>
|
||||
</record>
|
||||
|
||||
<!-- Best sales practices messages -->
|
||||
<record id="mail_message_channel_1_1" model="mail.message">
|
||||
|
||||
@@ -23,11 +23,87 @@ class Followers(models.Model):
|
||||
res_id = fields.Integer(
|
||||
'Related Document ID', select=1, help='Id of the followed resource')
|
||||
partner_id = fields.Many2one(
|
||||
'res.partner', string='Related Partner', ondelete='cascade', required=True, select=1)
|
||||
'res.partner', string='Related Partner', ondelete='cascade', select=1)
|
||||
channel_id = fields.Many2one(
|
||||
'mail.channel', string='Listener', ondelete='cascade', select=1)
|
||||
subtype_ids = fields.Many2many(
|
||||
'mail.message.subtype', string='Subtype',
|
||||
help="Message subtypes followed, meaning subtypes that will be pushed onto the user's Wall.")
|
||||
|
||||
@api.model
|
||||
def _add_follower_command(self, res_model, res_ids, partner_data, channel_data, force=True):
|
||||
""" Please upate me
|
||||
:param force: if True, delete existing followers before creating new one
|
||||
using the subtypes given in the parameters
|
||||
"""
|
||||
force_mode = force or (all(data for data in partner_data.values()) and all(data for data in channel_data.values()))
|
||||
generic = []
|
||||
specific = {}
|
||||
existing = {} # {res_id: follower_ids}
|
||||
p_exist = {} # {partner_id: res_ids}
|
||||
c_exist = {} # {channel_id: res_ids}
|
||||
|
||||
followers = self.sudo().search([
|
||||
'&',
|
||||
'&', ('res_model', '=', res_model), ('res_id', 'in', res_ids),
|
||||
'|', ('partner_id', 'in', partner_data.keys()), ('channel_id', 'in', channel_data.keys())])
|
||||
|
||||
if force_mode:
|
||||
followers.unlink()
|
||||
else:
|
||||
for follower in followers:
|
||||
existing.setdefault(follower.res_id, list()).append(follower)
|
||||
if follower.partner_id:
|
||||
p_exist.setdefault(follower.partner_id.id, list()).append(follower.res_id)
|
||||
if follower.channel_id:
|
||||
c_exist.setdefault(follower.channel_id.id, list()).append(follower.res_id)
|
||||
|
||||
default_subtypes = self.env['mail.message.subtype'].search([
|
||||
('default', '=', True),
|
||||
'|', ('res_model', '=', res_model), ('res_model', '=', False)])
|
||||
|
||||
if force_mode:
|
||||
for pid, data in partner_data.iteritems():
|
||||
if not data:
|
||||
partner_data[pid] = default_subtypes.ids
|
||||
for cid, data in channel_data.iteritems():
|
||||
if not data:
|
||||
channel_data[cid] = default_subtypes.ids
|
||||
|
||||
# create new followers, batch ok
|
||||
gen_new_pids = [pid for pid in partner_data.keys() if pid not in p_exist]
|
||||
gen_new_cids = [cid for cid in channel_data.keys() if cid not in c_exist]
|
||||
for pid in gen_new_pids:
|
||||
generic.append([0, 0, {'res_model': res_model, 'partner_id': pid, 'subtype_ids': [(6, 0, partner_data.get(pid) or default_subtypes.ids)]}])
|
||||
for cid in gen_new_cids:
|
||||
generic.append([0, 0, {'res_model': res_model, 'channel_id': cid, 'subtype_ids': [(6, 0, channel_data.get(cid) or default_subtypes.ids)]}])
|
||||
|
||||
# create new followers, each document at a time because of existing followers to avoid erasing
|
||||
if not force_mode:
|
||||
for res_id in res_ids:
|
||||
command = []
|
||||
doc_followers = existing.get(res_id, list())
|
||||
|
||||
new_pids = set(partner_data.keys()) - set([sub.partner_id.id for sub in doc_followers if sub.partner_id]) - set(gen_new_pids)
|
||||
new_cids = set(channel_data.keys()) - set([sub.channel_id.id for sub in doc_followers if sub.channel_id]) - set(gen_new_cids)
|
||||
|
||||
# subscribe new followers
|
||||
for new_pid in new_pids:
|
||||
command.append((0, 0, {
|
||||
'res_model': res_model,
|
||||
'partner_id': new_pid,
|
||||
'subtype_ids': [(6, 0, partner_data.get(new_pid) or default_subtypes.ids)],
|
||||
}))
|
||||
for new_cid in new_cids:
|
||||
command.append((0, 0, {
|
||||
'res_model': res_model,
|
||||
'channel_id': new_cid,
|
||||
'subtype_ids': [(6, 0, channel_data.get(new_cid) or default_subtypes.ids)],
|
||||
}))
|
||||
if command:
|
||||
specific[res_id] = command
|
||||
return generic, specific
|
||||
|
||||
#
|
||||
# Modifying followers change access rights to individual documents. As the
|
||||
# cache may contain accessible/inaccessible data, one has to refresh it.
|
||||
@@ -50,7 +126,10 @@ class Followers(models.Model):
|
||||
self.invalidate_cache()
|
||||
return res
|
||||
|
||||
_sql_constraints = [('mail_followers_res_partner_res_model_id_uniq', 'unique(res_model,res_id,partner_id)', 'Error, a partner cannot follow twice the same object.')]
|
||||
_sql_constraints = [
|
||||
('mail_followers_res_partner_res_model_id_uniq', 'unique(res_model,res_id,partner_id)', 'Error, a partner cannot follow twice the same object.'),
|
||||
('mail_followers_res_channel_res_model_id_uniq', 'unique(res_model,res_id,channel_id)', 'Error, a channel cannot follow twice the same object.'),
|
||||
]
|
||||
|
||||
|
||||
class Notification(models.Model):
|
||||
|
||||
@@ -66,11 +66,16 @@ class MailThread(models.AbstractModel):
|
||||
_mail_post_access = 'write' # access required on the document to post on it
|
||||
_mail_mass_mailing = False # enable mass mailing on this model
|
||||
|
||||
message_is_follower = fields.Boolean('Is Follower', compute='_get_followers', search='_search_is_follower')
|
||||
message_follower_ids = fields.Many2many(
|
||||
comodel_name='res.partner', string='Followers',
|
||||
inverse='_set_followers',
|
||||
compute='_get_followers', search='_search_followers', type='many2many')
|
||||
message_is_follower = fields.Boolean('Is Follower', compute='_compute_is_follower')
|
||||
message_follower_ids = fields.One2many(
|
||||
'mail.followers', 'res_id', string='Followers',
|
||||
domain=lambda self: [('res_model', '=', self._name)])
|
||||
message_partner_ids = fields.Many2many(
|
||||
comodel_name='res.partner', string='Followers (Partners)',
|
||||
compute='_get_followers', search='_search_follower_partners')
|
||||
message_channel_ids = fields.Many2many(
|
||||
comodel_name='mail.channel', string='Followers (Channels)',
|
||||
compute='_get_followers', search='_search_follower_channels')
|
||||
message_ids = fields.One2many(
|
||||
'mail.message', 'res_id', string='Messages',
|
||||
domain=lambda self: [('model', '=', self._name)], auto_join=True,
|
||||
@@ -83,72 +88,45 @@ class MailThread(models.AbstractModel):
|
||||
'Unread Messages', compute='_get_message_unread',
|
||||
help="Number of unread messages")
|
||||
|
||||
@api.multi
|
||||
@api.one
|
||||
@api.depends('message_follower_ids')
|
||||
def _get_followers(self):
|
||||
res = dict.fromkeys(self.ids, self.env['res.partner'])
|
||||
followers = self.env['mail.followers'].sudo().search([('res_model', '=', self._name), ('res_id', 'in', self.ids)])
|
||||
for follower in followers:
|
||||
res[follower.res_id] |= follower.partner_id
|
||||
for record in self:
|
||||
if not record.id:
|
||||
continue
|
||||
record.message_follower_ids = res[record.id]
|
||||
record.message_is_follower = self.env.user.partner_id in record.message_follower_ids
|
||||
|
||||
@api.multi
|
||||
def _set_followers(self):
|
||||
# read the old set of followers, and determine the new set of followers
|
||||
old = self.env['mail.followers'].sudo().search([('res_model', '=', self._name), ('res_id', 'in', self.ids)]).mapped('partner_id')
|
||||
new = self.env['res.partner']
|
||||
Partner = self.env['res.partner']
|
||||
|
||||
old_style_commands = self._fields['message_follower_ids'].convert_to_write(self.message_follower_ids)
|
||||
for command in old_style_commands:
|
||||
if command[0] == 0:
|
||||
new |= Partner.create(command[2])
|
||||
elif command[0] == 1:
|
||||
partner = Partner.browse(command[1])
|
||||
partner.write(command[2])
|
||||
new |= partner
|
||||
elif command[0] == 2:
|
||||
partner = Partner.browse(command[1])
|
||||
new -= partner
|
||||
partner.unlink()
|
||||
elif command[0] == 3:
|
||||
new -= Partner.browse(command[1])
|
||||
elif command[0] == 4:
|
||||
new |= Partner.browse(command[1])
|
||||
elif command[0] == 5:
|
||||
new = self.env['res.partner']
|
||||
elif command[0] == 6:
|
||||
new = self.env['res.partner'].browse(command[2])
|
||||
|
||||
# remove partners that are no longer followers
|
||||
self.message_unsubscribe((old-new).ids)
|
||||
# add new followers
|
||||
self.message_subscribe((new-old).ids)
|
||||
self.message_partner_ids = self.message_follower_ids.mapped('partner_id')
|
||||
self.message_channel_ids = self.message_follower_ids.mapped('channel_id')
|
||||
|
||||
@api.model
|
||||
def _search_followers(self, operator, operand):
|
||||
def _search_follower_partners(self, operator, operand):
|
||||
"""Search function for message_follower_ids
|
||||
|
||||
Do not use with operator 'not in'. Use instead message_is_followers
|
||||
"""
|
||||
# TOFIX make it work with not in
|
||||
assert operator != "not in", "Do not search message_follower_ids with 'not in'"
|
||||
followers = self.env['mail.followers'].sudo().search([('res_model', '=', self._name), ('partner_id', operator, operand)])
|
||||
followers = self.env['mail.followers'].sudo().search([
|
||||
('res_model', '=', self._name),
|
||||
('partner_id', operator, operand)])
|
||||
return [('id', 'in', followers.mapped('res_id'))]
|
||||
|
||||
@api.model
|
||||
def _search_is_follower(self, operator, operand):
|
||||
"""Search function for message_is_follower"""
|
||||
user_pid = self.env.user.partner_id.id
|
||||
if (operator == '=' and operand) or (operator == '!=' and not operand): # is a follower
|
||||
followers = self.env['mail.followers'].sudo().search([('res_model', '=', self._name), ('partner_id', '=', user_pid)])
|
||||
return [('id', 'in', followers.mapped('res_id'))]
|
||||
else: # is not a follower or unknown domain
|
||||
followers = self.env['mail.followers'].sudo().search([('res_model', '=', self._name), ('partner_id', '=', user_pid)])
|
||||
return [('id', 'not in', followers.mapped('res_id'))]
|
||||
def _search_follower_channels(self, operator, operand):
|
||||
"""Search function for message_follower_ids
|
||||
|
||||
Do not use with operator 'not in'. Use instead message_is_followers
|
||||
"""
|
||||
followers = self.env['mail.followers'].sudo().search([
|
||||
('res_model', '=', self._name),
|
||||
('channel_id', operator, operand)])
|
||||
return [('id', 'in', followers.mapped('res_id'))]
|
||||
|
||||
@api.multi
|
||||
@api.depends('message_follower_ids')
|
||||
def _compute_is_follower(self):
|
||||
followers = self.env['mail.followers'].sudo().search([
|
||||
('res_model', '=', self._name),
|
||||
('res_id', 'in', self.ids),
|
||||
('partner_id', '=', self.env.user.partner_id.id),
|
||||
])
|
||||
following_ids = followers.mapped('res_id')
|
||||
for record in self:
|
||||
record.message_is_follower = record.id in following_ids
|
||||
|
||||
@api.multi
|
||||
def _get_message_unread(self):
|
||||
@@ -188,7 +166,7 @@ class MailThread(models.AbstractModel):
|
||||
# subscribe uid unless asked not to
|
||||
if not self._context.get('mail_create_nosubscribe'):
|
||||
message_follower_ids = values.get('message_follower_ids') or [] # webclient can send None or False
|
||||
message_follower_ids.append([4, self.env.user.partner_id.id])
|
||||
message_follower_ids += self.env['mail.followers']._add_follower_command(self._name, [], {self.env.user.partner_id.id: None}, {}, force=True)[0]
|
||||
values['message_follower_ids'] = message_follower_ids
|
||||
thread = super(MailThread, self).create(values)
|
||||
|
||||
@@ -765,7 +743,7 @@ class MailThread(models.AbstractModel):
|
||||
obj = record_set[0]
|
||||
else:
|
||||
obj = self.env[alias.alias_parent_model_id.model].browse(alias.alias_parent_thread_id)
|
||||
if not author_id or author_id not in [fol.id for fol in obj.message_follower_ids]:
|
||||
if not author_id or author_id not in [fol.id for fol in obj.message_partner_ids]:
|
||||
_warn('alias %s restricted to internal followers, skipping' % alias.alias_name)
|
||||
_create_bounce_email()
|
||||
return False
|
||||
@@ -1296,7 +1274,7 @@ class MailThread(models.AbstractModel):
|
||||
partner = self.env['res.partner'].sudo().browse([partner_info['partner_id']])[0]
|
||||
if email and email in [val[1] for val in result[self.ids[0]]]: # already existing email -> skip
|
||||
return result
|
||||
if partner and partner in self.message_follower_ids: # recipient already in the followers -> skip
|
||||
if partner and partner in self.message_partner_ids: # recipient already in the followers -> skip
|
||||
return result
|
||||
if partner and partner.id in [val[0] for val in result[self.ids[0]]]: # already existing partner ID -> skip
|
||||
return result
|
||||
@@ -1339,8 +1317,8 @@ class MailThread(models.AbstractModel):
|
||||
followers = self.env['res.partner']
|
||||
if res_model and res_id:
|
||||
record = self.env[res_model].browse(res_id)
|
||||
if hasattr(record, 'message_follower_ids'):
|
||||
followers = record.message_follower_ids
|
||||
if hasattr(record, 'message_partner_ids'):
|
||||
followers = record.message_partner_ids
|
||||
|
||||
Partner = self.env['res.partner'].sudo()
|
||||
partner_ids = []
|
||||
@@ -1601,16 +1579,18 @@ class MailThread(models.AbstractModel):
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def message_subscribe(self, partner_ids, subtype_ids=None):
|
||||
def message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None, force=True):
|
||||
""" Add partners to the records followers. """
|
||||
# not necessary for computation, but saves an access right check
|
||||
if not partner_ids:
|
||||
if not partner_ids and not channel_ids:
|
||||
return True
|
||||
if partner_ids is None:
|
||||
partner_ids = []
|
||||
if channel_ids is None:
|
||||
channel_ids = []
|
||||
|
||||
Followers = self.env['mail.followers']
|
||||
Subtype = self.env['mail.message.subtype']
|
||||
|
||||
if set(partner_ids) == set([self.env.user.partner_id.id]):
|
||||
# TDE CHECK THIS
|
||||
if not channel_ids and partner_ids and set(partner_ids) == set([self.env.user.partner_id.id]):
|
||||
try:
|
||||
self.check_access_rights('read')
|
||||
self.check_access_rule('read')
|
||||
@@ -1620,38 +1600,14 @@ class MailThread(models.AbstractModel):
|
||||
self.check_access_rights('write')
|
||||
self.check_access_rule('write')
|
||||
|
||||
existing_pids_dict = dict.fromkeys(self.ids, self.env['res.partner'])
|
||||
followers = Followers.sudo().search([
|
||||
'&', '&',
|
||||
('res_model', '=', self._name),
|
||||
('res_id', 'in', self.ids),
|
||||
('partner_id', 'in', partner_ids)])
|
||||
for follower in followers:
|
||||
existing_pids_dict[follower.res_id] |= follower.partner_id
|
||||
|
||||
# subtype_ids specified: update already subscribed partners
|
||||
if subtype_ids and followers:
|
||||
followers.write({'subtype_ids': [(6, 0, subtype_ids)]})
|
||||
# subtype_ids not specified: do not update already subscribed partner, fetch default subtypes for new partners
|
||||
if subtype_ids is None:
|
||||
subtype_ids = Subtype.search([
|
||||
('default', '=', True),
|
||||
'|',
|
||||
('res_model', '=', self._name),
|
||||
('res_model', '=', False)]).ids
|
||||
|
||||
for record in self:
|
||||
existing_pids = existing_pids_dict[record.id]
|
||||
new_partners = self.env['res.partner'].browse(partner_ids) - existing_pids
|
||||
|
||||
# subscribe new followers
|
||||
for new_partner in new_partners:
|
||||
Followers.sudo().create({
|
||||
'res_model': self._name,
|
||||
'res_id': record.id,
|
||||
'partner_id': new_partner.id,
|
||||
'subtype_ids': [(6, 0, subtype_ids)]})
|
||||
partner_data = dict((pid, subtype_ids) for pid in partner_ids)
|
||||
channel_data = dict((cid, subtype_ids) for cid in channel_ids)
|
||||
gen, part = self.env['mail.followers']._add_follower_command(self._name, self.ids, partner_data, channel_data, force=force)
|
||||
self.sudo().write({'message_follower_ids': gen})
|
||||
for record in self.filtered(lambda self: self.id in part):
|
||||
record.write(part[record.id])
|
||||
|
||||
self.invalidate_cache()
|
||||
return True
|
||||
|
||||
@api.multi
|
||||
@@ -1667,13 +1623,13 @@ class MailThread(models.AbstractModel):
|
||||
return result
|
||||
|
||||
@api.multi
|
||||
def message_unsubscribe(self, partner_ids):
|
||||
def message_unsubscribe(self, partner_ids=None, channel_ids=None):
|
||||
""" Remove partners from the records followers. """
|
||||
# not necessary for computation, but saves an access right check
|
||||
if not partner_ids:
|
||||
if not partner_ids and not channel_ids:
|
||||
return True
|
||||
user_pid = self.env.user.partner_id.id
|
||||
if set(partner_ids) == set([user_pid]):
|
||||
if not channel_ids and set(partner_ids) == set([user_pid]):
|
||||
self.check_access_rights('read')
|
||||
self.check_access_rule('read')
|
||||
else:
|
||||
@@ -1682,7 +1638,9 @@ class MailThread(models.AbstractModel):
|
||||
self.env['mail.followers'].sudo().search([
|
||||
('res_model', '=', self._name),
|
||||
('res_id', 'in', self.ids),
|
||||
('partner_id', 'in', partner_ids)
|
||||
'|',
|
||||
('partner_id', 'in', partner_ids or []),
|
||||
('channel_id', 'in', channel_ids or [])
|
||||
]).unlink()
|
||||
|
||||
@api.model
|
||||
@@ -1808,7 +1766,7 @@ class MailThread(models.AbstractModel):
|
||||
|
||||
for pid, subtypes in new_followers.items():
|
||||
subtypes = list(subtypes) if subtypes is not None else None
|
||||
self.message_subscribe([pid], subtypes)
|
||||
self.message_subscribe([pid], subtype_ids=subtypes)
|
||||
|
||||
self._message_auto_subscribe_notify(user_pids)
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ class Users(models.Model):
|
||||
def message_update(self, msg_dict, update_vals=None):
|
||||
return True
|
||||
|
||||
def message_subscribe(self, partner_ids, subtype_ids=None):
|
||||
def message_subscribe(self, partner_ids=None, channel_ids=None, subtype_ids=None, force=True):
|
||||
return True
|
||||
|
||||
@api.cr_uid_context
|
||||
|
||||
@@ -7,8 +7,8 @@ access_mail_mail_portal,mail.mail.portal,model_mail_mail,base.group_portal,1,1,1
|
||||
access_mail_mail_user,mail.mail.user,model_mail_mail,base.group_user,1,1,1,0
|
||||
access_mail_mail_system,mail.mail.system,model_mail_mail,base.group_system,1,1,1,1
|
||||
access_mail_followers_all,mail.followers.all,model_mail_followers,,1,0,0,0
|
||||
access_mail_followers_portal,mail.followers.portal,model_mail_followers,base.group_portal,1,1,0,0
|
||||
access_mail_followers_user,mail.followers.user,model_mail_followers,base.group_user,1,1,0,0
|
||||
access_mail_followers_portal,mail.followers.portal,model_mail_followers,base.group_portal,1,1,1,0
|
||||
access_mail_followers_user,mail.followers.user,model_mail_followers,base.group_user,1,1,1,0
|
||||
access_mail_followers_system,mail.followers.system,model_mail_followers,base.group_system,1,1,1,1
|
||||
access_mail_notification_all,mail.notification.all,model_mail_notification,,1,0,0,0
|
||||
access_mail_notification_portal,mail.notification.portal,model_mail_notification,base.group_portal,1,1,1,0
|
||||
|
||||
|
@@ -7,17 +7,18 @@
|
||||
<field name="name">Mail.channel: access only public and joined groups</field>
|
||||
<field name="model_id" ref="model_mail_channel"/>
|
||||
<!-- This rule has to be improved for employee only groups -->
|
||||
<field name="domain_force">['|', '|', ('public', '=', 'public'), ('message_follower_ids', 'in', [user.partner_id.id]), '&', ('public','=','groups'), ('group_public_id','in', [g.id for g in user.groups_id])]</field>
|
||||
<field name="domain_force">['|', '|', ('public', '=', 'public'), ('message_partner_ids', 'in', [user.partner_id.id]), '&', ('public','=','groups'), ('group_public_id','in', [g.id for g in user.groups_id])]</field>
|
||||
<field name="perm_create" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="mail_followers_read_write_own" model="ir.rule">
|
||||
<field name="name">mail.followers: read and write its own entries</field>
|
||||
<field name="name">mail.followers: write its own entries</field>
|
||||
<field name="model_id" ref="model_mail_followers"/>
|
||||
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
||||
<field name="domain_force">[('partner_id', '=', user.partner_id.id)]</field>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_unlink" eval="False"/>
|
||||
<field name="perm_read" eval="False"/>
|
||||
</record>
|
||||
|
||||
<!-- If technical rights then read and write others subscriptions -->
|
||||
|
||||
@@ -77,7 +77,7 @@ var Followers = form_common.AbstractField.extend({
|
||||
self.do_follow();
|
||||
}
|
||||
else {
|
||||
self.do_unfollow();
|
||||
self.do_unfollow([session.uid]);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -145,15 +145,10 @@ var Followers = form_common.AbstractField.extend({
|
||||
},
|
||||
|
||||
on_remove_follower: function (event) {
|
||||
var partner_id = $(event.target).data('id');
|
||||
var name = $(event.target).parent().find("a").html();
|
||||
if (confirm(_.str.sprintf(_t("Warning! \n %s won't be notified of any email or discussion on this document. Do you really want to remove him from the followers ?"), name))) {
|
||||
var context = new data.CompoundContext(this.build_context(), {});
|
||||
return this.ds_model.call('message_unsubscribe', [[this.view.datarecord.id],
|
||||
[partner_id],
|
||||
context])
|
||||
.then(this.proxy('read_value'));
|
||||
}
|
||||
var res_model = $(event.target).parent().find('a').data('res-model');
|
||||
var res_id = $(event.target).parent().find('a').data('res-id');
|
||||
if (res_model == 'res.partner') { return this.do_unfollow(undefined, [res_id], undefined); }
|
||||
else { return this.do_unfollow(undefined, undefined, [res_id]); }
|
||||
},
|
||||
|
||||
on_follower_clicked: function (event) {
|
||||
@@ -245,19 +240,13 @@ var Followers = form_common.AbstractField.extend({
|
||||
|
||||
// truncate number of displayed followers
|
||||
_(this.followers).each(function (record) {
|
||||
var partner = {
|
||||
'id': record['id'],
|
||||
'name': record['name'],
|
||||
'is_uid': record['is_uid'],
|
||||
'is_editable': record['is_editable'],
|
||||
'avatar_url': mail_utils.get_image(session, 'res.partner', 'image_small', record['id']),
|
||||
}
|
||||
|
||||
$(qweb.render('mail_followers_partner', {'record': partner, 'widget': self}))
|
||||
.appendTo(node_user_list);
|
||||
$(qweb.render('mail_followers_partner', {
|
||||
'record': _.extend(record, {'avatar_url': mail_utils.get_image(session, record['res_model'], 'image_small', record['id'])}),
|
||||
'widget': self})
|
||||
).appendTo(node_user_list);
|
||||
|
||||
// On mouse-enter it will show the edit_subtype pencil.
|
||||
if (partner.is_editable) {
|
||||
if (record.is_editable) {
|
||||
self.$('.o_timeline_follower_list').on('mouseenter mouseleave', function(e) {
|
||||
self.$('.o_timeline_edit_subtype')
|
||||
.toggleClass('oe_hidden', e.type == 'mouseleave');
|
||||
@@ -358,26 +347,33 @@ var Followers = form_common.AbstractField.extend({
|
||||
$(record).attr('checked', 'checked');
|
||||
});
|
||||
},
|
||||
|
||||
do_unfollow: function (user_pid) {
|
||||
if (confirm(_t("Warning! \nYou won't be notified of any email or discussion on this document. Do you really want to unfollow this document ?"))) {
|
||||
|
||||
do_unfollow: function (user_ids, partner_ids, channel_ids) {
|
||||
if (confirm(_t("Warning! \n If you remove a follower, he won't be notified of any email or discussion on this document. Do you really want to remove this follower ?"))) {
|
||||
_(this.$('.o_timeline_msg_subtype_check')).each(function (record) {
|
||||
$(record).attr('checked',false);
|
||||
});
|
||||
|
||||
var action_unsubscribe = 'message_unsubscribe_users';
|
||||
this.$('.o_timeline_subtype_list > .dropdown-toggle').attr('disabled', true);
|
||||
var follower_ids = [session.uid];
|
||||
|
||||
if (user_pid) {
|
||||
action_unsubscribe = 'message_unsubscribe';
|
||||
follower_ids = [user_pid];
|
||||
}
|
||||
|
||||
var context = new data.CompoundContext(this.build_context(), {});
|
||||
return this.ds_model.call(action_unsubscribe, [[this.view.datarecord.id],
|
||||
follower_ids, context])
|
||||
.then(this.proxy('read_value'));
|
||||
|
||||
if (partner_ids || channel_ids) {
|
||||
return this.ds_model.call(
|
||||
'message_unsubscribe', [
|
||||
[this.view.datarecord.id],
|
||||
partner_ids,
|
||||
channel_ids,
|
||||
context]
|
||||
).then(this.proxy('read_value'));
|
||||
}
|
||||
else {
|
||||
return this.ds_model.call(
|
||||
'message_unsubscribe_users', [
|
||||
[this.view.datarecord.id],
|
||||
user_ids,
|
||||
context]
|
||||
).then(this.proxy('read_value'));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
@@ -404,7 +400,7 @@ var Followers = form_common.AbstractField.extend({
|
||||
});
|
||||
|
||||
if (!checklist.length) {
|
||||
if (!this.do_unfollow(user_pid)) {
|
||||
if (!this.do_unfollow(undefined, [user_pid], undefined)) {
|
||||
$(event.target).attr("checked", "checked");
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -42,14 +42,17 @@
|
||||
<span> <img class="oe_mail_thumbnail oe_mail_frame" t-att-src="record.avatar_url"/> </span>
|
||||
<span class="oe_partner_name">
|
||||
<a t-attf-href="#model=res.partner&id=#{record.id}"
|
||||
t-att-title="record.name" t-att-data-partner="record.id">
|
||||
<t t-esc="record.name"/> </a>
|
||||
t-att-title="record.name"
|
||||
t-att-data-res-model="record.res_model"
|
||||
t-att-data-res-id="record.res_id"
|
||||
t-att-data-id="record.id">
|
||||
<t t-esc="record.name"/></a>
|
||||
</span>
|
||||
<i t-if="record.is_editable and (widget.records_length > 1)"
|
||||
class="oe_edit_subtype fa fa-pencil oe_hidden" title="Edit subscription"
|
||||
t-att-data-id="record.id"/>
|
||||
<i t-if="widget.view_is_editable" class="oe_remove_follower fa fa-remove"
|
||||
title="Remove this follower" t-att-data-id="record.id"/>
|
||||
title="Remove this follower"/>
|
||||
</li>
|
||||
|
||||
<t t-name="mail_followers_add_more">
|
||||
@@ -66,7 +69,7 @@
|
||||
<t t-name="mail_followers_subtype">
|
||||
<li class="oe_subtype">
|
||||
<input type="checkbox" t-att-checked="record.followed"
|
||||
t-att-id="'input_mail_followers_subtype_'+record.id+(dialog ? '_in_dialog': '')"
|
||||
t-att-id="'input_mail_followers_subtype_'+record.id+(dialog ? '_in_dialog': '')"
|
||||
t-att-data-id="record.id" t-att-name="record.name" class="o_timeline_msg_subtype_check"/>
|
||||
|
||||
<label t-att-for="'input_mail_followers_subtype_'+record.id+(dialog ? '_in_dialog': '')">
|
||||
|
||||
@@ -17,9 +17,12 @@ class TestInvite(TestMail):
|
||||
mail_invite.add_followers()
|
||||
|
||||
# Test: Pigs followers should contain Admin, Bert
|
||||
self.assertEqual(self.group_pigs.message_follower_ids,
|
||||
self.assertEqual(self.group_pigs.message_partner_ids,
|
||||
self.user_portal.partner_id | self.partner_1,
|
||||
'invite wizard: Pigs followers after invite is incorrect, should be Admin + added follower')
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('channel_id'),
|
||||
self.env['mail.channel'],
|
||||
'invite wizard: Pigs followers after invite is incorrect, should not have channels')
|
||||
|
||||
# Test: (pretend to) send email and check subject, body
|
||||
self.assertEqual(len(self._mails), 2, 'invite wizard: sent email number incorrect, should be only for Bert')
|
||||
|
||||
@@ -81,7 +81,7 @@ class TestMailGroup(TestMail):
|
||||
trigger_read = chell_pigs.name
|
||||
for message in chell_pigs.message_ids:
|
||||
trigger_read = message.subject
|
||||
for partner in chell_pigs.message_follower_ids:
|
||||
for partner in chell_pigs.message_partner_ids:
|
||||
if partner.id == self.user_portal.partner_id.id:
|
||||
# Chell can read her own partner record
|
||||
continue
|
||||
|
||||
@@ -160,38 +160,43 @@ class TestMessagePost(TestMail):
|
||||
|
||||
@mute_logger('openerp.addons.mail.models.mail_mail')
|
||||
def test_post_no_subscribe_author(self):
|
||||
original_followers = self.group_pigs.message_follower_ids
|
||||
original = self.group_pigs.message_follower_ids
|
||||
self.group_pigs.sudo(self.user_employee).with_context({'mail_create_nosubscribe': True}).message_post(
|
||||
body='Test Body', message_type='comment', subtype='mt_comment')
|
||||
self.assertEqual(self.group_pigs.message_follower_ids, original_followers)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('partner_id'), original.mapped('partner_id'))
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('channel_id'), original.mapped('channel_id'))
|
||||
|
||||
@mute_logger('openerp.addons.mail.models.mail_mail')
|
||||
def test_post_subscribe_author(self):
|
||||
original_followers = self.group_pigs.message_follower_ids
|
||||
original = self.group_pigs.message_follower_ids
|
||||
self.group_pigs.sudo(self.user_employee).message_post(
|
||||
body='Test Body', message_type='comment', subtype='mt_comment')
|
||||
self.assertEqual(self.group_pigs.message_follower_ids, original_followers | self.user_employee.partner_id)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('partner_id'), original.mapped('partner_id') | self.user_employee.partner_id)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('channel_id'), original.mapped('channel_id'))
|
||||
|
||||
@mute_logger('openerp.addons.mail.models.mail_mail')
|
||||
def test_post_no_subscribe_recipients(self):
|
||||
original_followers = self.group_pigs.message_follower_ids
|
||||
original = self.group_pigs.message_follower_ids
|
||||
self.group_pigs.sudo(self.user_employee).with_context({'mail_create_nosubscribe': True}).message_post(
|
||||
body='Test Body', message_type='comment', subtype='mt_comment', partner_ids=[(4, self.partner_1.id), (4, self.partner_2.id)])
|
||||
self.assertEqual(self.group_pigs.message_follower_ids, original_followers)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('partner_id'), original.mapped('partner_id'))
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('channel_id'), original.mapped('channel_id'))
|
||||
|
||||
@mute_logger('openerp.addons.mail.models.mail_mail')
|
||||
def test_post_subscribe_recipients(self):
|
||||
original_followers = self.group_pigs.message_follower_ids
|
||||
original = self.group_pigs.message_follower_ids
|
||||
self.group_pigs.sudo(self.user_employee).with_context({'mail_create_nosubscribe': True, 'mail_post_autofollow': True}).message_post(
|
||||
body='Test Body', message_type='comment', subtype='mt_comment', partner_ids=[(4, self.partner_1.id), (4, self.partner_2.id)])
|
||||
self.assertEqual(self.group_pigs.message_follower_ids, original_followers | self.partner_1 | self.partner_2)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('partner_id'), original.mapped('partner_id') | self.partner_1 | self.partner_2)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('channel_id'), original.mapped('channel_id'))
|
||||
|
||||
@mute_logger('openerp.addons.mail.models.mail_mail')
|
||||
def test_post_subscribe_recipients_partial(self):
|
||||
original_followers = self.group_pigs.message_follower_ids
|
||||
original = self.group_pigs.message_follower_ids
|
||||
self.group_pigs.sudo(self.user_employee).with_context({'mail_create_nosubscribe': True, 'mail_post_autofollow': True, 'mail_post_autofollow_partner_ids': [self.partner_2.id]}).message_post(
|
||||
body='Test Body', message_type='comment', subtype='mt_comment', partner_ids=[(4, self.partner_1.id), (4, self.partner_2.id)])
|
||||
self.assertEqual(self.group_pigs.message_follower_ids, original_followers | self.partner_2)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('partner_id'), original.mapped('partner_id') | self.partner_2)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('channel_id'), original.mapped('channel_id'))
|
||||
|
||||
@mute_logger('openerp.addons.mail.models.mail_mail')
|
||||
def test_post_notifications(self):
|
||||
|
||||
@@ -15,41 +15,55 @@ class TestMailFollowers(TestMail):
|
||||
self.mt_al_nodef = Subtype.create({'name': 'mt_al_nodef', 'default': False, 'res_model': False})
|
||||
self.default_group_subtypes = Subtype.search([('default', '=', True), '|', ('res_model', '=', 'mail.channel'), ('res_model', '=', False)])
|
||||
|
||||
def test_message_follower_ids_commands(self):
|
||||
# Create some dummy data on other groups to ensure they are not altered
|
||||
group_dummy = self.env['mail.channel'].with_context({'mail_create_nolog': True}).create({'name': 'Dummy group'})
|
||||
self.env['mail.followers'].create({'res_model': 'mail.thread', 'res_id': group_dummy.id, 'partner_id': self.partner_1.id})
|
||||
def test_m2o_command_new(self):
|
||||
test_channel = self.env['mail.channel'].create({'name': 'Test'})
|
||||
groups = self.group_pigs | self.group_public
|
||||
generic, specific = self.env['mail.followers']._add_follower_command(
|
||||
'mail.channel', groups.ids,
|
||||
{self.user_employee.partner_id.id: [self.mt_mg_nodef.id]},
|
||||
{test_channel.id: [self.mt_al_nodef.id]})
|
||||
self.assertFalse(specific)
|
||||
self.assertEqual(len(generic), 2)
|
||||
|
||||
# Add 2 followers through the (4, ID) command
|
||||
self.group_pigs.write({'message_follower_ids': [(4, self.partner_1.id), (4, self.partner_2.id)]})
|
||||
self.assertEqual(self.group_pigs.message_follower_ids, self.partner_1 | self.partner_2)
|
||||
self.assertEqual(set([generic[0][2]['res_model'], generic[1][2]['res_model']]),
|
||||
set(['mail.channel']))
|
||||
self.assertEqual(set(filter(None, [generic[0][2].get('channel_id'), generic[1][2].get('channel_id')])),
|
||||
set([test_channel.id]))
|
||||
self.assertEqual(set(filter(None, [generic[0][2].get('partner_id'), generic[1][2].get('partner_id')])),
|
||||
set([self.user_employee.partner_id.id]))
|
||||
self.assertEqual(set(generic[0][2]['subtype_ids'][0][2] + generic[1][2]['subtype_ids'][0][2]),
|
||||
set([self.mt_mg_nodef.id, self.mt_al_nodef.id]))
|
||||
|
||||
# Remove 1 follower through the (3, ID) command
|
||||
self.group_pigs.write({'message_follower_ids': [(3, self.partner_2.id)]})
|
||||
self.assertEqual(self.group_pigs.message_follower_ids, self.partner_1)
|
||||
def test_m2o_command_update_selective(self):
|
||||
test_channel = self.env['mail.channel'].create({'name': 'Test'})
|
||||
groups = self.group_pigs | self.group_public
|
||||
self.env['mail.followers'].create({'partner_id': self.user_employee.partner_id.id, 'res_model': 'mail.channel', 'res_id': self.group_pigs.id})
|
||||
generic, specific = self.env['mail.followers']._add_follower_command(
|
||||
'mail.channel', groups.ids,
|
||||
{self.user_employee.partner_id.id: [self.mt_mg_nodef.id]},
|
||||
{test_channel.id: False},
|
||||
force=False)
|
||||
self.assertEqual(len(generic), 1)
|
||||
self.assertEqual(len(specific), 1)
|
||||
|
||||
# Set followers through the (6, 0, IDs) command
|
||||
self.group_pigs.write({'message_follower_ids': [(6, 0, [self.partner_2.id, self.env.user.partner_id.id])]})
|
||||
self.assertEqual(self.group_pigs.message_follower_ids,
|
||||
self.partner_2 | self.env.user.partner_id)
|
||||
self.assertEqual(generic[0][2]['res_model'], 'mail.channel')
|
||||
self.assertEqual(generic[0][2]['channel_id'], test_channel.id)
|
||||
self.assertEqual(set(generic[0][2]['subtype_ids'][0][2]), set(self.default_group_subtypes.ids))
|
||||
|
||||
# Add 1 follower through the (0, 0, values) command
|
||||
self.group_pigs.write({'message_follower_ids': [(0, 0, {'name': 'Patrick Fiori'})]})
|
||||
partner_patrick = self.env['res.partner'].search([('name', '=', 'Patrick Fiori')], limit=1)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids,
|
||||
self.partner_2 | self.env.user.partner_id | partner_patrick)
|
||||
self.assertEqual(specific.keys(), [self.group_public.id])
|
||||
self.assertEqual(specific[self.group_public.id][0][2]['res_model'], 'mail.channel')
|
||||
self.assertEqual(specific[self.group_public.id][0][2]['partner_id'], self.user_employee.partner_id.id)
|
||||
self.assertEqual(set(specific[self.group_public.id][0][2]['subtype_ids'][0][2]), set([self.mt_mg_nodef.id]))
|
||||
|
||||
# Remove all followers through a (5, 0) command
|
||||
self.group_pigs.write({'message_follower_ids': [(5, 0)]})
|
||||
self.assertFalse(self.group_pigs.message_follower_ids)
|
||||
|
||||
# Test dummy data has not been altered
|
||||
followers = self.env['mail.followers'].search([('res_model', '=', 'mail.thread'), ('res_id', '=', group_dummy.id)])
|
||||
self.assertEqual(followers.mapped('partner_id'), self.partner_1, 'dummy data altered')
|
||||
def test_message_is_follower(self):
|
||||
self.assertFalse(self.group_pigs.sudo(self.user_employee).message_is_follower)
|
||||
self.group_pigs.message_subscribe_users(user_ids=[self.user_employee.id])
|
||||
self.assertTrue(self.group_pigs.sudo(self.user_employee).message_is_follower)
|
||||
|
||||
def test_followers_subtypes_default(self):
|
||||
self.group_pigs.message_subscribe_users(user_ids=[self.user_employee.id])
|
||||
self.assertEqual(self.group_pigs.message_follower_ids, self.user_employee.partner_id)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('partner_id'), self.user_employee.partner_id)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('channel_id'), self.env['mail.channel'])
|
||||
follower = self.env['mail.followers'].search([
|
||||
('res_model', '=', 'mail.channel'),
|
||||
('res_id', '=', self.group_pigs.id),
|
||||
@@ -59,7 +73,8 @@ class TestMailFollowers(TestMail):
|
||||
|
||||
def test_followers_subtypes_specified(self):
|
||||
self.group_pigs.sudo(self.user_employee).message_subscribe_users(subtype_ids=[self.mt_mg_nodef.id])
|
||||
self.assertEqual(self.group_pigs.message_follower_ids, self.user_employee.partner_id)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('partner_id'), self.user_employee.partner_id)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('channel_id'), self.env['mail.channel'])
|
||||
follower = self.env['mail.followers'].search([
|
||||
('res_model', '=', 'mail.channel'),
|
||||
('res_id', '=', self.group_pigs.id),
|
||||
@@ -69,7 +84,8 @@ class TestMailFollowers(TestMail):
|
||||
|
||||
def test_followers_multiple_subscription(self):
|
||||
self.group_pigs.sudo(self.user_employee).message_subscribe_users(subtype_ids=[self.mt_mg_nodef.id])
|
||||
self.assertEqual(self.group_pigs.message_follower_ids, self.user_employee.partner_id)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('partner_id'), self.user_employee.partner_id)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('channel_id'), self.env['mail.channel'])
|
||||
follower = self.env['mail.followers'].search([
|
||||
('res_model', '=', 'mail.channel'),
|
||||
('res_id', '=', self.group_pigs.id),
|
||||
@@ -78,7 +94,8 @@ class TestMailFollowers(TestMail):
|
||||
self.assertEqual(follower.subtype_ids, self.mt_mg_nodef)
|
||||
|
||||
self.group_pigs.sudo(self.user_employee).message_subscribe_users(subtype_ids=[self.mt_mg_nodef.id, self.mt_al_nodef.id])
|
||||
self.assertEqual(self.group_pigs.message_follower_ids, self.user_employee.partner_id)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('partner_id'), self.user_employee.partner_id)
|
||||
self.assertEqual(self.group_pigs.message_follower_ids.mapped('channel_id'), self.env['mail.channel'])
|
||||
follower = self.env['mail.followers'].search([
|
||||
('res_model', '=', 'mail.channel'),
|
||||
('res_id', '=', self.group_pigs.id),
|
||||
|
||||
@@ -278,7 +278,7 @@ class TestMailgateway(TestMail):
|
||||
self.assertIn('test.sylvie.lelitre@agrolait.com', new_groups.message_ids[0].email_from,
|
||||
'message_process: unrecognized email -> email_from')
|
||||
|
||||
self.assertEqual(len(new_groups.message_follower_ids), 0,
|
||||
self.assertEqual(len(new_groups.message_partner_ids), 0,
|
||||
'message_process: newly create group should not have any follower')
|
||||
|
||||
@mute_logger('openerp.addons.mail.models.mail_thread', 'openerp.models')
|
||||
@@ -291,7 +291,7 @@ class TestMailgateway(TestMail):
|
||||
self.assertIn('Valid Lelitre <valid.lelitre@agrolait.com>', new_groups.message_ids[0].email_from,
|
||||
'message_process: recognized email -> email_from')
|
||||
|
||||
self.assertEqual(new_groups.message_follower_ids, self.partner_1,
|
||||
self.assertEqual(new_groups.message_partner_ids, self.partner_1,
|
||||
'message_process: recognized email -> added as follower')
|
||||
|
||||
self.assertEqual(len(self._mails), 0,
|
||||
@@ -380,7 +380,7 @@ class TestMailgateway(TestMail):
|
||||
self.assertIn('valid.lelitre@agrolait.com', self._mails[0].get('email_to')[0],
|
||||
'message_process: email should be sent to Sylvie')
|
||||
# Test: author (and not recipient) added as follower
|
||||
self.assertEqual(self.group_public.message_follower_ids, self.partner_1 | self.partner_2,
|
||||
self.assertEqual(self.group_public.message_partner_ids, self.partner_1 | self.partner_2,
|
||||
'message_process: after reply, group should have 2 followers')
|
||||
|
||||
@mute_logger('openerp.addons.mail.models.mail_thread', 'openerp.models')
|
||||
|
||||
@@ -27,6 +27,7 @@ class Invite(models.TransientModel):
|
||||
res_model = fields.Char('Related Document Model', required=True, select=1, help='Model of the followed resource')
|
||||
res_id = fields.Integer('Related Document ID', select=1, help='Id of the followed resource')
|
||||
partner_ids = fields.Many2many('res.partner', string='Recipients', help="List of partners that will be added as follower of the current document.")
|
||||
channel_ids = fields.Many2many('mail.channel', string='Channels', help='List of channels that will be added as listeners of the current document.')
|
||||
message = fields.Html('Message')
|
||||
send_mail = fields.Boolean('Send Email', default=True, help="If checked, the partners will receive an email warning they have been added in the document's followers.")
|
||||
|
||||
@@ -38,8 +39,9 @@ class Invite(models.TransientModel):
|
||||
document = Model.browse(wizard.res_id)
|
||||
|
||||
# filter partner_ids to get the new followers, to avoid sending email to already following partners
|
||||
new_followers = wizard.partner_ids - document.message_follower_ids
|
||||
document.message_subscribe(new_followers.ids)
|
||||
new_partners = wizard.partner_ids - document.message_partner_ids
|
||||
new_channels = wizard.channel_ids - document.message_channel_ids
|
||||
document.message_subscribe(new_partners.ids, new_channels.ids)
|
||||
|
||||
model_ids = self.env['ir.model'].search([('model', '=', wizard.res_model)])
|
||||
model_name = model_ids.name_get()[0][1]
|
||||
@@ -62,5 +64,5 @@ class Invite(models.TransientModel):
|
||||
'body_html': '%s' % wizard.message,
|
||||
'auto_delete': True,
|
||||
'message_id': self.env['mail.message']._get_message_id({'no_auto_thread': True}),
|
||||
'recipient_ids': [(4, id) for id in new_followers.ids]}).send()
|
||||
'recipient_ids': [(4, id) for id in new_partners.ids]}).send()
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
@@ -14,6 +14,8 @@
|
||||
<field name="partner_ids" widget="many2many_tags_email"
|
||||
placeholder="Add contacts to notify..."
|
||||
context="{'force_email':True, 'show_email':True}"/>
|
||||
<field name="channel_ids" widget="many2many_tags"
|
||||
placeholder="Add channels to notify..."/>
|
||||
<field name="send_mail"/>
|
||||
<field name="message" attrs="{'invisible': [('send_mail','!=',True)]}" options="{'style-inline': true}" class="test_message"/>
|
||||
</group>
|
||||
|
||||
@@ -36,7 +36,6 @@
|
||||
</field>
|
||||
<field name="stage_id" ref="demo_note_stage_01"/>
|
||||
<field name="color">2</field>
|
||||
<field name="message_follower_ids" eval="[(4, ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="note_2" model="note.note">
|
||||
@@ -61,7 +60,6 @@
|
||||
]]>
|
||||
</field>
|
||||
<field name="stage_id" ref="demo_note_stage_02"/>
|
||||
<field name="message_follower_ids" eval="[(4, ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="note_6" model="note.note">
|
||||
@@ -93,7 +91,6 @@
|
||||
</field>
|
||||
<field name="stage_id" ref="note_stage_03"/>
|
||||
<field name="color">3</field>
|
||||
<field name="message_follower_ids" eval="[(4, ref('base.group_user'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="note_9" model="note.note">
|
||||
@@ -111,7 +108,6 @@
|
||||
<br/>* Odoo for Retail and Industrial Management
|
||||
]]>
|
||||
</field>
|
||||
<field name="message_follower_ids" eval="[(4, ref('base.group_user'))]"/>
|
||||
<field name="color">7</field>
|
||||
<field name="stage_ids" eval="['note_stage_03','demo_note_stage_04']"/>
|
||||
</record>
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<record id="note_note_rule_global" model="ir.rule">
|
||||
<field name="name">Only followers can access a sticky notes</field>
|
||||
<field name="model_id" ref="model_note_note"/>
|
||||
<field name="domain_force">['|', ('user_id', '=', user.id), ('message_follower_ids', '=', user.partner_id.id)]</field>
|
||||
<field name="domain_force">['|', ('user_id', '=', user.id), ('message_partner_ids', '=', user.partner_id.id)]</field>
|
||||
<field name="global" eval="True"/>
|
||||
<field name="perm_create" eval="False"/>
|
||||
<field name="perm_unlink" eval="False"/>
|
||||
|
||||
@@ -47,7 +47,7 @@ class test_portal(TestMail):
|
||||
'partner_ids': [(4, partner_carine.id)], 'send_mail': True})
|
||||
mail_invite.add_followers()
|
||||
# Test: Pigs followers should contain Admin and Bert
|
||||
self.assertEqual(group_pigs.message_follower_ids, partner_carine)
|
||||
self.assertEqual(group_pigs.message_partner_ids, partner_carine)
|
||||
# Test: partner must have been prepared for signup
|
||||
self.assertTrue(partner_carine.signup_valid, 'partner has not been prepared for signup')
|
||||
self.assertTrue(base_url in partner_carine.signup_url, 'signup url is incorrect')
|
||||
|
||||
@@ -10,10 +10,10 @@ class mail_mail(osv.osv):
|
||||
order = so_obj.browse(cr, uid, mail.res_id, context=context)
|
||||
partner = order.partner_id
|
||||
# Add the customer in the SO as follower
|
||||
if partner not in order.message_follower_ids:
|
||||
if partner not in order.message_partner_ids:
|
||||
so_obj.message_subscribe(cr, uid, [mail.res_id], [partner.id], context=context)
|
||||
# Add all recipients of the email as followers
|
||||
for p in mail.partner_ids:
|
||||
if p not in order.message_follower_ids:
|
||||
if p not in order.message_partner_ids:
|
||||
so_obj.message_subscribe(cr, uid, [mail.res_id], [p.id], context=context)
|
||||
return super(mail_mail, self)._postprocess_sent_message(cr, uid, mail=mail, context=context, mail_sent=mail_sent)
|
||||
|
||||
@@ -44,7 +44,7 @@ class sale_order(osv.Model):
|
||||
assert len(ids) == 1
|
||||
document = self.browse(cr, uid, ids[0], context=context)
|
||||
partner = document.partner_id
|
||||
if partner not in document.message_follower_ids:
|
||||
if partner not in document.message_partner_ids:
|
||||
self.message_subscribe(cr, uid, ids, [partner.id], context=context)
|
||||
return super(sale_order, self).action_button_confirm(cr, uid, ids, context=context)
|
||||
|
||||
@@ -103,7 +103,7 @@ class account_invoice(osv.Model):
|
||||
# fetch the partner's id and subscribe the partner to the invoice
|
||||
for invoice in self.browse(cr, uid, ids, context=context):
|
||||
partner = invoice.partner_id
|
||||
if partner not in invoice.message_follower_ids:
|
||||
if partner not in invoice.message_partner_ids:
|
||||
self.message_subscribe(cr, uid, [invoice.id], [partner.id], context=context)
|
||||
return super(account_invoice, self).invoice_validate(cr, uid, ids, context=context)
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ their documents through the portal.</field>
|
||||
<record id="portal_sale_order_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Quotations/Sales Orders</field>
|
||||
<field name="model_id" ref="sale.model_sale_order"/>
|
||||
<field name="domain_force">[('message_follower_ids','child_of',[user.commercial_partner_id.id])]</field>
|
||||
<field name="domain_force">[('message_partner_ids','child_of',[user.commercial_partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
<field eval="1" name="perm_unlink"/>
|
||||
<field eval="1" name="perm_write"/>
|
||||
@@ -29,7 +29,7 @@ their documents through the portal.</field>
|
||||
<record id="portal_sale_order_line_rule" model="ir.rule">
|
||||
<field name="name">Portal Sales Orders Line</field>
|
||||
<field name="model_id" ref="sale.model_sale_order_line"/>
|
||||
<field name="domain_force">[('order_id.message_follower_ids','child_of',[user.commercial_partner_id.id])]</field>
|
||||
<field name="domain_force">[('order_id.message_partner_ids','child_of',[user.commercial_partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
@@ -37,21 +37,21 @@ their documents through the portal.</field>
|
||||
<record id="portal_account_invoice_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Account Invoices</field>
|
||||
<field name="model_id" ref="account.model_account_invoice"/>
|
||||
<field name="domain_force">[('message_follower_ids','child_of',[user.commercial_partner_id.id])]</field>
|
||||
<field name="domain_force">[('message_partner_ids','child_of',[user.commercial_partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_account_invoice_line_rule" model="ir.rule">
|
||||
<field name="name">Portal Invoice Lines</field>
|
||||
<field name="model_id" ref="account.model_account_invoice_line"/>
|
||||
<field name="domain_force">[('invoice_id.message_follower_ids','child_of',[user.commercial_partner_id.id])]</field>
|
||||
<field name="domain_force">[('invoice_id.message_partner_ids','child_of',[user.commercial_partner_id.id])]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_personal_contact" model="ir.rule">
|
||||
<field name="name">Portal Personal Contacts</field>
|
||||
<field name="model_id" ref="base.model_res_partner"/>
|
||||
<field name="domain_force">[('message_follower_ids','in',[user.commercial_partner_id.id])]</field>
|
||||
<field name="domain_force">[('message_partner_ids','in',[user.commercial_partner_id.id])]</field>
|
||||
<field eval="0" name="perm_read"/>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
@@ -6,14 +6,14 @@
|
||||
<record id="portal_stock_picking_portal_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Follower Pickings</field>
|
||||
<field name="model_id" ref="stock.model_stock_picking"/>
|
||||
<field name="domain_force">['|', ('message_follower_ids','in',[user.partner_id.id]), ('partner_id.id','=',user.partner_id.id)]</field>
|
||||
<field name="domain_force">['|', ('message_partner_ids','in',[user.partner_id.id]), ('partner_id.id','=',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="portal_stock_pack_operation_portal_user_rule" model="ir.rule">
|
||||
<field name="name">Portal Follower Pack Operations</field>
|
||||
<field name="model_id" ref="stock.model_stock_pack_operation"/>
|
||||
<field name="domain_force">['|', ('picking_id.message_follower_ids','in',[user.partner_id.id]), ('picking_id.partner_id.id','=',user.partner_id.id)]</field>
|
||||
<field name="domain_force">['|', ('picking_id.message_partner_ids','in',[user.partner_id.id]), ('picking_id.partner_id.id','=',user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
@@ -13,7 +13,7 @@ class account_invoice(osv.Model):
|
||||
if invoice.type != 'out_invoice':
|
||||
continue
|
||||
# subscribe the partner to the invoice
|
||||
if invoice.partner_id not in invoice.message_follower_ids:
|
||||
if invoice.partner_id not in invoice.message_partner_ids:
|
||||
self.message_subscribe(cr, uid, [invoice.id], [invoice.partner_id.id], context=context)
|
||||
for line in invoice.invoice_line_ids:
|
||||
if line.product_id.email_template_id:
|
||||
|
||||
@@ -113,7 +113,6 @@
|
||||
<field name="privacy_visibility">followers</field>
|
||||
<field name="user_id" ref="base.user_root"/>
|
||||
<field name="alias_model">project.task</field>
|
||||
<field name="message_follower_ids" eval="[(6, 0, [ref('base.partner_root')])]"/>
|
||||
</record>
|
||||
|
||||
<record id="project_stage_data_1" model="project.task.type">
|
||||
|
||||
@@ -59,10 +59,9 @@
|
||||
<field name="description">Implement new website for Sale and Warehouse Management for a customer.</field>
|
||||
<field name="alias_model">project.task</field>
|
||||
<field name="type_ids" eval="[(4, ref('project_stage_0')) ,(4,ref('project_stage_1'))]"/>
|
||||
<field name="message_follower_ids" eval="[(6, 0, [
|
||||
ref('base.partner_root'),
|
||||
ref('base.partner_demo'),
|
||||
ref('portal.partner_demo_portal')])]"/>
|
||||
<field name="message_follower_ids" eval="[
|
||||
(0, 0, {'res_model': 'project.project', 'partner_id': ref('portal.partner_demo_portal')})
|
||||
]"/>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -72,9 +71,6 @@
|
||||
<field name="privacy_visibility">followers</field>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="alias_model">project.task</field>
|
||||
<field name="message_follower_ids" eval="[(6, 0, [
|
||||
ref('base.partner_root'),
|
||||
ref('base.partner_demo')])]"/>
|
||||
</record>
|
||||
|
||||
<record id="project_project_3" model="project.project">
|
||||
|
||||
@@ -51,7 +51,7 @@
|
||||
<field name="model_id" ref="model_project_project"/>
|
||||
<field name="domain_force">['|',
|
||||
('privacy_visibility', 'in', ['portal', 'employees']),
|
||||
('message_follower_ids', 'in', [user.partner_id.id])
|
||||
('message_partner_ids', 'in', [user.partner_id.id])
|
||||
]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_user'))]"/>
|
||||
</record>
|
||||
@@ -75,9 +75,9 @@
|
||||
'|',
|
||||
'&',
|
||||
('project_id.privacy_visibility', '=', 'followers'),
|
||||
('project_id.message_follower_ids', 'in', [user.partner_id.id]),
|
||||
('project_id.message_partner_ids', 'in', [user.partner_id.id]),
|
||||
'|',
|
||||
('message_follower_ids', 'in', [user.partner_id.id]),
|
||||
('message_partner_ids', 'in', [user.partner_id.id]),
|
||||
# to subscribe check access to the record, follower is not enough at creation
|
||||
('user_id', '=', user.id)
|
||||
]</field>
|
||||
@@ -99,10 +99,10 @@
|
||||
'|',
|
||||
'&',
|
||||
('privacy_visibility', '=', 'portal'),
|
||||
('message_follower_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
|
||||
('message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
|
||||
'&',
|
||||
('privacy_visibility', '=', 'followers'),
|
||||
('message_follower_ids', 'in', [user.partner_id.id])
|
||||
('message_partner_ids', 'in', [user.partner_id.id])
|
||||
]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
@@ -115,14 +115,14 @@
|
||||
'|',
|
||||
'&',
|
||||
('project_id.privacy_visibility', '=', 'portal'),
|
||||
('project_id.message_follower_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
|
||||
('project_id.message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
|
||||
'&',
|
||||
('project_id.privacy_visibility', '=', 'followers'),
|
||||
('project_id.message_follower_ids', 'in', [user.partner_id.id]),
|
||||
('project_id.message_partner_ids', 'in', [user.partner_id.id]),
|
||||
'&',
|
||||
# on employee project can receive messages but not access the object
|
||||
('project_id.privacy_visibility', '!=', 'employees'),
|
||||
('message_follower_ids', 'in', [user.partner_id.id])
|
||||
('message_partner_ids', 'in', [user.partner_id.id])
|
||||
]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
@@ -127,7 +127,9 @@ class TestPortalProject(TestPortalProjectBase):
|
||||
self.task_3.sudo(self.user_projectmanager).message_subscribe_users(user_ids=[self.user_portal.id, self.user_projectuser.id])
|
||||
|
||||
# Do: Alfred reads project -> ok (follower ok followers)
|
||||
pigs.sudo(self.user_projectuser).read(['state'])
|
||||
prout = pigs.sudo(self.user_projectuser)
|
||||
prout.invalidate_cache()
|
||||
prout.read(['state'])
|
||||
# Do: Chell reads project -> ok (follower ok follower)
|
||||
pigs.sudo(self.user_portal).read(['state'])
|
||||
# Do: Donovan reads project -> ko (public ko follower even if follower)
|
||||
|
||||
@@ -88,7 +88,7 @@ class TestProjectFlow(TestProjectBase):
|
||||
# Test: one task created by mailgateway administrator
|
||||
self.assertEqual(len(task), 1, 'project: message_process: a new project.task should have been created')
|
||||
# Test: check partner in message followers
|
||||
self.assertIn(self.partner_2, task.message_follower_ids, "Partner in message cc is not added as a task followers.")
|
||||
self.assertIn(self.partner_2, task.message_partner_ids, "Partner in message cc is not added as a task followers.")
|
||||
# Test: messages
|
||||
self.assertEqual(len(task.message_ids), 2,
|
||||
'project: message_process: newly created task should have 2 messages: creation and email')
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
('project_id.privacy_visibility', '=', 'employees'),
|
||||
'&',
|
||||
('project_id.privacy_visibility', '=', 'followers'),
|
||||
('message_follower_ids', 'in', [user.partner_id.id]),
|
||||
('message_partner_ids', 'in', [user.partner_id.id]),
|
||||
]</field>
|
||||
<field name="groups" eval="[(4,ref('base.group_user'))]"/>
|
||||
</record>
|
||||
@@ -27,10 +27,10 @@
|
||||
<field name="domain_force">['|',
|
||||
'&',
|
||||
('project_id.privacy_visibility', '=', 'portal'),
|
||||
('message_follower_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
|
||||
('message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
|
||||
'&',
|
||||
('project_id.privacy_visibility', '=', 'followers'),
|
||||
('message_follower_ids', 'in', [user.partner_id.id]),
|
||||
('message_partner_ids', 'in', [user.partner_id.id]),
|
||||
]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
@@ -41,7 +41,7 @@
|
||||
('project_id.privacy_visibility', 'in', ['portal', 'employees']),
|
||||
'&',
|
||||
('project_id.privacy_visibility', '=', 'followers'),
|
||||
('message_follower_ids', 'in', [user.partner_id.id]),
|
||||
('message_partner_ids', 'in', [user.partner_id.id]),
|
||||
]</field>
|
||||
</record>
|
||||
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
<field name="domain_force">['|',
|
||||
'&',
|
||||
('issue_id.project_id.privacy_visibility', '=', 'portal'),
|
||||
('issue_id.message_follower_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
|
||||
('issue_id.message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
|
||||
'&',
|
||||
('issue_id.project_id.privacy_visibility', '=', 'followers'),
|
||||
('issue_id.message_follower_ids', 'in', [user.partner_id.id]),
|
||||
('issue_id.message_partner_ids', 'in', [user.partner_id.id]),
|
||||
]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
@@ -11,10 +11,10 @@
|
||||
<field name="domain_force">['|',
|
||||
'&',
|
||||
('task_id.project_id.privacy_visibility', '=', 'portal'),
|
||||
('task_id.message_follower_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
|
||||
('task_id.message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
|
||||
'&',
|
||||
('task_id.project_id.privacy_visibility', '=', 'followers'),
|
||||
('task_id.message_follower_ids', 'in', [user.partner_id.id]),
|
||||
('task_id.message_partner_ids', 'in', [user.partner_id.id]),
|
||||
]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
@@ -21,7 +21,7 @@ class TestWebsiteBlogFlow(TestWebsiteBlogCommon):
|
||||
'name': 'New Blog',
|
||||
})
|
||||
self.assertIn(
|
||||
self.user_blogmanager.partner_id, test_blog.message_follower_ids,
|
||||
self.user_blogmanager.partner_id, test_blog.message_partner_ids,
|
||||
'website_blog: blog create should be in the blog followers')
|
||||
test_blog.message_subscribe([self.user_employee.partner_id.id, self.user_public.partner_id.id])
|
||||
|
||||
@@ -31,10 +31,10 @@ class TestWebsiteBlogFlow(TestWebsiteBlogCommon):
|
||||
'blog_id': test_blog.id,
|
||||
})
|
||||
self.assertNotIn(
|
||||
self.user_employee.partner_id, test_blog_post.message_follower_ids,
|
||||
self.user_employee.partner_id, test_blog_post.message_partner_ids,
|
||||
'website_blog: subscribing to a blog should not subscribe to its posts')
|
||||
self.assertNotIn(
|
||||
self.user_public.partner_id, test_blog_post.message_follower_ids,
|
||||
self.user_public.partner_id, test_blog_post.message_partner_ids,
|
||||
'website_blog: subscribing to a blog should not subscribe to its posts')
|
||||
|
||||
# Publish the blog
|
||||
@@ -55,5 +55,5 @@ class TestWebsiteBlogFlow(TestWebsiteBlogCommon):
|
||||
subtype='mt_comment',
|
||||
)
|
||||
self.assertIn(
|
||||
self.user_employee.partner_id, test_blog_post.message_follower_ids,
|
||||
self.user_employee.partner_id, test_blog_post.message_partner_ids,
|
||||
'website_blog: people commenting a post should follow it afterwards')
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<record id="portal_claim_rule" model="ir.rule">
|
||||
<field name="name">Portal Personal Claims</field>
|
||||
<field ref="crm_claim.model_crm_claim" name="model_id"/>
|
||||
<field name="domain_force">['|', ('message_follower_ids','in', [user.partner_id.id]), ('partner_id','=', user.partner_id.id)]</field>
|
||||
<field name="domain_force">['|', ('message_partner_ids','in', [user.partner_id.id]), ('partner_id','=', user.partner_id.id)]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
<field eval="0" name="perm_unlink"/>
|
||||
<field eval="0" name="perm_write"/>
|
||||
|
||||
@@ -114,7 +114,7 @@ class WebsiteForum(http.Controller):
|
||||
if filters == 'unanswered':
|
||||
domain += [('child_ids', '=', False)]
|
||||
elif filters == 'followed':
|
||||
domain += [('message_follower_ids', '=', request.env.user.partner_id.id)]
|
||||
domain += [('message_partner_ids', '=', request.env.user.partner_id.id)]
|
||||
if post_type:
|
||||
domain += [('post_type', '=', post_type)]
|
||||
|
||||
|
||||
@@ -73,6 +73,7 @@ class WebsiteMail(http.Controller):
|
||||
|
||||
@http.route(['/website_mail/follow'], type='json', auth="public", website=True)
|
||||
def website_message_subscribe(self, id=0, object=None, message_is_follower="on", email=False, **post):
|
||||
# TDE FIXME: check this method with new followers
|
||||
cr, uid, context = request.cr, request.uid, request.context
|
||||
|
||||
partner_obj = request.registry['res.partner']
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
<field name="state">sent</field>
|
||||
<field name="team_id" ref="sales_team.team_sales_department"/>
|
||||
<field name="date_order" eval="(DateTime.today() - relativedelta(months=1)).strftime('%Y-%m-%d %H:%M')"/>
|
||||
<field name="message_follower_ids" eval="[(4, ref('portal.partner_demo_portal'))]"/>
|
||||
<field name="message_partner_ids" eval="[(4, ref('portal.partner_demo_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_1" model="sale.order.line">
|
||||
@@ -52,7 +52,7 @@
|
||||
<field name="order_policy">manual</field>
|
||||
<field name="team_id" ref="sales_team.team_sales_department"/>
|
||||
<field name="date_order" eval="(DateTime.today() - relativedelta(months=1)).strftime('%Y-%m-%d %H:%M')"/>
|
||||
<field name="message_follower_ids" eval="[(4, ref('portal.partner_demo_portal'))]"/>
|
||||
<field name="message_partner_ids" eval="[(4, ref('portal.partner_demo_portal'))]"/>
|
||||
</record>
|
||||
|
||||
<record id="sale_order_line_4" model="sale.order.line">
|
||||
|
||||
@@ -10,13 +10,14 @@ class WebsiteAccount(website_account):
|
||||
def account(self):
|
||||
response = super(WebsiteAccount, self).account()
|
||||
user = request.env.user
|
||||
# TDE FIXME: shouldn't that be mnaged by the access rule itself ?
|
||||
# portal projects where you or someone from your company are a follower
|
||||
project_issues = request.env['project.issue'].search([
|
||||
'&',
|
||||
('project_id.privacy_visibility', '=', 'portal'),
|
||||
'|',
|
||||
('message_follower_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
|
||||
('message_follower_ids', 'child_of', [user.partner_id.id])
|
||||
('message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
|
||||
('message_partner_ids', 'child_of', [user.partner_id.id])
|
||||
])
|
||||
response.qcontext.update({'issues': project_issues})
|
||||
return response
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
<field name="domain_force">['|',
|
||||
'&',
|
||||
('project_id.privacy_visibility', '=', 'portal'),
|
||||
('message_follower_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
|
||||
('message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
|
||||
'&',
|
||||
('project_id.privacy_visibility', '=', 'followers'),
|
||||
('message_follower_ids', 'in', [user.partner_id.id]),
|
||||
('message_partner_ids', 'in', [user.partner_id.id]),
|
||||
]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
@@ -22,7 +22,7 @@
|
||||
('project_id.privacy_visibility', 'in', ['portal', 'employees']),
|
||||
'&',
|
||||
('project_id.privacy_visibility', '=', 'followers'),
|
||||
('message_follower_ids', 'in', [user.partner_id.id]),
|
||||
('message_partner_ids', 'in', [user.partner_id.id]),
|
||||
]</field>
|
||||
</record>
|
||||
</data>
|
||||
|
||||
@@ -8,10 +8,10 @@
|
||||
<field name="domain_force">['|',
|
||||
'&',
|
||||
('issue_id.project_id.privacy_visibility', '=', 'portal'),
|
||||
('issue_id.message_follower_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
|
||||
('issue_id.message_partner_ids', 'child_of', [user.partner_id.commercial_partner_id.id]),
|
||||
'&',
|
||||
('issue_id.project_id.privacy_visibility', '=', 'followers'),
|
||||
('issue_id.message_follower_ids', 'in', [user.partner_id.id]),
|
||||
('issue_id.message_partner_ids', 'in', [user.partner_id.id]),
|
||||
]</field>
|
||||
<field name="groups" eval="[(4, ref('base.group_portal'))]"/>
|
||||
</record>
|
||||
|
||||
@@ -589,7 +589,7 @@ class website_sale(http.Controller):
|
||||
|
||||
order_info = {
|
||||
'partner_id': partner_id,
|
||||
'message_follower_ids': [(4, partner_id), (3, request.website.partner_id.id)],
|
||||
'message_partner_ids': [(4, partner_id), (3, request.website.partner_id.id)],
|
||||
'partner_invoice_id': partner_id,
|
||||
}
|
||||
order_info.update(order_obj.onchange_partner_id(cr, SUPERUSER_ID, [], partner_id, context=context)['value'])
|
||||
|
||||
Reference in New Issue
Block a user