[FIX]Merge Lead/Opp on convert to opportunity

bzr revid: dle@openerp.com-20130204175106-q2r6xmox16co4n35
This commit is contained in:
dle@openerp.com 2013-02-04 18:51:06 +01:00
parent 91954d029f
commit 1b9503923c
5 changed files with 62 additions and 72 deletions

View File

@ -36,7 +36,6 @@ CRM_LEAD_FIELDS_TO_MERGE = ['name',
'company_id',
'country_id',
'section_id',
'stage_id',
'state_id',
'type_id',
'user_id',
@ -472,6 +471,15 @@ class crm_lead(base_stage, format_address, osv.osv):
return 'lead'
def _merge_get_result_stage(self, cr, uid, opps, context=None):
stage = None
for opp in opps:
if not stage:
stage = opp.stage_id.id
if opp.type == 'opportunity':
return opp.stage_id.id
return stage
def _merge_data(self, cr, uid, ids, oldest, fields, context=None):
"""
Prepare lead/opp data into a dictionary for merging. Different types
@ -520,7 +528,7 @@ class crm_lead(base_stage, format_address, osv.osv):
# Define the resulting type ('lead' or 'opportunity')
data['type'] = self._merge_get_result_type(cr, uid, opportunities, context)
data['stage_id'] = self._merge_get_result_stage(cr, uid, opportunities, context)
return data
def _merge_find_oldest(self, cr, uid, ids, context=None):
@ -533,9 +541,6 @@ class crm_lead(base_stage, format_address, osv.osv):
if context is None:
context = {}
if context.get('convert'):
ids = list(set(ids) - set(context.get('lead_ids', [])))
# Search opportunities order by create date
opportunity_ids = self.search(cr, uid, [('id', 'in', ids)], order='create_date', context=context)
oldest_opp_id = opportunity_ids[0]
@ -643,19 +648,11 @@ class crm_lead(base_stage, format_address, osv.osv):
if len(ids) <= 1:
raise osv.except_osv(_('Warning!'),_('Please select more than one element (lead or opportunity) from the list view.'))
lead_ids = context.get('lead_ids', [])
ctx_opportunities = self.browse(cr, uid, lead_ids, context=context)
opportunities = self.browse(cr, uid, ids, context=context)
opportunities_list = list(set(opportunities) - set(ctx_opportunities))
ids.sort()
oldest = self._merge_find_oldest(cr, uid, ids, context=context)
if ctx_opportunities:
first_opportunity = ctx_opportunities[0]
tail_opportunities = opportunities_list + ctx_opportunities[1:]
else:
first_opportunity = opportunities_list[0]
tail_opportunities = opportunities_list[1:]
opportunities_rest = self.browse(cr, uid, list(set(ids) - set([oldest.id])), context=context)
first_opportunity = oldest
tail_opportunities = opportunities_rest
merged_data = self._merge_data(cr, uid, ids, oldest, CRM_LEAD_FIELDS_TO_MERGE, context=context)
@ -664,7 +661,7 @@ class crm_lead(base_stage, format_address, osv.osv):
self._merge_opportunity_attachments(cr, uid, first_opportunity.id, tail_opportunities, context=context)
# Merge notifications about loss of information
self._merge_notify(cr, uid, first_opportunity, opportunities, context=context)
self._merge_notify(cr, uid, first_opportunity, tail_opportunities, context=context)
# Write merged data into first opportunity
self.write(cr, uid, [first_opportunity.id], merged_data, context=context)
# Delete tail opportunities
@ -763,7 +760,9 @@ class crm_lead(base_stage, format_address, osv.osv):
res = False
res_partner = self.pool.get('res.partner')
if partner_id:
res_partner.write(cr, uid, partner_id, {'section_id': lead.section_id.id or False})
if lead.section_id:
print '---TESTTRUE---'
res_partner.write(cr, uid, partner_id, {'section_id': lead.section_id and lead.section_id.id or False})
contact_id = res_partner.address_get(cr, uid, [partner_id])['default']
res = lead.write({'partner_id': partner_id}, context=context)
message = _("<b>Partner</b> set to <em>%s</em>." % (lead.partner_id.name))
@ -870,10 +869,6 @@ class crm_lead(base_stage, format_address, osv.osv):
'res_model': 'crm.lead',
'domain': [('type', '=', 'opportunity')],
'res_id': int(opportunity_id),
'view_id': False,
'views': [(form_view or False, 'form'),
(tree_view or False, 'tree'),
(False, 'calendar'), (False, 'graph')],
'type': 'ir.actions.act_window',
}

View File

@ -34,7 +34,8 @@ class crm_lead2opportunity_partner(osv.osv_memory):
('convert', 'Convert to opportunity'),
('merge', 'Merge with existing opportunities')
], 'Conversion Action', required=True),
'opportunity_ids': fields.many2many('crm.lead', string='Opportunities', domain=[('type', '=', 'opportunity')]),
'opportunity_ids': fields.many2many('crm.lead', string='Opportunities'),
'partner_id': fields.many2one('res.partner', 'Customer'),
}
def default_get(self, cr, uid, fields, context=None):
@ -55,15 +56,14 @@ class crm_lead2opportunity_partner(osv.osv_memory):
#TOFIX: use mail.mail_message.to_mail
email = re.findall(r'([^ ,<@]+@[^> ,]+)', lead.email_from or '')
email = email[0]
if partner_id:
# Search for opportunities that have the same partner and that arent done or cancelled
ids = lead_obj.search(cr, uid, [('partner_id', '=', partner_id), ('type', '=', 'opportunity')])
ids = lead_obj.search(cr, uid, [('partner_id', '=', partner_id)])
for id in ids:
tomerge.add(id)
if email:
ids = lead_obj.search(cr, uid, [('email_from', 'ilike', email), ('type', '=', 'opportunity')])
ids = lead_obj.search(cr, uid, [('email_from', 'ilike', email[0])])
for id in ids:
tomerge.add(id)
@ -72,7 +72,7 @@ class crm_lead2opportunity_partner(osv.osv_memory):
if 'partner_id' in fields:
res.update({'partner_id' : partner_id})
if 'name' in fields:
res.update({'name' : ids and 'merge' or 'convert'})
res.update({'name' : len(tomerge) >= 2 and 'merge' or 'convert'})
if 'opportunity_ids' in fields and len(tomerge) >= 2:
res.update({'opportunity_ids': list(tomerge)})
@ -108,39 +108,44 @@ class crm_lead2opportunity_partner(osv.osv_memory):
lead.allocate_salesman(cr, uid, lead_ids, user_ids, team_id=team_id, context=context)
return res
def _merge_opportunity(self, cr, uid, ids, opportunity_ids, context=None):
if context is None:
context = {}
res = False
# Expected: all newly-converted leads (active_ids) will be merged with the opportunity(ies)
# that have been selected in the 'opportunity_ids' m2m, with all these records
# merged into the first opportunity (and the rest deleted)
opportunity_ids = [o.id for o in opportunity_ids]
lead_ids = context.get('active_ids', [])
if lead_ids and opportunity_ids:
# Add the leads in the to-merge list, next to other opps
# (the fact that they're passed in context['lead_ids'] means that
# they cannot be selected to contain the result of the merge.
opportunity_ids.extend(lead_ids)
context.update({'lead_ids': lead_ids, "convert" : True})
res = self.pool.get('crm.lead').merge_opportunity(cr, uid, opportunity_ids, context=context)
return res
def action_apply(self, cr, uid, ids, context=None):
"""
Convert lead to opportunity or merge lead and opportunity and open
the freshly created opportunity view.
"""
if context is None:
context = {}
w = self.browse(cr, uid, ids, context=context)[0]
opp_ids = [o.id for o in w.opportunity_ids]
if w.name == 'merge':
lead_id = self.pool.get('crm.lead').merge_opportunity(cr, uid, opp_ids, context=context)
lead_ids = [lead_id]
lead = self.pool.get('crm.lead').read(cr, uid, lead_id, ['type'], context=context)
if lead['type'] == "lead":
self._convert_opportunity(cr, uid, ids, {'lead_ids': lead_ids}, context=context)
else:
lead_ids = context.get('active_ids', [])
self._convert_opportunity(cr, uid, ids, {'lead_ids': lead_ids}, context=context)
return self.pool.get('crm.lead').redirect_opportunity_view(cr, uid, lead_ids[0], context=context)
def _create_partner(self, cr, uid, ids, context=None):
"""
Create partner based on action.
:return dict: dictionary organized as followed: {lead_id: partner_assigned_id}
"""
#TODO this method in only called by crm_lead2opportunity_partner
#wizard and would probably diserve to be refactored or at least
#moved to a better place
if context is None:
context = {}
lead = self.pool.get('crm.lead')
lead_ids = context.get('active_ids', [])
data = self.browse(cr, uid, ids, context=context)[0]
self._convert_opportunity(cr, uid, ids, {'lead_ids': lead_ids}, context=context)
if data.name == 'merge':
self._merge_opportunity(cr, uid, ids, data.opportunity_ids, context=context)
return lead.redirect_opportunity_view(cr, uid, lead_ids[0], context=context)
print repr(data._table._columns)
partner_id = data.partner_id and data.partner_id.id or False
return lead.handle_partner_assignation(cr, uid, lead_ids, data.action, partner_id, context=context)
class crm_lead2opportunity_mass_convert(osv.osv_memory):
_name = 'crm.lead2opportunity.partner.mass'

View File

@ -13,7 +13,7 @@
<group string="Opportunities">
<field name="opportunity_ids" attrs="{'invisible': [('name', '!=', 'merge')]}" nolabel="1">
<tree>
<field name="create_date" groups="base.group_no_one"/>
<field name="create_date"/>
<field name="name"/>
<field name="type"/>
<field name="contact_name"/>
@ -59,10 +59,16 @@
<group string="Select Opportunities" attrs="{'invisible': [('name', '!=', 'merge')]}">
<field name="opportunity_ids" colspan="4" nolabel="1" attrs="{'invisible': [('name', '=', 'convert')]}">
<tree>
<field name="create_date"/>
<field name="name"/>
<field name="partner_id"/>
<field name="user_id"/>
<field name="section_id"/>
<field name="type"/>
<field name="contact_name"/>
<field name="country_id" invisible="context.get('invisible_country', True)"/>
<field name="email_from"/>
<field name="phone"/>
<field name="stage_id"/>
<field name="user_id" invisible="1"/>
<field name="section_id" invisible="context.get('invisible_section', True)"/>
</tree>
</field>
</group>

View File

@ -11,7 +11,7 @@
<separator string="Select Leads/Opportunities"/>
<field name="opportunity_ids">
<tree>
<field name="create_date" groups="base.group_no_one"/>
<field name="create_date"/>
<field name="name"/>
<field name="type"/>
<field name="contact_name"/>

View File

@ -96,20 +96,4 @@ class crm_partner_binding(osv.osv_memory):
return res
def _create_partner(self, cr, uid, ids, context=None):
"""
Create partner based on action.
:return dict: dictionary organized as followed: {lead_id: partner_assigned_id}
"""
#TODO this method in only called by crm_lead2opportunity_partner
#wizard and would probably diserve to be refactored or at least
#moved to a better place
if context is None:
context = {}
lead = self.pool.get('crm.lead')
lead_ids = context.get('active_ids', [])
data = self.browse(cr, uid, ids, context=context)[0]
partner_id = data.partner_id and data.partner_id.id or False
return lead.handle_partner_assignation(cr, uid, lead_ids, data.action, partner_id, context=context)
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4: