From 30a7ef804a1457fb0274994993c86a01dbb114d4 Mon Sep 17 00:00:00 2001
From: Hitesh Trivedi <htr@openerp.com>
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                  | 133 +++++++++++-------
 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               |  31 ++--
 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, 304 insertions(+), 144 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 b790f9bc2330..4818a507db5e 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 db580a6835de..54632487de78 100644
--- a/addons/crm/base_partner_merge_view.xml
+++ b/addons/crm/base_partner_merge_view.xml
@@ -1,22 +1,17 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <openerp>
     <data>
-        <!-- the sequence of the configuration sub menu is 30 -->
 
-        <record model="ir.actions.act_window" id="base_partner_merge_automatic_act">
-            <field name="name">Deduplicate Contacts</field>
-            <field name="res_model">base.partner.merge.automatic.wizard</field>
-            <field name="view_type">form</field>
-            <field name="view_mode">form</field>
-            <field name="target">new</field>
-            <field name="context">{'active_test': False}</field>
-        </record>
-
-        <menuitem id='partner_merge_automatic_menu'
-            action='base_partner_merge_automatic_act'
-            groups='base.group_system'
-            parent='base.menu_config_address_book' 
-            sequence='4'/>
+        <act_window id="action_partner_deduplicate"
+            res_model="base.partner.merge.automatic.wizard"
+            src_model="res.partner"
+            target="new"
+            multi="True"
+            key2="client_action_multi"
+            view_mode="form"
+            name="Deduplicate Contact"
+            context="{'default_state': 'option'}"
+        />
 
         <record model='ir.ui.view' id='base_partner_merge_automatic_wizard_form'>
             <field name='name'>base.partner.merge.automatic.wizard.form</field>
@@ -26,7 +21,7 @@
                     <sheet>
                         <group attrs="{'invisible': [('state', '!=', 'finished')]}" col="1">
                             <h2>There is no more contacts to merge for this request...</h2>
-                            <button name="%(base_partner_merge_automatic_act)d" string="Deduplicate the other Contacts" class="oe_highlight"
+                            <button name="%(action_partner_deduplicate)d" string="Deduplicate the other Contacts" class="oe_highlight"
                             type="action"/>
                         </group>
                         <p class="oe_grey" attrs="{'invisible': [('state', '!=', ('option'))]}">
@@ -118,7 +113,7 @@
         </record>
         
         <act_window id="action_partner_merge" res_model="base.partner.merge.automatic.wizard" src_model="res.partner"
-            target="new" multi="True" key2="client_action_multi" view_mode="form" name="Automatic Merge"/>
+            target="new" multi="True" key2="client_action_multi" view_mode="form" name="Merge Selected Contacts"/>
 
     </data>
 
diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py
index 5c42e2831e4f..2cc6f85a5287 100644
--- a/addons/crm/crm_lead.py
+++ b/addons/crm/crm_lead.py
@@ -58,14 +58,6 @@ class crm_lead(format_address, osv.osv):
     _inherit = ['mail.thread', 'ir.needaction_mixin', 'utm.mixin']
     _mail_mass_mailing = _('Leads / Opportunities')
 
-    def get_empty_list_help(self, cr, uid, help, context=None):
-        context = dict(context or {})
-        if context.get('default_type') == 'lead':
-            context['empty_list_help_model'] = 'crm.team'
-            context['empty_list_help_id'] = context.get('default_team_id')
-        context['empty_list_help_document_name'] = _("leads")
-        return super(crm_lead, self).get_empty_list_help(cr, uid, help, context=context)
-
     def _get_default_stage_id(self, cr, uid, context=None):
         """ Gives default stage_id """
         team_id = self.pool['crm.team']._get_default_team_id(cr, uid, context=context)
@@ -91,7 +83,7 @@ class crm_lead(format_address, osv.osv):
         # - OR ('fold', '=', False): add default columns that are not folded
         # - OR ('team_ids', '=', team_id), ('fold', '=', False) if team_id: add team columns that are not folded
         search_domain = []
-        team_id = self.pool['crm.team']._resolve_team_id_from_context(cr, uid, context=context)
+        team_id = context and context.get('default_team_id') or False
         if team_id:
             search_domain += ['|', ('team_ids', '=', team_id)]
             search_domain += [('id', 'in', ids)]
@@ -183,7 +175,7 @@ class crm_lead(format_address, osv.osv):
             [('lead', 'Lead'), ('opportunity', 'Opportunity')],
             string='Type', select=True, required=True,
             help="Type is used to separate Leads and Opportunities"),
-        'priority': fields.selection(crm_stage.AVAILABLE_PRIORITIES, 'Priority', select=True),
+        'priority': fields.selection(crm_stage.AVAILABLE_PRIORITIES, 'Rating', select=True),
         'date_closed': fields.datetime('Closed', readonly=True, copy=False),
         'stage_id': fields.many2one('crm.stage', 'Stage', track_visibility='onchange', select=True,
                         domain="['&', ('team_ids', '=', team_id), '|', ('type', '=', type), ('type', '=', 'both')]"),
@@ -204,8 +196,6 @@ class crm_lead(format_address, osv.osv):
         # Only used for type opportunity
         'probability': fields.float('Probability', group_operator="avg"),
         'planned_revenue': fields.float('Expected Revenue', track_visibility='always'),
