[IMP] crm_partner_assign: clean test case and APIs
bzr revid: hmo@tinyerp.com-20111026092133-xdrikqkxs4e5usw3
This commit is contained in:
parent
afc57b31cd
commit
477e4c09b4
|
@ -335,7 +335,7 @@ class crm_lead(crm_case, osv.osv):
|
||||||
return self.set_priority(cr, uid, ids, '3')
|
return self.set_priority(cr, uid, ids, '3')
|
||||||
|
|
||||||
|
|
||||||
def _merge_data(self, cr, uid, ids, oldest, context=None):
|
def _merge_data(self, cr, uid, ids, oldest, fields, context=None):
|
||||||
# prepare opportunity data into dictionary for merging
|
# prepare opportunity data into dictionary for merging
|
||||||
opportunities = self.browse(cr, uid, ids, context=context)
|
opportunities = self.browse(cr, uid, ids, context=context)
|
||||||
def _get_first_not_null(attr):
|
def _get_first_not_null(attr):
|
||||||
|
@ -353,40 +353,20 @@ class crm_lead(crm_case, osv.osv):
|
||||||
def _concat_all(attr):
|
def _concat_all(attr):
|
||||||
return ', '.join([getattr(opportunity, attr) or '' for opportunity in opportunities if hasattr(opportunity, attr)])
|
return ', '.join([getattr(opportunity, attr) or '' for opportunity in opportunities if hasattr(opportunity, attr)])
|
||||||
|
|
||||||
data = {
|
data = {}
|
||||||
'partner_id': _get_first_not_null_id('partner_id'), # !!
|
for field_name in fields:
|
||||||
'title': _get_first_not_null_id('title'),
|
field_info = self._all_columns.get(field_name)
|
||||||
'name' : _get_first_not_null('name'), #not lost
|
if field_info is None:
|
||||||
'categ_id' : _get_first_not_null_id('categ_id'), # !!
|
continue
|
||||||
'channel_id' : _get_first_not_null_id('channel_id'), # !!
|
field = field_info.column
|
||||||
'city' : _get_first_not_null('city'), # !!
|
if field._type in ('many2many', 'one2many'):
|
||||||
'company_id' : _get_first_not_null_id('company_id'), #!!
|
continue
|
||||||
'contact_name' : _get_first_not_null('contact_name'), #not lost
|
elif field._type == 'many2one':
|
||||||
'country_id' : _get_first_not_null_id('country_id'), #!!
|
data[field_name] = _get_first_not_null_id(field_name) # !!
|
||||||
'partner_address_id' : _get_first_not_null_id('partner_address_id'), #!!
|
elif field._type == 'text':
|
||||||
'type_id' : _get_first_not_null_id('type_id'), #!!
|
data[field_name] = _concat_all(field_name) #not lost
|
||||||
'user_id' : _get_first_not_null_id('user_id'), #!!
|
else:
|
||||||
'section_id' : _get_first_not_null_id('section_id'), #!!
|
data[field_name] = _get_first_not_null(field_name) #not lost
|
||||||
'state_id' : _get_first_not_null_id('state_id'),
|
|
||||||
'description' : _concat_all('description'), #not lost
|
|
||||||
'email' : _get_first_not_null('email'), # !!
|
|
||||||
'fax' : _get_first_not_null('fax'),
|
|
||||||
'mobile' : _get_first_not_null('mobile'),
|
|
||||||
'partner_name' : _get_first_not_null('partner_name'),
|
|
||||||
'phone' : _get_first_not_null('phone'),
|
|
||||||
'probability' : _get_first_not_null('probability'),
|
|
||||||
'planned_revenue' : _get_first_not_null('planned_revenue'),
|
|
||||||
'street' : _get_first_not_null('street'),
|
|
||||||
'street2' : _get_first_not_null('street2'),
|
|
||||||
'zip' : _get_first_not_null('zip'),
|
|
||||||
'state' : 'open',
|
|
||||||
'create_date' : _get_first_not_null('create_date'),
|
|
||||||
'date_action_last': _get_first_not_null('date_action_last'),
|
|
||||||
'date_action_next': _get_first_not_null('date_action_next'),
|
|
||||||
'email_from' : _get_first_not_null('email_from'),
|
|
||||||
'email_cc' : _get_first_not_null('email_cc'),
|
|
||||||
'partner_name' : _get_first_not_null('partner_name'),
|
|
||||||
}
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
def _merge_find_oldest(self, cr, uid, ids, context=None):
|
def _merge_find_oldest(self, cr, uid, ids, context=None):
|
||||||
|
@ -401,35 +381,45 @@ class crm_lead(crm_case, osv.osv):
|
||||||
oldest_id = opportunity_ids[0]
|
oldest_id = opportunity_ids[0]
|
||||||
return self.browse(cr, uid, oldest_id, context=context)
|
return self.browse(cr, uid, oldest_id, context=context)
|
||||||
|
|
||||||
|
def _mail_body_text(self, cr, uid, lead, fields, title=False, context=None):
|
||||||
|
body = []
|
||||||
|
if title:
|
||||||
|
body.append("%s\n" % (title))
|
||||||
|
for field_name in fields:
|
||||||
|
field_info = self._all_columns.get(field_name)
|
||||||
|
if field_info is None:
|
||||||
|
continue
|
||||||
|
field = field_info.column
|
||||||
|
value = None
|
||||||
|
|
||||||
|
if field._type == 'selection':
|
||||||
|
if hasattr(field.selection, '__call__'):
|
||||||
|
key = field.selection(self, cr, uid, context=context)
|
||||||
|
else:
|
||||||
|
key = field.selection
|
||||||
|
value = dict(key).get(lead[field_name], lead[field_name])
|
||||||
|
elif field._type == 'many2one':
|
||||||
|
if lead[field_name]:
|
||||||
|
value = lead[field_name].name_get()[0][1]
|
||||||
|
else:
|
||||||
|
value = lead[field_name]
|
||||||
|
|
||||||
|
body.append("%s: %s\n" % (field.string, value or ''))
|
||||||
|
return "\n".join(body + ['---'])
|
||||||
|
|
||||||
def _merge_notification(self, cr, uid, opportunity_id, opportunities, context=None):
|
def _merge_notification(self, cr, uid, opportunity_id, opportunities, context=None):
|
||||||
#TOFIX: mail template should be used instead of fix body, subject text
|
#TOFIX: mail template should be used instead of fix body, subject text
|
||||||
details = []
|
details = []
|
||||||
merge_message = _('Merged opportunities')
|
merge_message = _('Merged opportunities')
|
||||||
subject = [merge_message]
|
subject = [merge_message]
|
||||||
|
fields = ['name', 'partner_id', 'stage_id', 'section_id', 'user_id', 'categ_id', 'channel_id', 'company_id', 'contact_name',
|
||||||
|
'email_from', 'phone', 'fax', 'mobile', 'state_id', 'description', 'probability', 'planned_revenue',
|
||||||
|
'country_id', 'city', 'street', 'street2', 'zip']
|
||||||
for opportunity in opportunities:
|
for opportunity in opportunities:
|
||||||
subject.append(opportunity.name)
|
subject.append(opportunity.name)
|
||||||
details.append(_('%s : %s\n Partner: %s\n Stage: %s\n Section: %s\n Salesman: %s\n Category: %s\n Channel: %s\n Company: %s\n Contact name: %s\n Email: %s\n Phone number: %s\n Fax: %s\n Mobile: %s\n State: %s\n Description: %s\n Probability: %s\n Planned revennue: %s\n Country: %s\n City: %s\n Street: %s\n Street 2: %s\n Zip 2: %s') % (merge_message, opportunity.name, opportunity.partner_id.name or '',
|
title = "%s : %s" % (merge_message, opportunity.name)
|
||||||
opportunity.stage_id.name or '',
|
details.append(self._mail_body_text(cr, uid, opportunity, fields, title=title, context=context))
|
||||||
opportunity.section_id.name or '',
|
|
||||||
opportunity.user_id.name or '',
|
|
||||||
opportunity.categ_id.name or '',
|
|
||||||
opportunity.channel_id.name or '',
|
|
||||||
opportunity.company_id.name or '',
|
|
||||||
opportunity.contact_name or '',
|
|
||||||
opportunity.email_from or '',
|
|
||||||
opportunity.phone or '',
|
|
||||||
opportunity.fax or '',
|
|
||||||
opportunity.mobile or '',
|
|
||||||
opportunity.state_id.name or '',
|
|
||||||
opportunity.description or '',
|
|
||||||
opportunity.probability or '',
|
|
||||||
opportunity.planned_revenue or '',
|
|
||||||
opportunity.country_id.name or '',
|
|
||||||
opportunity.city or '',
|
|
||||||
opportunity.street or '',
|
|
||||||
opportunity.street2 or '',
|
|
||||||
opportunity.zip or '',
|
|
||||||
))
|
|
||||||
subject = subject[0] + ", ".join(subject[1:])
|
subject = subject[0] + ", ".join(subject[1:])
|
||||||
details = "\n\n".join(details)
|
details = "\n\n".join(details)
|
||||||
return self.message_append(cr, uid, [opportunity_id], subject, body_text=details, context=context)
|
return self.message_append(cr, uid, [opportunity_id], subject, body_text=details, context=context)
|
||||||
|
@ -493,7 +483,12 @@ class crm_lead(crm_case, osv.osv):
|
||||||
first_opportunity = opportunities_list[0]
|
first_opportunity = opportunities_list[0]
|
||||||
tail_opportunities = opportunities_list[1:]
|
tail_opportunities = opportunities_list[1:]
|
||||||
|
|
||||||
data = self._merge_data(cr, uid, ids, oldest, context=context)
|
fields = ['partner_id', 'title', 'name', 'categ_id', 'channel_id', 'city', 'company_id', 'contact_name', 'country_id',
|
||||||
|
'partner_address_id', 'type_id', 'user_id', 'section_id', 'state_id', 'description', 'email', 'fax', 'mobile',
|
||||||
|
'partner_name', 'phone', 'probability', 'planned_revenue', 'street', 'street2', 'zip', 'create_date', 'date_action_last',
|
||||||
|
'date_action_next', 'email_from', 'email_cc', 'partner_name']
|
||||||
|
|
||||||
|
data = self._merge_data(cr, uid, ids, oldest, fields, context=context)
|
||||||
|
|
||||||
# merge data into first opportunity
|
# merge data into first opportunity
|
||||||
self.write(cr, uid, [first_opportunity.id], data, context=context)
|
self.write(cr, uid, [first_opportunity.id], data, context=context)
|
||||||
|
@ -507,6 +502,8 @@ class crm_lead(crm_case, osv.osv):
|
||||||
#delete tail opportunities
|
#delete tail opportunities
|
||||||
self.unlink(cr, uid, [x.id for x in tail_opportunities], context=context)
|
self.unlink(cr, uid, [x.id for x in tail_opportunities], context=context)
|
||||||
|
|
||||||
|
#open first opportunity
|
||||||
|
self.case_open(cr, uid, [first_opportunity.id])
|
||||||
return first_opportunity.id
|
return first_opportunity.id
|
||||||
|
|
||||||
def _convert_opportunity_data(self, cr, uid, lead, customer, section_id=False, context=None):
|
def _convert_opportunity_data(self, cr, uid, lead, customer, section_id=False, context=None):
|
||||||
|
@ -571,9 +568,17 @@ class crm_lead(crm_case, osv.osv):
|
||||||
})
|
})
|
||||||
return partner_id
|
return partner_id
|
||||||
|
|
||||||
def _lead_assign_partner(self, cr, uid, ids, partner_id, context=None):
|
def assign_partner(self, cr, uid, ids, partner_id=None, context=None):
|
||||||
contact_id = self.pool.get('res.partner').address_get(cr, uid, [partner_id])['default']
|
res = False
|
||||||
return self.write(cr, uid, ids, {'partner_id' : partner_id, 'partner_address_id': contact_id}, context=context)
|
res_partner = self.pool.get('res.partner')
|
||||||
|
if partner_id:
|
||||||
|
contact_id = res_partner.address_get(cr, uid, [partner_id])['default']
|
||||||
|
res = self.write(cr, uid, ids, {'partner_id' : partner_id, 'partner_address_id': contact_id}, context=context)
|
||||||
|
partner = res_partner.browse(cr, uid, partner_id, context=context)
|
||||||
|
if partner.user_id:
|
||||||
|
for lead_id in ids:
|
||||||
|
self.allocate_salesman(cr, uid, [lead_id], [partner.user_id.id], context=context)
|
||||||
|
return res
|
||||||
|
|
||||||
def _lead_create_partner_address(self, cr, uid, lead, partner_id, context=None):
|
def _lead_create_partner_address(self, cr, uid, lead, partner_id, context=None):
|
||||||
address = self.pool.get('res.partner.address')
|
address = self.pool.get('res.partner.address')
|
||||||
|
@ -609,7 +614,7 @@ class crm_lead(crm_case, osv.osv):
|
||||||
if not partner_id:
|
if not partner_id:
|
||||||
partner_id = self._lead_create_partner(cr, uid, lead, context=context)
|
partner_id = self._lead_create_partner(cr, uid, lead, context=context)
|
||||||
self._lead_create_partner_address(cr, uid, lead, partner_id, context=context)
|
self._lead_create_partner_address(cr, uid, lead, partner_id, context=context)
|
||||||
self._lead_assign_partner(cr, uid, [lead.id], partner_id, context=context)
|
self.assign_partner(cr, uid, [lead.id], partner_id, context=context)
|
||||||
partner_ids[lead.id] = partner_id
|
partner_ids[lead.id] = partner_id
|
||||||
return partner_ids
|
return partner_ids
|
||||||
|
|
||||||
|
|
|
@ -38,6 +38,9 @@ You can also use the geolocalization without using the GPS coordinates.
|
||||||
""",
|
""",
|
||||||
'author': 'OpenERP SA',
|
'author': 'OpenERP SA',
|
||||||
'depends': ['crm'],
|
'depends': ['crm'],
|
||||||
|
'demo_xml': [
|
||||||
|
'res_partner_demo.xml',
|
||||||
|
],
|
||||||
'update_xml': [
|
'update_xml': [
|
||||||
'security/ir.model.access.csv',
|
'security/ir.model.access.csv',
|
||||||
'res_partner_view.xml',
|
'res_partner_view.xml',
|
||||||
|
@ -46,8 +49,9 @@ You can also use the geolocalization without using the GPS coordinates.
|
||||||
'report/crm_lead_report_view.xml',
|
'report/crm_lead_report_view.xml',
|
||||||
'report/crm_partner_report_view.xml',
|
'report/crm_partner_report_view.xml',
|
||||||
],
|
],
|
||||||
'test': ['test/process/partner_assign.yml',
|
'test': [
|
||||||
'test/ui/partner_assign_form.yml'],
|
'test/process/partner_assign.yml',
|
||||||
|
],
|
||||||
'installable': True,
|
'installable': True,
|
||||||
'active': False,
|
'active': False,
|
||||||
'certificate': '00503409558942442061',
|
'certificate': '00503409558942442061',
|
||||||
|
|
|
@ -24,22 +24,25 @@ from osv import fields
|
||||||
import urllib,re
|
import urllib,re
|
||||||
import random, time
|
import random, time
|
||||||
from tools.translate import _
|
from tools.translate import _
|
||||||
|
import tools
|
||||||
|
|
||||||
def geo_find(addr):
|
def geo_find(addr):
|
||||||
|
addr = addr.encode('utf8')
|
||||||
|
regex = '<coordinates>([+-]?[0-9\.]+),([+-]?[0-9\.]+),([+-]?[0-9\.]+)</coordinates>'
|
||||||
|
url = 'http://maps.google.com/maps/geo?q=' + urllib.quote(addr) + '&output=xml&oe=utf8&sensor=false'
|
||||||
try:
|
try:
|
||||||
regex = '<coordinates>([+-]?[0-9\.]+),([+-]?[0-9\.]+),([+-]?[0-9\.]+)</coordinates>'
|
|
||||||
url = 'http://maps.google.com/maps/geo?q=' + urllib.quote(addr) + '&output=xml&oe=utf8&sensor=false'
|
|
||||||
xml = urllib.urlopen(url).read()
|
xml = urllib.urlopen(url).read()
|
||||||
if '<error>' in xml:
|
|
||||||
return None
|
|
||||||
result = re.search(regex, xml, re.M|re.I)
|
|
||||||
if not result:
|
|
||||||
return None
|
|
||||||
return float(result.group(2)),float(result.group(1))
|
|
||||||
except Exception, e:
|
except Exception, e:
|
||||||
raise osv.except_osv(_('Network error'),
|
raise osv.except_osv(_('Network error'),
|
||||||
_('Could not contact geolocation servers, please make sure you have a working internet connection (%s)') % e)
|
_('Could not contact geolocation servers, please make sure you have a working internet connection (%s)') % e)
|
||||||
|
|
||||||
|
if '<error>' in xml:
|
||||||
|
return None
|
||||||
|
result = re.search(regex, xml, re.M|re.I)
|
||||||
|
if not result:
|
||||||
|
return None
|
||||||
|
return float(result.group(2)),float(result.group(1))
|
||||||
|
|
||||||
|
|
||||||
class res_partner_grade(osv.osv):
|
class res_partner_grade(osv.osv):
|
||||||
_order = 'sequence'
|
_order = 'sequence'
|
||||||
|
@ -74,9 +77,13 @@ class res_partner(osv.osv):
|
||||||
for partner in self.browse(cr, uid, ids, context=context):
|
for partner in self.browse(cr, uid, ids, context=context):
|
||||||
if not partner.address:
|
if not partner.address:
|
||||||
continue
|
continue
|
||||||
part = partner.address[0]
|
contact = partner.address[0] #TOFIX: should be get latitude and longitude for default contact?
|
||||||
addr = ', '.join(filter(None, [part.street, (part.zip or '')+' '+(part.city or ''), part.state_id and part.state_id.name, part.country_id and part.country_id.name]))
|
addr = ', '.join(filter(None, [
|
||||||
result = geo_find(addr.encode('utf8'))
|
contact.street,
|
||||||
|
"%s %s" % (contact.zip , contact.city),
|
||||||
|
contact.state_id and contact.state_id.name,
|
||||||
|
contact.country_id and contact.country_id.name]))
|
||||||
|
result = geo_find(tools.ustr(addr))
|
||||||
if result:
|
if result:
|
||||||
self.write(cr, uid, [partner.id], {
|
self.write(cr, uid, [partner.id], {
|
||||||
'partner_latitude': result[0],
|
'partner_latitude': result[0],
|
||||||
|
@ -94,14 +101,13 @@ class crm_lead(osv.osv):
|
||||||
'partner_assigned_id': fields.many2one('res.partner', 'Assigned Partner', help="Partner this case has been forwarded/assigned to.", select=True),
|
'partner_assigned_id': fields.many2one('res.partner', 'Assigned Partner', help="Partner this case has been forwarded/assigned to.", select=True),
|
||||||
'date_assign': fields.date('Assignation Date', help="Last date this case was forwarded/assigned to a partner"),
|
'date_assign': fields.date('Assignation Date', help="Last date this case was forwarded/assigned to a partner"),
|
||||||
}
|
}
|
||||||
|
def _merge_data(self, cr, uid, ids, oldest, fields, context=None):
|
||||||
|
fields += ['partner_latitude', 'partner_longitude', 'partner_assigned_id', 'date_assign']
|
||||||
|
return super(crm_lead, self)._merge_data(cr, uid, ids, oldest, fields, context=context)
|
||||||
|
|
||||||
def onchange_assign_id(self, cr, uid, ids, partner_assigned_id, context=None):
|
def onchange_assign_id(self, cr, uid, ids, partner_assigned_id, context=None):
|
||||||
"""This function updates the "assignation date" automatically, when manually assign a partner in the geo assign tab
|
"""This function updates the "assignation date" automatically, when manually assign a partner in the geo assign tab
|
||||||
@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 """
|
|
||||||
|
|
||||||
if not partner_assigned_id:
|
if not partner_assigned_id:
|
||||||
return {'value':{'date_assign': False}}
|
return {'value':{'date_assign': False}}
|
||||||
else:
|
else:
|
||||||
|
@ -112,72 +118,102 @@ class crm_lead(osv.osv):
|
||||||
'user_id' : user_id}
|
'user_id' : user_id}
|
||||||
}
|
}
|
||||||
|
|
||||||
def assign_partner(self, cr, uid, ids, context=None):
|
def assign_partner(self, cr, uid, ids, partner_id=None, context=None):
|
||||||
ok = False
|
partner_ids = {}
|
||||||
for part in self.browse(cr, uid, ids, context=context):
|
res = False
|
||||||
if not part.country_id:
|
if partner_id is None:
|
||||||
continue
|
partner_ids = self.search_geo_partner(cr, uid, ids, context=context)
|
||||||
addr = ', '.join(filter(None, [part.street, (part.zip or '')+' '+(part.city or ''), part.state_id and part.state_id.name, part.country_id and part.country_id.name]))
|
for lead in self.browse(cr, uid, ids, context=context):
|
||||||
result = geo_find(addr.encode('utf8'))
|
if not partner_id:
|
||||||
if result:
|
partner_id = partner_ids.get(lead.id, False)
|
||||||
self.write(cr, uid, [part.id], {
|
res = super(crm_lead, self).assign_partner(cr, uid, [lead.id], partner_id, context=context)
|
||||||
'partner_latitude': result[0],
|
self.write(cr, uid, [lead.id], {'date_assign': time.strftime('%Y-%m-%d'), 'partner_assigned_id': partner_id}, context=context)
|
||||||
'partner_longitude': result[1]
|
return res
|
||||||
}, context=context)
|
|
||||||
|
|
||||||
|
def assign_geo_localize(self, cr, uid, ids, latitude=False, longitude=False, context=None):
|
||||||
|
for lead in self.browse(cr, uid, ids, context=context):
|
||||||
|
if not lead.country_id:
|
||||||
|
continue
|
||||||
|
addr = ', '.join(filter(None, [
|
||||||
|
lead.street,
|
||||||
|
"%s %s" % (lead.zip, lead.city),
|
||||||
|
lead.state_id and lead.state_id.name or '',
|
||||||
|
lead.country_id and lead.country_id.name or ''
|
||||||
|
]))
|
||||||
|
result = geo_find(tools.ustr(addr))
|
||||||
|
if not latitude and result:
|
||||||
|
latitude = result[0]
|
||||||
|
if not longitude and result:
|
||||||
|
longitude = result[1]
|
||||||
|
self.write(cr, uid, [lead.id], {
|
||||||
|
'partner_latitude': latitude,
|
||||||
|
'partner_longitude': longitude
|
||||||
|
}, context=context)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def search_geo_partner(self, cr, uid, ids, context=None):
|
||||||
|
res_partner = self.pool.get('res.partner')
|
||||||
|
res_partner_ids = {}
|
||||||
|
self.assign_geo_localize(cr, uid, ids, context=context)
|
||||||
|
for lead in self.browse(cr, uid, ids, context=context):
|
||||||
|
partner_ids = []
|
||||||
|
if not lead.country_id:
|
||||||
|
continue
|
||||||
|
latitude = lead.partner_latitude
|
||||||
|
longitude = lead.partner_longitude
|
||||||
|
if latitude and longitude:
|
||||||
# 1. first way: in the same country, small area
|
# 1. first way: in the same country, small area
|
||||||
part_ids = self.pool.get('res.partner').search(cr, uid, [
|
partner_ids = res_partner.search(cr, uid, [
|
||||||
('partner_weight','>',0),
|
('partner_weight', '>', 0),
|
||||||
('partner_latitude','>',result[0]-2), ('partner_latitude','<',result[0]+2),
|
('partner_latitude', '>', latitude - 2), ('partner_latitude', '<', latitude + 2),
|
||||||
('partner_longitude','>',result[1]-1.5), ('partner_longitude','<',result[1]+1.5),
|
('partner_longitude', '>', longitude - 1.5), ('partner_longitude', '<', longitude + 1.5),
|
||||||
('country', '=', part.country_id.id),
|
('country', '=', lead.country_id.id),
|
||||||
], context=context)
|
], context=context)
|
||||||
|
|
||||||
# 2. second way: in the same country, big area
|
# 2. second way: in the same country, big area
|
||||||
if not part_ids:
|
if not partner_ids:
|
||||||
part_ids = self.pool.get('res.partner').search(cr, uid, [
|
partner_ids = res_partner.search(cr, uid, [
|
||||||
('partner_weight','>',0),
|
('partner_weight', '>', 0),
|
||||||
('partner_latitude','>',result[0]-4), ('partner_latitude','<',result[0]+4),
|
('partner_latitude', '>', latitude - 4), ('partner_latitude', '<', latitude + 4),
|
||||||
('partner_longitude','>',result[1]-3), ('partner_longitude','<',result[1]+3),
|
('partner_longitude', '>', longitude - 3), ('partner_longitude', '<' , longitude + 3),
|
||||||
('country', '=', part.country_id.id),
|
('country', '=', lead.country_id.id),
|
||||||
], context=context)
|
], context=context)
|
||||||
|
|
||||||
|
|
||||||
# 5. fifth way: anywhere in same country
|
# 5. fifth way: anywhere in same country
|
||||||
if not part_ids:
|
if not partner_ids:
|
||||||
# still haven't found any, let's take all partners in the country!
|
# still haven't found any, let's take all partners in the country!
|
||||||
part_ids = self.pool.get('res.partner').search(cr, uid, [
|
partner_ids = partner.search(cr, uid, [
|
||||||
('partner_weight','>',0),
|
('partner_weight', '>', 0),
|
||||||
('country', '=', part.country_id.id),
|
('country', '=', lead.country_id.id),
|
||||||
], context=context)
|
], context=context)
|
||||||
|
|
||||||
# 6. sixth way: closest partner whatsoever, just to have at least one result
|
# 6. sixth way: closest partner whatsoever, just to have at least one result
|
||||||
if not part_ids:
|
if not partner_ids:
|
||||||
# warning: point() type takes (longitude, latitude) as parameters in this order!
|
# warning: point() type takes (longitude, latitude) as parameters in this order!
|
||||||
cr.execute("""SELECT id, distance
|
cr.execute("""SELECT id, distance
|
||||||
FROM (select id, (point(partner_longitude, partner_latitude) <-> point(%s,%s)) AS distance FROM res_partner
|
FROM (select id, (point(partner_longitude, partner_latitude) <-> point(%s,%s)) AS distance FROM res_partner
|
||||||
WHERE partner_longitude is not null
|
WHERE partner_longitude is not null
|
||||||
AND partner_latitude is not null
|
AND partner_latitude is not null
|
||||||
AND partner_weight > 0) AS d
|
AND partner_weight > 0) AS d
|
||||||
ORDER BY distance LIMIT 1""", (result[1],result[0]))
|
ORDER BY distance LIMIT 1""", (longitude, latitude))
|
||||||
res = cr.dictfetchone()
|
res = cr.dictfetchone()
|
||||||
if res:
|
if res:
|
||||||
part_ids.append(res['id'])
|
partner_ids.append(res['id'])
|
||||||
|
|
||||||
total = 0
|
total_weight = 0
|
||||||
toassign = []
|
toassign = []
|
||||||
for part2 in self.pool.get('res.partner').browse(cr, uid, part_ids, context=context):
|
for partner in res_partner.browse(cr, uid, partner_ids, context=context):
|
||||||
total += part2.partner_weight
|
total_weight += partner.partner_weight
|
||||||
toassign.append( (part2.id, total) )
|
toassign.append( (partner.id, total_weight) )
|
||||||
|
|
||||||
random.shuffle(toassign) # avoid always giving the leads to the first ones in db natural order!
|
random.shuffle(toassign) # avoid always giving the leads to the first ones in db natural order!
|
||||||
mypartner = random.randint(0,total)
|
nearest_weight = random.randint(0, total_weight)
|
||||||
for t in toassign:
|
for partner_id, weight in toassign:
|
||||||
if mypartner<=t[1]:
|
if nearest_weight <= weight:
|
||||||
vals = self.onchange_assign_id(cr,uid, ids, t[0], context=context)['value']
|
res_partner_ids[lead.id] = partner_id
|
||||||
vals.update({'partner_assigned_id': t[0], 'date_assign': time.strftime('%Y-%m-%d')})
|
|
||||||
self.write(cr, uid, [part.id], vals, context=context)
|
|
||||||
break
|
break
|
||||||
ok = True
|
return res_partner_ids
|
||||||
return ok
|
|
||||||
crm_lead()
|
crm_lead()
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<openerp>
|
||||||
|
<data>
|
||||||
|
<record id="res_partner_grade_first" model="res.partner.grade">
|
||||||
|
<field name="name">First</field>
|
||||||
|
<field name="sequence">1</field>
|
||||||
|
</record>
|
||||||
|
<record id="base.res_partner_ericdubois0" model="res.partner">
|
||||||
|
<field name="grade_id" ref="res_partner_grade_first"/>
|
||||||
|
<field name="partner_weight">10</field>
|
||||||
|
</record>
|
||||||
|
</data>
|
||||||
|
</openerp>
|
|
@ -1,58 +1,38 @@
|
||||||
-
|
-
|
||||||
In order to test find nearest Partner functionality and assign to opportunity ,
|
In order to test find nearest Partner functionality and assign to opportunity ,
|
||||||
so First i create a grade 'First' for partner.
|
|
||||||
-
|
-
|
||||||
!record {model: res.partner.grade, id: res_partner_grade_first}:
|
I Set Geo Lattitude and Longitude according to partner address.
|
||||||
name: First
|
|
||||||
sequence: 1
|
|
||||||
-
|
|
||||||
I assign grade 'First' to the partner 'Eric' and give more probability to assign a lead to this partner.
|
|
||||||
-
|
|
||||||
!record {model: res.partner, id: base.res_partner_ericdubois0}:
|
|
||||||
grade_id: res_partner_grade_first
|
|
||||||
partner_weight: 10
|
|
||||||
-
|
|
||||||
Set Lattitude and Longitude according to partner address.
|
|
||||||
-
|
-
|
||||||
!python {model: res.partner}: |
|
!python {model: res.partner}: |
|
||||||
self.geo_localize(cr, uid, [ref('base.res_partner_ericdubois0')], context)
|
self.geo_localize(cr, uid, [ref('base.res_partner_ericdubois0')], context)
|
||||||
|
-
|
||||||
|
I check Geo Lattitude and Longitude of partner after set
|
||||||
|
-
|
||||||
|
!python {model: res.partner}: |
|
||||||
partner = self.browse(cr, uid, ref('base.res_partner_ericdubois0'))
|
partner = self.browse(cr, uid, ref('base.res_partner_ericdubois0'))
|
||||||
assert partner.partner_latitude == 50.4530495 , "Lattitude is wrong"
|
assert partner.partner_latitude == 50.4530495 , "Lattitude is wrong"
|
||||||
assert partner.partner_longitude == 3.9693885 , "Longitude is wrong"
|
assert partner.partner_longitude == 3.9693885 , "Longitude is wrong"
|
||||||
-
|
-
|
||||||
I would like to change the assign partner on opportunity, so find nearest partner assign to this opportunity.
|
I assign nearest partner to opportunity.
|
||||||
-
|
-
|
||||||
!python {model: crm.lead}: |
|
!python {model: crm.lead}: |
|
||||||
res = self.onchange_assign_id(cr, uid, [ref('crm.crm_case_abcfuelcounits0')], ref('base.res_partner_ericdubois0'), context)
|
self.assign_partner(cr, uid, [ref('crm.crm_case_abcfuelcounits0')], context=context)
|
||||||
assert res['value']['user_id'] == ref('base.user_demo'), "User not correct"
|
|
||||||
self.assign_partner(cr, uid, [ref('crm.crm_case_abcfuelcounits0')], context)
|
|
||||||
-
|
-
|
||||||
In order to assigned partner to opportunity, so i test latitude and longitude of partner of opportunity
|
I check assigned partner of opportunity who is nearest Geo Lattitude and Longitude of opportunity.
|
||||||
and opportuniy assign to assigned partner.
|
|
||||||
-
|
-
|
||||||
!python {model: crm.lead}: |
|
!python {model: crm.lead}: |
|
||||||
lead = self.browse(cr, uid, [ref('crm.crm_case_abcfuelcounits0')])[0]
|
lead = self.browse(cr, uid, ref('crm.crm_case_abcfuelcounits0'))
|
||||||
|
assert lead.partner_assigned_id.id == ref('base.res_partner_ericdubois0') , "Opportuniy is not assigned nearest partner"
|
||||||
assert lead.partner_latitude == 50.8495239 , "Lattitude is wrong"
|
assert lead.partner_latitude == 50.8495239 , "Lattitude is wrong"
|
||||||
assert lead.partner_longitude == 4.3667002 , "Longitude is wrong"
|
assert lead.partner_longitude == 4.3667002 , "Longitude is wrong"
|
||||||
assert lead.partner_assigned_id.id == ref('base.res_partner_ericdubois0') , "Opportuniy not assign partner"
|
|
||||||
-
|
-
|
||||||
Oppportuniry forword to its nearest partner, so first i create record of forword mail
|
I forward this opportunity to its nearest partner.
|
||||||
-
|
|
||||||
!record {model: crm.lead.forward.to.partner, id: crm_lead_forward_to_partner_rec}:
|
|
||||||
send_to: email
|
|
||||||
email_from: 'admin@openerp.com'
|
|
||||||
email_to: 'admin@tinyerp.com'
|
|
||||||
subject: 'Openerp lead forward'
|
|
||||||
history: latest
|
|
||||||
-
|
|
||||||
I forword this opportunity to its nearest partner.
|
|
||||||
-
|
-
|
||||||
!python {model: crm.lead.forward.to.partner}: |
|
!python {model: crm.lead.forward.to.partner}: |
|
||||||
from tools import config
|
context.update({'active_model': 'crm.lead', 'active_id': ref('crm.crm_case_abcfuelcounits0'), 'active_ids': [ref('crm.crm_case_abcfuelcounits0')]})
|
||||||
host = config.get('smtp_user', '127.0.0.1')
|
forward_id = self.create(cr, uid, {'send_to': 'partner'}, context=context)
|
||||||
assert config.get(host, True), 'SMTP not configured !'
|
|
||||||
try:
|
try:
|
||||||
self.action_forward(cr, uid, ref("crm_lead_forward_to_partner_rec"), context={'active_id': ref('crm.crm_case_abcfuelcounits0'),
|
self.action_forward(cr, uid, ref("crm_lead_forward_to_partner_rec"), context=context)
|
||||||
'active_ids': [ref('crm.crm_case_abcfuelcounits0')], 'active_model': 'crm.lead'})
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -1,18 +0,0 @@
|
||||||
-
|
|
||||||
For onchange on partner , i assign an email address to Administrator user.
|
|
||||||
-
|
|
||||||
!record {model: res.users, id: base.user_root}:
|
|
||||||
user_email: admin@openerp.com
|
|
||||||
|
|
||||||
-
|
|
||||||
I check onchange on email, partner, history and test the data accordingly change.
|
|
||||||
-
|
|
||||||
!python {model: crm.lead.forward.to.partner}: |
|
|
||||||
context.update({'history': 'latest', 'active_id': ref('crm.crm_case_abcfuelcounits0')})
|
|
||||||
email = self.on_change_email(cr, uid, [ref('crm.crm_case_abcfuelcounits0')], ref('base.user_root'))
|
|
||||||
assert email['value']['email_to'] == "Administrator <admin@openerp.com>", "Email is not correct"
|
|
||||||
partner = self.on_change_partner(cr, uid, [ref('crm.crm_case_abcfuelcounits0')], ref('base.res_partner_desertic_hispafuentes'))
|
|
||||||
assert partner['value']['address_id'] == ref('base.res_partner_desertic_hispafuentes'), "Address invalid"
|
|
||||||
assert partner['value']['email_to'] == 'info@axelor.com', "Email id incorrect"
|
|
||||||
history = self.on_change_history(cr, uid, [ref('crm.crm_case_abcfuelcounits0')], context.get('history'), context)
|
|
||||||
assert history, "History is blank"
|
|
|
@ -20,4 +20,3 @@
|
||||||
##############################################################################
|
##############################################################################
|
||||||
|
|
||||||
import crm_forward_to_partner
|
import crm_forward_to_partner
|
||||||
import crm_merge_opportunity
|
|
||||||
|
|
|
@ -24,6 +24,7 @@ import time
|
||||||
import re
|
import re
|
||||||
from osv import osv, fields
|
from osv import osv, fields
|
||||||
from tools.translate import _
|
from tools.translate import _
|
||||||
|
from mail.mail_message import to_email
|
||||||
|
|
||||||
class crm_lead_forward_to_partner(osv.osv_memory):
|
class crm_lead_forward_to_partner(osv.osv_memory):
|
||||||
"""Forwards lead history"""
|
"""Forwards lead history"""
|
||||||
|
@ -46,48 +47,8 @@ class crm_lead_forward_to_partner(osv.osv_memory):
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
def get_whole_history(self, cr, uid, ids, context=None):
|
|
||||||
"""This function gets whole communication history and returns as top posting style
|
|
||||||
@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 history IDs
|
|
||||||
@param context: A standard dictionary for contextual values
|
|
||||||
"""
|
|
||||||
whole = []
|
|
||||||
for hist_id in ids:
|
|
||||||
whole.append(self.get_latest_history(cr, uid, hist_id, context=context))
|
|
||||||
whole = '\n\n'.join(whole)
|
|
||||||
return whole or ''
|
|
||||||
|
|
||||||
def get_latest_history(self, cr, uid, hist_id, context=None):
|
|
||||||
"""This function gets latest communication and returns as top posting style
|
|
||||||
@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 hist_id: Id of latest history
|
|
||||||
@param context: A standard dictionary for contextual values
|
|
||||||
"""
|
|
||||||
log_pool = self.pool.get('mail.message')
|
|
||||||
hist = log_pool.browse(cr, uid, hist_id, context=context)
|
|
||||||
header = '-------- Original Message --------'
|
|
||||||
sender = 'From: %s' %(hist.email_from or '')
|
|
||||||
to = 'To: %s' % (hist.email_to or '')
|
|
||||||
sentdate = 'Date: %s' % (hist.date or '')
|
|
||||||
desc = '\n%s'%(hist.body_text)
|
|
||||||
original = [header, sender, to, sentdate, desc]
|
|
||||||
original = '\n'.join(original)
|
|
||||||
return original
|
|
||||||
|
|
||||||
def on_change_email(self, cr, uid, ids, user):
|
def on_change_email(self, cr, uid, ids, user):
|
||||||
"""This function fills email information based on user selected
|
|
||||||
@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 Mail’s IDs
|
|
||||||
@param user: Changed User id
|
|
||||||
@param partner: Changed Partner id
|
|
||||||
"""
|
|
||||||
if not user:
|
if not user:
|
||||||
return {'value': {'email_to': False}}
|
return {'value': {'email_to': False}}
|
||||||
email = self.pool.get('res.users')._get_email_from(cr, uid, [user])[user]
|
email = self.pool.get('res.users')._get_email_from(cr, uid, [user])[user]
|
||||||
|
@ -98,54 +59,19 @@ class crm_lead_forward_to_partner(osv.osv_memory):
|
||||||
* info: Forward the case information
|
* info: Forward the case information
|
||||||
* whole: Send the whole history
|
* whole: Send the whole history
|
||||||
* latest: Send the latest histoy
|
* latest: Send the latest histoy
|
||||||
@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 history IDs
|
|
||||||
@param context: A standard dictionary for contextual values
|
|
||||||
"""
|
"""
|
||||||
#TODO: ids and context are not comming
|
#TODO: ids and context are not comming
|
||||||
res = False
|
res = {}
|
||||||
res_id = context.get('active_id')
|
res_id = context.get('active_id')
|
||||||
msg_val = self._get_case_history(cr, uid, history_type, res_id, context=context)
|
model = context.get('active_model')
|
||||||
|
body_text = self._get_body_text(cr, uid, model, res_id, history_type, context=context)
|
||||||
|
context['mail.compose.message.body'] = history_type
|
||||||
if msg_val:
|
if msg_val:
|
||||||
res = {'value': {'body_text' : '\n\n' + msg_val}}
|
res = {'value': {'body_text' : body_text}}
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def _get_case_history(self, cr, uid, history_type, res_id, context=None):
|
|
||||||
if not res_id:
|
|
||||||
return
|
|
||||||
|
|
||||||
msg_val = ''
|
|
||||||
case_info = self.get_lead_details(cr, uid, res_id, context=context)
|
|
||||||
model_pool = self.pool.get('crm.lead')
|
|
||||||
|
|
||||||
if history_type == 'info':
|
|
||||||
msg_val = case_info
|
|
||||||
|
|
||||||
elif history_type == 'whole':
|
|
||||||
log_ids = model_pool.browse(cr, uid, res_id, context=context).message_ids
|
|
||||||
log_ids = map(lambda x: x.id, filter(lambda x: x.email_from, log_ids))
|
|
||||||
msg_val = case_info + '\n\n' + self.get_whole_history(cr, uid, log_ids, context=context)
|
|
||||||
|
|
||||||
elif history_type == 'latest':
|
|
||||||
log_ids = model_pool.browse(cr, uid, res_id, context=context).message_ids
|
|
||||||
log_ids = filter(lambda x: x.email_from and x.id, log_ids)
|
|
||||||
if not log_ids:
|
|
||||||
msg_val = case_info
|
|
||||||
else:
|
|
||||||
msg_val = case_info + '\n\n' + self.get_latest_history(cr, uid, log_ids[0].id, context=context)
|
|
||||||
|
|
||||||
return msg_val
|
|
||||||
|
|
||||||
def on_change_partner(self, cr, uid, ids, partner_id):
|
def on_change_partner(self, cr, uid, ids, partner_id):
|
||||||
"""This function fills address information based on partner/user selected
|
"""This function fills address information based on partner/user selected
|
||||||
@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 Mail’s IDs
|
|
||||||
@param user: Changed User id
|
|
||||||
@param partner: Changed Partner id
|
|
||||||
"""
|
"""
|
||||||
if not partner_id:
|
if not partner_id:
|
||||||
return {'value' : {'email_to' : False, 'address_id': False}}
|
return {'value' : {'email_to' : False, 'address_id': False}}
|
||||||
|
@ -158,11 +84,11 @@ class crm_lead_forward_to_partner(osv.osv_memory):
|
||||||
partner = partner_obj.browse(cr, uid, [partner_id])
|
partner = partner_obj.browse(cr, uid, [partner_id])
|
||||||
user_id = partner and partner[0].user_id or False
|
user_id = partner and partner[0].user_id or False
|
||||||
email = user_id and user_id.user_email or ''
|
email = user_id and user_id.user_email or ''
|
||||||
data.update({'email_cc' : email})
|
data.update({'email_cc' : email, 'user_id': user_id and user_id.id or False})
|
||||||
return {
|
return {
|
||||||
'value' : data,
|
'value' : data,
|
||||||
'domain' : {'address_id' : partner_id and "[('partner_id', '=', partner_id)]" or "[]"}
|
'domain' : {'address_id' : partner_id and "[('partner_id', '=', partner_id)]" or "[]"}
|
||||||
}
|
}
|
||||||
|
|
||||||
def on_change_address(self, cr, uid, ids, address_id):
|
def on_change_address(self, cr, uid, ids, address_id):
|
||||||
email = ''
|
email = ''
|
||||||
|
@ -170,155 +96,126 @@ class crm_lead_forward_to_partner(osv.osv_memory):
|
||||||
email = self.pool.get('res.partner.address').browse(cr, uid, address_id).email
|
email = self.pool.get('res.partner.address').browse(cr, uid, address_id).email
|
||||||
return {'value': {'email_to' : email}}
|
return {'value': {'email_to' : email}}
|
||||||
|
|
||||||
def send_mail(self, cr, uid, ids, context=None):
|
|
||||||
if context is None:
|
|
||||||
context = {}
|
|
||||||
super(crm_lead_forward_to_partner, self).send_mail(cr, uid, ids, context=context)
|
|
||||||
self.action_forward(cr, uid, ids, context)
|
|
||||||
return {'type': 'ir.actions.act_window_close'}
|
|
||||||
|
|
||||||
def action_forward(self, cr, uid, ids, context=None):
|
def action_forward(self, cr, uid, ids, context=None):
|
||||||
"""
|
"""
|
||||||
Forward the lead to a partner
|
Forward the lead to a partner
|
||||||
"""
|
"""
|
||||||
if context is None:
|
if context is None:
|
||||||
context = {}
|
context = {}
|
||||||
|
res = {'type': 'ir.actions.act_window_close'}
|
||||||
|
model = context.get('active_model')
|
||||||
|
if model not in ('crm.lead'):
|
||||||
|
return res
|
||||||
|
|
||||||
this = self.browse(cr, uid, ids[0], context=context)
|
this = self.browse(cr, uid, ids[0], context=context)
|
||||||
case_pool = self.pool.get(context.get('active_model'))
|
lead = self.pool.get(model)
|
||||||
res_id = context and context.get('active_id', False) or False
|
lead_id = context and context.get('active_id', False) or False
|
||||||
case = case_pool.browse(cr, uid, res_id, context=context)
|
lead_ids = lead_id and [lead_id] or []
|
||||||
context.update({'mail': 'forward'})
|
mode = context.get('mail.compose.message.mode')
|
||||||
|
if mode == 'mass_mail':
|
||||||
to_write = {'date_assign': time.strftime('%Y-%m-%d')}
|
lead_ids = context and context.get('active_ids', []) or []
|
||||||
if (this.send_to == 'partner' and this.partner_id):
|
|
||||||
to_write['partner_assigned_id'] = this.partner_id.id
|
|
||||||
|
|
||||||
if this.send_to == 'user':
|
|
||||||
to_write.update({'user_id' : this.user_id.id})
|
|
||||||
email_re = r'([^ ,<@]+@[^> ,]+)'
|
|
||||||
email_cc = re.findall(email_re, case.email_cc or '')
|
|
||||||
new_cc = []
|
|
||||||
if case.email_cc:
|
|
||||||
new_cc.append(case.email_cc)
|
|
||||||
for to in this.email_to.split(','):
|
|
||||||
email_to = re.findall(email_re, to)
|
|
||||||
email_to = email_to and email_to[0] or ''
|
|
||||||
if email_to not in email_cc:
|
|
||||||
new_cc.append(to)
|
|
||||||
to_write.update({'email_cc' : ', '.join(new_cc) })
|
|
||||||
case_pool.write(cr, uid, case.id, to_write, context=context)
|
|
||||||
return {'type': 'ir.actions.act_window_close'}
|
|
||||||
|
|
||||||
def get_lead_details(self, cr, uid, lead_id, context=None):
|
|
||||||
body = []
|
|
||||||
lead_proxy = self.pool.get('crm.lead')
|
|
||||||
lead = lead_proxy.browse(cr, uid, lead_id, context=context)
|
|
||||||
if not lead.type or lead.type == 'lead' or not lead.partner_address_id:
|
|
||||||
field_names = [
|
|
||||||
'partner_name', 'title', 'function', 'street', 'street2',
|
|
||||||
'zip', 'city', 'country_id', 'state_id', 'email_from',
|
|
||||||
'phone', 'fax', 'mobile', 'categ_id', 'description',
|
|
||||||
]
|
|
||||||
|
|
||||||
for field_name in field_names:
|
|
||||||
field_definition = lead_proxy._columns[field_name]
|
|
||||||
value = None
|
|
||||||
|
|
||||||
if field_definition._type == 'selection':
|
|
||||||
if hasattr(field_definition.selection, '__call__'):
|
|
||||||
key = field_definition.selection(lead_proxy, cr, uid, context=context)
|
|
||||||
else:
|
|
||||||
key = field_definition.selection
|
|
||||||
value = dict(key).get(lead[field_name], lead[field_name])
|
|
||||||
elif field_definition._type == 'many2one':
|
|
||||||
if lead[field_name]:
|
|
||||||
value = lead[field_name].name_get()[0][1]
|
|
||||||
else:
|
|
||||||
value = lead[field_name]
|
|
||||||
|
|
||||||
body.append("%s: %s" % (field_definition.string, value or ''))
|
|
||||||
elif lead.type == 'opportunity':
|
|
||||||
pa = lead.partner_address_id
|
|
||||||
body += [
|
|
||||||
"Partner: %s" % (lead.partner_id and lead.partner_id.name_get()[0][1]),
|
|
||||||
"Contact: %s" % (pa.name or ''),
|
|
||||||
"Title: %s" % (pa.title or ''),
|
|
||||||
"Function: %s" % (pa.function or ''),
|
|
||||||
"Street: %s" % (pa.street or ''),
|
|
||||||
"Street2: %s" % (pa.street2 or ''),
|
|
||||||
"Zip: %s" % (pa.zip or ''),
|
|
||||||
"City: %s" % (pa.city or ''),
|
|
||||||
"Country: %s" % (pa.country_id and pa.country_id.name_get()[0][1] or ''),
|
|
||||||
"State: %s" % (pa.state_id and pa.state_id.name_get()[0][1] or ''),
|
|
||||||
"Email: %s" % (pa.email or ''),
|
|
||||||
"Phone: %s" % (pa.phone or ''),
|
|
||||||
"Fax: %s" % (pa.fax or ''),
|
|
||||||
"Mobile: %s" % (pa.mobile or ''),
|
|
||||||
"Lead Category: %s" % (lead.categ_id and lead.categ_id.name or ''),
|
|
||||||
"Details: %s" % (lead.description or ''),
|
|
||||||
]
|
|
||||||
return "\n".join(body + ['---'])
|
|
||||||
|
|
||||||
def default_get(self, cr, uid, fields, context=None):
|
|
||||||
"""
|
|
||||||
This function gets default values
|
|
||||||
"""
|
|
||||||
|
|
||||||
if context is None:
|
|
||||||
context = {}
|
|
||||||
|
|
||||||
defaults = super(crm_lead_forward_to_partner, self).default_get(cr, uid, fields, context=context)
|
|
||||||
active_id = context.get('active_id')
|
|
||||||
if not active_id:
|
|
||||||
return defaults
|
|
||||||
|
|
||||||
lead_proxy = self.pool.get('crm.lead')
|
|
||||||
partner_obj = self.pool.get('res.partner')
|
|
||||||
lead = lead_proxy.browse(cr, uid, active_id, context=context)
|
|
||||||
|
|
||||||
email_cc = ''
|
|
||||||
email = ''
|
|
||||||
if lead.partner_assigned_id:
|
|
||||||
partner = partner_obj.browse(cr, uid, [lead.partner_assigned_id.id])
|
|
||||||
user_id = partner and partner[0].user_id or False
|
|
||||||
email_cc = user_id and user_id.user_email or ''
|
|
||||||
|
|
||||||
addr = partner_obj.address_get(cr, uid, [partner[0].id], ['contact'])
|
|
||||||
email = self.pool.get('res.partner.address').browse(cr, uid, addr['contact']).email
|
|
||||||
|
|
||||||
body = self._get_case_history(cr, uid, defaults.get('history', 'latest'), lead.id, context=context)
|
|
||||||
defaults.update({
|
|
||||||
'subject' : '%s: %s - %s' % (_('Fwd'), 'Openerp lead forward', lead.name),
|
|
||||||
'body_text' : body,
|
|
||||||
'email_cc' : email_cc,
|
|
||||||
'email_to' : email or 'dummy@dummy.ly'
|
|
||||||
})
|
|
||||||
return defaults
|
|
||||||
|
|
||||||
class crm_lead_mass_forward_to_partner(osv.osv_memory):
|
|
||||||
_name = 'crm.lead.mass.forward.to.partner'
|
|
||||||
_inherit = 'crm.lead.forward.to.partner'
|
|
||||||
|
|
||||||
def action_mass_forward(self, cr, uid, ids, context=None):
|
|
||||||
if not context:
|
|
||||||
context = {}
|
|
||||||
|
|
||||||
active_ids = context.get('active_ids')
|
|
||||||
case_obj = self.pool.get('crm.lead')
|
|
||||||
for case in case_obj.browse(cr, uid, active_ids, context=context):
|
|
||||||
if not case.partner_assigned_id:
|
|
||||||
case_obj.assign_partner(cr,uid, [case.id], context=context)
|
|
||||||
case = case_obj.browse(cr, uid, case.id, context=context)
|
|
||||||
|
|
||||||
if not case.partner_assigned_id:
|
|
||||||
continue
|
|
||||||
|
|
||||||
context.update({'active_id' : case.id})
|
|
||||||
value = self.default_get(cr, uid, ['body_text', 'email_to', 'email_cc', 'subject', 'history'], context=context)
|
value = self.default_get(cr, uid, ['body_text', 'email_to', 'email_cc', 'subject', 'history'], context=context)
|
||||||
self.write(cr, uid, ids, value, context=context)
|
self.write(cr, uid, ids, value, context=context)
|
||||||
self.action_forward(cr,uid, ids, context=context)
|
context['mail.compose.message.mode'] = mode
|
||||||
|
|
||||||
return {'type': 'ir.actions.act_window_close'}
|
self.send_mail(cr, uid, ids, context=context)
|
||||||
|
for case in lead.browse(cr, uid, lead_ids, context=context):
|
||||||
|
if (this.send_to == 'partner' and this.partner_id):
|
||||||
|
lead.assign_partner(cr, uid, [case.id], this.partner_id.id, context=context)
|
||||||
|
|
||||||
|
if this.send_to == 'user':
|
||||||
|
lead.assign_salesman(cr, uid, [case.id], [this.user_id.id], context=context)
|
||||||
|
|
||||||
|
email_cc = to_email(case.email_cc)
|
||||||
|
email_cc = email_to and email_cc[0] or ''
|
||||||
|
new_cc = []
|
||||||
|
if email_cc:
|
||||||
|
new_cc.append(email_cc)
|
||||||
|
for to in this.email_to.split(','):
|
||||||
|
email_to = to_email(to)
|
||||||
|
email_to = email_to and email_to[0] or ''
|
||||||
|
if email_to not in new_cc:
|
||||||
|
new_cc.append(to)
|
||||||
|
update_vals = {'email_cc' : ', '.join(new_cc) }
|
||||||
|
lead.write(cr, uid, case.id, update_vals, context=context)
|
||||||
|
return res
|
||||||
|
|
||||||
|
def _get_info_body_text(self, cr, uid, lead, context=None):
|
||||||
|
field_names = []
|
||||||
|
proxy = self.pool.get(lead._name)
|
||||||
|
if lead.type == 'opportunity':
|
||||||
|
field_names += ['partner_id']
|
||||||
|
field_names += [
|
||||||
|
'partner_name' , 'title', 'function', 'street', 'street2',
|
||||||
|
'zip', 'city', 'country_id', 'state_id', 'email_from',
|
||||||
|
'phone', 'fax', 'mobile', 'categ_id', 'description',
|
||||||
|
]
|
||||||
|
return proxy._mail_body_text(cr, uid, lead, field_names, context=context)
|
||||||
|
|
||||||
|
def _get_message_body_text(self, cr, uid, lead, mode='whole', context=None):
|
||||||
|
"""This function gets whole communication history and returns as top posting style
|
||||||
|
"""
|
||||||
|
mail_message = self.pool.get('mail.message')
|
||||||
|
message_ids = []
|
||||||
|
body = self._get_info_body_text(cr, uid, lead, context=context)
|
||||||
|
if mode in ('whole', 'latest'):
|
||||||
|
message_ids = lead.message_ids
|
||||||
|
message_ids = map(lambda x: x.id, filter(lambda x: x.email_from, message_ids))
|
||||||
|
if mode == 'latest' and len(message_ids):
|
||||||
|
message_ids = [message_ids[0]]
|
||||||
|
for message in mail_message.browse(cr, uid, message_ids, context=context):
|
||||||
|
header = '-------- Original Message --------'
|
||||||
|
sender = 'From: %s' %(message.email_from or '')
|
||||||
|
to = 'To: %s' % (message.email_to or '')
|
||||||
|
sentdate = 'Date: %s' % (message.date or '')
|
||||||
|
desc = '\n%s'%(message.body_text)
|
||||||
|
original = [header, sender, to, sentdate, desc]
|
||||||
|
original = '\n'.join(original)
|
||||||
|
body += original
|
||||||
|
return body or ''
|
||||||
|
|
||||||
|
def get_value(self, cr, uid, model, res_id, context=None):
|
||||||
|
if context is None:
|
||||||
|
context = {}
|
||||||
|
res = super(crm_lead_forward_to_partner, self).get_value(cr, uid, model, res_id, context=context)
|
||||||
|
if model not in ("crm.lead"):
|
||||||
|
return res
|
||||||
|
proxy = self.pool.get(model)
|
||||||
|
partner = self.pool.get('res.partner')
|
||||||
|
lead = proxy.browse(cr, uid, res_id, context=context)
|
||||||
|
mode = context.get('mail.compose.message.mode')
|
||||||
|
if mode == "forward":
|
||||||
|
body_type = context.get('mail.compose.message.body')
|
||||||
|
email_cc = res.get('email_cc', "")
|
||||||
|
email = res.get('email_to', "")
|
||||||
|
subject = '%s: %s - %s' % (_('Fwd'), 'Lead forward', lead.name)
|
||||||
|
body = self._get_message_body_text(cr, uid, lead, body_type, context=context)
|
||||||
|
partner_assigned_id = lead.partner_assigned_id and lead.partner_assigned_id.id or False
|
||||||
|
user_id = False
|
||||||
|
if not partner_assigned_id:
|
||||||
|
partner_assigned_id = lead.search_geo_partner(cr, uid, [lead.id], context=None).get(lead.id, False)
|
||||||
|
if partner_assigned_id:
|
||||||
|
assigned_partner = partner.browse(cr, uid, partner_assigned_id, context=context)
|
||||||
|
user_id = assigned_partner.user_id and assigned_partner.user_id.id or False
|
||||||
|
email_cc = assigned_partner.user_id and assigned_partner.user_id.user_email or ''
|
||||||
|
email = assigned_partner.email
|
||||||
|
|
||||||
|
|
||||||
|
res.update({
|
||||||
|
'subject' : subject,
|
||||||
|
'body_text' : body,
|
||||||
|
'email_cc' : email_cc,
|
||||||
|
'email_to' : email,
|
||||||
|
'partner_assigned_id': partner_assigned_id,
|
||||||
|
'user_id': user_id,
|
||||||
|
})
|
||||||
|
return res
|
||||||
|
|
||||||
|
|
||||||
|
def default_get(self, cr, uid, fields, context=None):
|
||||||
|
if context is None:
|
||||||
|
context = {}
|
||||||
|
context['mail.compose.message.mode'] = 'forward'
|
||||||
|
context['mail.compose.message.body'] = 'info'
|
||||||
|
return super(crm_lead_forward_to_partner, self).default_get(cr, uid, fields, context=context)
|
||||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||||
|
|
|
@ -45,7 +45,7 @@
|
||||||
<group col="4" colspan="4">
|
<group col="4" colspan="4">
|
||||||
<label string="" colspan="1"/>
|
<label string="" colspan="1"/>
|
||||||
<button icon="gtk-close" special="cancel" string="Close"/>
|
<button icon="gtk-close" special="cancel" string="Close"/>
|
||||||
<button icon="gtk-ok" name="send_mail" string="Send" type="object"/>
|
<button name="action_forward" string="Send" type="object" icon="gtk-go-forward"/>
|
||||||
</group>
|
</group>
|
||||||
</form>
|
</form>
|
||||||
</field>
|
</field>
|
||||||
|
@ -61,56 +61,14 @@
|
||||||
</record>
|
</record>
|
||||||
|
|
||||||
|
|
||||||
<record model="ir.ui.view" id="crm_forward_mass_mail_view">
|
|
||||||
<field name="name">crm.new.mass.forward.mail.form</field>
|
|
||||||
<field name="model">crm.lead.mass.forward.to.partner</field>
|
|
||||||
<field name="type">form</field>
|
|
||||||
<field name="arch" type="xml">
|
|
||||||
<form string="Send Mail" col="4">
|
|
||||||
<group colspan="4" col="2">
|
|
||||||
<separator string="Forward to Partner" colspan="4" />
|
|
||||||
|
|
||||||
<field name="history" colspan="2" on_change="on_change_history(history, context)" invisible="1"/>
|
|
||||||
<field name="email_from"/>
|
|
||||||
<field name="reply_to"/>
|
|
||||||
<field name="email_to" invisible="1" />
|
|
||||||
<field name="email_cc" invisible="1" />
|
|
||||||
<field name="subject" invisible="1" />
|
|
||||||
<field name="html"/>
|
|
||||||
</group>
|
|
||||||
<notebook colspan="6" >
|
|
||||||
<page string="Message" >
|
|
||||||
<field name="body_text" nolabel="1" colspan="4" default_focus="1" readonly="1"/>
|
|
||||||
</page>
|
|
||||||
<page string="Attachments" >
|
|
||||||
<field name="attachment_ids" colspan="4" nolabel="1">
|
|
||||||
<form string="Attachment">
|
|
||||||
<field name="binary" filename="name" />
|
|
||||||
<field name="name" />
|
|
||||||
</form>
|
|
||||||
<tree string="Attachments">
|
|
||||||
<field name="name" />
|
|
||||||
</tree>
|
|
||||||
</field>
|
|
||||||
</page>
|
|
||||||
</notebook>
|
|
||||||
<separator string="" colspan="6"/>
|
|
||||||
<group colspan="6" col="4" >
|
|
||||||
<field name="state" />
|
|
||||||
<button string="_Cancel" icon="gtk-cancel" special="cancel" />
|
|
||||||
<button name="action_mass_forward" type="object" string="_Mass forward" icon="gtk-go-forward" />
|
|
||||||
</group>
|
|
||||||
</form>
|
|
||||||
</field>
|
|
||||||
</record>
|
|
||||||
|
|
||||||
<act_window id="action_crm_send_mass_forward"
|
<act_window id="action_crm_send_mass_forward"
|
||||||
multi="True"
|
multi="True"
|
||||||
key2="client_action_multi" name="Mass forward to partner"
|
key2="client_action_multi" name="Mass forward to partner"
|
||||||
res_model="crm.lead.mass.forward.to.partner" src_model="crm.lead"
|
res_model="crm.lead.forward.to.partner" src_model="crm.lead"
|
||||||
view_mode="form" target="new" view_type="form"
|
view_mode="form" target="new" view_type="form"
|
||||||
context="{'mass_forward' : True}"
|
context="{'mail.compose.message.mode' : 'mass_mail'}"
|
||||||
view_id="crm_forward_mass_mail_view"
|
view_id="crm_lead_forward_to_partner_form"
|
||||||
/>
|
/>
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
# -*- coding: utf-8 -*-
|
|
||||||
##############################################################################
|
|
||||||
#
|
|
||||||
# OpenERP, Open Source Management Solution
|
|
||||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
|
||||||
#
|
|
||||||
# This program is free software: you can redistribute it and/or modify
|
|
||||||
# it under the terms of the GNU Affero General Public License as
|
|
||||||
# published by the Free Software Foundation, either version 3 of the
|
|
||||||
# License, or (at your option) any later version.
|
|
||||||
#
|
|
||||||
# This program is distributed in the hope that it will be useful,
|
|
||||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
# GNU Affero General Public License for more details.
|
|
||||||
#
|
|
||||||
# You should have received a copy of the GNU Affero General Public License
|
|
||||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
#
|
|
||||||
##############################################################################
|
|
||||||
from osv import osv, fields
|
|
||||||
from tools.translate import _
|
|
||||||
|
|
||||||
|
|
||||||
class crm_merge_opportunity_assign_partner(osv.osv_memory):
|
|
||||||
"""Merge two Opportunities"""
|
|
||||||
|
|
||||||
_inherit = 'crm.merge.opportunity'
|
|
||||||
|
|
||||||
def _update_data(self, op_ids, oldest_opp):
|
|
||||||
data = super(crm_merge_opportunity_assign_partner, self)._update_data(op_ids, oldest_opp)
|
|
||||||
|
|
||||||
new_data = {
|
|
||||||
'partner_latitude': self._get_first_not_null('partner_latitude', op_ids, oldest_opp),
|
|
||||||
'partner_longitude': self._get_first_not_null('partner_longitude', op_ids, oldest_opp),
|
|
||||||
'partner_assigned_id': self._get_first_not_null_id('partner_assigned_id', op_ids, oldest_opp),
|
|
||||||
'date_assign' : self._get_first_not_null('date_assign', op_ids, oldest_opp),
|
|
||||||
}
|
|
||||||
data.update(new_data)
|
|
||||||
return data
|
|
||||||
|
|
||||||
crm_merge_opportunity_assign_partner()
|
|
Loading…
Reference in New Issue