From 30a7ef804a1457fb0274994993c86a01dbb114d4 Mon Sep 17 00:00:00 2001 From: Hitesh Trivedi Date: Thu, 18 Jun 2015 12:36:19 +0530 Subject: [PATCH] [IMP] crm: usability improvements Among various small fixes, some changes : - correct computation of default sales team, located in sales_team with a small code cleaning. Rely on this method everywhere it is necessary. - add a configuration option to enable the use of leads in sales team; otherwise it is hidden - better display of alias in empty list help; - add a menu for next activities, that are the opportunities with an action whose deadline is near assigned to the current user; - automatic update of aliases configuration on sales team, based on whether they use leads and/or opportunities; - add a wizard to log the lost reasong when deactivating a lead or an opportunity --- addons/crm/__openerp__.py | 1 + addons/crm/base_partner_merge_view.xml | 29 ++-- addons/crm/crm_lead.py | 41 +++--- addons/crm/crm_lead_menu.xml | 31 +++- addons/crm/crm_lead_view.xml | 135 +++++++++++------- addons/crm/crm_tip_data.xml | 22 +++ addons/crm/report/crm_activity_report.py | 6 +- .../report/crm_opportunity_report_view.xml | 2 +- addons/crm/res_config.py | 3 + addons/crm/res_config_view.xml | 7 + addons/crm/sales_team.py | 37 ++++- addons/crm/sales_team_dashboard.xml | 4 +- addons/crm/sales_team_view.xml | 14 +- addons/crm/security/crm_security.xml | 5 + addons/crm/wizard/__init__.py | 1 + addons/crm/wizard/crm_lead_lost.py | 18 +++ addons/crm/wizard/crm_lead_lost_view.xml | 29 ++++ .../wizard/crm_lead_to_opportunity_view.xml | 4 +- addons/sale_crm/sale_crm_view.xml | 5 +- addons/sales_team/sales_team.py | 33 ++--- addons/website_crm_score/models/crm_lead.py | 9 -- addons/website_crm_score/models/sales_team.py | 9 ++ addons/website_crm_score/tests/common.py | 3 + addons/website_crm_score/views/sales.xml | 4 +- 24 files changed, 306 insertions(+), 146 deletions(-) create mode 100644 addons/crm/wizard/crm_lead_lost.py create mode 100644 addons/crm/wizard/crm_lead_lost_view.xml diff --git a/addons/crm/__openerp__.py b/addons/crm/__openerp__.py index b790f9bc233..4818a507db5 100644 --- a/addons/crm/__openerp__.py +++ b/addons/crm/__openerp__.py @@ -54,6 +54,7 @@ Dashboard for CRM will include: 'security/crm_security.xml', 'security/ir.model.access.csv', + 'wizard/crm_lead_lost_view.xml', 'wizard/crm_lead_to_opportunity_view.xml', 'wizard/crm_merge_opportunities_view.xml', diff --git a/addons/crm/base_partner_merge_view.xml b/addons/crm/base_partner_merge_view.xml index db580a6835d..54632487de7 100644 --- a/addons/crm/base_partner_merge_view.xml +++ b/addons/crm/base_partner_merge_view.xml @@ -1,22 +1,17 @@ - - - Deduplicate Contacts - base.partner.merge.automatic.wizard - form - form - new - {'active_test': False} - - - + base.partner.merge.automatic.wizard.form @@ -26,7 +21,7 @@

There is no more contacts to merge for this request...

