Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[FIX] im_livechat: fix operator assignation #162357

Conversation

tsm-odoo
Copy link
Contributor

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

@robodoo
Copy link
Contributor

robodoo commented Apr 18, 2024

@C3POdoo C3POdoo requested a review from a team April 18, 2024 05:55
@C3POdoo C3POdoo added the OE the report is linked to a support ticket (opw-...) label Apr 18, 2024
@tsm-odoo tsm-odoo force-pushed the 17.0-im_livechat-fix_get_less_active_operator-tsm branch from 3d4d7bb to 7512e33 Compare April 18, 2024 06:31
Copy link
Contributor

@phenix-factory phenix-factory left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tsm-odoo tsm-odoo force-pushed the 17.0-im_livechat-fix_get_less_active_operator-tsm branch 2 times, most recently from 4b5dade to 4fdf418 Compare April 18, 2024 06:55
Copy link
Contributor

@odony odony left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@tsm-odoo thanks for the quick fix and the test!

@robodoo delegate+ (an update has discarded @phenix-factory's review)

Additionally, may I offer the following nitpicking for free? ;-)

🧦 The code of _get_less_active_operator() seems too "clever" and (prematurely) optimised, and this tends to make it harder to read, and possibly more difficult to get right / maintain.

Considering that it's not designed to deal with large volumes of records (it's bounded by the number of connected operators), I think it might be good to make the code more straightforward and explicit, even if less optimized.

Here's a suggestion for such a rewrite, assuming I got it right.
I've slightly altered the parameter names to increase readability, as they seem to always be passed positionally. To be strictly conservative with API stability we might want to preserve the original ones.

def _get_less_active_operator(self, active_operator_statuses, available_operators):
    """ Retrieve the most available operator based on the following criteria:
    - Lowest number of active chats.
    - Not in  a call.
    - If an operator is in a call and has two or more active chats, don't
      give priority over an operator with more conversations who is not in a
      call.

    :param active_operator_statuses: list of dictionaries containing the operator's
        id, the number of active chats and a boolean indicating if the
        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 available_operators: recordset of :class:`ResUsers` operators to choose from.
    :return: the :class:`ResUsers` record for the chosen operator
    """
    if not available_operators:
        return False

    # 1) first try to select an inactive op, i.e. one w/ no active status (no recent chat)
    active_op_partner_ids = set(s['livechat_operator_id'] for s in active_operator_statuses)
    candidates = available_operators.filtered(lambda o: o.partner_id.id not in active_op_partner_ids)
    if candidates:
        return random.choice(candidates)

    # 2) otherwise select least active ops, based on status ordering (count + in_call)
    best_status = active_operator_statuses[0]  # best means "least active"
    best_status_op_partner_ids = set(
         s['livechat_operator_id']
         for s in active_operator_statuses
         if (s['count'], s['in_call']) == (best_status['count'], best_status['in_call'])
    )
    candidates = available_operators.filtered(lambda o: o.partner_id.id in best_status_op_partner_ids)
    return random.choice(candidates)

What do you think? It doesn't have optimal run time complexity for some operations, but considering that we're dealing with small lists (likely less than 10 or 100 items), it won't make any measurable difference.
And the code simplicity and readability is worth it, IMO.

I leave it up to you, your current fix is fine too ;-)

@alexkuhn
Copy link
Contributor

@odony Also the code would also be much simpler in general if available_operator_ids was a many on res.partner rather than res.users.

@odony
Copy link
Contributor

odony commented Apr 19, 2024

@odony Also the code would also be much simpler in general if available_operator_ids was a many on res.partner rather than res.users.

Certainly, but operators are supposed to be users, not just partners, so that m2m seems correctly defined, I think. An alternative is to retrieve the user IDs as well as part of the operator_statuses, for a (hopefully small) extra SQL cost.

@tsm-odoo tsm-odoo force-pushed the 17.0-im_livechat-fix_get_less_active_operator-tsm branch 2 times, most recently from e6d5730 to 0062ec1 Compare April 19, 2024 08:32
@tsm-odoo
Copy link
Contributor Author

Hello @odony,

Thank you for your advice; it's definitely simpler! I noticed a small mistake in the algorithm's second part. It initially retrieves the best_status from the list of all available operators, whereas it should only consider the best status for operators we want to choose from. To solve this, I filtered the list of operator_statuses to only include operators we are allowed to choose from, and I updated the test to reflect this scenario.

@tsm-odoo tsm-odoo force-pushed the 17.0-im_livechat-fix_get_less_active_operator-tsm branch 2 times, most recently from c45b9cf to 030a4b7 Compare April 19, 2024 08:41
Copy link
Contributor

@alexkuhn alexkuhn left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@robodoo
Copy link
Contributor

robodoo commented Apr 19, 2024

@alexkuhn you may want to rebuild or fix this PR as it has failed CI.

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
@tsm-odoo tsm-odoo force-pushed the 17.0-im_livechat-fix_get_less_active_operator-tsm branch from 030a4b7 to aa7acf5 Compare April 19, 2024 15:22
@tsm-odoo
Copy link
Contributor Author

@robodoo r+

Rebased to latest 17.0 to fix already fixed runbot error.

robodoo pushed a commit that referenced this pull request Apr 19, 2024
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 #162357

Signed-off-by: Matthieu Stockbauer (tsm) <tsm@odoo.com>
@robodoo robodoo closed this in 09295d2 Apr 20, 2024
goffauxs pushed a commit to odoo-dev/odoo that referenced this pull request Apr 25, 2024
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#162357

Signed-off-by: Matthieu Stockbauer (tsm) <tsm@odoo.com>
willylohws pushed a commit to willylohws/odoo that referenced this pull request May 1, 2024
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#162357

Signed-off-by: Matthieu Stockbauer (tsm) <tsm@odoo.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
OE the report is linked to a support ticket (opw-...)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

6 participants