-        'ref': fields.reference('Reference', selection=openerp.addons.base.res.res_request.referencable_models),
-        'ref2': fields.reference('Reference 2', selection=openerp.addons.base.res.res_request.referencable_models),
         'phone': fields.char("Phone", size=64),
         'date_deadline': fields.date('Expected Closing', help="Estimate of the date on which the opportunity will be won."),
         # CRM Actions
@@ -213,8 +203,8 @@ class crm_lead(format_address, osv.osv):
         'next_activity_1': fields.related("next_activity_id", "activity_1_id", "name", type="char", string="Next Activity 1"),
         'next_activity_2': fields.related("next_activity_id", "activity_2_id", "name", type="char", string="Next Activity 2"),
         'next_activity_3': fields.related("next_activity_id", "activity_3_id", "name", type="char", string="Next Activity 3"),
-        'date_action': fields.date('Next Action Date', select=True),
-        'title_action': fields.char('Next Action Summary'),
+        'date_action': fields.date('Next Activity Date', select=True),
+        'title_action': fields.char('Next Activity Summary'),
 
         'color': fields.integer('Color Index'),
         'partner_address_name': fields.related('partner_id', 'name', type='char', string='Partner Contact Name', readonly=True),
@@ -242,7 +232,7 @@ class crm_lead(format_address, osv.osv):
 
     _defaults = {
         'active': 1,
-        'type': 'lead',
+        'type': lambda s, cr, uid, c: 'lead' if s.pool['res.users'].has_group(cr, uid, 'crm.group_use_lead') else 'opportunity',
         'user_id': lambda s, cr, uid, c: uid,
         'stage_id': lambda s, cr, uid, c: s._get_default_stage_id(cr, uid, c),
         'team_id': lambda s, cr, uid, c: s.pool['crm.team']._get_default_team_id(cr, uid, context=c),
@@ -291,11 +281,7 @@ class crm_lead(format_address, osv.osv):
     def on_change_user(self, cr, uid, ids, user_id, context=None):
         """ When changing the user, also set a team_id or restrict team id
             to the ones user_id is member of. """
-        team_id = self.pool['crm.team']._get_default_team_id(cr, uid, user_id=user_id, context=context)
-        if user_id and not team_id:
-            team_ids = self.pool.get('crm.team').search(cr, uid, ['|', ('user_id', '=', user_id), ('member_ids', '=', user_id)], context=context)
-            if team_ids:
-                team_id = team_ids[0]
+        team_id = self.pool['crm.team']._get_default_team_id(cr, uid, context=context, user_id=user_id)
         return {'value': {'team_id': team_id}}
 
     def stage_find(self, cr, uid, cases, team_id, domain=None, order='sequence', context=None):
@@ -918,9 +904,18 @@ class crm_lead(format_address, osv.osv):
         context = dict(context or {})
         context['empty_list_help_model'] = 'crm.team'
         context['empty_list_help_id'] = context.get('default_team_id', None)
-        context['empty_list_help_document_name'] = _("opportunity")
-        if context.get('default_type') == 'lead':
-            context['empty_list_help_document_name'] = _("lead")
+        context['empty_list_help_document_name'] = _("opportunities")
+        if help:
+            alias_record = self.pool['ir.model.data'].xmlid_to_object(cr, uid, "crm.mail_alias_lead_info")
+            if alias_record and alias_record.alias_domain and alias_record.alias_name:
+                dynamic_help = '<p>%s</p>' % _("""All email incoming to %(link)s  will automatically create new opportunity.
+Update your business card, phone book, social media,... Send an email right now and see it here.""") % {
+                    'link': "<a href='mailto:%s'>%s</a>" % (alias_record.alias_name, alias_record.alias_domain)
+                }
+                return '<p class="oe_view_nocontent_create">%s</p>%s%s' % (
+                    _('Click to add a new opportunity'),
+                    help,
+                    dynamic_help)
         return super(crm_lead, self).get_empty_list_help(cr, uid, help, context=context)
 
     # ----------------------------------------
diff --git a/addons/crm/crm_lead_menu.xml b/addons/crm/crm_lead_menu.xml
index f6ec9e09b88c..b7c124b03824 100644
--- a/addons/crm/crm_lead_menu.xml
+++ b/addons/crm/crm_lead_menu.xml
@@ -77,7 +77,36 @@
 
     <menuitem id="base.menu_sales" name="Sales" parent="base.menu_base_partner" sequence="5"/>
     <menuitem name="Leads" id="menu_crm_leads" parent="base.menu_sales" sequence="1"
-            action="crm_lead_all_leads"/>
+            action="crm_lead_all_leads" groups="crm.group_use_lead"/>
+
+    <record id="crm_lead_action_activities" model="ir.actions.act_window">
+        <field name="name">Next Activities</field>
+        <field name="type">ir.actions.act_window</field>
+        <field name="res_model">crm.lead</field>
+        <field name="view_mode">tree,form</field>
+        <field name="search_view_id" ref="crm.view_crm_case_opportunities_filter"/>
+        <field name="view_ids"
+               eval="[(5, 0, 0),
+                      (0, 0, {'view_mode': 'tree', 'view_id': ref('crm_lead_view_tree_activity')}),
+                      (0, 0, {'view_mode': 'form', 'view_id': ref('crm_case_form_view_oppor')}), 
+                      (0, 0, {'view_mode': 'kanban'})]"/>
+        <field name="domain">[('type','=','opportunity'), ('date_action','!=',False)]</field>
+        <field name="context">{
+                'default_type': 'opportunity',
+                'default_user_id': uid,
+                'search_default_assigned_to_me': 1
+            }
+        </field>
+        <field name="help" type="html">
+            <p>
+               Here is the list of your next activities. Those are linked to your opportunities.
+               To set a next activity, go on an opportunity and add one. It will then appear in this list.
+            </p>
+        </field>
+    </record>
+
+    <menuitem id="crm_lead_menu_activities" name="Next Activities" sequence="5"
+        parent="base.menu_sales" action="crm_lead_action_activities" />
 
 </data>
 </openerp>
diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml
index 8f5a77c0a5b9..8880876962f6 100644
--- a/addons/crm/crm_lead_view.xml
+++ b/addons/crm/crm_lead_view.xml
@@ -126,20 +126,24 @@
                 <sheet>
                     <div class="oe_button_box" name="button_box"/>
                     <div class="oe_title">
-                        <label for="name" class="oe_edit_only"/>
+                        <label for="name" class="oe_edit_only" string="Lead"/>
                         <h1><field name="name" placeholder="Describe the lead..."/></h1>
-                        <span class="label label-danger"
-                            attrs="{'invisible': ['|', ('probability', '&gt;', 0), ('active', '=', True)]}">Lost</span>
-                        <span class="label label-success"
-                            attrs="{'invisible': [('probability', '&lt;', 100)]}">Won</span>
+                        <label for="tag_ids" class="oe_edit_only"/>
+                        <field name="tag_ids" widget="many2many_tags"/>
+                        <div class="mt4">
+                            <span class="label label-danger"
+                                attrs="{'invisible': ['|', ('probability', '&gt;', 0), ('active', '=', True)]}">Lost</span>
+                            <span class="label label-success"
+                                attrs="{'invisible': [('probability', '&lt;', 100)]}">Won</span>
+                        </div>
                     </div>
                     <group>
                         <group>
-                            <field name="partner_name" string="Company Name"/>
                             <!-- Preload all the partner's information -->
                             <field name="partner_id" string="Customer"
                                 options='{"create_name_field": "name"}'
-                                context="{'default_name': contact_name, 'default_street': street, 'default_city': city, 'default_state_id': state_id, 'default_zip': zip, 'default_country_id': country_id, 'default_function': function, 'default_phone': phone, 'default_mobile': mobile, 'default_fax': fax, 'default_email': email_from, 'default_user_id': user_id, 'default_team_id': team_id}"/>
+                                context="{'default_name': contact_name, 'default_street': street, 'default_city': city, 'default_state_id': state_id, 'default_zip': zip, 'default_country_id': country_id, 'default_function': function, 'default_phone': phone, 'default_mobile': mobile, 'default_fax': fax, 'default_email': email_from, 'default_user_id': user_id, 'default_team_id': team_id}" groups="base.group_no_one"/>
+                            <field name="partner_name" string="Company Name"/>
                             <label for="street" string="Address"/>
                             <div class="o_address_format">
                                 <field name="street" placeholder="Street..." class="o_address_street"/>
@@ -153,7 +157,7 @@
                         <group>
                             <label for="contact_name"/>
                             <div class="o_row">
-                                <field name="contact_name"/><span attrs="{'invisible': [('title', '=', '')]}">, </span>
+                                <field name="contact_name"/>
                                 <field name="title" placeholder="Title" domain="[('domain', '=', 'contact')]" options='{"no_open": True}'/>
                             </div>
                             <field name="email_from" widget="email"/>
@@ -164,15 +168,11 @@
                         </group>
                         <group>
                             <field name="user_id" on_change="on_change_user(user_id, context)"
-                                context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'base.group_sale_salesman_all_leads'] }"/>
-                            <label for="team_id"/>
-                            <div class="o_row">
-                                <field name="team_id"/>
-                            </div>
+                                context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'base.group_sale_salesman_all_leads'] }" widget="selection"/>
+                            <field name="team_id" widget="selection" domain="[('use_leads','=',True)]"/>
                             <field name="type" invisible="1"/>
                         </group>
                         <group>
-                            <field name="tag_ids" widget="many2many_tags"/>
                             <field name="priority" widget="priority"/>
                         </group>
                     </group>
@@ -182,9 +182,9 @@
                     </page>
                     <page name="extra" string="Extra Info">
                         <group>
-                            <group string="Mailings">
+                            <group>
                                 <field name="opt_out"/>
-                                <field name="message_bounce" readonly="1"/>
+                                <field name="message_bounce" readonly="1" groups="base.group_no_one"/>
                             </group>
                             <group string="Categorization" groups="base.group_multi_company,base.group_no_one" name="categorization">
                                 <field name="company_id"
@@ -194,7 +194,7 @@
                                 <field name="medium_id"/>
                                 <field name="source_id" />
                             </group>
