diff --git a/addons/mail/controllers/discuss.py b/addons/mail/controllers/discuss.py index 3ef41e6901d..dc8f575b0f8 100644 --- a/addons/mail/controllers/discuss.py +++ b/addons/mail/controllers/discuss.py @@ -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, diff --git a/addons/mail/models/res_partner.py b/addons/mail/models/res_partner.py index 681a42c72d4..2907006766c 100644 --- a/addons/mail/models/res_partner.py +++ b/addons/mail/models/res_partner.py @@ -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 diff --git a/addons/mail/static/src/models/follower/follower.js b/addons/mail/static/src/models/follower/follower.js index 68fdcfb2118..13b7e713f6c 100644 --- a/addons/mail/static/src/models/follower/follower.js +++ b/addons/mail/static/src/models/follower/follower.js @@ -36,6 +36,9 @@ registerModel({ data2.partner = insert(partnerData); } } + if (data.partner) { + data2.partner = insertAndReplace(this.models['mail.partner'].convertData(data.partner)); + } return data2; }, }, diff --git a/addons/mail/tests/test_res_partner.py b/addons/mail/tests/test_res_partner.py index be9784d0717..c2fb68464c2 100644 --- a/addons/mail/tests/test_res_partner.py +++ b/addons/mail/tests/test_res_partner.py @@ -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']