[FIX] im_livechat: fix operator assignation
Before this PR, trying to get an available operator could result in an error. When a live chat is created, an operator is selected based on various criteria such as language, country, number of ongoing chats and availability for calls. This selection process involves the `_get_less_active_operator` method, which receives the status of all operators and a list of operators to choose from. Prior to this fix, an operator not included in the list of operators to choose from could still be selected, resulting in errors when trying to locate them in the operator list. This PR resolves the issue by ensuring that operators are only selected from the provided list. opw-3874872 closes odoo/odoo#162357 Signed-off-by: Matthieu Stockbauer (tsm) <tsm@odoo.com>
This commit is contained in:
@@ -187,23 +187,32 @@ class ImLivechatChannel(models.Model):
|
||||
operator is in a call. The list is ordered by the number of active
|
||||
chats (ascending) and whether the operator is in a call
|
||||
(descending).
|
||||
:param operators: list of operators to choose from
|
||||
:param operators: recordset of :class:`ResUsers` operators to choose from.
|
||||
:return: the :class:`ResUsers` record for the chosen operator
|
||||
"""
|
||||
if not operators:
|
||||
return False
|
||||
active_operator_ids = set(map(lambda s: s['livechat_operator_id'], operator_statuses))
|
||||
inactive_operators = [
|
||||
operator for operator in operators if operator.partner_id.id not in active_operator_ids
|
||||
|
||||
# 1) only consider operators in the list to choose from
|
||||
operator_statuses = [
|
||||
s for s in operator_statuses if s['livechat_operator_id'] in set(operators.partner_id.ids)
|
||||
]
|
||||
if inactive_operators:
|
||||
return random.choice(inactive_operators)
|
||||
count, in_call = itemgetter('count', 'in_call')(operator_statuses[0])
|
||||
i = 1
|
||||
while i < len(operator_statuses) and operator_statuses[i]['in_call'] == in_call and operator_statuses[i]['count'] == count:
|
||||
i += 1
|
||||
less_active_operator_id = random.choice(operator_statuses[:i])['livechat_operator_id']
|
||||
# convert the selected 'partner_id' to its corresponding res.users
|
||||
return next(operator for operator in operators if operator.partner_id.id == less_active_operator_id)
|
||||
|
||||
# 2) try to select an inactive op, i.e. one w/ no active status (no recent chat)
|
||||
active_op_partner_ids = {s['livechat_operator_id'] for s in operator_statuses}
|
||||
candidates = operators.filtered(lambda o: o.partner_id.id not in active_op_partner_ids)
|
||||
if candidates:
|
||||
return random.choice(candidates)
|
||||
|
||||
# 3) otherwise select least active ops, based on status ordering (count + in_call)
|
||||
best_status = operator_statuses[0]
|
||||
best_status_op_partner_ids = {
|
||||
s['livechat_operator_id']
|
||||
for s in operator_statuses
|
||||
if (s['count'], s['in_call']) == (best_status['count'], best_status['in_call'])
|
||||
}
|
||||
candidates = operators.filtered(lambda o: o.partner_id.id in best_status_op_partner_ids)
|
||||
return random.choice(candidates)
|
||||
|
||||
def _get_operator(self, previous_operator_id=None, lang=None, country_id=None):
|
||||
""" Return an operator for a livechat. Try to return the previous
|
||||
|
||||
@@ -66,6 +66,20 @@ class TestGetOperator(HttpCase):
|
||||
self.assertEqual(fr_operator, livechat_channel._get_operator(lang="fr_FR"))
|
||||
self.assertEqual(en_operator, livechat_channel._get_operator(lang="en_US"))
|
||||
|
||||
def test_get_by_lang_both_operator_active(self):
|
||||
fr_operator = self._create_operator("fr_FR")
|
||||
en_operator = self._create_operator("en_US")
|
||||
livechat_channel = self.env["im_livechat.channel"].create(
|
||||
{
|
||||
"name": "Livechat Channel",
|
||||
"user_ids": [fr_operator.id, en_operator.id],
|
||||
}
|
||||
)
|
||||
self._create_chat(livechat_channel, fr_operator)
|
||||
self._create_chat(livechat_channel, en_operator)
|
||||
self._create_chat(livechat_channel, en_operator)
|
||||
self.assertEqual(en_operator, livechat_channel._get_operator(lang="en_US"))
|
||||
|
||||
def test_get_by_lang_no_operator_matching_lang(self):
|
||||
fr_operator = self._create_operator("fr_FR")
|
||||
livechat_channel = self.env["im_livechat.channel"].create(
|
||||
|
||||
Reference in New Issue
Block a user