[IMP] crm: when unlink team, merge its pls frequencies with "no team" frequencies

PURPOSE

Purpose is to avoid loosing frequencies and also avoid rebuilding the whole
frequency table. We choose to merge frequencies from team about to be unlinked
with "no team" frequencies.

SPECIFICATIONS

Update PLS frequencies of "no team" leads when unlinking teams. Instead
of loosing those statistics merging them with "no team" is probably better even
if not completely right. Removing teams with a lot of PLS information is
something that is not a primary use case

LINKS

Task ID-2507750
COM PR odoo#70645
This commit is contained in:
Thibault Delavallée
2021-06-23 08:56:40 +00:00
parent ec59b73c04
commit dedfbd0c4f
3 changed files with 120 additions and 3 deletions
@@ -12,7 +12,6 @@ class LeadScoringFrequency(models.Model):
lost_count = fields.Float('Lost Count', digits=(16, 1)) # Float because we add 0.1 to avoid zero Frequency issue
team_id = fields.Many2one('crm.team', 'Sales Team', ondelete="cascade")
class FrequencyField(models.Model):
_name = 'crm.lead.scoring.frequency.field'
_description = 'Fields that can be used for predictive lead scoring computation'
+37
View File
@@ -10,6 +10,7 @@ from ast import literal_eval
from odoo import api, exceptions, fields, models, _
from odoo.osv import expression
from odoo.tools import float_compare, float_round
from odoo.tools.safe_eval import safe_eval
_logger = logging.getLogger(__name__)
@@ -138,6 +139,42 @@ class Team(models.Model):
})
return result
def unlink(self):
""" When unlinking, concatenate ``crm.lead.scoring.frequency`` linked to
the team into "no team" statistics. """
frequencies = self.env['crm.lead.scoring.frequency'].search([('team_id', 'in', self.ids)])
if frequencies:
existing_noteam = self.env['crm.lead.scoring.frequency'].sudo().search([
('team_id', '=', False),
('variable', 'in', frequencies.mapped('variable'))
])
for frequency in frequencies:
# skip void-like values
if float_compare(frequency.won_count, 0.1, 2) != 1 and float_compare(frequency.lost_count, 0.1, 2) != 1:
continue
match = existing_noteam.filtered(lambda frequ_nt: frequ_nt.variable == frequency.variable and frequ_nt.value == frequency.value)
if match:
# remove extra .1 that may exist in db as those are artifacts of initializing
# frequency table. Final value of 0 will be set to 0.1.
exist_won_count = float_round(match.won_count, precision_digits=0, rounding_method='HALF-UP')
exist_lost_count = float_round(match.lost_count, precision_digits=0, rounding_method='HALF-UP')
add_won_count = float_round(frequency.won_count, precision_digits=0, rounding_method='HALF-UP')
add_lost_count = float_round(frequency.lost_count, precision_digits=0, rounding_method='HALF-UP')
new_won_count = exist_won_count + add_won_count
new_lost_count = exist_lost_count + add_lost_count
match.won_count = new_won_count if float_compare(new_won_count, 0.1, 2) == 1 else 0.1
match.lost_count = new_lost_count if float_compare(new_lost_count, 0.1, 2) == 1 else 0.1
else:
existing_noteam += self.env['crm.lead.scoring.frequency'].sudo().create({
'lost_count': frequency.lost_count if float_compare(frequency.lost_count, 0.1, 2) == 1 else 0.1,
'team_id': False,
'value': frequency.value,
'variable': frequency.variable,
'won_count': frequency.won_count if float_compare(frequency.won_count, 0.1, 2) == 1 else 0.1,
})
return super(Team, self).unlink()
# ------------------------------------------------------------
# MESSAGING
# ------------------------------------------------------------
+83 -2
View File
@@ -3,14 +3,35 @@
from datetime import timedelta
from odoo.tests.common import TransactionCase
from odoo.tests import Form
from odoo import tools
from odoo.addons.mail.tests.common import mail_new_test_user
from odoo.fields import Date
from odoo.tests import Form, tagged, users
from odoo.tests.common import TransactionCase
@tagged('crm_lead_pls')
class TestCRMPLS(TransactionCase):
@classmethod
def setUpClass(cls):
""" Keep a limited setup to ensure tests are not impacted by other
records created in CRM common. """
super(TestCRMPLS, cls).setUpClass()
cls.company_main = cls.env.user.company_id
cls.user_sales_manager = mail_new_test_user(
cls.env, login='user_sales_manager',
name='Martin PLS Sales Manager', email='crm_manager@test.example.com',
company_id=cls.company_main.id,
notification_type='inbox',
groups='sales_team.group_sale_manager,base.group_partner_manager',
)
cls.pls_team = cls.env['crm.team'].create({
'name': 'PLS Team',
})
def _get_lead_values(self, team_id, name_suffix, country_id, state_id, email_state, phone_state, source_id, stage_id):
return {
'name': 'lead_' + name_suffix,
@@ -478,3 +499,63 @@ class TestCRMPLS(TransactionCase):
res_config_new = resConfig.new()
self.assertEqual(Date.to_string(res_config_new.predictive_lead_scoring_start_date),
str_date_8_days_ago, "If config param is not a valid date, date in settings should be set to 8 days before today")
@users('user_sales_manager')
def test_team_unlink(self):
""" Test that frequencies are sent to "no team" when unlinking a team
in order to avoid loosing too much informations. """
pls_team = self.env["crm.team"].browse(self.pls_team.ids)
# clean existing data
self.env["crm.lead.scoring.frequency"].sudo().search([('team_id', '=', False)]).unlink()
# existing no-team data
no_team = [
('stage_id', '1', 20, 10),
('stage_id', '2', 0.1, 0.1),
('stage_id', '3', 10, 0),
('country_id', '1', 10, 0.1),
]
self.env["crm.lead.scoring.frequency"].sudo().create([
{'variable': variable, 'value': value,
'won_count': won_count, 'lost_count': lost_count,
'team_id': False,
} for variable, value, won_count, lost_count in no_team
])
# add some frequencies to team to unlink
team = [
('stage_id', '1', 20, 10), # existing noteam
('country_id', '1', 0.1, 10), # existing noteam
('country_id', '2', 0.1, 0), # new but void
('country_id', '3', 30, 30), # new
]
existing_plsteam = self.env["crm.lead.scoring.frequency"].sudo().create([
{'variable': variable, 'value': value,
'won_count': won_count, 'lost_count': lost_count,
'team_id': pls_team.id,
} for variable, value, won_count, lost_count in team
])
pls_team.unlink()
final_noteam = [
('stage_id', '1', 40, 20),
('stage_id', '2', 0.1, 0.1),
('stage_id', '3', 10, 0),
('country_id', '1', 10, 10),
('country_id', '3', 30, 30),
]
self.assertEqual(
existing_plsteam.exists(), self.env["crm.lead.scoring.frequency"],
'Frequencies of unlinked teams should be unlinked (cascade)')
existing_noteam = self.env["crm.lead.scoring.frequency"].sudo().search([
('team_id', '=', False),
('variable', 'in', ['stage_id', 'country_id']),
])
for frequency in existing_noteam:
stat = next(item for item in final_noteam if item[0] == frequency.variable and item[1] == frequency.value)
self.assertEqual(frequency.won_count, stat[2])
self.assertEqual(frequency.lost_count, stat[3])
self.assertEqual(len(existing_noteam), len(final_noteam))