From 675623d39022c57c0ebda7c988aec6ea467fade5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Thibault=20Delavall=C3=A9e?= Date: Fri, 8 Jan 2021 11:36:05 +0000 Subject: [PATCH] [REF] crm: simplify evaluation of assignment domains GLOBAL PURPOSE Ability to have salesmen belonging to several sales team is a core requirement of CRM. It is therefore moved from website_crm_score to crm along with cleaning and behavior improvement. Automatic lead assignment is also moved and cleaned. SPECIFICATIONS Remove safe_eval and its support of datetime and context_today. Check in existing dbs show that it is not used in team or member assignment domains. We therefore choose to limit content of domains to what goes through a literal_eval. It allows to reduce potential issues. We also improve warning messages in order to give clearer message to users when dealing with input errors. LINKS Task ID-2086889 (main task) Task ID-2357969 (scoring migration task) Community PR odoo/odoo#48422 Enterprise PR odoo/enterprise#499 Upgrade PR odoo/upgrade#996 --- addons/crm/models/crm_lead.py | 6 ------ addons/crm/models/crm_team.py | 10 +++++----- addons/crm/models/crm_team_member.py | 16 ++++++++++------ 3 files changed, 15 insertions(+), 17 deletions(-) diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py index 508a72cd079..c28cbe080f7 100644 --- a/addons/crm/models/crm_lead.py +++ b/addons/crm/models/crm_lead.py @@ -71,12 +71,6 @@ PARTNER_ADDRESS_FIELDS_TO_SYNC = [ PLS_COMPUTE_BATCH_STEP = 50000 # odoo.models.PREFETCH_MAX = 1000 but larger cluster can speed up global computation PLS_UPDATE_BATCH_STEP = 5000 -# Evaluation context for all domain-based lead auto assignment -LEAD_ASSIGN_EVAL_CONTEXT = { - 'datetime': safe_eval.datetime, - 'context_today': datetime.now, -} - class Lead(models.Model): _name = "crm.lead" diff --git a/addons/crm/models/crm_team.py b/addons/crm/models/crm_team.py index 927defc8c22..48073e744b2 100644 --- a/addons/crm/models/crm_team.py +++ b/addons/crm/models/crm_team.py @@ -9,7 +9,6 @@ import threading from ast import literal_eval from odoo import api, exceptions, fields, models, _ -from odoo.addons.crm.models.crm_lead import LEAD_ASSIGN_EVAL_CONTEXT from odoo.osv import expression from odoo.tools.safe_eval import safe_eval @@ -118,10 +117,11 @@ class Team(models.Model): def _constrains_assignment_domain(self): for team in self: try: - domain = safe_eval(team.assignment_domain or '[]', LEAD_ASSIGN_EVAL_CONTEXT) - self.env['crm.lead'].search_count(domain) + domain = literal_eval(team.assignment_domain or '[]') + if domain: + self.env['crm.lead'].search(domain, limit=1) except Exception: - raise Warning('Domain for %s is incorrectly formatted' % team.name) + raise exceptions.ValidationError(_('Assignment domain for team %(team)s is incorrectly formatted', team=team.name)) # ------------------------------------------------------------ # ORM @@ -419,7 +419,7 @@ class Team(models.Model): # compute assign domain for each team before looping on them by bundle size teams_domain = dict( - (team, safe_eval(team.assignment_domain or '[]', LEAD_ASSIGN_EVAL_CONTEXT)) + (team, literal_eval(team.assignment_domain or '[]')) for team in remaining_teams ) # compute limit of leads to assign to each team: 2 times team capacity, based on given work_days diff --git a/addons/crm/models/crm_team_member.py b/addons/crm/models/crm_team_member.py index ddb5c9db0c7..e1776761c85 100644 --- a/addons/crm/models/crm_team_member.py +++ b/addons/crm/models/crm_team_member.py @@ -7,10 +7,10 @@ import math import threading import random +from ast import literal_eval + from odoo import api, exceptions, fields, models, _ -from odoo.addons.crm.models.crm_lead import LEAD_ASSIGN_EVAL_CONTEXT from odoo.osv import expression -from odoo.tools import safe_eval _logger = logging.getLogger(__name__) @@ -38,10 +38,14 @@ class Team(models.Model): def _constrains_assignment_domain(self): for member in self: try: - domain = safe_eval.safe_eval(member.assignment_domain or '[]', LEAD_ASSIGN_EVAL_CONTEXT) - self.env['crm.lead'].search(domain, limit=1) + domain = literal_eval(member.assignment_domain or '[]') + if domain: + self.env['crm.lead'].search(domain, limit=1) except Exception: - raise exceptions.UserError(_('Team membership assign domain is incorrectly formatted')) + raise exceptions.ValidationEreror(_( + 'Member assignment domain for user %(user)s and team %(team)s is incorrectly formatted', + user=member.user_id.name, team=member.crm_team_id.name + )) def _get_lead_month_domain(self): limit_date = fields.Datetime.now() - datetime.timedelta(days=30) @@ -133,7 +137,7 @@ class Team(models.Model): # could probably be optimized for member in members: lead_domain = expression.AND([ - safe_eval.safe_eval(member.assignment_domain or '[]', LEAD_ASSIGN_EVAL_CONTEXT), + literal_eval(member.assignment_domain or '[]'), ['&', '&', ('user_id', '=', False), ('date_open', '=', False), ('team_id', '=', member.crm_team_id.id)] ])