-                            <group name="misc" string="Misc">
+                            <group name="misc">
                                 <field name="probability" groups="base.group_no_one"/>
                                 <field name="active"/>
                                 <field name="referred"/>
@@ -247,7 +247,7 @@
                 <tree string="Leads" decoration-bf="message_unread==True" decoration-muted="probability == 100">
                     <field name="date_deadline" invisible="1"/>
                     <field name="create_date"/>
-                    <field name="name"/>
+                    <field name="name" string="Lead"/>
                     <field name="contact_name"/>
                     <field name="country_id"/>
                     <field name="email_from"/>
@@ -324,6 +324,14 @@
                                     <div class="text-muted">
                                         <span t-if="record.planned_revenue.raw_value"><t t-esc="record.planned_revenue.value"/><field name="company_currency"/></span> <span t-if="record.partner_id.value"> - <t t-esc="record.partner_id.value"/></span>
                                     </div>
+                                    <div class="text-muted">
+                                        <t t-if="record.date_deadline.raw_value and record.date_deadline.raw_value lt (new Date())" t-set="red">oe_kanban_text_red</t>
+                                        <span t-attf-class="#{red || ''}">
+                                            <field name="date_action"/>
+                                            <t t-if="record.date_action.raw_value"> : </t>
+                                            <field name="next_activity_id"/>
+                                        </span>
+                                    </div>
                                     <div class="o_kanban_footer">
                                         <field name="priority" widget="priority" groups="base.group_user"/>
                                         <t t-if="record.message_unread_counter.raw_value">
@@ -410,8 +418,9 @@
                         <button name="action_set_won" string="Mark Won"
                                 type="object" class="oe_highlight"
                                 attrs="{'invisible': ['|', ('active','=',False), ('probability', '=', 100)]}"/>
-                        <button name="action_set_lost" string="Mark Lost"
-                                type="object" class="oe_highlight"
+                        <button name="%(crm.crm_lead_lost_action)d" string="Mark Lost"
+                                type="action" class="oe_highlight"
+                                context="{'default_lead_id': active_id}"
                                 attrs="{'invisible': [('active', '=', False)]}"/>
                         <button name="action_set_active" string="Unarchive"
                                 type="object" class="oe_highlight"
@@ -426,27 +435,41 @@
                             <button class="oe_stat_button" type="object"
                                 context="{'partner_id': partner_id}"
                                 name="action_schedule_meeting" icon="fa-calendar">
-                                <field string="Meetings" name="meeting_count" widget="statinfo"/>
+                                <div class="o_stat_info">
+                                    <field name="meeting_count" class="o_stat_value"/>
+                                    <span class="o_stat_text" attrs="{'invisible': [('meeting_count', '&lt;', 2)]}"> Meetings</span>
+                                    <span class="o_stat_text" attrs="{'invisible': [('meeting_count', '&gt;', 1)]}"> Meeting</span>
+                                </div>
                             </button>
                         </div>
-                        <div class="oe_title">
+                        <div>
                             <label for="name" class="oe_edit_only"/>
                             <h1><field name="name" placeholder="e.g. Product Pricing"/></h1>
-                            <span class="label label-danger"
-                                attrs="{'invisible': ['|', ('probability', '&gt;', 0), ('active', '=', True)]}">Lost</span>
-                            <span class="label label-success"
-                                attrs="{'invisible': [('probability', '&lt;', 100)]}">Won</span>
+                            <label for="tag_ids" class="oe_edit_only"/>
+                            <field name="tag_ids" widget="many2many_tags"/>
+                            <div class="mt4">
+                                <span class="label label-danger"
+                                    attrs="{'invisible': ['|', ('probability', '&gt;', 0), ('active', '=', True)]}">Lost</span>
+                                <span class="label label-success"
+                                    attrs="{'invisible': [('probability', '&lt;', 100)]}">Won</span>
+                            </div>
                             <div class="o_row">
-                                <label for="planned_revenue" class="oe_edit_only"/>
-                                <label for="probability" class="oe_edit_only"/>
+                                <div class="oe_left">
+                                    <label for="planned_revenue" class="oe_edit_only"/>
+                                    <h2 class="o_row">
+                                        <field name="company_currency" invisible="1"/>
+                                        <field name="planned_revenue" widget='monetary' options="{'currency_field': 'company_currency'}"/>
+                                        <span class="oe_grey"> at </span>
+                                    </h2>
+                                </div>
+                                <div>
+                                    <label for="probability" class="oe_edit_only"/>
+                                    <h2 class="o_row">
+                                        <field name="probability" widget="integer"/>
+                                        <span>%%</span>
+                                    </h2>
+                                </div>
                             </div>
-                            <h2 class="o_row">
-                                <field name="company_currency" invisible="1"/>
-                                <field name="planned_revenue" widget='monetary' options="{'currency_field': 'company_currency'}"/>
-                                <span class="oe_grey"> at </span>
-                                <field name="probability" widget="integer"/>
-                                <span>%%</span>
-                            </h2>
                         </div>
                         <group>
                             <group>
@@ -489,19 +512,15 @@
                                     </div>
                                 </div>
                                 <field name="date_deadline"/>
-                                <field name="priority" widget="priority"/>
                             </group>
 
                             <group>
