[MERGE] 7.0 branch

bzr revid: nicolas.vanhoren@openerp.com-20130206152123-4x9d23nr1prfpu0g
This commit is contained in:
niv-openerp 2013-02-06 16:21:23 +01:00
commit d1a175323b
4 changed files with 39 additions and 44 deletions

View File

@ -37,6 +37,7 @@ CRM_LEAD_FIELDS_TO_MERGE = ['name',
'country_id',
'section_id',
'state_id',
'stage_id',
'type_id',
'user_id',
'title',
@ -471,15 +472,6 @@ 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
@ -506,7 +498,7 @@ class crm_lead(base_stage, format_address, osv.osv):
return res and res.id or False
def _concat_all(attr):
return ', '.join(filter(lambda x: x, [getattr(opp, attr) or '' for opp in opportunities if hasattr(opp, attr)]))
return '\n\n'.join(filter(lambda x: x, [getattr(opp, attr) or '' for opp in opportunities if hasattr(opp, attr)]))
# Process the fields' values
data = {}
@ -526,24 +518,8 @@ 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):
"""
Return the oldest lead found among ids.
:param list ids: list of ids of the leads to inspect
:return object: browse record of the oldest of the leads
"""
if context is None:
context = {}
# 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]
return self.browse(cr, uid, oldest_opp_id, context=context)
def _mail_body(self, cr, uid, lead, fields, title=False, context=None):
body = []
if title:
@ -590,7 +566,7 @@ class crm_lead(base_stage, format_address, osv.osv):
subject = [merge_message]
for opportunity in opportunities:
subject.append(opportunity.name)
title = "%s : %s" % (merge_message, opportunity.name)
title = "%s : %s" % (opportunity.type == 'opportunity' and _('Merged opportunity') or _('Merged lead'), opportunity.name)
details.append(self._mail_body(cr, uid, opportunity, CRM_LEAD_FIELDS_TO_MERGE, title=title, context=context))
# Chatter message's subject
@ -642,32 +618,46 @@ class crm_lead(base_stage, format_address, osv.osv):
:param list ids: leads/opportunities ids to merge
:return int id: id of the resulting lead/opp
"""
if context is None: context = {}
if context is None:
context = {}
if len(ids) <= 1:
raise osv.except_osv(_('Warning!'),_('Please select more than one element (lead or opportunity) from the list view.'))
ids.sort()
oldest = self._merge_find_oldest(cr, uid, ids, context=context)
opportunities_rest = self.browse(cr, uid, list(set(ids) - set([oldest.id])), context=context)
first_opportunity = oldest
raise osv.except_osv(_('Warning!'), _('Please select more than one element (lead or opportunity) from the list view.'))
opportunities = self.browse(cr, uid, ids, context=context)
sequenced_opps = []
for opportunity in opportunities:
sequenced_opps.append((opportunity.stage_id and opportunity.stage_id.state != 'cancel' and opportunity.stage_id.sequence or 0, opportunity))
sequenced_opps.sort(key=lambda tup: tup[0], reverse=True)
opportunities = [opportunity for sequence, opportunity in sequenced_opps]
ids = [opportunity.id for opportunity in opportunities]
highest = opportunities[0]
opportunities_rest = opportunities[1:]
tail_opportunities = opportunities_rest
merged_data = self._merge_data(cr, uid, ids, oldest, CRM_LEAD_FIELDS_TO_MERGE, context=context)
merged_data = self._merge_data(cr, uid, ids, highest, CRM_LEAD_FIELDS_TO_MERGE, context=context)
# Merge messages and attachements into the first opportunity
self._merge_opportunity_history(cr, uid, first_opportunity.id, tail_opportunities, context=context)
self._merge_opportunity_attachments(cr, uid, first_opportunity.id, tail_opportunities, context=context)
self._merge_opportunity_history(cr, uid, highest.id, tail_opportunities, context=context)
self._merge_opportunity_attachments(cr, uid, highest.id, tail_opportunities, context=context)
# Merge notifications about loss of information
opportunities = [oldest]
opportunities = [highest]
opportunities.extend(opportunities_rest)
self._merge_notify(cr, uid, first_opportunity, opportunities, context=context)
self._merge_notify(cr, uid, highest, opportunities, context=context)
# Check if the stage is in the stages of the sales team. If not, assign the stage with the lowest sequence
if merged_data.get('type') == 'opportunity' and merged_data.get('section_id'):
section_stages = self.pool.get('crm.case.section').read(cr, uid, merged_data['section_id'], ['stage_ids'], context=context)
if merged_data.get('stage_id') not in section_stages['stage_ids']:
stages_sequences = self.pool.get('crm.case.stage').search(cr, uid, [('id','in',section_stages['stage_ids'])], order='sequence', limit=1, context=context)
merged_data['stage_id'] = stages_sequences[0]
# Write merged data into first opportunity
self.write(cr, uid, [first_opportunity.id], merged_data, context=context)
self.write(cr, uid, [highest.id], merged_data, context=context)
# Delete tail opportunities
self.unlink(cr, uid, [x.id for x in tail_opportunities], context=context)
return first_opportunity.id
return highest.id
def _convert_opportunity_data(self, cr, uid, lead, customer, section_id=False, context=None):
crm_stage = self.pool.get('crm.case.stage')

View File

@ -41,7 +41,7 @@
assert merge_id, 'Fail to create merge opportunity wizard'
merge_result = self.browse(cr, uid, merge_id)[0]
assert merge_result.partner_id.id == ref("base.res_partner_1"), 'Partner mismatch: when merging leads/opps with different m2o values, the first not null value prevails (the other are dropped)'
assert merge_result.description == 'This is the description of the test lead 1., This is the description of the test lead 2., This is the description of the test opp 1.', 'Description mismatch: when merging leads/opps with different text values, these values should get concatenated and separeted with ", "'
assert merge_result.description == 'This is the description of the test lead 1.\n\nThis is the description of the test lead 2.\n\nThis is the description of the test opp 1.', 'Description mismatch: when merging leads/opps with different text values, these values should get concatenated and separated with line returns'
assert merge_result.type == 'opportunity', 'Type mismatch: when at least one opp in involved in the merge, the result should be a new opp (instead of %s)' % merge_result.type
-
The other (tailing) leads/opps shouldn't exist anymore.

View File

@ -34,12 +34,12 @@ def get_sys_logs(self, cr, uid):
limit_date = limit_date - datetime.timedelta(15)
limit_date_str = limit_date.strftime(misc.DEFAULT_SERVER_DATETIME_FORMAT)
nbr_users = pool.get("res.users").search(cr, uid, [], count=True)
nbr_active_users = pool.get("res.users").search(cr, uid, [("date", ">=", limit_date_str)], count=True)
nbr_active_users = pool.get("res.users").search(cr, uid, [("login_date", ">=", limit_date_str)], count=True)
nbr_share_users = False
nbr_active_share_users = False
if "share" in pool.get("res.users")._all_columns:
nbr_share_users = pool.get("res.users").search(cr, uid, [("share", "=", True)], count=True)
nbr_active_share_users = pool.get("res.users").search(cr, uid, [("share", "=", True), ("date", ">=", limit_date_str)], count=True)
nbr_active_share_users = pool.get("res.users").search(cr, uid, [("share", "=", True), ("login_date", ">=", limit_date_str)], count=True)
user = pool.get("res.users").browse(cr, uid, uid)
web_base_url = self.pool.get('ir.config_parameter').get_param(cr, uid, 'web.base.url', 'False')

View File

@ -29,7 +29,12 @@ class Binary(openerp.addons.web.http.Controller):
_cp_path = "/web_linkedin/binary"
@openerp.addons.web.http.jsonrequest
def url2binary(self, req,url):
def url2binary(self, req, url):
if not url.startswith("http"):
raise Exception("Not allowed to load a file using this protocol")
if url.count("?") > 0 or url.count("&") > 0 or url.count("=") > 0:
raise Exception("Not allowed to use GET parameters")
req.session.assert_valid(force=True)
bfile = urllib2.urlopen(url)
return base64.b64encode(bfile.read())