- -
+
-
- - - - + + @@ -510,7 +529,7 @@ - + @@ -534,26 +553,20 @@ + - - - - + - - - - @@ -608,6 +621,8 @@ + + @@ -648,6 +663,20 @@
+ + crm.lead.next.activity.tree + crm.lead + + + + + + + + + + + diff --git a/addons/crm/crm_tip_data.xml b/addons/crm/crm_tip_data.xml index d07a03f447c..c2df524d710 100644 --- a/addons/crm/crm_tip_data.xml +++ b/addons/crm/crm_tip_data.xml @@ -34,5 +34,27 @@ auto top + + + + crm.lead + kanban + .o_kanban_record:eq(20):visible + button[data-view-type=graph] + mousedown + left + + + + + + crm.lead + form + .oe_form_field_status.oe_form_status_clickable:visible + .oe_form_field_status.oe_form_status_clickable + mousedown + bottom + +
diff --git a/addons/crm/report/crm_activity_report.py b/addons/crm/report/crm_activity_report.py index 3f29a01f4da..5bf4445fc72 100644 --- a/addons/crm/report/crm_activity_report.py +++ b/addons/crm/report/crm_activity_report.py @@ -16,7 +16,7 @@ class crm_activity_report(models.Model): author_id = fields.Many2one('res.partner', 'Author', readonly=True) user_id = fields.Many2one('res.users', 'Responsible', readonly=True) team_id = fields.Many2one('crm.team', 'Sales Team', readonly=True) - subtype_id = fields.Many2one('mail.message.subtype', 'Action', readonly=True) + subtype_id = fields.Many2one('mail.message.subtype', 'Activity', readonly=True) country_id = fields.Many2one('res.country', 'Country', readonly=True) company_id = fields.Many2one('res.company', 'Company', readonly=True) stage_id = fields.Many2one('crm.stage', 'Stage', readonly=True) @@ -48,6 +48,10 @@ class crm_activity_report(models.Model): "crm_lead" l on (m.res_id = l.id) + inner join + "crm_activity" a + on + (m.subtype_id = a.subtype_id) WHERE (m.model = 'crm.lead') )""") diff --git a/addons/crm/report/crm_opportunity_report_view.xml b/addons/crm/report/crm_opportunity_report_view.xml index 2c97a41a95b..ac2a51fde45 100644 --- a/addons/crm/report/crm_opportunity_report_view.xml +++ b/addons/crm/report/crm_opportunity_report_view.xml @@ -179,7 +179,7 @@ teams of the sales pipeline. (including those converted into opportunities). + parent="base.menu_sale_report" groups="crm.group_use_lead" action="crm_opportunity_report_action_lead" sequence="6"/> diff --git a/addons/crm/res_config.py b/addons/crm/res_config.py index 160f6982bc8..bed7d5437a6 100644 --- a/addons/crm/res_config.py +++ b/addons/crm/res_config.py @@ -15,6 +15,9 @@ class crm_configuration(osv.TransientModel): help="Odoo will generate an email alias based on the sales team name"), 'alias_prefix': fields.char('Default Alias Name for Leads'), 'alias_domain' : fields.char('Alias Domain'), + 'group_use_lead': fields.boolean( + "Use leads if you need a qualification step before creating an opportunity or a customer", + implied_group='crm.group_use_lead') } _defaults = { diff --git a/addons/crm/res_config_view.xml b/addons/crm/res_config_view.xml index 723318dcd68..ab879f47d22 100644 --- a/addons/crm/res_config_view.xml +++ b/addons/crm/res_config_view.xml @@ -32,6 +32,13 @@ + + diff --git a/addons/crm/sales_team.py b/addons/crm/sales_team.py index e33edaa2ec6..ef273eb57bf 100644 --- a/addons/crm/sales_team.py +++ b/addons/crm/sales_team.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- from openerp.osv import fields, osv +from openerp.tools.safe_eval import safe_eval as eval from openerp.tools.translate import _ @@ -46,10 +47,25 @@ class crm_team(osv.Model): 'use_opportunities': True, } - def onchange_use_leads(self, cr, uid, ids, use_leads, context=None): - if not use_leads: - return {'value': {'alias_name': False}} - return {'value': {}} + def onchange_use_leads_opportunities(self, cr, uid, ids, use_leads, use_opportunities, context=None): + if use_leads or use_opportunities: + return {'value': {}} + return {'value': {'alias_name': False}} + + def _get_alias_defaults_values(self, cr, uid, ids, context=None): + res = dict.fromkeys(ids, False) + is_group_use_lead = self.pool['res.users'].has_group(cr, uid, 'crm.group_use_lead') + for team in self.browse(cr, uid, ids, context=context): + alias_defaults = eval(team.alias_defaults) + alias_defaults.update({ + 'type': 'lead' if is_group_use_lead and team.use_leads else 'opportunity', + 'team_id': team.id, + }) + res[team.id] = { + 'alias_defaults': alias_defaults, + 'alias_parent_thread_id': team.id, + } + return res def create(self, cr, uid, vals, context=None): if context is None: @@ -59,10 +75,19 @@ class crm_team(osv.Model): if generate_alias_name and not vals.get('alias_name'): vals['alias_name'] = vals.get('name') team_id = super(crm_team, self).create(cr, uid, vals, context=create_context) - team = self.browse(cr, uid, team_id, context=context) - self.pool.get('mail.alias').write(cr, uid, [team.alias_id.id], {'alias_parent_thread_id': team_id, 'alias_defaults': {'team_id': team_id, 'type': 'lead'}}, context=context) + self.write(cr, uid, [team_id], + self._get_alias_defaults_values(cr, uid, [team_id], context=context)[team_id], + context=context) return team_id + def write(self, cr, uid, ids, vals, context=None): + res = super(crm_team, self).write(cr, uid, ids, vals, context=context) + if vals.get('use_leads') or vals.get('alias_defaults'): + alias_res = self._get_alias_defaults_values(cr, uid, ids, context=context) + for team_id, values in alias_res.iteritems(): + super(crm_team, self).write(cr, uid, [team_id], values, context=context) + return res + def unlink(self, cr, uid, ids, context=None): # Cascade-delete mail aliases as well, as they should not exist without the sales team. mail_alias = self.pool.get('mail.alias') diff --git a/addons/crm/sales_team_dashboard.xml b/addons/crm/sales_team_dashboard.xml index c75be5ae658..bef7416a3f8 100644 --- a/addons/crm/sales_team_dashboard.xml +++ b/addons/crm/sales_team_dashboard.xml @@ -42,7 +42,7 @@ -
+
Leads @@ -63,7 +63,7 @@ -
+
Leads diff --git a/addons/crm/sales_team_view.xml b/addons/crm/sales_team_view.xml index 2cbf338e328..5f09103dd28 100644 --- a/addons/crm/sales_team_view.xml +++ b/addons/crm/sales_team_view.xml @@ -87,9 +87,11 @@ - - @@ -101,10 +103,10 @@