-                                <field name="user_id" on_change="on_change_user(user_id, context)" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'base.group_sale_salesman_all_leads']}"/>
-                                <label for="team_id"/>
-                                <div class="o_row">
-                                    <field name="team_id" widget="selection"/>
-                                </div>
+                                <field name="user_id" on_change="on_change_user(user_id, context)" context="{'default_groups_ref': ['base.group_user', 'base.group_partner_manager', 'base.group_sale_salesman_all_leads']}" widget="selection"/>
+                                <field name="team_id" widget="selection"/>
                             </group>
                             <group>
-                                <field name="tag_ids" widget="many2many_tags"/>
-                                <field name="lost_reason"/>
+                                <field name="priority" widget="priority"/>
+                                <field name="lost_reason" attrs="{'invisible': [('active', '=', True)]}"/>
                                 <field name="date_conversion" invisible="1"/>
                             </group>
                         </group>
@@ -510,7 +529,7 @@
                         <page string="Internal Notes">
                             <field name="description"/>
                         </page>
-                        <page name="lead" string="Lead">
+                        <page name="lead" string="Lead" groups="crm.group_use_lead">
                             <group>
                                 <group>
                                     <field name="partner_name"/>
@@ -534,26 +553,20 @@
                                     <field name="function"/>
                                     <field name="mobile"/>
                                     <field name="fax"/>
+                                    <field name="opt_out"/>
                                 </group>
                                 <group string="Marketing">
                                     <field name="campaign_id" />
                                     <field name="medium_id" />
                                     <field name="source_id" />
                                 </group>
-                                <group string="Mailings" name="mailings">
-                                    <field name="opt_out"/>
-                                </group>
-                                <group string="Misc">
+                                <group string="Misc" name="Misc">
                                     <field name="active"/>
                                     <field name="day_open" groups="base.group_no_one"/>
                                     <field name="day_close" groups="base.group_no_one"/>
                                     <field name="referred"/>
                                     <field name="type" invisible="1"/>
                                 </group>
-                                <group name="references" string="References">
-                                    <field name="ref"/>
-                                    <field name="ref2"/>
-                                </group>
                             </group>
                         </page>
                         </notebook>
@@ -608,6 +621,8 @@
                     <field name="user_id"/>
                     <field name="partner_id" operator="child_of" string="Customer"/>
                     <field name="stage_id" domain="[]"/>
+                    <field name="next_activity_id"/>
+                    <field name="title_action"/>
                     <field name="probability"/>
                     <field name="lost_reason"/>
                     <separator/>
@@ -648,6 +663,20 @@
             </field>
         </record>
 
+        <record id="crm_lead_view_tree_activity" model="ir.ui.view">
+            <field name="name">crm.lead.next.activity.tree</field>
+            <field name="model">crm.lead</field>
+            <field name="arch" type="xml">
+                <tree string="Next Activity" create="false" colors="red:date_action and (date_action &lt; current_date)" default_order="date_action">
+                    <field name="name"/>
+                    <field name="date_action"/>
+                    <field name="next_activity_id"/>
+                    <field name="title_action"/>
+                    <field name="date_deadline"/>
+                </tree>
+            </field>
+        </record>
+
         <!--
             MASS MAILING
         -->
diff --git a/addons/crm/crm_tip_data.xml b/addons/crm/crm_tip_data.xml
index d07a03f447c7..c2df524d710d 100644
--- a/addons/crm/crm_tip_data.xml
+++ b/addons/crm/crm_tip_data.xml
@@ -34,5 +34,27 @@
             <field name="placement">auto top</field>
         </record>
 
+        <record model="web.tip" id="crm_tip_5">
+            <field name="title"></field>
+            <field name="description"><![CDATA[Use the graph view to have a clear reporting of your opportunity pipeline.]]></field>
+            <field name="model">crm.lead</field>
+            <field name="mode">kanban</field>
+            <field name="trigger_selector">.o_kanban_record:eq(20):visible</field>
+            <field name="highlight_selector">button[data-view-type=graph]</field>
+            <field name="end_event">mousedown</field>
+            <field name="placement">left</field>
+        </record>
+
+        <record model="web.tip" id="crm_tip_6">
+            <field name="title"></field>
+            <field name="description"><![CDATA[Gain some time and change the stage of your opportunity right here, no need to go back to your pipeline.]]></field>
+            <field name="model">crm.lead</field>
+            <field name="mode">form</field>
+            <field name="trigger_selector">.oe_form_field_status.oe_form_status_clickable:visible</field>
+            <field name="highlight_selector">.oe_form_field_status.oe_form_status_clickable</field>
+            <field name="end_event">mousedown</field>
+            <field name="placement">bottom</field>
+        </record>
+
     </data>
 </openerp>
diff --git a/addons/crm/report/crm_activity_report.py b/addons/crm/report/crm_activity_report.py
index 3f29a01f4da2..5bf4445fc720 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 2c97a41a95bc..ac2a51fde459 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.</field>
 (including those converted into opportunities).</field>
         </record>
         <menuitem id="crm_opportunity_report_menu_lead" name="Leads Analysis"
-             parent="base.menu_sale_report" action="crm_opportunity_report_action_lead" sequence="6"/>
+             parent="base.menu_sale_report" groups="crm.group_use_lead" action="crm_opportunity_report_action_lead" sequence="6"/>
 
     </data>
 </openerp>
