diff --git a/addons/crm/data/crm_stage_data.xml b/addons/crm/data/crm_stage_data.xml
index 81c69cf5697..4f24ec2e511 100644
--- a/addons/crm/data/crm_stage_data.xml
+++ b/addons/crm/data/crm_stage_data.xml
@@ -2,27 +2,20 @@
New
- 10
- 1
1
Qualified
- 30
- 1
2
Proposition
- 70
- 1
3
Won
- 100
- 1
+ True
70
\ No newline at end of file
diff --git a/addons/crm/models/crm_lead.py b/addons/crm/models/crm_lead.py
index efba9117dc8..4b869d65ca7 100644
--- a/addons/crm/models/crm_lead.py
+++ b/addons/crm/models/crm_lead.py
@@ -53,15 +53,6 @@ class Lead(models.Model):
_inherit = ['mail.thread.cc', 'mail.thread.blacklist', 'mail.activity.mixin', 'utm.mixin', 'format.address.mixin']
_primary_email = 'email_from'
- def _default_probability(self):
- if 'default_stage_id' in self._context:
- stage_id = self._context.get('default_stage_id')
- else:
- stage_id = self._default_stage_id()
- if stage_id:
- return self.env['crm.stage'].browse(stage_id).probability
- return 10
-
def _default_stage_id(self):
team = self.env['crm.team'].sudo()._get_default_team_id(user_id=self.env.uid)
return self._stage_find(team_id=team.id, domain=[('fold', '=', False)]).id
@@ -100,7 +91,7 @@ class Lead(models.Model):
date_conversion = fields.Datetime('Conversion Date', readonly=True)
# Only used for type opportunity
- probability = fields.Float('Probability', group_operator="avg", default=lambda self: self._default_probability())
+ probability = fields.Float('Probability', group_operator="avg", default=10.0)
planned_revenue = fields.Monetary('Expected Revenue', currency_field='company_currency', tracking=True)
expected_revenue = fields.Monetary('Prorated Revenue', currency_field='company_currency', store=True, compute="_compute_expected_revenue")
date_deadline = fields.Date('Expected Closing', help="Estimate of the date on which the opportunity will be won.")
@@ -196,21 +187,6 @@ class Lead(models.Model):
for lead in self:
lead.meeting_count = mapped_data.get(lead.id, 0)
- @api.model
- def _onchange_stage_id_values(self, stage_id):
- """ returns the new values when stage_id has changed """
- if not stage_id:
- return {}
- stage = self.env['crm.stage'].browse(stage_id)
- if stage.on_change:
- return {'probability': stage.probability}
- return {}
-
- @api.onchange('stage_id')
- def _onchange_stage_id(self):
- values = self._onchange_stage_id_values(self.stage_id.id)
- self.update(values)
-
def _onchange_partner_id_values(self, partner_id):
""" returns the new values when partner_id has changed """
if partner_id:
@@ -299,14 +275,6 @@ class Lead(models.Model):
# ORM override (CRUD, fields_view_get, ...)
# ----------------------------------------
- @api.model
- def name_create(self, name):
- res = super(Lead, self).name_create(name)
-
- # update the probability of the lead if the stage is set to update it automatically
- self.browse(res[0])._onchange_stage_id()
- return res
-
@api.model
def create(self, vals):
# set up context used to find the lead's Sales Team which is needed
@@ -329,19 +297,22 @@ class Lead(models.Model):
@api.multi
def write(self, vals):
- # stage change: update date_last_stage_update
+ # stage change:
if 'stage_id' in vals:
vals['date_last_stage_update'] = fields.Datetime.now()
+ stage_id = self.env['crm.stage'].browse(vals['stage_id'])
+ if stage_id.is_won:
+ vals.update({'probability': 100})
# Only write the 'date_open' if no salesperson was assigned.
if vals.get('user_id') and 'date_open' not in vals and not self.mapped('user_id'):
vals['date_open'] = fields.Datetime.now()
# stage change with new stage: update probability and date_closed
- if vals.get('stage_id') and 'probability' not in vals:
- vals.update(self._onchange_stage_id_values(vals.get('stage_id')))
if vals.get('probability', 0) >= 100 or not vals.get('active', True):
vals['date_closed'] = fields.Datetime.now()
elif 'probability' in vals:
vals['date_closed'] = False
+ if vals.get('user_id') and 'date_open' not in vals:
+ vals['date_open'] = fields.Datetime.now()
return super(Lead, self).write(vals)
@api.multi
@@ -385,7 +356,7 @@ class Lead(models.Model):
def action_set_won(self):
""" Won semantic: probability = 100 (active untouched) """
for lead in self:
- stage_id = lead._stage_find(domain=[('probability', '=', 100.0), ('on_change', '=', True)])
+ stage_id = lead._stage_find(domain=[('is_won', '=', True)])
lead.write({'stage_id': stage_id.id, 'probability': 100})
return True
@@ -478,14 +449,6 @@ class Lead(models.Model):
'context': {'default_type': 'opportunity'}
}
- def toggle_active(self):
- """ When re-activating leads and opportunities set their probability
- to the default stage one. """
- res = super(Lead, self).toggle_active()
- for lead in self.filtered(lambda lead: lead.active and lead.stage_id.probability):
- lead.probability = lead.stage_id.probability
- return res
-
# ----------------------------------------
# Business Methods
# ----------------------------------------
@@ -686,13 +649,10 @@ class Lead(models.Model):
raise UserError(_('Please select more than one element (lead or opportunity) from the list view.'))
# Sorting the leads/opps according to the confidence level of its stage, which relates to the probability of winning it
- # The confidence level increases with the stage sequence, except when the stage probability is 0.0 (Lost cases)
- # An Opportunity always has higher confidence level than a lead, unless its stage probability is 0.0
+ # The confidence level increases with the stage sequence
+ # An Opportunity always has higher confidence level than a lead
def opps_key(opportunity):
- sequence = -1
- if opportunity.stage_id.on_change:
- sequence = opportunity.stage_id.sequence
- return (sequence != -1 and opportunity.type == 'opportunity'), sequence, -opportunity.id
+ return opportunity.type == 'opportunity', opportunity.stage_id.sequence, -opportunity.id
opportunities = self.sorted(key=opps_key, reverse=True)
# get SORTED recordset of head and tail, and complete list
@@ -778,8 +738,6 @@ class Lead(models.Model):
if not self.stage_id:
stage = self._stage_find(team_id=team_id)
value['stage_id'] = stage.id
- if stage:
- value['probability'] = stage.probability
return value
@api.multi
@@ -1042,7 +1000,7 @@ class Lead(models.Model):
if date_deadline < today:
result['activity']['overdue'] += 1
# Won in Opportunities
- if opp.date_closed and opp.stage_id.probability == 100:
+ if opp.date_closed and opp.stage_id.is_won:
date_closed = fields.Date.from_string(opp.date_closed)
if today.replace(day=1) <= date_closed <= today:
if opp.planned_revenue:
@@ -1122,7 +1080,7 @@ class Lead(models.Model):
@api.multi
def _track_subtype(self, init_values):
self.ensure_one()
- if 'stage_id' in init_values and self.probability == 100 and self.stage_id and self.stage_id.on_change:
+ if 'stage_id' in init_values and self.probability == 100 and self.stage_id:
return self.env.ref('crm.mt_lead_won')
elif 'active' in init_values and self.probability == 0 and not self.active:
return self.env.ref('crm.mt_lead_lost')
diff --git a/addons/crm/models/crm_stage.py b/addons/crm/models/crm_stage.py
index d324a3fc00a..6902a9b4ccd 100644
--- a/addons/crm/models/crm_stage.py
+++ b/addons/crm/models/crm_stage.py
@@ -34,8 +34,7 @@ class Stage(models.Model):
name = fields.Char('Stage Name', required=True, translate=True)
sequence = fields.Integer('Sequence', default=1, help="Used to order stages. Lower is better.")
- probability = fields.Float('Probability (%)', required=True, default=10.0, help="This percentage depicts the default/average probability of the Case for this stage to be a success")
- on_change = fields.Boolean('Change Probability Automatically', help="Setting this stage will change the probability automatically on the opportunity.")
+ is_won = fields.Boolean('Is Won Stage?')
requirements = fields.Text('Requirements', help="Enter here the internal requirements for this stage (ex: Offer sent to customer). It will appear as a tooltip over the stage's name.")
team_id = fields.Many2one('crm.team', string='Sales Team', ondelete='set null',
help='Specific team that uses this stage. Other teams will not be able to see or use this stage.')
@@ -44,7 +43,7 @@ class Stage(models.Model):
fold = fields.Boolean('Folded in Pipeline',
help='This stage is folded in the kanban view when there are no records in that stage to display.')
- #This field for interface only
+ # This field for interface only
team_count = fields.Integer('team_count', compute='_compute_team_count')
@api.multi
diff --git a/addons/crm/report/crm_activity_report_views.xml b/addons/crm/report/crm_activity_report_views.xml
index b143b0ad713..8e751d916ea 100644
--- a/addons/crm/report/crm_activity_report_views.xml
+++ b/addons/crm/report/crm_activity_report_views.xml
@@ -52,7 +52,7 @@
+ domain="['&', ('stage_id.is_won', '=', True)]"/>
diff --git a/addons/crm/tests/test_crm_lead.py b/addons/crm/tests/test_crm_lead.py
index 8e701932050..69100f463bf 100644
--- a/addons/crm/tests/test_crm_lead.py
+++ b/addons/crm/tests/test_crm_lead.py
@@ -40,7 +40,7 @@ class TestCRMLead(TestCrmCases):
# Now I change the stage of opportunity to won.
lead.action_set_won()
# I check stage of opp should won, after change stage.
- stage_id = lead._stage_find(domain=[('probability', '=', 100.0)])
+ stage_id = lead._stage_find(domain=[('is_won', '=', True)])
self.assertEqual(stage_id, lead.stage_id, "Stage of opportunity is incorrect!")
def test_crm_lead_message(self):
diff --git a/addons/crm/views/crm_lead_views.xml b/addons/crm/views/crm_lead_views.xml
index 5d6064fbccc..65372748bcf 100644
--- a/addons/crm/views/crm_lead_views.xml
+++ b/addons/crm/views/crm_lead_views.xml
@@ -753,7 +753,7 @@
-
+
-
+
@@ -21,7 +21,7 @@
-
+
@@ -44,14 +44,11 @@
-
-
-
-
-
+
+
diff --git a/addons/website_crm_partner_assign/controllers/main.py b/addons/website_crm_partner_assign/controllers/main.py
index 429e8f9d822..3acffdacd50 100644
--- a/addons/website_crm_partner_assign/controllers/main.py
+++ b/addons/website_crm_partner_assign/controllers/main.py
@@ -102,7 +102,7 @@ class WebsiteAccount(CustomerPortal):
'week': {'label': _('This Week Activities'),
'domain': [('activity_date_deadline', '>=', today), ('activity_date_deadline', '<=', this_week_end_date)]},
'overdue': {'label': _('Overdue Activities'), 'domain': [('activity_date_deadline', '<', today)]},
- 'won': {'label': _('Won'), 'domain': [('stage_id.probability', '=', 100), ('stage_id.on_change', '=', True)]},
+ 'won': {'label': _('Won'), 'domain': [('stage_id.is_won', '=', True)]},
'lost': {'label': _('Lost'), 'domain': [('active', '=', False), ('probability', '=', 0)]},
}
searchbar_sortings = {
@@ -170,7 +170,7 @@ class WebsiteAccount(CustomerPortal):
"website_crm_partner_assign.portal_my_opportunity", {
'opportunity': opp,
'user_activity': opp.sudo().activity_ids.filtered(lambda activity: activity.user_id == request.env.user)[:1],
- 'stages': request.env['crm.stage'].search([('probability', '!=', '100')], order='sequence desc, name desc, id desc'),
+ 'stages': request.env['crm.stage'].search([('is_won', '!=', True)], order='sequence desc, name desc, id desc'),
'activity_types': request.env['mail.activity.type'].sudo().search([]),
'states': request.env['res.country.state'].sudo().search([]),
'countries': request.env['res.country'].sudo().search([]),
diff --git a/addons/website_crm_partner_assign/models/crm_lead.py b/addons/website_crm_partner_assign/models/crm_lead.py
index 153aa703939..4bca5f4878d 100644
--- a/addons/website_crm_partner_assign/models/crm_lead.py
+++ b/addons/website_crm_partner_assign/models/crm_lead.py
@@ -40,7 +40,7 @@ class CrmLead(models.Model):
def assign_salesman_of_assigned_partner(self):
salesmans_leads = {}
for lead in self:
- if (lead.stage_id.probability > 0 and lead.stage_id.probability < 100) or lead.stage_id.sequence == 1:
+ if (lead.probability > 0 and lead.probability < 100) or lead.stage_id.sequence == 1:
if lead.partner_assigned_id and lead.partner_assigned_id.user_id != lead.user_id:
salesmans_leads.setdefault(lead.partner_assigned_id.user_id.id, []).append(lead.id)