From 1c501f891288845730cd9d9dc0234fec66f1156b Mon Sep 17 00:00:00 2001 From: Thibault Francois Date: Tue, 14 Dec 2010 14:19:59 +0100 Subject: [PATCH 1/5] [IMP] stage view : type depend on module installed, and stage view give the opportunity to choose the sales team bzr revid: tfr@openerp.com-20101214131959-gzire7hxl07o1g3q --- addons/crm/crm.py | 11 ++++++-- addons/crm/crm_lead_view.xml | 14 ++++++++++ addons/crm/crm_view.xml | 33 +++++++++++++++++++++++ addons/crm_claim/crm_claim.py | 17 ++++++++++++ addons/crm_fundraising/crm_fundraising.py | 16 +++++++++++ 5 files changed, 89 insertions(+), 2 deletions(-) diff --git a/addons/crm/crm.py b/addons/crm/crm.py index 5336bdd23fb..e0b32e4fde5 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -479,6 +479,12 @@ class crm_case_stage(osv.osv): _description = "Stage of case" _rec_name = 'name' _order = "sequence" + + + + def _get_type_value(self, cr, user, context): + return [('lead','Lead'),('opportunity','Opportunity')] + _columns = { 'name': fields.char('Stage Name', size=64, required=True, translate=True), @@ -487,9 +493,10 @@ class crm_case_stage(osv.osv): 'on_change': fields.boolean('Change Probability Automatically', \ help="Change Probability on next and previous stages."), 'requirements': fields.text('Requirements'), - 'type': fields.selection([('lead','Lead'),('opportunity','Opportunity'),('claim','Claim'), ('fundraising','Fundraising')], 'Type'), + 'type': fields.selection(_get_type_value, 'Type'), } - + + def _find_stage_type(self, cr, uid, context=None): """Finds type of stage according to object. @param self: The object pointer diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 979ab26cfd1..1ff9daf8608 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -13,6 +13,20 @@ {'type':'lead'} Create specific stages that will help your sales better organise their sales pipeline by maintaining them to their leads and sales opportunities. It will allow them to easily track how is positioned a specific lead or opportunity in the sales cycle. + + + + tree + + + + + + + form + + + + @@ -118,6 +119,7 @@ crm.case.stage.form crm.case.stage form +
@@ -132,6 +134,36 @@
+ + + crm.case.stage.form + crm.case.stage + form + + +
+ + + + + + + + + + + + + + + + + + + + + +
@@ -141,6 +173,7 @@ form + diff --git a/addons/crm_claim/crm_claim.py b/addons/crm_claim/crm_claim.py index cc6a1ac6868..c241b36ab83 100644 --- a/addons/crm_claim/crm_claim.py +++ b/addons/crm_claim/crm_claim.py @@ -135,4 +135,21 @@ class crm_claim(crm.crm_case, osv.osv): crm_claim() + +class crm_stage_claim(osv.osv): + + def _get_type_value(self, cr, user, context): + list = super(crm_stage_claim, self)._get_type_value(cr, user, context) + list.append(('claim','Claim')) + return list + + _inherit = "crm.case.stage" + _columns = { + 'type': fields.selection(_get_type_value, 'Type'), + } + + +crm_stage_claim() + + # vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: diff --git a/addons/crm_fundraising/crm_fundraising.py b/addons/crm_fundraising/crm_fundraising.py index f4950842800..19ac21e6ab9 100644 --- a/addons/crm_fundraising/crm_fundraising.py +++ b/addons/crm_fundraising/crm_fundraising.py @@ -94,3 +94,19 @@ class crm_fundraising(crm.crm_case, osv.osv): } crm_fundraising() + + +class crm_stage_fundraising(osv.osv): + + def _get_type_value(self, cr, user, context): + list = super(crm_stage_fundraising, self)._get_type_value(cr, user, context) + list.append(('fundraising','Fundraising')) + return list + + _inherit = "crm.case.stage" + _columns = { + 'type': fields.selection(_get_type_value, 'Type'), + } + + +crm_stage_fundraising() From 23ce5a59ffd34c1db2ae3b7ef23e9bd9b8b1c036 Mon Sep 17 00:00:00 2001 From: Thibault Francois Date: Tue, 14 Dec 2010 14:38:35 +0100 Subject: [PATCH 2/5] [FIX] stages_view :type invisible, each stage type has his menu and sales team are display only if needed bzr revid: tfr@openerp.com-20101214133835-wxihjl7g4mqam96r --- addons/crm/crm_lead_view.xml | 2 +- addons/crm/crm_opportunity_view.xml | 14 ++++++++++++++ addons/crm/crm_view.xml | 9 ++++----- addons/crm_claim/crm_claim_view.xml | 15 ++++++++++++++- addons/crm_fundraising/crm_fundraising_view.xml | 14 ++++++++++++++ 5 files changed, 47 insertions(+), 7 deletions(-) diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 1ff9daf8608..7bd9689e403 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -14,7 +14,7 @@ Create specific stages that will help your sales better organise their sales pipeline by maintaining them to their leads and sales opportunities. It will allow them to easily track how is positioned a specific lead or opportunity in the sales cycle. - + tree diff --git a/addons/crm/crm_opportunity_view.xml b/addons/crm/crm_opportunity_view.xml index 4dff3dd6337..70dedb28276 100644 --- a/addons/crm/crm_opportunity_view.xml +++ b/addons/crm/crm_opportunity_view.xml @@ -11,6 +11,20 @@ {'type':'opportunity'} Create specific stages that will help your sales better organise their sales pipeline by maintaining them to their sales opportunities. It will allow them to easily track how is positioned a specific opportunity in the sales cycle. + + + + tree + + + + + + + form + + + - @@ -142,11 +141,11 @@
- - - + + + - + diff --git a/addons/crm_claim/crm_claim_view.xml b/addons/crm_claim/crm_claim_view.xml index a6f81885714..a0a7eb7c545 100644 --- a/addons/crm_claim/crm_claim_view.xml +++ b/addons/crm_claim/crm_claim_view.xml @@ -33,7 +33,20 @@ {'type':'claim'} You can create claim stages to categorize the status of every claim entered in the system. The stages define all the steps required for the resolution of a claim. - + + + + tree + + + + + + + form + + + diff --git a/addons/crm_fundraising/crm_fundraising_view.xml b/addons/crm_fundraising/crm_fundraising_view.xml index 51a2a2fa6b4..9c61017c33c 100644 --- a/addons/crm_fundraising/crm_fundraising_view.xml +++ b/addons/crm_fundraising/crm_fundraising_view.xml @@ -33,6 +33,20 @@ {'type':'fundraising'} Create and manage fund raising activity categories you want to be maintained in the system. + + + + tree + + + + + + + form + + + Date: Thu, 16 Dec 2010 11:28:40 +0100 Subject: [PATCH 3/5] [FIX] crm : button mark won, lost, close, open behave like we define in http://pad.openerp.com/stages-behavior bzr revid: tfr@openerp.com-20101216102840-5haeomzrga2rs1lw --- addons/crm/crm.py | 71 ++++++++++++++++++- addons/crm/crm_lead.py | 59 +++++++-------- addons/crm/crm_lead_view.xml | 14 +--- addons/crm/crm_opportunity.py | 49 +++++++------ addons/crm/crm_opportunity_view.xml | 14 +--- addons/crm/crm_view.xml | 34 +-------- addons/crm_claim/crm_claim.py | 16 ++++- addons/crm_claim/crm_claim_view.xml | 31 ++++---- .../crm_fundraising/crm_fundraising_view.xml | 14 +--- 9 files changed, 157 insertions(+), 145 deletions(-) diff --git a/addons/crm/crm.py b/addons/crm/crm.py index e0b32e4fde5..233bfcc4b5a 100644 --- a/addons/crm/crm.py +++ b/addons/crm/crm.py @@ -46,7 +46,67 @@ AVAILABLE_PRIORITIES = [ class crm_case(object): """A simple python class to be used for common functions """ + + def _find_lost_stage(self, cr, uid, type, section_id): + return self._find_percent_stage(cr, uid, 0.0, type, section_id) + + def _find_won_stage(self, cr, uid, type, section_id): + return self._find_percent_stage(cr, uid, 100.0, type, section_id) + + def _find_percent_stage(self, cr, uid, percent, type, section_id): + """ + Return the first stage with a probability == percent + """ + stage_pool = self.pool.get('crm.case.stage') + if section_id : + ids = stage_pool.search(cr, uid, [("probability", '=', percent), ("type", 'like', type), ("section_ids", 'in', [section_id])]) + else : + ids = stage_pool.search(cr, uid, [("probability", '=', percent), ("type", 'like', type)]) + + if ids: + return ids[0] + return False + + + def _find_first_stage(self, cr, uid, type, section_id): + """ + return the first stage that has a sequence number equal or higher than sequence + """ + stage_pool = self.pool.get('crm.case.stage') + if section_id : + ids = stage_pool.search(cr, uid, [("sequence", '>', 0), ("type", 'like', type), ("section_ids", 'in', [section_id])]) + else : + ids = stage_pool.search(cr, uid, [("sequence", '>', 0), ("type", 'like', type)]) + + if ids: + stages = stage_pool.browse(cr, uid, ids) + stage_min = stages[0] + for stage in stages: + if stage_min.sequence > stage.sequence: + stage_min = stage + return stage_min.id + else : + return False + + def onchange_stage_id(self, cr, uid, ids, stage_id, context={}): + """ @param self: The object pointer + @param cr: the current row, from the database cursor, + @param uid: the current user’s ID for security checks, + @param ids: List of stage’s IDs + @stage_id: change state id on run time """ + + + print "CALL on change ID" + if not stage_id: + return {'value':{}} + + stage = self.pool.get('crm.case.stage').browse(cr, uid, stage_id, context) + + if not stage.on_change: + return {'value':{}} + return {'value':{'probability': stage.probability}} + def _get_default_partner_address(self, cr, uid, context): """Gives id of default address for current user @param self: The object pointer @@ -145,6 +205,9 @@ class crm_case(object): return False next_seq = next_stage.sequence + if not current_seq : + current_seq = 0 + if (abs(next_seq - current_seq)) >= 1: return next_stage else : @@ -172,6 +235,7 @@ class crm_case(object): index = stages.index(case.stage_id.id) next_stage = self._find_next_stage(cr, uid, stages, index, current_seq, stage_pool, context=context) + if next_stage: next_stage_id = next_stage.id data = {'stage_id': next_stage.id} @@ -179,6 +243,7 @@ class crm_case(object): data.update({'probability': next_stage.probability}) self.write(cr, uid, [case.id], data, context=context) + return next_stage_id @@ -190,7 +255,6 @@ class crm_case(object): @param uid: the current user’s ID for security checks, @param ids: List of case IDs @param context: A standard dictionary for contextual values""" - return self.stage_change(cr, uid, ids, context=context, order='sequence') @@ -253,6 +317,7 @@ class crm_case(object): @param ids: List of case Ids @param *args: Tuple Value for additional Params """ + cases = self.browse(cr, uid, ids) self._history(cr, uid, cases, _('Open')) for case in cases: @@ -260,7 +325,9 @@ class crm_case(object): if not case.user_id: data['user_id'] = uid self.write(cr, uid, case.id, data) - self._action(cr, uid, cases, 'open') + + + self._action(cr, uid, cases, 'open') return True def case_close(self, cr, uid, ids, *args): diff --git a/addons/crm/crm_lead.py b/addons/crm/crm_lead.py index 8cc45c75e57..3f5e9ba27d6 100644 --- a/addons/crm/crm_lead.py +++ b/addons/crm/crm_lead.py @@ -151,18 +151,6 @@ class crm_lead(crm_case, osv.osv): 'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('model','=',_name)]), } - def _get_stage_id(self, cr, uid, context=None): - """Finds type of stage according to object. - @param self: The object pointer - @param cr: the current row, from the database cursor, - @param uid: the current user’s ID for security checks, - @param context: A standard dictionary for contextual values - """ - if context is None: - context = {} - type = context and context.get('stage_type', '') - stage_ids = self.pool.get('crm.case.stage').search(cr, uid, [('type','=',type),('sequence','>=',1)]) - return stage_ids and stage_ids[0] or False _defaults = { 'active': lambda *a: 1, @@ -173,8 +161,10 @@ class crm_lead(crm_case, osv.osv): 'section_id': crm_case._get_section, '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.AVAILABLE_PRIORITIES[2][0], - 'stage_id': _get_stage_id, + #'stage_id': _get_stage_id, } + + def onchange_partner_address_id(self, cr, uid, ids, add, email=False): """This function returns value of partner email based on Partner Address @@ -198,27 +188,30 @@ class crm_lead(crm_case, osv.osv): @param ids: List of case's Ids @param *args: Give Tuple Value """ - old_state = self.read(cr, uid, ids, ['state'])[0]['state'] - old_stage_id = self.read(cr, uid, ids, ['stage_id'])[0]['stage_id'] + leads = self.browse(cr, uid, ids) + + + + for i in xrange(0, len(ids)): + if leads[i].state == 'draft': + value = {} + if not leads[i].stage_id : + stage_id = self._find_first_stage(cr, uid, leads[i].type, leads[i].section_id.id or False) + value.update({'stage_id' : stage_id}) + value.update({'date_open': time.strftime('%Y-%m-%d %H:%M:%S')}) + self.write(cr, uid, [ids[i]], value) + self.log_open( cr, uid, leads[i]) res = super(crm_lead, self).case_open(cr, uid, ids, *args) - if old_state == 'draft': - value = {} - if not old_stage_id: - stage_id = super(crm_lead, self).stage_next(cr, uid, ids, *args) - if stage_id: - value.update(self.onchange_stage_id(cr, uid, ids, stage_id, context={})['value']) - value.update({'date_open': time.strftime('%Y-%m-%d %H:%M:%S')}) - self.write(cr, uid, ids, value) - - for case in self.browse(cr, uid, ids): - if case.type == 'lead': - message = _("The lead '%s' has been opened.") % case.name - elif case.type == 'opportunity': - message = _("The opportunity '%s' has been opened.") % case.name - else: - message = _("The case '%s' has been opened.") % case.name - self.log(cr, uid, case.id, message) return res + + def log_open(self, cr, uid, case): + if case.type == 'lead': + message = _("The lead '%s' has been opened.") % case.name + elif case.type == 'opportunity': + message = _("The opportunity '%s' has been opened.") % case.name + else: + message = _("The case '%s' has been opened.") % case.name + self.log(cr, uid, case.id, message) def case_close(self, cr, uid, ids, *args): """Overrides close for crm_case for setting close date @@ -228,7 +221,7 @@ class crm_lead(crm_case, osv.osv): @param ids: List of case Ids @param *args: Tuple Value for additional Params """ - res = super(crm_lead, self).case_close(cr, uid, ids, args) + res = super(crm_lead, self).case_close(cr, uid, ids, *args) self.write(cr, uid, ids, {'date_closed': time.strftime('%Y-%m-%d %H:%M:%S')}) for case in self.browse(cr, uid, ids): if case.type == 'lead': diff --git a/addons/crm/crm_lead_view.xml b/addons/crm/crm_lead_view.xml index 7bd9689e403..63056b89539 100644 --- a/addons/crm/crm_lead_view.xml +++ b/addons/crm/crm_lead_view.xml @@ -14,19 +14,7 @@ Create specific stages that will help your sales better organise their sales pipeline by maintaining them to their leads and sales opportunities. It will allow them to easily track how is positioned a specific lead or opportunity in the sales cycle. - - - tree - - - - - - - form - - - + Create specific stages that will help your sales better organise their sales pipeline by maintaining them to their sales opportunities. It will allow them to easily track how is positioned a specific opportunity in the sales cycle. - - - tree - - - - - - - form - - - + + @@ -124,42 +125,13 @@ - + - - - - - - crm.case.stage.form - crm.case.stage - form - - -
- - - - - - - - - - - - - - - - - - - +
diff --git a/addons/crm_claim/crm_claim.py b/addons/crm_claim/crm_claim.py index c241b36ab83..71da913c7a1 100644 --- a/addons/crm_claim/crm_claim.py +++ b/addons/crm_claim/crm_claim.py @@ -96,7 +96,7 @@ class crm_claim(crm.crm_case, osv.osv): 'date': lambda *a: time.strftime('%Y-%m-%d %H:%M:%S'), 'company_id': lambda s, cr, uid, c: s.pool.get('res.company')._company_default_get(cr, uid, 'crm.case', context=c), 'priority': lambda *a: crm.AVAILABLE_PRIORITIES[2][0], - 'stage_id': _get_stage_id, + #'stage_id': _get_stage_id, } def onchange_partner_id(self, cr, uid, ids, part, email=False): @@ -132,6 +132,20 @@ class crm_claim(crm.crm_case, osv.osv): return {'value': {'email_from': False}} address = self.pool.get('res.partner.address').browse(cr, uid, add) return {'value': {'email_from': address.email, 'partner_phone': address.phone, 'partner_mobile': address.mobile}} + + def case_open(self, cr, uid, ids, *args): + """ + Opens Claim + """ + res = super(crm_claim, self).case_open(cr, uid, ids, *args) + claims = self.browse(cr, uid, ids) + + for i in xrange(0, len(ids)): + if not claims[i].stage_id : + stage_id = self._find_first_stage(cr, uid, 'claim', claims[i].section_id.id or False) + self.write(cr, uid, [ids[i]], {'stage_id' : stage_id}) + + return res crm_claim() diff --git a/addons/crm_claim/crm_claim_view.xml b/addons/crm_claim/crm_claim_view.xml index a0a7eb7c545..4b34da6a58e 100644 --- a/addons/crm_claim/crm_claim_view.xml +++ b/addons/crm_claim/crm_claim_view.xml @@ -34,19 +34,6 @@ You can create claim stages to categorize the status of every claim entered in the system. The stages define all the steps required for the resolution of a claim. - - - tree - - - - - - - form - - - @@ -83,18 +70,26 @@ form
- + - - + + + + + + - + + - +