[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:
@@ -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'
|
||||
|
||||
@@ -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
|
||||
# ------------------------------------------------------------
|
||||
|
||||
@@ -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))
|
||||
|
||||
Reference in New Issue
Block a user