summaryrefslogtreecommitdiff
path: root/addons
diff options
context:
space:
mode:
Diffstat (limited to 'addons')
-rw-r--r--addons/im_livechat/models/im_livechat_channel.py48
-rw-r--r--addons/im_livechat/tests/__init__.py4
-rw-r--r--addons/im_livechat/tests/test_get_mail_channel.py60
3 files changed, 107 insertions, 5 deletions
diff --git a/addons/im_livechat/models/im_livechat_channel.py b/addons/im_livechat/models/im_livechat_channel.py
index acba917036c..4a682c912f1 100644
--- a/addons/im_livechat/models/im_livechat_channel.py
+++ b/addons/im_livechat/models/im_livechat_channel.py
@@ -142,12 +142,9 @@ class ImLivechatChannel(models.Model):
:rtype : dict
"""
self.ensure_one()
- # get the avalable user of the channel
- operators = self._get_available_users()
- if len(operators) == 0:
+ operator = self._get_random_operator()
+ if not operator:
return False
- # choose the res.users operator and get its partner id
- operator = random.choice(operators)
operator_partner_id = operator.partner_id.id
# partner to add to the mail.channel
channel_partner_to_add = [(4, operator_partner_id)]
@@ -168,6 +165,47 @@ class ImLivechatChannel(models.Model):
mail_channel._broadcast([operator_partner_id])
return mail_channel.sudo().channel_info()[0]
+ def _get_random_operator(self):
+ """ Return a random operator from the available users of the channel that have the lowest number of active livechats.
+ A livechat is considered 'active' if it has at least one message within the 30 minutes.
+
+ (Some annoying conversions have to be made on the fly because this model holds 'res.users' as available operators
+ and the mail_channel model stores the partner_id of the randomly selected operator)
+
+ :return : user
+ :rtype : res.users
+ """
+ operators = self._get_available_users()
+ if len(operators) == 0:
+ return False
+
+ self.env.cr.execute("""SELECT COUNT(DISTINCT c.id), c.livechat_operator_id
+ FROM mail_channel c
+ LEFT OUTER JOIN mail_message_mail_channel_rel r ON c.id = r.mail_channel_id
+ LEFT OUTER JOIN mail_message m ON r.mail_message_id = m.id
+ WHERE m.create_date > ((now() at time zone 'UTC') - interval '30 minutes')
+ AND c.channel_type = 'livechat'
+ AND c.livechat_operator_id in %s
+ GROUP BY c.livechat_operator_id
+ ORDER BY COUNT(DISTINCT c.id) asc""", (tuple(operators.mapped('partner_id').ids),))
+ active_channels = self.env.cr.dictfetchall()
+
+ # If inactive operator(s), return one of them
+ active_channel_operator_ids = [active_channel['livechat_operator_id'] for active_channel in active_channels]
+ inactive_operators = [operator for operator in operators if operator.partner_id.id not in active_channel_operator_ids]
+ if inactive_operators:
+ return random.choice(inactive_operators)
+
+ # If no inactive operator, active_channels is not empty as len(operators) > 0 (see above).
+ # Get the less active operator using the active_channels first element's count (since they are sorted 'ascending')
+ lowest_number_of_conversations = active_channels[0]['count']
+ less_active_operator = random.choice([
+ active_channel['livechat_operator_id'] for active_channel in active_channels
+ if active_channel['count'] == lowest_number_of_conversations])
+
+ # 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)
+
def _get_channel_infos(self):
self.ensure_one()
diff --git a/addons/im_livechat/tests/__init__.py b/addons/im_livechat/tests/__init__.py
new file mode 100644
index 00000000000..a22a67032d1
--- /dev/null
+++ b/addons/im_livechat/tests/__init__.py
@@ -0,0 +1,4 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from . import test_get_mail_channel
diff --git a/addons/im_livechat/tests/test_get_mail_channel.py b/addons/im_livechat/tests/test_get_mail_channel.py
new file mode 100644
index 00000000000..ac3d5807333
--- /dev/null
+++ b/addons/im_livechat/tests/test_get_mail_channel.py
@@ -0,0 +1,60 @@
+# -*- coding: utf-8 -*-
+# Part of Odoo. See LICENSE file for full copyright and licensing details.
+
+from odoo.tests.common import TransactionCase
+
+
+class TestGetMailChannel(TransactionCase):
+ def setUp(self):
+ super(TestGetMailChannel, self).setUp()
+ self.operators = self.env['res.users'].create([{
+ 'name': 'Michel',
+ 'login': 'michel'
+ }, {
+ 'name': 'Paul',
+ 'login': 'paul'
+ }, {
+ 'name': 'Pierre',
+ 'login': 'pierre'
+ }, {
+ 'name': 'Jean',
+ 'login': 'jean'
+ }, {
+ 'name': 'Georges',
+ 'login': 'georges'
+ }])
+
+ self.livechat_channel = self.env['im_livechat.channel'].create({
+ 'name': 'The channel',
+ 'user_ids': (6, 0, self.operators.ids)
+ })
+
+ operators = self.operators
+ def get_available_users(self):
+ return operators
+
+ self.patch(type(self.env['im_livechat.channel']), '_get_available_users', get_available_users)
+
+ def test_get_mail_channel(self):
+ """For a livechat with 5 available operators, we open 5 channels 5 times (25 channels total).
+ For every 5 channels opening, we check that all operators were assigned.
+ """
+
+ for i in range(5):
+ mail_channels = self._get_mail_channels()
+ channel_operators = [channel_info['operator_pid'] for channel_info in mail_channels]
+ channel_operator_ids = [channel_operator[0] for channel_operator in channel_operators]
+ self.assertTrue(all(partner_id in channel_operator_ids for partner_id in self.operators.mapped('partner_id').ids))
+
+ def _get_mail_channels(self):
+ mail_channels = []
+
+ for i in range(5):
+ mail_channel = self.livechat_channel._get_mail_channel('Anonymous')
+ mail_channels.append(mail_channel)
+ # send a message to mark this channel as 'active'
+ self.env['mail.channel'].browse(mail_channel['id']).write({
+ 'channel_message_ids': [(0, 0, {'body': 'cc'})]
+ })
+
+ return mail_channels