[IMP] crm: stage management

Stages are now sales team dependant, and not shared anymore. This comes
with a sales-team way of working :
- sales team is the entrance point, click on the big Pipeline button to
see the opportunities pipeline of this specific sales team
- no more opportunities menu entry, as you should come from a sales team
- leads are still sales-team agnostic

The stage management has been updated :
- Won is still a stage (probability=100, onchange=1).
- Lost is not a stage anymore. Lost is equivalent to archiving. Archiving
uses the active field. Setting a lead or an opportunity as lost set them
as unactive.

Downside of the no more share policy: multi sales team opportunities
management can quickly become complicated. Indeed you may have stages
with the same name, not being the same stage, therefore not displayed
in the same column. Grouping on the stage name leads to other issues
(sequencing incoherence, impossible to drag n drop), so this is not
an option.
This commit is contained in:
Fabien Pinckaers
2015-07-30 10:19:14 +02:00
committed by Thibault Delavallée
parent a056a5d890
commit f255aa7b36
13 changed files with 173 additions and 118 deletions
+1
View File
@@ -46,6 +46,7 @@ Dashboard for CRM will include:
'data': [
'data/crm_action_data.xml',
'crm_data.xml',
'data/crm_stage_data.xml',
'crm_lead_data.xml',
'crm_tip_data.xml',
-6
View File
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<openerp>
<data noupdate="1">
<record id="base.user_demo" model="res.users">
<field name="groups_id" eval="[(4,ref('base.group_sale_salesman'))]"/>
</record>
@@ -9,10 +8,5 @@
<record id="sales_team.team_sales_department" model="crm.team">
<field name="member_ids" eval="[(4, ref('base.user_demo'))]"/>
</record>
<record model="crm.team" id="sales_team.crm_team_1">
<field name="name">Indirect Sales</field>
<field name="member_ids" eval="[(4, ref('base.user_root')),(4, ref('base.user_demo'))]"/>
</record>
</data>
</openerp>
+25 -37
View File
@@ -249,6 +249,7 @@ class crm_lead(format_address, osv.osv):
'team_id': lambda s, cr, uid, c: s.pool['crm.team']._get_default_team_id(cr, uid, context=c),
'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.lead', context=c),
'priority': lambda *a: crm_stage.AVAILABLE_PRIORITIES[0][0],
'probability': 10,
'color': 0,
'date_last_stage_update': fields.datetime.now,
}
@@ -260,13 +261,10 @@ class crm_lead(format_address, osv.osv):
def onchange_stage_id(self, cr, uid, ids, stage_id, context=None):
if not stage_id:
return {'value': {}}
stage = self.pool.get('crm.stage').browse(cr, uid, stage_id, context=context)
stage = self.pool['crm.stage'].browse(cr, uid, stage_id, context=context)
if not stage.on_change:
return {'value': {}}
vals = {'probability': stage.probability}
if stage.on_change and (stage.probability >= 100 or (stage.probability == 0 and stage.sequence > 1)):
vals['date_closed'] = fields.datetime.now()
return {'value': vals}
return {'value': {'probability': stage.probability}}
def on_change_partner_id(self, cr, uid, ids, partner_id, context=None):
values = {}
@@ -345,28 +343,20 @@ class crm_lead(format_address, osv.osv):
return stage_ids[0]
return False
def case_mark_lost(self, cr, uid, ids, context=None):
""" Mark the case as lost: state=cancel and probability=0
"""
stages_leads = {}
for lead in self.browse(cr, uid, ids, context=context):
stage_id = self.stage_find(cr, uid, [lead], lead.team_id.id or False, [('probability', '=', 0.0), ('on_change', '=', True), ('sequence', '>', 1)], context=context)
if stage_id:
if stages_leads.get(stage_id):
stages_leads[stage_id].append(lead.id)
else:
stages_leads[stage_id] = [lead.id]
else:
raise UserError(_('To relieve your sales pipe and group all Lost opportunities, configure one of your sales stage as follow:\n'
'probability = 0 %, select "Change Probability Automatically".\n'
'Create a specific stage or edit an existing one by editing columns of your opportunity pipe.'))
for stage_id, lead_ids in stages_leads.items():
self.write(cr, uid, lead_ids, {'stage_id': stage_id}, context=context)
return True
def action_set_lost(self, cr, uid, ids, context=None):
""" Lost semantic: probability = 0, active = False """
return self.write(cr, uid, ids, {'probability': 0, 'active': False}, context=context)
# Backward compatibility
case_mark_lost = action_set_lost
def case_mark_won(self, cr, uid, ids, context=None):
""" Mark the case as won: state=done and probability=100
"""
def action_set_active(self, cr, uid, ids, context=None):
return self.write(cr, uid, ids, {'active': True}, context=context)
def action_set_unactive(self, cr, uid, ids, context=None):
return self.write(cr, uid, ids, {'active': False}, context=context)
def action_set_won(self, cr, uid, ids, context=None):
""" Won semantic: probability = 100 (active untouched) """
stages_leads = {}
for lead in self.browse(cr, uid, ids, context=context):
stage_id = self.stage_find(cr, uid, [lead], lead.team_id.id or False, [('probability', '=', 100.0), ('on_change', '=', True)], context=context)
@@ -375,13 +365,11 @@ class crm_lead(format_address, osv.osv):
stages_leads[stage_id].append(lead.id)
else:
stages_leads[stage_id] = [lead.id]
else:
raise UserError(_('To relieve your sales pipe and group all Won opportunities, configure one of your sales stage as follow:\n'
'probability = 100 % and select "Change Probability Automatically".\n'
'Create a specific stage or edit an existing one by editing columns of your opportunity pipe.'))
for stage_id, lead_ids in stages_leads.items():
self.write(cr, uid, lead_ids, {'stage_id': stage_id}, context=context)
return True
return self.write(cr, uid, ids, {'probability': 100}, context=context)
# Backward compatibility
case_mark_won = action_set_won
def log_next_activity_1(self, cr, uid, ids, context=None):
return self.log_next_activity_done(cr, uid, ids, next_activity_name='activity_1_id', context=context)
@@ -615,7 +603,6 @@ class crm_lead(format_address, osv.osv):
"""
Search for opportunities that have the same partner and that arent done or cancelled
"""
final_stage_domain = ['|', '|', ('stage_id.on_change', '=', False), ('stage_id.probability', 'not in', [0, 100]), ('stage_id.sequence', '<=', 1)]
partner_match_domain = []
for email in set(email_split(email) + [email]):
partner_match_domain.append(('email_from', '=ilike', email))
@@ -626,7 +613,7 @@ class crm_lead(format_address, osv.osv):
return []
domain = partner_match_domain
if not include_lost:
domain += final_stage_domain
domain += ['&', ('active', '=', True), ('probability', '<', 100)]
return self.search(cr, uid, domain, context=context)
def merge_dependences(self, cr, uid, highest, opportunities, context=None):
@@ -723,8 +710,7 @@ class crm_lead(format_address, osv.osv):
partner = self.pool.get('res.partner')
customer = partner.browse(cr, uid, partner_id, context=context)
for lead in self.browse(cr, uid, ids, context=context):
# TDE: was if lead.state in ('done', 'cancel'):
if (lead.probability == 100 or lead.probability == 0) and lead.stage_id.on_change and lead.stage_id.sequence > 1:
if not lead.active or lead.probability == 100:
continue
vals = self._convert_opportunity_data(cr, uid, lead, customer, team_id, context=context)
self.write(cr, uid, [lead.id], vals, context=context)
@@ -907,9 +893,11 @@ class crm_lead(format_address, osv.osv):
if vals.get('user_id') and 'date_open' not in vals:
vals['date_open'] = fields.datetime.now()
# stage change with new stage: update probability and date_closed
if vals.get('stage_id') and not vals.get('probability'):
if vals.get('stage_id') and 'probability' not in vals:
onchange_stage_values = self.onchange_stage_id(cr, uid, ids, vals.get('stage_id'), context=context)['value']
vals.update(onchange_stage_values)
if vals.get('probability') >= 100 or not vals.get('active', True):
vals['date_closed'] = fields.datetime.now()
return super(crm_lead, self).write(cr, uid, ids, vals, context=context)
def copy(self, cr, uid, id, default=None, context=None):
@@ -944,7 +932,7 @@ class crm_lead(format_address, osv.osv):
record = self.browse(cr, uid, ids[0], context=context)
if 'stage_id' in init_values and record.probability == 100 and record.stage_id and record.stage_id.on_change:
return 'crm.mt_lead_won'
elif 'stage_id' in init_values and record.probability == 0 and record.stage_id and record.stage_id.on_change and record.stage_id.sequence > 1:
elif 'active' in init_values and record.probability == 0 and not record.active:
return 'crm.mt_lead_lost'
elif 'stage_id' in init_values and record.probability == 0 and record.stage_id and record.stage_id.sequence <= 1:
return 'crm.mt_lead_create'
+2 -4
View File
@@ -5,12 +5,13 @@
<record model="ir.actions.act_window" id="crm_lead_all_leads">
<field name="name">Leads</field>
<field name="res_model">crm.lead</field>
<field name="view_mode">tree,form</field>
<field name="view_mode">tree,kanban,graph,pivot,calendar,form</field>
<field name="domain">['|', ('type','=','lead'), ('type','=',False)]</field>
<field name="view_id" ref="crm_case_tree_view_leads"/>
<field name="search_view_id" ref="crm.view_crm_case_leads_filter"/>
<field name="context">{
'default_type':'lead',
'search_default_type': 'lead',
'stage_type':'lead',
'needaction_menu_ref': 'crm.menu_crm_opportunities',
'search_default_to_process':1,
@@ -77,9 +78,6 @@
<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"/>
<menuitem name="Opportunities" id="menu_crm_opportunities" parent="base.menu_sales" sequence="2"
action="crm_lead_opportunities"
groups="base.group_sale_salesman,base.group_sale_manager"/>
</data>
</openerp>
+51 -11
View File
@@ -106,6 +106,18 @@
<header>
<button name="%(crm.action_crm_lead2opportunity_partner)d" string="Convert to Opportunity" type="action"
help="Convert to Opportunity" class="oe_highlight"/>
<button name="action_set_unactive" string="Archive"
type="object" class="oe_highlight"
attrs="{'invisible': ['|', ('active','=',False), ('probability', '&lt;', 100)]}"/>
<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"
attrs="{'invisible': [('active', '=', False)]}"/>
<button name="action_set_active" string="Unarchive"
type="object" class="oe_highlight"
attrs="{'invisible': [('active', '=', True)]}"/>
<field name="stage_id" widget="statusbar" clickable="True"
domain="['&amp;', ('team_ids', '=', team_id), '|', ('type', '=', type), ('type', '=', 'both')]"
options="{'fold_field': 'fold'}"
@@ -116,6 +128,10 @@
<div class="oe_title">
<label for="name" class="oe_edit_only"/>
<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>
</div>
<group>
<group>
@@ -280,6 +296,7 @@
<field name="message_unread_counter"/>
<field name="tag_ids"/>
<field name="partner_id"/>
<field name="active"/>
<templates>
<field name="date_deadline"/>
<t t-name="kanban-box">
@@ -290,10 +307,10 @@
<span class="fa fa-bars fa-lg"/>
</a>
<ul class="dropdown-menu" role="menu" aria-labelledby="dLabel">
<t t-if="widget.editable"><li><a type="edit">Edit Opportunity</a></li></t>
<t t-if="widget.editable"><li><a type="edit">Edit</a></li></t>
<t t-if="widget.deletable"><li><a type="delete">Delete</a></li></t>
<li><a name="%(mail.action_email_compose_message_wizard)d" type="action" >Send Email</a></li>
<li><a name="action_schedule_meeting" type="object">Schedule Meeting</a></li>
<li t-if="! record.active.value"><a name="action_set_active" type="object">Unarchive</a></li>
<li t-if="record.active.value"><a name="action_set_unactive" type="object">Archive</a></li>
<li><ul class="oe_kanban_colorpicker" data-field="color"/></li>
</ul>
</div>
@@ -337,15 +354,22 @@
<field name="create_date"/>
<field name="country_id"/>
<separator/>
<filter string="Archived"
domain="[('active', '=', False)]"/>
<separator />
<filter string="Leads"
name="type_lead"
domain="[('type', '=', 'lead')]"/>
<filter string="Opportunities"
name="type_opportunity"
domain="[('type', '=', 'opportunity')]"/>
<separator/>
<filter string="My Leads"
domain="[('user_id','=',uid)]"
help="Leads that are assigned to me"/>
<filter string="Unassigned" name="unassigned"
domain="[('user_id','=', False)]"
help="No salesperson"/>
<filter string="To Process" name="to_process"
domain="['|',('stage_id.probability','>', 0),('stage_id.fold','=', False)]"
help="Not marked as Dead"/>
<separator />
<filter string="New Mail" name="message_unread" domain="[('message_unread','=',True)]"/>
<separator />
@@ -380,11 +404,22 @@
<field name="arch" type="xml">
<form string="Opportunities">
<header>
<button name="case_mark_won" string="Mark Won" attrs="{'invisible': [('probability', '=', 100)]}" type="object" class="oe_highlight"/>
<button name="case_mark_lost" string="Mark Lost" attrs="{'invisible': [('probability', '=', 100)]}" type="object" class="oe_highlight"/>
<button name="action_set_unactive" string="Archive"
type="object" class="oe_highlight"
attrs="{'invisible': ['|', ('active','=',False), ('probability', '&lt;', 100)]}"/>
<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"
attrs="{'invisible': [('active', '=', False)]}"/>
<button name="action_set_active" string="Unarchive"
type="object" class="oe_highlight"
attrs="{'invisible': [('active', '=', True)]}"/>
<field name="stage_id" widget="statusbar" clickable="True"
options="{'fold_field': 'fold'}"
domain="['&amp;', ('team_ids', '=', team_id), '|', ('type', '=', type), ('type', '=', 'both')]"/>
domain="['&amp;', ('team_ids', '=', team_id), '|', ('type', '=', type), ('type', '=', 'both')]"
attrs="{'invisible': [('active', '=', False)]}"/>
</header>
<sheet>
<div class="oe_button_box" name="button_box">
@@ -397,6 +432,10 @@
<div class="oe_title">
<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>
<div class="o_row">
<label for="planned_revenue" class="oe_edit_only"/>
<label for="probability" class="oe_edit_only"/>
@@ -577,8 +616,9 @@
<field name="probability"/>
<field name="lost_reason"/>
<separator/>
<filter string="New" name="new"
domain="['&amp;', ('stage_id.probability', '=', 0), ('stage_id.sequence', '&lt;=', 1)]"/>
<filter string="Archived"
domain="[('active', '=', False)]"/>
<separator/>
<filter string="Won" name="won"
domain="['&amp;', ('stage_id.probability', '=', 100), ('stage_id.fold', '=', True)]"/>
<filter string="Lost" name="lost"
+6 -2
View File
@@ -2,7 +2,6 @@
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from openerp.osv import osv, fields
from openerp.http import request
AVAILABLE_PRIORITIES = [
('0', 'Normal'),
@@ -11,6 +10,7 @@ AVAILABLE_PRIORITIES = [
('3', 'Very High'),
]
class crm_stage(osv.Model):
""" Model for case stages. This models the main stages of a document
management flow. Main CRM objects (leads, opportunities, project
@@ -22,6 +22,9 @@ class crm_stage(osv.Model):
_rec_name = 'name'
_order = "sequence"
def _default_team_ids(self, cr, uid, context=None):
return context.get('default_team_id') and [(6, 0, [context['default_team_id']])] or False
_columns = {
'name': fields.char('Stage Name', required=True, translate=True),
'sequence': fields.integer('Sequence', help="Used to order stages. Lower is better."),
@@ -43,7 +46,8 @@ class crm_stage(osv.Model):
_defaults = {
'sequence': 1,
'probability': 1.0,
'probability': 10.0,
'team_ids': _default_team_ids,
'fold': False,
'type': 'both',
}
+3 -10
View File
@@ -23,18 +23,11 @@
<group>
<field name="name"/>
<field name="type"/>
<field name="on_change"/>
<label for="probability" attrs="{'invisible': [('on_change', '=', False)]}"/>
<div attrs="{'invisible': [('on_change', '=', False)]}">
<field name="probability"/>
<p class="text-muted">
A stage will be considered as 'Won' if the probability is 100% and if 'Change Probability Automatically' is true.<br/>
A stage will be considered as 'Lost' or 'Dead' if the probability is 0% and if 'Change Probability Automatically' is true.
</p>
</div>
<field name="fold"/>
</group>
<group>
<field name="fold"/>
<field name="on_change"/>
<field name="probability" attrs="{'invisible': [('on_change', '=', False)]}"/>
</group>
</group>
<separator string="Requirements"/>
+23
View File
@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<odoo noupdate="1">
<record model="crm.stage" id="stage_lead1">
<field name="name">New</field>
<field name="probability">10</field>
<field name="on_change">1</field>
<field name="sequence">1</field>
<field name="type">both</field>
</record>
<record model="crm.stage" id="stage_lead5">
<field name="name">Won</field>
<field name="fold" eval="True"/>
<field name="probability">100</field>
<field name="on_change">1</field>
<field name="sequence">70</field>
<field name="type">opportunity</field>
</record>
<!-- Update data sales team with default stages -->
<record model="crm.team" id="sales_team.team_sales_department">
<field name="stage_ids" eval="[(4, ref('stage_lead1')), (4, ref('stage_lead5'))]"/>
</record>
</odoo>
+35 -31
View File
@@ -3,64 +3,68 @@
<data>
<!-- Crm stages -->
<record model="crm.stage" id="stage_lead1">
<field name="name">New</field>
<field name="probability">0</field>
<field name="on_change">1</field>
<field name="sequence">1</field>
<field name="type">both</field>
</record>
<record model="crm.stage" id="stage_lead2">
<field name="name">Dead</field>
<field name="fold">1</field>
<field name="probability">0</field>
<field name="on_change">1</field>
<field name="sequence">30</field>
<field name="type">lead</field>
</record>
<record model="crm.stage" id="stage_lead3">
<field name="name">Qualification</field>
<field name="probability">20</field>
<field name="on_change">1</field>
<field name="sequence">40</field>
<field name="type">opportunity</field>
</record>
<record model="crm.stage" id="stage_lead4">
<record model="crm.stage" id="stage_lead3">
<field name="name">Proposition</field>
<field name="probability">40</field>
<field name="on_change">1</field>
<field name="sequence">50</field>
<field name="type">opportunity</field>
</record>
<record model="crm.stage" id="stage_lead5">
<record model="crm.stage" id="stage_lead4">
<field name="name">Negotiation</field>
<field name="probability">60</field>
<field name="on_change">1</field>
<field name="sequence">60</field>
<field name="type">opportunity</field>
</record>
<record model="crm.stage" id="stage_lead6">
<record model="crm.stage" id="crm_stage_2_1">
<field name="name">New</field>
<field name="probability">10</field>
<field name="on_change">1</field>
<field name="sequence">1</field>
<field name="type">both</field>
</record>
<record model="crm.stage" id="crm_stage_2_2">
<field name="name">Qualification</field>
<field name="probability">20</field>
<field name="on_change">1</field>
<field name="sequence">40</field>
<field name="type">opportunity</field>
</record>
<record model="crm.stage" id="crm_stage_2_3">
<field name="name">Negotiation</field>
<field name="probability">60</field>
<field name="on_change">1</field>
<field name="sequence">60</field>
<field name="type">opportunity</field>
</record>
<record model="crm.stage" id="crm_stage_2_4">
<field name="name">Won</field>
<field name="fold">1</field>
<field name="fold" eval="True"/>
<field name="probability">100</field>
<field name="on_change">1</field>
<field name="sequence">70</field>
<field name="type">opportunity</field>
</record>
<record model="crm.stage" id="stage_lead7">
<field name="name">Lost</field>
<field name="fold">1</field>
<field name="probability">0</field>
<field name="on_change">1</field>
<field name="sequence">80</field>
<field name="type">opportunity</field>
</record>
<record model="crm.team" id="sales_team.team_sales_department">
<field name="stage_ids" eval="[ (4, ref('stage_lead1')), (4, ref('stage_lead2')),
(4, ref('stage_lead3')), (4, ref('stage_lead4')),
(4, ref('stage_lead5')), (4, ref('stage_lead6')),
(4, ref('stage_lead7'))]"/>
<field name="stage_ids" eval="[(4, ref('stage_lead2')), (4, ref('stage_lead3')),
(4, ref('stage_lead4'))]"/>
</record>
<record model="crm.team" id="sales_team.crm_team_1">
<field name="member_ids" eval="[(4, ref('base.user_root')),(4, ref('base.user_demo'))]"/>
<field name="stage_ids" eval="[(4, ref('crm_stage_2_1')),
(4, ref('crm_stage_2_2')),
(4, ref('crm_stage_2_3')),
(4, ref('crm_stage_2_4'))]"/>
</record>
</data>
+21
View File
@@ -1,12 +1,32 @@
# -*- coding: utf-8 -*-
from openerp.osv import fields, osv
from openerp.tools.translate import _
class crm_team(osv.Model):
_inherit = 'crm.team'
_inherits = {'mail.alias': 'alias_id'}
def _get_default_stage_ids(self, cr, uid, context=None):
return [
(0, 0, {
'name': _('New'),
'sequence': 1,
'probability': 10.0,
'on_change': True,
'fold': False,
'type': 'both',
}),
(0, 0, {
'name': _('Won'),
'sequence': 50,
'probability': 100.0,
'on_change': True,
'fold': True,
'type': 'both',
})]
_columns = {
'resource_calendar_id': fields.many2one('resource.calendar', "Working Time", help="Used to compute open days"),
'stage_ids': fields.many2many('crm.stage', 'crm_team_stage_rel', 'team_id', 'stage_id', 'Stages'),
@@ -22,6 +42,7 @@ class crm_team(osv.Model):
'crm.lead', self._columns['alias_id'], 'name', alias_prefix='Lead+', alias_defaults={}, context=context)
_defaults = {
'stage_ids': _get_default_stage_ids,
'use_leads': True,
'use_opportunities': True,
}
+3 -12
View File
@@ -11,28 +11,19 @@
I check default stage of lead.
-
!python {model: crm.lead}: |
stage = self.pool.get('crm.stage').search_read(cr,uid,[('sequence','=',1)],['id'],context)[0]
stage = self.pool.get('crm.stage').search_read(cr, uid, [], ['id'], context)[0]
lead = self.browse(cr, uid, ref('test_crm_lead_new'))
stage_id = self.stage_find(cr, uid , [lead], lead.team_id.id or False,[], context)
assert stage_id == stage['id'], "Default stage of lead is incorrect!"
assert lead.stage_id.id == stage['id'], "Default stage of lead is incorrect!"
-
I change type from lead to opportunity.
-
!python {model: crm.lead}: |
self.convert_opportunity(cr, uid ,[ref("test_crm_lead_new")], ref("base.res_partner_2"))
-
Now I check default stage after change type.
-
!python {model: crm.lead}: |
stage = self.pool.get('crm.stage').search_read(cr,uid,[('sequence','=',1)],['id'],context)[0]
opp = self.browse(cr, uid, ref('test_crm_lead_new'))
stage_id = self.stage_find(cr, uid , [opp], opp.team_id.id or False,[], context)
assert stage_id == stage['id'], "Default stage of opportunity is incorrect!"
-
Now I change the stage of opportunity to won.
-
!python {model: crm.lead}: |
self.case_mark_won(cr, uid, [ref("test_crm_lead_new")])
self.action_set_won(cr, uid, [ref("test_crm_lead_new")])
-
I check statge of opp should won, after change stage.
-
-2
View File
@@ -73,8 +73,6 @@
-
!python {model: crm.lead}: |
lead = self.browse(cr, uid, ref('crm_case_2'))
assert lead.stage_id.id == ref('crm.stage_lead7'), "Opportunity stage should be 'Lost'."
assert lead.stage_id.sequence != 1 and lead.stage_id.probability == 0.0, "Lost opportunity is not in 'cancel' state!"
assert lead.probability == 0.0, "Revenue probability should be 0.0!"
-
I confirm review needs meeting.
@@ -1,9 +1,9 @@
# -*- coding: utf-8 -*-
# Part of Odoo. See LICENSE file for full copyright and licensing details.
from openerp.osv import fields,osv
from openerp.osv import fields, osv
from openerp import tools
from openerp.addons.crm import crm
from openerp.addons.crm import crm_stage
class crm_lead_report_assign(osv.osv):
@@ -33,7 +33,7 @@ class crm_lead_report_assign(osv.osv):
'date_closed': fields.datetime('Close Date', readonly=True),
'nbr': fields.integer('# of Cases', readonly=True), # TDE FIXME master: rename into nbr_cases
'company_id': fields.many2one('res.company', 'Company', readonly=True),
'priority': fields.selection(crm.AVAILABLE_PRIORITIES, 'Priority'),
'priority': fields.selection(crm_stage.AVAILABLE_PRIORITIES, 'Priority'),
'type':fields.selection([
('lead','Lead'),
('opportunity','Opportunity')