[FIX] mail: prioritize internal users when looking for mentions

Since https://github.com/odoo/odoo/pull/73689 all internal users are no longer
known at init. Unlike what was stated in the corresponding PR, the code of
mentions wasn't actually good enough to allow it without any drawback.

This PR fixes the issue by prioritizing internal users on the result of the RPC.

As a bonus the internal user state is immediately returned when fetching
followers, which allows mentions to be accurate even before the RPC is done.

task-2695224

closes odoo/odoo#80645

X-original-commit: 86de2f231be87b289deb85c3b20b93d890cce918
Signed-off-by: Alexandre Kühn (aku) <aku@odoo.com>
This commit is contained in:
Sébastien Theys
2021-11-30 18:23:49 +00:00
parent ef70369eaa
commit 08a3df6428
4 changed files with 32 additions and 13 deletions
+2 -1
View File
@@ -416,7 +416,8 @@ class DiscussController(http.Controller):
'is_active': follower.is_active,
# When editing the followers, the "pencil" icon that leads to the edition of subtypes
# should be always be displayed and not only when "debug" mode is activated.
'is_editable': True
'is_editable': True,
'partner': follower.partner_id.mail_partner_format()[follower.partner_id],
})
return {
'followers': followers,
+13 -11
View File
@@ -187,7 +187,7 @@ class Partner(models.Model):
@api.model
def get_mention_suggestions(self, search, limit=8, channel_id=None):
""" Return 'limit'-first partners' such that the name or email matches a 'search' string.
Prioritize partners that are also users, and then extend the research to all partners.
Prioritize partners that are also (internal) users, and then extend the research to all partners.
If channel_id is given, only members of this channel are returned.
The return format is a list of partner data (as per returned by `mail_partner_format()`).
"""
@@ -195,16 +195,18 @@ class Partner(models.Model):
search_dom = expression.AND([[('active', '=', True), ('type', '!=', 'private')], search_dom])
if channel_id:
search_dom = expression.AND([[('channel_ids', 'in', channel_id)], search_dom])
# Search partners that are also users
domain = expression.AND([[('user_ids.id', '!=', False), ('user_ids.active', '=', True)], search_dom])
partners = self.search(domain, limit=limit)
# Search partners that are not users if less than 'limit' partner that are users found
remaining_limit = limit - len(partners)
if remaining_limit > 0:
partners |= self.search(expression.AND([[('id', 'not in', partners.ids)], search_dom]), limit=remaining_limit)
domain_is_user = expression.AND([[('user_ids.id', '!=', False), ('user_ids.active', '=', True)], search_dom])
priority_conditions = [
expression.AND([domain_is_user, [('partner_share', '=', False)]]), # Search partners that are internal users
domain_is_user, # Search partners that are users
search_dom, # Search partners that are not users
]
partners = self.env['res.partner']
for domain in priority_conditions:
remaining_limit = limit - len(partners)
if remaining_limit <= 0:
break
partners |= self.search(expression.AND([[('id', 'not in', partners.ids)], domain]), limit=remaining_limit)
return list(partners.mail_partner_format().values())
@api.model
@@ -36,6 +36,9 @@ registerModel({
data2.partner = insert(partnerData);
}
}
if (data.partner) {
data2.partner = insertAndReplace(this.models['mail.partner'].convertData(data.partner));
}
return data2;
},
},
+14 -1
View File
@@ -1,7 +1,9 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from odoo.addons.mail.tests.common import MailCommon
from uuid import uuid4
from odoo.addons.mail.tests.common import MailCommon, mail_new_test_user
from odoo.tests.common import Form, users
@@ -126,6 +128,17 @@ class TestPartner(MailCommon):
self.assertIn('Portal Access Granted', new_msg.body)
self.assertEqual(new_msg.subtype_id, subtype_note)
def test_res_partner_get_mention_suggestions_priority(self):
name = uuid4() # unique name to avoid conflict with already existing users
self.env['res.partner'].create([{'name': f'{name}-{i}-not-user'} for i in range(0, 2)])
for i in range(0, 2):
mail_new_test_user(self.env, login=f'{name}-{i}-portal-user', groups='base.group_portal')
mail_new_test_user(self.env, login=f'{name}-{i}-internal-user', groups='base.group_user')
partners_format = self.env['res.partner'].get_mention_suggestions(name, limit=5)
self.assertEqual(len(partners_format), 5, "should have found limit (5) partners")
self.assertEqual(list(map(lambda p: p['is_internal_user'], partners_format)), [True, True, False, False, False], "should return internal users in priority")
self.assertEqual(list(map(lambda p: bool(p['user_id']), partners_format)), [True, True, True, True, False], "should return partners without users last")
@users('admin')
def test_res_partner_merge_wizards(self):
Partner = self.env['res.partner']