From 576933ff08bb7a31ceb86f8a1ca08256ae9d3d0c Mon Sep 17 00:00:00 2001 From: Jeremy Kersten Date: Tue, 13 Jan 2015 12:04:25 +0100 Subject: [PATCH] [IMP] website_crm_score: multi improvements Move section_user before the use of this one in a many2many, else demo data are not installable because field id is never created in db. (same 'issue' that https://github.com/odoo/odoo/issues/2386) Add a cron to compute score each hours Add merge pageview and merge (clean) score when we merge opportunities via merge_opportunities/merge_dependencies Score the lead after the assignation to salesteam. Because when we assign to salesteam, sometimes we call the method merge_opportunities which one delete old scores on this lead, all score rules needs to be recomputed since the fields have been updated. So we compute now the score not at starting, but between assignation to salesteam and salesman. --- .../demo/website_crm_score_demo.xml | 2 +- addons/website_crm_score/models/crm_lead.py | 21 +++- addons/website_crm_score/models/sales_team.py | 101 +++++++++--------- .../models/website_crm_score.py | 1 + addons/website_crm_score/views/marketing.xml | 16 ++- 5 files changed, 85 insertions(+), 56 deletions(-) diff --git a/addons/website_crm_score/demo/website_crm_score_demo.xml b/addons/website_crm_score/demo/website_crm_score_demo.xml index bb965beb6fd..bd68d5cd478 100644 --- a/addons/website_crm_score/demo/website_crm_score_demo.xml +++ b/addons/website_crm_score/demo/website_crm_score_demo.xml @@ -12,7 +12,7 @@ Toni Buchanan - Toni.Buchanan@yourcompany?com + Toni.Buchanan@yourcompany.com none diff --git a/addons/website_crm_score/models/crm_lead.py b/addons/website_crm_score/models/crm_lead.py index 141b47bd610..ea2a818d946 100644 --- a/addons/website_crm_score/models/crm_lead.py +++ b/addons/website_crm_score/models/crm_lead.py @@ -10,7 +10,7 @@ class Lead(models.Model): def _count_pageviews(self): self.pageviews_count = len(self.score_pageview_ids) - @api.depends('score_ids.value') + @api.depends('score_ids', 'score_ids.value') def _compute_score(self): self._cr.execute(""" SELECT @@ -54,4 +54,23 @@ class Lead(models.Model): def get_score_domain_cookies(self): # TODO should be return request.httprequest.host in master + # return request.httprequest.host return "." + ".".join(request.httprequest.host.rsplit(".", 2)[1:]) + + def _merge_pageviews(self, cr, uid, opportunity_id, opportunities, context=None): + lead_ids = [opp.id for opp in opportunities if opp.id != opportunity_id] + pv_ids = self.pool.get('website.crm.pageview').search(cr, uid, [('lead_id', 'in', lead_ids)], context=context) + self.pool.get('website.crm.pageview').write(cr, uid, pv_ids, {'lead_id': opportunity_id}, context=context) + return True + + def _merge_scores(self, cr, uid, opportunity_id, opportunities, context=None): + # We needs to delete score from opportunity_id, to be sure that all rules will be re-evaluated. + self.write(cr, uid, [opportunity_id], {'score_ids': [(6, 0, [])]}, context=context) + return True + + def merge_dependences(self, cr, uid, highest, opportunities, context=None): + self._merge_pageviews(cr, uid, highest, opportunities, context=context) + self._merge_scores(cr, uid, highest, opportunities, context=context) + + # Call default merge function + super(Lead, self).merge_dependences(cr, uid, highest, opportunities, context=context) diff --git a/addons/website_crm_score/models/sales_team.py b/addons/website_crm_score/models/sales_team.py index db607bdaa68..0bdafeb91da 100644 --- a/addons/website_crm_score/models/sales_team.py +++ b/addons/website_crm_score/models/sales_team.py @@ -26,6 +26,51 @@ except ImportError: return True +class section_user(models.Model): + _name = 'section.user' + + @api.one + def _count_leads(self): + if self.id: + limit_date = datetime.datetime.now() - datetime.timedelta(days=30) + domain = [('user_id', '=', self.user_id.id), + ('section_id', '=', self.section_id.id), + ('assign_date', '>', limit_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT)) + ] + self.leads_count = self.env['crm.lead'].search_count(domain) + else: + self.leads_count = 0 + + @api.one + def _get_percentage(self): + try: + self.percentage_leads = round(100 * self.leads_count / float(self.maximum_user_leads), 2) + except ZeroDivisionError: + self.percentage_leads = 0.0 + + @api.one + @api.constrains('section_user_domain') + def _assert_valid_domain(self): + try: + domain = safe_eval(self.section_user_domain or '[]', evaluation_context) + self.env['crm.lead'].search(domain) + except Exception: + raise Warning('The domain is incorrectly formatted') + + section_id = fields.Many2one('crm.case.section', string='SaleTeam', required=True) + user_id = fields.Many2one('res.users', string='Saleman', required=True) + name = fields.Char(related='user_id.partner_id.display_name') + running = fields.Boolean(string='Running', default=True) + section_user_domain = fields.Char('Domain') + maximum_user_leads = fields.Integer('Leads Per Month') + leads_count = fields.Integer('Assigned Leads', compute='_count_leads', help='Assigned Leads this last month') + percentage_leads = fields.Float(compute='_get_percentage', string='Percentage leads') + + @api.one + def toggle_active(self): + self.running = not self.running + + class crm_case_section(osv.osv): _inherit = "crm.case.section" @@ -72,11 +117,6 @@ class crm_case_section(osv.osv): user_ids = fields.Many2many('res.users', 'section_user', 'section_id', 'user_id', readonly=True) # Use for display in Kanban min_for_assign = fields.Integer("Minimum score", help="Minimum Score for a lead to be automatically assign (>=)", default=0, required=True) - @api.model - def score_and_assign_leads(self): - self.env['website.crm.score'].assign_scores_to_leads() - self._assign_leads() - @api.model def direct_assign_leads(self, ids=[]): self._assign_leads() @@ -183,8 +223,6 @@ class crm_case_section(osv.osv): if not user['nbr']: del users[i] - # ids is needed when the button is used to start the function, - # the default [] is needed for the function to be usable by the cron @api.model def _assign_leads(self, dry=False): # Emptying the table @@ -203,49 +241,8 @@ class crm_case_section(osv.osv): all_section_users = self.env['section.user'].search([('running', '=', True)]) self.assign_leads_to_salesteams(all_salesteams, dry=dry) + + # Compute score after assign to salesteam, because if a merge has been done, the score for leads is removed. + self.env['website.crm.score'].assign_scores_to_leads() + self.assign_leads_to_salesmen(all_section_users, dry=dry) - - -class section_user(models.Model): - _name = 'section.user' - - @api.one - def _count_leads(self): - if self.id: - limit_date = datetime.datetime.now() - datetime.timedelta(days=30) - domain = [('user_id', '=', self.user_id.id), - ('section_id', '=', self.section_id.id), - ('assign_date', '>', limit_date.strftime(DEFAULT_SERVER_DATETIME_FORMAT)) - ] - self.leads_count = self.env['crm.lead'].search_count(domain) - else: - self.leads_count = 0 - - @api.one - def _get_percentage(self): - try: - self.percentage_leads = round(100 * self.leads_count / float(self.maximum_user_leads), 2) - except ZeroDivisionError: - self.percentage_leads = 0.0 - - @api.one - @api.constrains('section_user_domain') - def _assert_valid_domain(self): - try: - domain = safe_eval(self.section_user_domain or '[]', evaluation_context) - self.env['crm.lead'].search(domain) - except Exception: - raise Warning('The domain is incorrectly formatted') - - section_id = fields.Many2one('crm.case.section', string='SaleTeam', required=True) - user_id = fields.Many2one('res.users', string='Saleman', required=True) - name = fields.Char(related='user_id.partner_id.display_name') - running = fields.Boolean(string='Running', default=True) - section_user_domain = fields.Char('Domain') - maximum_user_leads = fields.Integer('Leads Per Month') - leads_count = fields.Integer('Assigned Leads', compute='_count_leads', help='Assigned Leads this last month') - percentage_leads = fields.Float(compute='_get_percentage', string='Percentage leads') - - @api.one - def toggle_active(self): - self.running = not self.running diff --git a/addons/website_crm_score/models/website_crm_score.py b/addons/website_crm_score/models/website_crm_score.py index 02d6de69f33..c407c974dfb 100644 --- a/addons/website_crm_score/models/website_crm_score.py +++ b/addons/website_crm_score/models/website_crm_score.py @@ -11,6 +11,7 @@ evaluation_context = { 'context_today': datetime.datetime.now, } + class website_crm_score(models.Model): _name = 'website.crm.score' diff --git a/addons/website_crm_score/views/marketing.xml b/addons/website_crm_score/views/marketing.xml index 9ec35fb6e4b..b51b697fb48 100644 --- a/addons/website_crm_score/views/marketing.xml +++ b/addons/website_crm_score/views/marketing.xml @@ -6,7 +6,7 @@ - Lead Scoring and Assignation Cron + Lead Assignation 1 @@ -14,9 +14,21 @@ -1 - + + + + Lead Scoring + + + 1 + hours + -1 + + + + Apply marked scores