diff options
| author | Pierre Collinet (pic) <pic@odoo.com> | 2020-06-11 08:46:25 +0000 |
|---|---|---|
| committer | Pierre Collinet (pic) <pic@odoo.com> | 2020-06-11 12:26:51 +0000 |
| commit | 4c2db92aecc10103d2c8ef0269d342d20b61e979 (patch) | |
| tree | bbaf594ebbffe94432a81ad22b3ff22db8994321 /addons/crm_iap_lead | |
| parent | f1c99a60fa175095a2b4b2a6270d866e3999e05d (diff) | |
[IMP] crm_iap_lead: improve onboarding tour of module crm_iap_lead
- Improve crm onboarding tour text messages and display
- Modify CRMLeadMiningRequest to improve the Lead Generation Process
Default value for lead_number changes from 10 to 3;
Computed value for team_id : per default add the
current user sale_team_id;
Default value for user_id : per default add the current user;
Default values for country_ids : Per default, add the country
of the active company because it avoids a click and is usually correct;
- Improve crm_iap_lead_mining_request_form
Group fields by sections for more readability;
Change string attribute of some fields;
Change the position of the alert messages to the top of the form
(as a ribbon);
Change button string from Submit to Generate Leads to be more explicit;
Task ID 2226563
Community PR #51587
Signed-off-by: Thibault Delavallee (tde) <tde@openerp.com>
Diffstat (limited to 'addons/crm_iap_lead')
4 files changed, 100 insertions, 61 deletions
diff --git a/addons/crm_iap_lead/models/crm_iap_lead_mining_request.py b/addons/crm_iap_lead/models/crm_iap_lead_mining_request.py index 6f30f596d2a..8cd41ebb3bd 100644 --- a/addons/crm_iap_lead/models/crm_iap_lead_mining_request.py +++ b/addons/crm_iap_lead/models/crm_iap_lead_mining_request.py @@ -12,6 +12,7 @@ _logger = logging.getLogger(__name__) DEFAULT_ENDPOINT = 'https://iap-services.odoo.com' MAX_LEAD = 200 + MAX_CONTACT = 5 CREDIT_PER_COMPANY = 1 @@ -28,19 +29,25 @@ class CRMLeadMiningRequest(models.Model): else: return 'opportunity' + def _default_country_ids(self): + return self.env.user.company_id.country_id + name = fields.Char(string='Request Number', required=True, readonly=True, default=lambda self: _('New'), copy=False) state = fields.Selection([('draft', 'Draft'), ('done', 'Done'), ('error', 'Error')], string='Status', required=True, default='draft') # Request Data - lead_number = fields.Integer(string='Number of Leads', required=True, default=10) + lead_number = fields.Integer(string='Number of Leads', required=True, default=3) search_type = fields.Selection([('companies', 'Companies'), ('people', 'Companies and their Contacts')], string='Target', required=True, default='companies') error = fields.Text(string='Error', readonly=True) # Lead / Opportunity Data + lead_type = fields.Selection([('lead', 'Leads'), ('opportunity', 'Opportunities')], string='Type', required=True, default=_default_lead_type) display_lead_label = fields.Char(compute='_compute_display_lead_label') - team_id = fields.Many2one('crm.team', string='Sales Team', domain="[('use_opportunities', '=', True)]") - user_id = fields.Many2one('res.users', string='Salesperson') + team_id = fields.Many2one( + 'crm.team', string='Sales Team', + domain="[('use_opportunities', '=', True)]", readonly=False, compute='_compute_team_id', store=True) + user_id = fields.Many2one('res.users', string='Salesperson', default=lambda self: self.env.user) tag_ids = fields.Many2many('crm.tag', string='Tags') lead_ids = fields.One2many('crm.lead', 'lead_mining_request_id', string='Generated Lead / Opportunity') lead_count = fields.Integer(compute='_compute_lead_count', string='Number of Generated Leads') @@ -49,12 +56,12 @@ class CRMLeadMiningRequest(models.Model): filter_on_size = fields.Boolean(string='Filter on Size', default=False) company_size_min = fields.Integer(string='Size', default=1) company_size_max = fields.Integer(default=1000) - country_ids = fields.Many2many('res.country', string='Countries') + country_ids = fields.Many2many('res.country', string='Countries', default=_default_country_ids) state_ids = fields.Many2many('res.country.state', string='States') industry_ids = fields.Many2many('crm.iap.lead.industry', string='Industries') # Contact Generation Filter - contact_number = fields.Integer(string='Number of Contacts', default=1) + contact_number = fields.Integer(string='Number of Contacts', default=10) contact_filter_type = fields.Selection([('role', 'Role'), ('seniority', 'Seniority')], string='Filter on', default='role') preferred_role_id = fields.Many2one('crm.iap.lead.role', string='Preferred Role') role_ids = fields.Many2many('crm.iap.lead.role', string='Other Roles') @@ -98,6 +105,11 @@ class CRMLeadMiningRequest(models.Model): for request in self: request.lead_count = mapped_data.get(request.id, 0) + @api.depends('user_id') + def _compute_team_id(self): + for record in self: + record.team_id = record.user_id.sale_team_id + @api.onchange('lead_number') def _onchange_lead_number(self): if self.lead_number <= 0: diff --git a/addons/crm_iap_lead/static/src/js/tours/crm_iap_lead.js b/addons/crm_iap_lead/static/src/js/tours/crm_iap_lead.js new file mode 100644 index 00000000000..577b6cd14d9 --- /dev/null +++ b/addons/crm_iap_lead/static/src/js/tours/crm_iap_lead.js @@ -0,0 +1,41 @@ +odoo.define('crm_iap_lead.generate_leads_steps', function (require) { +"use strict"; + +var tour = require('web_tour.tour'); +var core = require('web.core'); + +require('crm.tour'); +var _t = core._t; + +var DragOppToWonStepIndex = _.findIndex(tour.tours.crm_tour.steps, function (step) { + return (step.id === 'drag_opportunity_to_won_step'); +}); + +tour.tours.crm_tour.steps.splice(DragOppToWonStepIndex + 1, 0, { + /** + * Add some steps between "Drag your opportunity to <b>Won</b> when you get + * the deal. Congrats !" and "Let’s have a look at an Opportunity." to + * include the steps related to the lead generation (crm_iap_lead). + * This eases the on boarding for the Lead Generation process. + * + */ + trigger: ".o_button_generate_leads", + content: _t("Looking for more opportunities ?<br>Try the <b>Lead Generation</b> tool."), + position: "bottom", + run: function (actions) { + actions.auto('.o_button_generate_leads'); + }, +}, { + trigger: '.modal-body .o_industry', + content: _t("Which Industry do you want to target?"), + position: "right", +}, { + trigger: '.modal-footer button[name=action_submit]', + content: _t("Now, just let the magic happen!"), + position: "bottom", + run: function (actions) { + actions.auto('.modal-footer button[special=cancel]'); +} +}); + +});
\ No newline at end of file diff --git a/addons/crm_iap_lead/views/crm_iap_lead_templates.xml b/addons/crm_iap_lead/views/crm_iap_lead_templates.xml index d6844a6a242..107a1140026 100644 --- a/addons/crm_iap_lead/views/crm_iap_lead_templates.xml +++ b/addons/crm_iap_lead/views/crm_iap_lead_templates.xml @@ -3,6 +3,7 @@ <template id="assets_backend" name="crm_iap_lead assets" inherit_id="web.assets_backend"> <xpath expr="." position="inside"> <script type="text/javascript" src="/crm_iap_lead/static/src/js/leads_tree_generate_leads.js"/> + <script type="text/javascript" src="/crm_iap_lead/static/src/js/tours/crm_iap_lead.js"></script> </xpath> </template> -</odoo> +</odoo>
\ No newline at end of file diff --git a/addons/crm_iap_lead/views/crm_iap_lead_views.xml b/addons/crm_iap_lead/views/crm_iap_lead_views.xml index 5621f10109e..e1a967d71b2 100644 --- a/addons/crm_iap_lead/views/crm_iap_lead_views.xml +++ b/addons/crm_iap_lead/views/crm_iap_lead_views.xml @@ -6,25 +6,19 @@ <field name="arch" type="xml"> <form> <header> - <button name="action_submit" type="object" - string="Submit" states="draft" - class="oe_highlight" invisible="context.get('is_modal')"/> - <button name="action_submit" type="object" - string="Retry" states="error" - class="oe_highlight"/> + <button name="action_submit" type="object" string="Submit" states="draft" class="oe_highlight" invisible="context.get('is_modal')"/> + <button name="action_submit" type="object" string="Retry" states="error" class="oe_highlight"/> <field name="state" widget="statusbar" statusbar_visible="draft,done" invisible="context.get('is_modal')"/> </header> <sheet> <div class="oe_button_box" name="button_box"> - <button name="action_get_opportunity_action" class="oe_stat_button" type="object" icon="fa-handshake-o" - attrs="{'invisible': ['|', ('lead_type', '!=', 'opportunity'), ('state', '!=' , 'done')]}"> + <button name="action_get_opportunity_action" class="oe_stat_button" type="object" icon="fa-handshake-o" attrs="{'invisible': ['|', ('lead_type', '!=', 'opportunity'), ('state', '!=' , 'done')]}"> <div class="o_stat_info"> <field name="lead_count"/> <span class="o_stat_text">Opportunities</span> </div> </button> - <button name="action_get_lead_action" class="oe_stat_button" type="object" icon="fa-handshake-o" groups="crm.group_use_lead" - attrs="{'invisible': ['|', ('lead_type', '!=', 'lead'), ('state', '!=' , 'done')]}"> + <button name="action_get_lead_action" class="oe_stat_button" type="object" icon="fa-handshake-o" groups="crm.group_use_lead" attrs="{'invisible': ['|', ('lead_type', '!=', 'lead'), ('state', '!=' , 'done')]}"> <div class="o_stat_info"> <field name="lead_count"/> <span class="o_stat_text">Leads</span> @@ -42,21 +36,24 @@ </div> </div> </span> - <group> - <group name="requests" string="Request"> - <field name="lead_number" attrs="{'readonly': [('state', '!=', 'draft')]}"/> - <field name="search_type" widget="radio" attrs="{'readonly': [('state', '!=', 'draft')]}"/> - <field name="error" attrs="{'invisible': [('state', '!=', 'error')]}"/> - </group> - <group name="lead_info" string="Lead Information"> - <field name="lead_type" groups="crm.group_use_lead" invisible="context.get('is_modal')" attrs="{'readonly': [('state', '!=', 'draft')]}"/> - <field name="team_id" attrs="{'readonly': [('state', '!=', 'draft')]}" kanban_view_ref="%(sales_team.crm_team_view_kanban)s"/> - <field name="user_id" attrs="{'readonly': [('state', '!=', 'draft')]}" domain="[('share', '=', False)]"/> - <field name="tag_ids" widget="many2many_tags" attrs="{'readonly': [('state', '!=', 'draft')]}"/> + + <h2>What do you need ?</h2> + + <group name="requests"> + <group> + <div class="o_row"> + <field name="lead_number" attrs="{'readonly': [('state', '!=', 'draft')]}" nolabel="1" class="oe_inline col-md-2 pl-0"/> + <field name="search_type" widget="selection" attrs="{'readonly': [('state', '!=', 'draft')]}" nolabel="1" class="oe_inline col-md-6"/> + <field name="error" attrs="{'invisible': [('state', '!=', 'error')]}"/> + </div> </group> </group> + <group> - <group name="companies" string="Companies"> + <group name="companies"> + <field name="country_ids" widget="many2many_tags" attrs="{'readonly': [('state', '!=', 'draft')]}" required="True" options="{'no_create': True, 'no_open': True}"/> + <field name="state_ids" widget="many2many_tags" attrs="{'invisible': [('country_ids', '=', [])], 'readonly': [('state', '!=', 'draft')]}" domain="[('country_id', 'in', country_ids)]" options="{'no_create': True, 'no_open': True}"/> + <field name="industry_ids" widget="many2many_tags" attrs="{'readonly': [('state', '!=', 'draft')]}" options="{'no_create': True, 'no_open': True}" class="o_industry"/> <field name="filter_on_size" attrs="{'readonly': [('state', '!=', 'draft')]}"/> <label for="company_size_min" attrs="{'invisible': [('filter_on_size', '=', False)]}"/> <div attrs="{'invisible': [('filter_on_size', '=', False)]}"> @@ -66,44 +63,32 @@ <field name="company_size_max" class="oe_inline col-sm-3" attrs="{'required': [('filter_on_size', '=', True)], 'readonly': [('state', '!=', 'draft')]}"/> employees </div> - <field name="country_ids" widget="many2many_tags" attrs="{'readonly': [('state', '!=', 'draft')]}" required="True" options="{'no_create': True, 'no_open': True}"/> - <field name="state_ids" widget="many2many_tags" attrs="{'invisible': [('country_ids', '=', [])], 'readonly': [('state', '!=', 'draft')]}" domain="[('country_id', 'in', country_ids)]" options="{'no_create': True, 'no_open': True}"/> - <field name="industry_ids" widget="many2many_tags" attrs="{'readonly': [('state', '!=', 'draft')]}" options="{'no_create': True, 'no_open': True}"/> + </group> - <group name="contacts" string="Contacts" attrs="{'invisible': [('search_type', '!=', 'people')]}"> - <field name="contact_number" attrs="{'readonly': [('state', '!=', 'draft')], 'required': [('search_type', '=', 'people')]}"/> - <field name="contact_filter_type" widget="radio" attrs="{'readonly': [('state', '!=', 'draft')]}"/> - <field name="preferred_role_id" - options="{'no_create_edit': True, 'no_quick_create': True}" - attrs="{'invisible': [('contact_filter_type','!=', 'role')], 'required': [('search_type', '=', 'people'), ('contact_filter_type', '=', 'role')], 'readonly': [('state', '!=', 'draft')]}"/> - <field name="role_ids" widget="many2many_tags" - options="{'color_field': 'color', 'no_create_edit': True, 'no_quick_create': True}" - attrs="{'invisible': ['|', ('preferred_role_id','=', False), ('contact_filter_type','!=', 'role')], 'readonly': [('state', '!=', 'draft')]}"/> - <field name="seniority_id" options="{'no_create_edit': True, 'no_quick_create': True}" - attrs="{'invisible': [('contact_filter_type', '!=', 'seniority')], 'required': [('search_type', '=', 'people'), ('contact_filter_type', '=', 'seniority')], 'readonly': [('state', '!=', 'draft')]}"/> + <group name="lead_info"> + <field name="lead_type" groups="crm.group_use_lead" invisible="context.get('is_modal')" attrs="{'readonly': [('state', '!=', 'draft')]}"/> + <field name="team_id" no_create="1" no_open="1" attrs="{'readonly': [('state', '!=', 'draft')]}" kanban_view_ref="812"/> + <field name="user_id" no_create="1" no_open="1" attrs="{'readonly': [('state', '!=', 'draft')]}"/> + <field name="tag_ids" string="Default Tags" widget="many2many_tags" attrs="{'readonly': [('state', '!=', 'draft')]}"/> </group> </group> - <div class="row"> - <div class="col-md-6"> - <div class="alert alert-info" role="alert"> - <field name="lead_credits"/> - <br/> - <span attrs="{'invisible': [('search_type', '!=', 'people')]}"> - <field name="lead_contacts_credits"/> - <br/> - <field name="lead_total_credits"/> - </span> - </div> - </div> - <div class="col-md-6"> - <div class="alert alert-info" role="alert" - attrs="{'invisible': [('search_type', '!=', 'people')]}"> - Make sure you know if you have to be GDPR compliant for storing personal data. - </div> + + <group name="contacts" attrs="{'invisible': [('search_type', '!=', 'people')]}"> + <div> + <field name="contact_number" attrs="{'readonly': [('state', '!=', 'draft')], 'required': [('search_type', '=', 'people')]}" nolabel="1" class="col-md-1"/> + <span class="col-md-6">Extra contacts per Company</span> </div> - </div> + </group> + <group attrs="{'invisible': [('search_type', '!=', 'people')]}"> + <group> + <field name="contact_filter_type" widget="radio" attrs="{'readonly': [('state', '!=', 'draft')]}" options="{'horizontal': true}"/> + <field name="preferred_role_id" options="{'no_create_edit': True, 'no_quick_create': True}" attrs="{'invisible': [('contact_filter_type','!=', 'role')], 'required': [('search_type', '=', 'people'), ('contact_filter_type', '=', 'role')], 'readonly': [('state', '!=', 'draft')]}"/> + <field name="role_ids" widget="many2many_tags" options="{'color_field': 'color', 'no_create_edit': True, 'no_quick_create': True}" attrs="{'invisible': ['|', ('preferred_role_id','=', False), ('contact_filter_type','!=', 'role')], 'readonly': [('state', '!=', 'draft')]}"/> + <field name="seniority_id" options="{'no_create_edit': True, 'no_quick_create': True}" attrs="{'invisible': [('contact_filter_type', '!=', 'seniority')], 'required': [('search_type', '=', 'people'), ('contact_filter_type', '=', 'seniority')], 'readonly': [('state', '!=', 'draft')]}"/> + </group> + </group> <footer> - <button string="Submit" name="action_submit" type="object" default_focus="1" class="btn-primary" invisible="not context.get('is_modal')"/> + <button string="Generate Leads" name="action_submit" type="object" default_focus="1" class="btn-primary" invisible="not context.get('is_modal')"/> <button string="Cancel" class="btn-secondary" special="cancel" invisible="not context.get('is_modal')"/> </footer> </sheet> |
