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
Move sales team automatic lead assignment from website_crm_score (enterprise)
directly into sales_team. Some cleaning and renaming is performed while moving
the code as it is old fashioned.
Scoring feature is removed completely from lead assignment. Indeed we consider
PLS is a better feature and provides more accurate results.
Minimal scoring specific field on team is removed. Indeed it can also be
integrated directly into domains linked to a sales team as this is a field
directly available on lead using ``probability``. It allows to reduce fields
of team model and move all logic in the team's domain itself.
Overall behavior as been kept as close as possible from the original one.
Purpose is to avoid too much undesired changes between versions.
In this commit we also add tests for automatic lead assignment.
ASSIGNMENT PROCESS DESCRIPTION
1- LEAD TO TEAM ALLOCATION
Allocate leads to teams given by self. This method sets ``team_id`` field
on lead records that are unassigned (no team and no responsible). No
salesperson is assigned in this process. Its purpose is simply to allocate
leads within teams.
Heuristic of this method is the following:
* first we randomize all teams;
* then for each team
* find unassigned leads, aka leads being
* without team, without user -> not assigned;
* not in a won stage, and not having False/0 (lost) or 100 (won)
probability) -> live leads;
* if set, a delay after creation can be applied (see BUNDLE_HOURS_DELAY)
parameter explanations here below;
* keep only leads matching the team's assignment domain (empty means
everything);
* assign maximum BUNDLE_SIZE leads to the team, then move to the next team.
This is done to ensure every team will have leads enough to fill its
capacity based on its domain;
* when setting a team on leads, leads belonging to the current batch
are also merged. Purpose is to clean database and avoid assigning
duplicates to same or different teams;
* for all teams that still have capacity (aka: a search on unassigned
available leads with team domain still give results), do another
assignment round. Each round teams are randomized so that team order
is not always the same;
Note that leads are assigned in batch meaning a team could receive leads that
could better fit another team. However this heuristics is based on hypothesis
that team domains do not overlap. Indeed if a company has several teams they
will probably target separate market segments: country-based, customer type or
size, ... Having several teams using same assignment domain could lead to less
fairness in assignment process but this should not be the target use case of this
heuristic.
Leads are allocated by batch. This can be configured using a config parameter.
Batch size depends on cron frequency, lead pipeline size and members assignment
maximum. Finding an optimal heuristic for this parameter is not easy as it
depends on internal processes and organization. Higher batch size leads to
better performances when running automatic assignment. It can also give unfair
results if teams domain overlap or if pipeline is not big enough to fill all
teams capacity.
2- LEAD TO MEMBER ASSIGN
Main processing method to assign leads to sales team members. It also converts
them into opportunities. Its main purpose is therefore to distribute team
workload on its members based on their capacity.
Preparation
* prepare lead domain for each member. It is done using a logical AND with
team's domain and member's domain. Member domains further restricts team
domain;
* prepare a set of available leads for each member by searching for leads
matching domain with a sufficient limit to ensure all members will receive
leads;
* prepare a weighted population sample. Population are members that should
receive leads. Initial weight is the number of leads to assign to that
specific member. This is minimum value between
* remaining this month: assignment_max - number of lead already assigned
this month;
* days-based assignment: assignment_max with a ratio based on ``work_days``
* e.g. Michel Poilvache (max: 30 - currently assigned: 15) limit
for 2 work days: min(30-15, 30/15) -> 2 leads assigned
* e.g. Michel Tartopoil (max: 30 - currently assigned: 26) limit
for 10 work days: min(30-26, 30/3) -> 4 leads assigned
Assign process then follows the following heuristic
* take a weighted random choice in population;
* find first available (not yet assigned) lead in its lead set;
* if found:
* convert it into an opportunity and assign member as salesperson;
* lessen member's weight so that other members have an higher
probability of being picked up next;
* if not found: consider this member is out of assignment process,
remove it from population so that it is not picked up anymore;
Assignment is performed one lead at a time for fairness purpose. Indeed members
may have overlapping domains within a given team. To ensure some fairness in
process once a member receives a lead, a new choice is performed with updated
weights. This is not optimal from performance point of view but increases
probability leads are correctly distributed within the team.
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
204 lines
13 KiB
XML
204 lines
13 KiB
XML
<?xml version="1.0" encoding="utf-8"?>
|
|
<odoo>
|
|
|
|
<record id="res_config_settings_view_form" model="ir.ui.view">
|
|
<field name="name">res.config.settings.view.form.inherit.crm</field>
|
|
<field name="model">res.config.settings</field>
|
|
<field name="priority" eval="5"/>
|
|
<field name="inherit_id" ref="base.res_config_settings_view_form"/>
|
|
<field name="arch" type="xml">
|
|
<xpath expr="//div[hasclass('settings')]" position="inside">
|
|
<div class="app_settings_block" data-string="CRM" string="CRM" data-key="crm" groups="sales_team.group_sale_manager">
|
|
<h2>CRM</h2>
|
|
<div class="row mt16 o_settings_container">
|
|
<div class="col-lg-6 o_setting_box">
|
|
<div class="o_setting_left_pane">
|
|
<field name="group_use_recurring_revenues"/>
|
|
</div>
|
|
<div class="o_setting_right_pane">
|
|
<label for="group_use_recurring_revenues"/>
|
|
<div class="text-muted">
|
|
Define recurring plans and revenues on Opportunities
|
|
</div>
|
|
<div attrs="{'invisible': [('group_use_recurring_revenues', '=', False)]}">
|
|
<button type="action" name="crm.crm_recurring_plan_action"
|
|
string="Manage Recurring Plans" icon="fa-arrow-right" class="oe_link"/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-6 o_setting_box" id="crm_lead"
|
|
title="Use leads if you need a qualification step before creating an opportunity or a customer. It can be a business card you received, a contact form filled in your website, or a file of unqualified prospects you import, etc. Once qualified, the lead can be converted into a business opportunity and/or a new customer in your address book.">
|
|
<div class="o_setting_left_pane">
|
|
<field name="group_use_lead"/>
|
|
</div>
|
|
<div class="o_setting_right_pane">
|
|
<label for="group_use_lead"/>
|
|
<div class="text-muted">
|
|
Add a qualification step before the creation of an opportunity
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row mt16 o_settings_container">
|
|
<div class="col-12 col-lg-6 o_setting_box">
|
|
<div class="o_setting_left_pane">
|
|
<field name="is_membership_multi"/>
|
|
</div>
|
|
<div class="o_setting_right_pane">
|
|
<label for="is_membership_multi"/>
|
|
<div class="text-muted">
|
|
Assign salespersons into multiple Sales Teams.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row mt16 o_settings_container">
|
|
<div class="col-lg-6 o_setting_box"
|
|
title="This can be used to compute statistical probability to close a lead"
|
|
name="predictive_lead_setting_container">
|
|
<div class="o_setting_left_pane"></div>
|
|
<div class="o_setting_right_pane">
|
|
<b>Predictive Lead Scoring</b>
|
|
<div class="text-muted">
|
|
The success rate is computed based on the stage, but you can add more fields in the statistical analysis.
|
|
</div>
|
|
<div class="mt16">
|
|
<field name="predictive_lead_scoring_fields" class="oe_inline" widget="many2many_tags" placeholder="Extra fields..."/>
|
|
<field name="predictive_lead_scoring_fields_str" invisible="1"/>
|
|
</div>
|
|
<div class="mt16">
|
|
Consider leads created as of the
|
|
<field name="predictive_lead_scoring_start_date_str" invisible="1"/>
|
|
<field name="predictive_lead_scoring_start_date" class="oe_inline" required="1"/>
|
|
</div>
|
|
<div class="mt16" groups="base.group_erp_manager">
|
|
<div class="text-muted mb-3">
|
|
Use this button to update the probabilities of all leads. This can take up to several minutes depending on how many there are.
|
|
</div>
|
|
<button name="action_reset_lead_probabilities" type="object" string="Update Probabilities" class="btn-primary"/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-12 col-lg-6 o_setting_box"
|
|
title="This can be used to automatically assign leads to sales persons based on rules">
|
|
<div class="o_setting_left_pane">
|
|
<field name="crm_use_auto_assignment"/>
|
|
</div>
|
|
<div class="o_setting_right_pane">
|
|
<label for="crm_use_auto_assignment"/>
|
|
<a href="https://www.odoo.com/documentation/user/14.0/crm/track_leads/lead_scoring.html#assign-leads"
|
|
title="Assign Documentation" class="o_doc_link" target="_blank"></a>
|
|
<div class="text-muted">
|
|
<span>Periodically assign leads based on rules</span><br />
|
|
<span attrs="{'invisible': [('crm_use_auto_assignment', '=', False)]}">
|
|
All sales teams will use this setting by default unless
|
|
specified otherwise.
|
|
</span>
|
|
</div>
|
|
<div class="row mt16" attrs="{'invisible': [('crm_use_auto_assignment', '=', False)]}">
|
|
<label string="Running" for="crm_auto_assignment_action" class="col-lg-3 o_light_label"/>
|
|
<field name="crm_auto_assignment_action"
|
|
attrs="{'required': [('crm_use_auto_assignment', '=', True)]}"/>
|
|
<button name="action_crm_assign_leads" type="object" class="btn-link">
|
|
<i title="Update now" role="img" aria-label="Update now" class="fa fa-fw fa-refresh"></i>
|
|
</button>
|
|
</div>
|
|
<div class="row mt16" attrs="{'invisible': ['|', ('crm_use_auto_assignment', '=', False), ('crm_auto_assignment_action', '=', 'manual')]}">
|
|
<label string="Repeat every" for="crm_auto_assignment_interval_type" class="col-lg-3 o_light_label"/>
|
|
<field name="crm_auto_assignment_interval_number"
|
|
class="oe_inline mr-2"
|
|
attrs="{'required': [('crm_use_auto_assignment', '=', True), ('crm_auto_assignment_action', '=', 'auto')]}"/>
|
|
<field name="crm_auto_assignment_interval_type"
|
|
class="oe_inline"
|
|
attrs="{'required': [('crm_use_auto_assignment', '=', True), ('crm_auto_assignment_action', '=', 'auto')]}"/>
|
|
</div>
|
|
<div class="row" attrs="{'invisible': ['|', ('crm_use_auto_assignment', '=', False), ('crm_auto_assignment_action', '=', 'manual')]}">
|
|
<label string="Next Run" for="crm_auto_assignment_run_datetime" class="col-lg-3 o_light_label"/>
|
|
<field name="crm_auto_assignment_run_datetime"/>
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h2>Lead Generation</h2>
|
|
<div class="row mt16 o_settings_container" name="convert_visitor_setting_container">
|
|
<div class="col-lg-6 o_setting_box">
|
|
<div class="o_setting_left_pane">
|
|
<field name="module_mail_client_extension"/>
|
|
</div>
|
|
|
|
<div class="o_setting_right_pane" id="mail_client_extension">
|
|
<label string="Outlook CRM Extension" for="module_mail_client_extension"/>
|
|
<a href="https://www.odoo.com/documentation/user/crm/optimize/outlook_extension.html" title="Documentation" class="o_doc_link" target="_blank"></a>
|
|
<div class="text-muted">
|
|
Turn emails received in your Outlook mailbox into leads and log their content as internal notes.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-6 o_setting_box">
|
|
<div class="o_setting_left_pane">
|
|
<field name="module_crm_iap_lead_enrich"/>
|
|
</div>
|
|
|
|
<div class="o_setting_right_pane" id="crm_iap_lead_enrich">
|
|
<label string="Lead Enrichment" for="module_crm_iap_lead_enrich"/>
|
|
<div class="text-muted">
|
|
Enrich your leads automatically with company data based on their email address
|
|
</div>
|
|
<div id="crm_iap_lead_enrich">
|
|
<div class="mt8" attrs="{'invisible': [('module_crm_iap_lead_enrich','=',False)]}">
|
|
<field name="lead_enrich_auto" class="o_light_label" widget="radio" required="True"/>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="row mt16 o_settings_container" name="generate_lead_setting_container">
|
|
<div class="col-lg-6 o_setting_box">
|
|
<div class="o_setting_left_pane">
|
|
<field name="module_crm_iap_lead"/>
|
|
</div>
|
|
|
|
<div class="o_setting_right_pane" id="crm_iap_lead_settings">
|
|
<label string="Lead Mining" for="module_crm_iap_lead"/>
|
|
<a href="https://www.odoo.com/documentation/user/14.0/crm/acquire_leads/lead_mining.html" title="Documentation" class="o_doc_link" target="_blank"></a>
|
|
<div class="text-muted">
|
|
Generate new leads based on their country, industry, size, etc.
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<div class="col-lg-6 o_setting_box">
|
|
<div class="o_setting_left_pane">
|
|
<field name="module_crm_iap_lead_website"/>
|
|
</div>
|
|
|
|
<div class="o_setting_right_pane" id="crm_iap_lead_website_settings">
|
|
<label string="Visits to Leads" for="module_crm_iap_lead_website"/>
|
|
<div class="text-muted">
|
|
Convert visitors of your website into leads and perform data enrichment based on their IP address
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</xpath>
|
|
</field>
|
|
</record>
|
|
|
|
<record id="crm_config_settings_action" model="ir.actions.act_window">
|
|
<field name="name">Settings</field>
|
|
<field name="type">ir.actions.act_window</field>
|
|
<field name="res_model">res.config.settings</field>
|
|
<field name="view_id" ref="res_config_settings_view_form"/>
|
|
<field name="view_mode">form</field>
|
|
<field name="target">inline</field>
|
|
<field name="context">{'module' : 'crm', 'bin_size': False}</field>
|
|
</record>
|
|
|
|
<record id="crm_config_settings_menu" model="ir.ui.menu">
|
|
<field name="action" ref="crm.crm_config_settings_action"/>
|
|
</record>
|
|
|
|
</odoo>
|