diff --git a/addons/crm/res_config.py b/addons/crm/res_config.py
index 160f6982bc84..bed7d5437a69 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 723318dcd68c..ab879f47d229 100644
--- a/addons/crm/res_config_view.xml
+++ b/addons/crm/res_config_view.xml
@@ -32,6 +32,13 @@
                         </div>
 
                     </group>
+                    <group>
+                        <label for="id" string="Manage Leads"/>
+                        <div>
+                            <field name="group_use_lead" class="oe_inline"/>
+                            <label for="group_use_lead"/>
+                        </div>
+                    </group>
                 </div>
                 </data>
             </field>
diff --git a/addons/crm/sales_team.py b/addons/crm/sales_team.py
index e33edaa2ec60..ef273eb57bff 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 c75be5ae6586..bef7416a3f88 100644
--- a/addons/crm/sales_team_dashboard.xml
+++ b/addons/crm/sales_team_dashboard.xml
@@ -42,7 +42,7 @@
                 </xpath>
 
                 <xpath expr="//div[contains(@class, 'o_kanban_manage_view')]" position="inside">
-                    <div t-if="record.use_leads.raw_value">
+                    <div t-if="record.use_leads.raw_value" groups="crm.group_use_lead">
                         <a name="%(crm_case_form_view_salesteams_lead)d" type="action">
                             Leads
                         </a>
@@ -63,7 +63,7 @@
                 </xpath>
 
                 <xpath expr="//div[contains(@class, 'o_kanban_manage_reports')]" position="inside">
-                    <div>
+                    <div t-if="record.use_leads.raw_value" groups="crm.group_use_lead">
                         <a name="%(action_report_crm_lead_salesteam)d" type="action">
                             Leads
                         </a>
diff --git a/addons/crm/sales_team_view.xml b/addons/crm/sales_team_view.xml
index 2cbf338e3287..5f09103dd281 100644
--- a/addons/crm/sales_team_view.xml
+++ b/addons/crm/sales_team_view.xml
@@ -87,9 +87,11 @@
                 <field name="inherit_id" ref="sales_team.crm_team_view_form"/>
                 <field name="arch" type="xml">
                     <xpath expr="//div[@name='options_active']" position="inside">
-                        <field name="use_leads" on_change="onchange_use_leads(use_leads)"/>
-                        <label for="use_leads" string="Leads"/>
-                        <field name="use_opportunities" class="oe_inline"/>
+                        <div groups="crm.group_use_lead">
+                            <field name="use_leads" on_change="onchange_use_leads_opportunities(use_leads, use_opportunities)"/>
+                            <label for="use_leads" string="Leads"/>
+                        </div>
+                        <field name="use_opportunities" class="oe_inline" on_change="onchange_use_leads_opportunities(use_leads, use_opportunities)"/>
                         <label for="use_opportunities"/>
                     </xpath>
                     <xpath expr="//page[@name='members']" position="after">
@@ -101,10 +103,10 @@
                    <xpath expr="//field[@name='code']" position="after">
                         <label for="alias_name" string="Email Alias"
                             groups="base.group_no_one"
-                            attrs="{'invisible': [('use_leads', '=', False)]}"/>
+                            attrs="{'invisible': [('use_leads', '=', False), ('use_opportunities', '=', False)]}"/>
                         <div name="alias_def"
                             groups="base.group_no_one"
-                            attrs="{'invisible': [('use_leads', '=', False)]}">
+                            attrs="{'invisible': [('use_leads', '=', False), ('use_opportunities', '=', False)]}">
                             <field name="alias_id" class="oe_read_only oe_inline"
                                 string="Email Alias" required="0"/>
                             <div class="oe_edit_only oe_inline" name="edit_alias" style="display: inline;" >
@@ -113,7 +115,7 @@
                         </div>
                         <field name="alias_contact" class="oe_inline"
                            string="Accept Emails From"
-                           attrs="{'invisible': [('use_leads', '=', False)]}"/>
+                           attrs="{'invisible': [('use_leads', '=', False), ('use_opportunities', '=', False)]}"/>
                    </xpath>
                 </field>
             </record>
diff --git a/addons/crm/security/crm_security.xml b/addons/crm/security/crm_security.xml
index ef398b6b35a3..765568140e26 100644
--- a/addons/crm/security/crm_security.xml
+++ b/addons/crm/security/crm_security.xml
@@ -24,6 +24,11 @@
         <field name="users" eval="[(4, ref('base.user_root'))]"/>
     </record>
 
+    <record id="group_use_lead" model="res.groups">
+        <field name="name">Show Lead Menu</field>
+        <field name="category_id" ref="base.module_category_hidden"/>
+    </record>
+
     <record model="res.users" id="base.user_root">
         <field eval="[(4,ref('base.group_partner_manager'))]" name="groups_id"/>
     </record>
diff --git a/addons/crm/wizard/__init__.py b/addons/crm/wizard/__init__.py
index 99dd897bb8b0..e4c563df3a1e 100644
--- a/addons/crm/wizard/__init__.py
+++ b/addons/crm/wizard/__init__.py
@@ -1,6 +1,7 @@
 # -*- coding: utf-8 -*-
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
 
