[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.
This commit is contained in:
@@ -12,7 +12,7 @@
|
||||
<!-- Creating salesmen -->
|
||||
<record id="website_crm_score_partner_0" model="res.partner">
|
||||
<field name="name">Toni Buchanan</field>
|
||||
<field name="email">Toni.Buchanan@yourcompany?com</field>
|
||||
<field name="email">Toni.Buchanan@yourcompany.com</field>
|
||||
<field name="supplier" eval="False"/>
|
||||
<field name="customer" eval="False"/>
|
||||
<field name="notify_email">none</field>
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -11,6 +11,7 @@ evaluation_context = {
|
||||
'context_today': datetime.datetime.now,
|
||||
}
|
||||
|
||||
|
||||
class website_crm_score(models.Model):
|
||||
_name = 'website.crm.score'
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
<!-- Scheduler for Lead Scoring and Assignation -->
|
||||
<record forcecreate="True" id="ir_cron_lead_assign" model="ir.cron">
|
||||
<field name="name">Lead Scoring and Assignation Cron</field>
|
||||
<field name="name">Lead Assignation</field>
|
||||
<field eval="False" name="active" />
|
||||
<field name="user_id" ref="base.user_root" />
|
||||
<field name="interval_number">1</field>
|
||||
@@ -14,9 +14,21 @@
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall" />
|
||||
<field eval="'crm.case.section'" name="model" />
|
||||
<field eval="'score_and_assign_leads'" name="function" />
|
||||
<field eval="'direct_assign_leads'" name="function" />
|
||||
</record>
|
||||
|
||||
<!-- Scheduler for Lead Scoring -->
|
||||
<record forcecreate="True" id="ir_cron_lead_scoring" model="ir.cron">
|
||||
<field name="name">Lead Scoring </field>
|
||||
<field eval="False" name="active" />
|
||||
<field name="user_id" ref="base.user_root" />
|
||||
<field name="interval_number">1</field>
|
||||
<field name="interval_type">hours</field>
|
||||
<field name="numbercall">-1</field>
|
||||
<field eval="False" name="doall" />
|
||||
<field eval="'website.crm.score'" name="model" />
|
||||
<field eval="'assign_scores_to_leads'" name="function" />
|
||||
</record>
|
||||
|
||||
<record id="action_score_now" model="ir.actions.server">
|
||||
<field name="name">Apply marked scores</field>
|
||||
|
||||
Reference in New Issue
Block a user