[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:
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
},
|
||||
},
|
||||
|
||||
@@ -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']
|
||||
|
||||
Reference in New Issue
Block a user