+import crm_lead_lost
 import crm_partner_binding
 import crm_lead_to_opportunity
 import crm_merge_opportunities
diff --git a/addons/crm/wizard/crm_lead_lost.py b/addons/crm/wizard/crm_lead_lost.py
new file mode 100644
index 000000000000..98b85771722e
--- /dev/null
+++ b/addons/crm/wizard/crm_lead_lost.py
@@ -0,0 +1,18 @@
+# -*- coding: utf-8 -*-
+from openerp import api, fields, models
+
+
+class CrmLeadLost(models.TransientModel):
+    _name = 'crm.lead.lost'
+    _description = 'Get Lost Reason'
+
+    lead_id = fields.Many2one('crm.lead', 'Lead', required=True)
+    lost_reason_id = fields.Many2one('crm.lost.reason', 'Lost Reason')
+
+    @api.multi
+    def action_lost_reason_apply(self):
+        res = False
+        for wizard in self:
+            self.lead_id.lost_reason_id = self.lost_reason_id.id
+            res = self.lead_id.action_set_lost()
+        return res
diff --git a/addons/crm/wizard/crm_lead_lost_view.xml b/addons/crm/wizard/crm_lead_lost_view.xml
new file mode 100644
index 000000000000..9acd3bd80bbc
--- /dev/null
+++ b/addons/crm/wizard/crm_lead_lost_view.xml
@@ -0,0 +1,29 @@
+<?xml version="1.0"?>
+<odoo>
+        <record id="crm_lead_lost_view_form" model="ir.ui.view">
+            <field name="name">crm.lead.lost.form</field>
+            <field name="model">crm.lead.lost</field>
+            <field name="arch" type="xml">
+                <form string="Lost Reason">
+                    <group class="oe_title">
+                        <field name="lead_id" invisible="1"/>
+                        <field name="lost_reason_id"/>
+                    </group>
+                    <footer>
+                        <button name="action_lost_reason_apply" string="Submit" type="object" class="oe_highlight"/>
+                        or
+                        <button string="Cancel" class="oe_link" special="cancel"/>
+                    </footer>
+                </form>
+            </field>
+        </record>
+ 
+        <record id="crm_lead_lost_action" model="ir.actions.act_window">
+            <field name="name">Lost Reason</field>
+            <field name="type">ir.actions.act_window</field>
+            <field name="res_model">crm.lead.lost</field>
+            <field name="view_mode">form</field>
+            <field name="view_id" ref="crm_lead_lost_view_form"/>
+            <field name="target">new</field>
+        </record>
+</odoo>
diff --git a/addons/crm/wizard/crm_lead_to_opportunity_view.xml b/addons/crm/wizard/crm_lead_to_opportunity_view.xml
index a67542a2ce27..903c63dd8a45 100644
--- a/addons/crm/wizard/crm_lead_to_opportunity_view.xml
+++ b/addons/crm/wizard/crm_lead_to_opportunity_view.xml
@@ -11,8 +11,8 @@
                         <field name="name" widget="radio"/>
                     </group>
                     <group string="Assign these opportunities to">
-                        <field name="user_id" on_change="on_change_user(user_id, team_id, context)"/>
-                        <field name="team_id"/>
+                        <field name="user_id" on_change="on_change_user(user_id, team_id, context)" widget="selection"/>
+                        <field name="team_id" widget="selection"/>
                     </group>
                     <group string="Opportunities" attrs="{'invisible': [('name', '!=', 'merge')]}">
                         <field name="opportunity_ids" nolabel="1">
diff --git a/addons/sale_crm/sale_crm_view.xml b/addons/sale_crm/sale_crm_view.xml
index cb8d14a708c9..e6814970fdee 100644
--- a/addons/sale_crm/sale_crm_view.xml
+++ b/addons/sale_crm/sale_crm_view.xml
@@ -33,7 +33,10 @@
                         <button class="oe_stat_button" type="action"
                                 name="%(sale_action_quotations)d" icon="fa-usd"
                                 context="{'search_default_partner_id': partner_id, 'default_partner_id': partner_id}">
-                            <field name="sale_number" widget="statinfo" string="Quotes"/>
+                            <div class="o_stat_info">
+                                <field name="sale_number" class="o_stat_value"/>
+                                <span class="o_stat_text"> Quote(s) </span>
+                            </div>
                         </button>
                         <button class="oe_stat_button" type="action" attrs="{'invisible': [('sale_amount_total', '=', 0)]}"
                                 name="%(sale_action_quotations)d" icon="fa-usd"
diff --git a/addons/sales_team/sales_team.py b/addons/sales_team/sales_team.py
index 4defeb4868d0..8c871b88bbc1 100644
--- a/addons/sales_team/sales_team.py
+++ b/addons/sales_team/sales_team.py
@@ -1,8 +1,6 @@
 # -*- coding: utf-8 -*-
 # Part of Odoo. See LICENSE file for full copyright and licensing details.
-from datetime import date, datetime
-from dateutil import relativedelta
-from openerp import tools
+
 from openerp.osv import fields, osv
 
 
@@ -16,28 +14,19 @@ class crm_team(osv.Model):
     def get_full_name(self, cr, uid, ids, field_name, arg, context=None):
         return dict(self.name_get(cr, uid, ids, context=context))
 
