105 lines
4.1 KiB
Python
105 lines
4.1 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
from odoo import api, fields, models
|
|
from odoo.osv import expression
|
|
from odoo.tools import SQL
|
|
from odoo.addons.mail.tools.discuss import Store
|
|
|
|
|
|
class ResPartner(models.Model):
|
|
_inherit = "res.partner"
|
|
|
|
channel_ids = fields.Many2many(
|
|
"discuss.channel",
|
|
"discuss_channel_member",
|
|
"partner_id",
|
|
"channel_id",
|
|
string="Channels",
|
|
copy=False,
|
|
)
|
|
|
|
@api.readonly
|
|
@api.model
|
|
def search_for_channel_invite(self, search_term, channel_id=None, limit=30):
|
|
"""Returns partners matching search_term that can be invited to a channel.
|
|
If the channel_id is specified, only partners that can actually be invited to the channel
|
|
are returned (not already members, and in accordance to the channel configuration).
|
|
"""
|
|
domain = expression.AND(
|
|
[
|
|
expression.OR(
|
|
[
|
|
[("name", "ilike", search_term)],
|
|
[("email", "ilike", search_term)],
|
|
]
|
|
),
|
|
[("active", "=", True)],
|
|
[("user_ids", "!=", False)],
|
|
[("user_ids.active", "=", True)],
|
|
[("user_ids.share", "=", False)],
|
|
]
|
|
)
|
|
channel = self.env["discuss.channel"]
|
|
if channel_id:
|
|
channel = self.env["discuss.channel"].search([("id", "=", int(channel_id))])
|
|
domain = expression.AND([domain, [("channel_ids", "not in", channel.id)]])
|
|
if channel.group_public_id:
|
|
domain = expression.AND(
|
|
[domain, [("user_ids.groups_id", "in", channel.group_public_id.id)]]
|
|
)
|
|
query = self._search(domain, limit=limit)
|
|
# bypass lack of support for case insensitive order in search()
|
|
query.order = SQL('LOWER(%s), "res_partner"."id"', self._field_to_sql(self._table, "name"))
|
|
store = Store()
|
|
self.env["res.partner"].browse(query)._search_for_channel_invite_to_store(store, channel)
|
|
return {
|
|
"count": self.env["res.partner"].search_count(domain),
|
|
"data": store.get_result(),
|
|
}
|
|
|
|
def _search_for_channel_invite_to_store(self, store: Store, channel):
|
|
store.add(self)
|
|
|
|
@api.readonly
|
|
@api.model
|
|
def get_mention_suggestions_from_channel(self, channel_id, search, limit=8):
|
|
"""Return 'limit'-first partners' such that the name or email matches a 'search' string.
|
|
Prioritize partners that are also (internal) users, and then extend the research to all partners.
|
|
Only members of the given channel are returned.
|
|
The return format is a list of partner data (as per returned by `_to_store()`).
|
|
"""
|
|
channel = self.env["discuss.channel"].search([("id", "=", channel_id)])
|
|
if not channel:
|
|
return []
|
|
domain = expression.AND(
|
|
[
|
|
self._get_mention_suggestions_domain(search),
|
|
[("channel_ids", "in", channel.id)],
|
|
]
|
|
)
|
|
extra_domain = expression.AND([
|
|
[('user_ids', '!=', False)],
|
|
[('user_ids.active', '=', True)],
|
|
[('partner_share', '=', False)]
|
|
])
|
|
allowed_group = (channel.parent_channel_id or channel).group_public_id
|
|
if allowed_group:
|
|
extra_domain = expression.AND(
|
|
[
|
|
extra_domain,
|
|
[("user_ids.groups_id", "in", allowed_group.id)],
|
|
]
|
|
)
|
|
partners = self._search_mention_suggestions(domain, limit, extra_domain)
|
|
members = self.env["discuss.channel.member"].search(
|
|
[
|
|
("channel_id", "=", channel.id),
|
|
("partner_id", "in", partners.ids),
|
|
]
|
|
)
|
|
store = Store(members, fields={"channel": [], "persona": []})
|
|
if allowed_group:
|
|
for p in partners:
|
|
store.add(p, {"groups_id": [("ADD", (allowed_group & p.user_ids.groups_id).ids)]})
|
|
return store.get_result()
|