-    def _get_default_team_id(self, cr, uid, user_id=None, context=None):
-        team_id = self._resolve_team_id_from_context(cr, uid, context=context) or False
+    def _get_default_team_id(self, cr, uid, context=None, user_id=None):
+        if context is None:
+            context = {}
+        if user_id is None:
+            user_id = uid
+        team_id = context.get('default_team_id')
         if not team_id:
-            team_ids = self.search(cr, uid, [('member_ids', '=', user_id or uid)], limit=1, context=context)
+            team_ids = self.search(cr, uid, ['|', ('user_id', '=', user_id), ('member_ids', 'in', user_id)], limit=1, context=context)
             team_id = team_ids[0] if team_ids else False
+        if not team_id:
+            team_id = self.pool['ir.model.data'].xmlid_to_res_id(cr, uid, 'sales_team.team_sales_department')
         return team_id
 
-    def _resolve_team_id_from_context(self, cr, uid, context=None):
-        """ Returns ID of team based on the value of 'default_team_id'
-            context key, or None if it cannot be resolved to a single
-            Sales Team.
-        """
-        if context is None:
-            context = {}
-        if type(context.get('default_team_id')) in (int, long):
-            return context.get('default_team_id')
-        if isinstance(context.get('default_team_id'), basestring):
-            team_ids = self.name_search(cr, uid, name=context['default_team_id'], context=context)
-            if len(team_ids) == 1:
-                return int(team_ids[0][0])
-        return None
-
     _columns = {
         'name': fields.char('Sales Team', size=64, required=True, translate=True),
         'complete_name': fields.function(get_full_name, type='char', size=256, readonly=True, store=True, string="Full Name"),
diff --git a/addons/website_crm_score/models/crm_lead.py b/addons/website_crm_score/models/crm_lead.py
index f17ddd689a5d..47e84cb82488 100644
--- a/addons/website_crm_score/models/crm_lead.py
+++ b/addons/website_crm_score/models/crm_lead.py
@@ -88,12 +88,3 @@ class Lead(models.Model):
         if 'user_id' in vals:
             vals['assign_date'] = vals.get('user_id') and fields.datetime.now() or False
         return super(Lead, self).write(vals)
-
-    @api.multi
-    @api.onchange('user_id')
-    def on_change_user(self, user_id):
-        ret = super(Lead, self).on_change_user(user_id)
-        if user_id:
-            team_ids = self.env['crm.team'].search([('team_user_ids.user_id', '=', user_id)])
-            ret['value']['team_id'] = team_ids and team_ids[0] or False
-        return ret
diff --git a/addons/website_crm_score/models/sales_team.py b/addons/website_crm_score/models/sales_team.py
index 528f5864237b..432ccc14ac31 100644
--- a/addons/website_crm_score/models/sales_team.py
+++ b/addons/website_crm_score/models/sales_team.py
@@ -75,6 +75,15 @@ class team_user(models.Model):
 class crm_team(osv.osv):
     _inherit = "crm.team"
 
+    @api.model
+    def _get_default_team_id(self, user_id=None):
+        team_id = super(crm_team, self)._get_default_team_id(user_id=user_id)
+        if user_id is None:
+            user_id = self.env.user.id
+        if not team_id:
+            team_id = self.search([('team_user_ids.user_id', '=', user_id)], limit=1).id
+        return team_id
+
     @api.one
     def _count_leads(self):
         if self.id:
diff --git a/addons/website_crm_score/tests/common.py b/addons/website_crm_score/tests/common.py
index 5bdfecc95e64..b76cf666dc47 100644
--- a/addons/website_crm_score/tests/common.py
+++ b/addons/website_crm_score/tests/common.py
@@ -60,6 +60,7 @@ class TestScoring(common.TransactionCase):
             'country_id': self.belgium,
             'email_from': 'lead0@test.com',
             'user_id': None,
+            'team_id': False,
             'stage_id': self.stage,
 
         })
@@ -68,12 +69,14 @@ class TestScoring(common.TransactionCase):
             'country_id': self.france,
             'email_from': 'lead1@test.com',
             'user_id': None,
+            'team_id': False,
             'stage_id': self.stage,
         })
         self.lead2 = self.crm_lead.create(cr, uid, {
             'name': 'lead2',
             'email_from': 'lead2@test.com',
             'user_id': None,
+            'team_id': False,
             'stage_id': self.stage,
         })
 
diff --git a/addons/website_crm_score/views/sales.xml b/addons/website_crm_score/views/sales.xml
index b4518eec4efb..d2fffcb80481 100644
--- a/addons/website_crm_score/views/sales.xml
+++ b/addons/website_crm_score/views/sales.xml
@@ -81,10 +81,10 @@
             <field name="model">crm.lead</field>
             <field name="inherit_id" ref="crm.crm_case_form_view_oppor" />
             <field name="arch" type="xml">
-                <field name="user_id" position="after">
+                <field name="priority" position="after">
                     <field name="score" />
                 </field>
-                <xpath expr="//group[@name='references']" position="after">
+                <xpath expr="//group[@name='Misc']" position="after">
                     <group string="Scoring">
                         <field name="score_ids"
                             widget="many2many_tags"
-- 
GitLab