[MERGE] improve_crm_leads_flux by abo
bzr revid: al@openerp.com-20121208144139-o9zr10b7qbij48d5
This commit is contained in:
@@ -67,15 +67,11 @@ Dashboard for CRM will include:
|
||||
'security/crm_security.xml',
|
||||
'security/ir.model.access.csv',
|
||||
|
||||
'wizard/crm_lead_to_partner_view.xml',
|
||||
'wizard/crm_lead_to_opportunity_view.xml',
|
||||
|
||||
'wizard/crm_phonecall_to_phonecall_view.xml',
|
||||
'wizard/crm_phonecall_to_partner_view.xml',
|
||||
'wizard/crm_phonecall_to_opportunity_view.xml',
|
||||
|
||||
'wizard/crm_opportunity_to_phonecall_view.xml',
|
||||
'wizard/crm_partner_to_opportunity_view.xml',
|
||||
|
||||
'wizard/crm_merge_opportunities_view.xml',
|
||||
|
||||
@@ -109,6 +105,7 @@ Dashboard for CRM will include:
|
||||
'test': [
|
||||
'test/process/communication_with_customer.yml',
|
||||
'test/process/lead2opportunity2win.yml',
|
||||
'test/process/lead2opportunity_assign_salesmen.yml',
|
||||
'test/process/merge_opportunity.yml',
|
||||
'test/process/cancel_lead.yml',
|
||||
'test/process/action_rule.yml',
|
||||
|
||||
@@ -1,7 +1,13 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data noupdate="1">
|
||||
<!-- email server actions -->
|
||||
<!-- demo automated actions add messge on new lead after 5 days -->
|
||||
<record id="filter_draft_lead" model="ir.filters">
|
||||
<field name="name">Draft Leads</field>
|
||||
<field name="model_id">crm.lead</field>
|
||||
<field name="domain">[('state','=','draft')]</field>
|
||||
<field name="user_id" eval="False"/>
|
||||
</record>
|
||||
<record id="action_email_reminder_lead" model="ir.actions.server">
|
||||
<field name="name">Reminder to User</field>
|
||||
<field name="model_id" ref="model_crm_lead"/>
|
||||
@@ -10,46 +16,12 @@
|
||||
<field name="state">email</field>
|
||||
<field name="email">object.user_id.email</field>
|
||||
<field name="subject">Reminder on Lead: [[object.id ]] [[object.partner_id and 'of ' +object.partner_id.name or '']]</field>
|
||||
<field name="message">Hello [[object.user_id.name]],
|
||||
can you check following lead, it's not open since 5 days ?
|
||||
|
||||
Lead: [[object.id ]]
|
||||
Description:
|
||||
|
||||
[[object.description]]
|
||||
|
||||
Thanks,
|
||||
<field name="message">Warning unprocessed incoming lead is more than 5 day old.
|
||||
Name: [[object.name ]]
|
||||
ID: [[object.id ]]
|
||||
Description: [[object.description]]
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="action_email_reminder_customer_lead" model="ir.actions.server">
|
||||
<field name="name">Reminder to Customer</field>
|
||||
<field name="model_id" ref="model_crm_lead"/>
|
||||
<field name="condition">True</field>
|
||||
<field name="type">ir.actions.server</field>
|
||||
<field name="state">email</field>
|
||||
<field name="email">object.email_from</field>
|
||||
<field name="subject">Reminder on Lead: [[object.id ]]</field>
|
||||
<field name="message">Hello [[object.partner_id and object.partner_id.name or '']],
|
||||
your following lead is not open since 5 days.
|
||||
|
||||
Lead: [[object.id ]]
|
||||
Description:
|
||||
|
||||
[[object.description]]
|
||||
|
||||
Thanks,
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record id="filter_draft_lead" model="ir.filters">
|
||||
<field name="name">Draft Leads</field>
|
||||
<field name="model_id">crm.lead</field>
|
||||
<field name="domain">[('state','=','draft')]</field>
|
||||
<field name="user_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
<!-- automated actions -->
|
||||
<record id="rule_set_reminder_lead" model="base.action.rule">
|
||||
<field name="name">Set Auto Reminder on leads which are not open since 5 days.</field>
|
||||
<field name="model_id" ref="model_crm_lead"/>
|
||||
@@ -58,16 +30,16 @@ Thanks,
|
||||
<field name="trg_date_type">create</field>
|
||||
<field name="trg_date_range">5</field>
|
||||
<field name="trg_date_range_type">day</field>
|
||||
<field name="server_action_ids" eval="[(6,0,[ref('action_email_reminder_customer_lead'), ref('action_email_reminder_lead')])]"/>
|
||||
<field name="server_action_ids" eval="[(6,0,[ref('action_email_reminder_lead')])]"/>
|
||||
</record>
|
||||
|
||||
<!-- demo automated actions add a followers on urgent USA leads -->
|
||||
<record id="filter_usa_lead" model="ir.filters">
|
||||
<field name="name">Leads from USA</field>
|
||||
<field name="model_id">crm.lead</field>
|
||||
<field name="domain">[('country_id','=','United States')]</field>
|
||||
<field name="user_id" eval="False"/>
|
||||
</record>
|
||||
|
||||
<record id="rule_set_followers_lead" model="base.action.rule">
|
||||
<field name="name">Set Auto Followers on leads which are urgent and come from USA.</field>
|
||||
<field name="model_id" ref="model_crm_lead"/>
|
||||
|
||||
+204
-84
@@ -30,6 +30,36 @@ from tools import html2plaintext
|
||||
|
||||
from base.res.res_partner import format_address
|
||||
|
||||
CRM_LEAD_FIELDS_TO_MERGE = ['name',
|
||||
'partner_id',
|
||||
'channel_id',
|
||||
'company_id',
|
||||
'country_id',
|
||||
'section_id',
|
||||
'stage_id',
|
||||
'state_id',
|
||||
'type_id',
|
||||
'user_id',
|
||||
'title',
|
||||
'city',
|
||||
'contact_name',
|
||||
'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']
|
||||
CRM_LEAD_PENDING_STATES = (
|
||||
crm.AVAILABLE_STATES[2][0], # Cancelled
|
||||
crm.AVAILABLE_STATES[3][0], # Done
|
||||
@@ -120,11 +150,7 @@ class crm_lead(base_stage, format_address, osv.osv):
|
||||
|
||||
def _compute_day(self, cr, uid, ids, fields, args, context=None):
|
||||
"""
|
||||
@param cr: the current row, from the database cursor,
|
||||
@param uid: the current user’s ID for security checks,
|
||||
@param ids: List of Openday’s IDs
|
||||
@return: difference between current date and log date
|
||||
@param context: A standard dictionary for contextual values
|
||||
:return dict: difference between current date and log date
|
||||
"""
|
||||
cal_obj = self.pool.get('resource.calendar')
|
||||
res_obj = self.pool.get('resource.resource')
|
||||
@@ -413,15 +439,46 @@ class crm_lead(base_stage, format_address, osv.osv):
|
||||
"""
|
||||
return self.set_priority(cr, uid, ids, '3')
|
||||
|
||||
def _merge_get_result_type(self, cr, uid, opps, context=None):
|
||||
"""
|
||||
Define the type of the result of the merge. If at least one of the
|
||||
element to merge is an opp, the resulting new element will be an opp.
|
||||
Otherwise it will be a lead.
|
||||
|
||||
We'll directly use a list of browse records instead of a list of ids
|
||||
for performances' sake: it will spare a second browse of the
|
||||
leads/opps.
|
||||
|
||||
:param list opps: list of browse records containing the leads/opps to process
|
||||
:return string type: the type of the final element
|
||||
"""
|
||||
for opp in opps:
|
||||
if (opp.type == 'opportunity'):
|
||||
return 'opportunity'
|
||||
|
||||
return 'lead'
|
||||
|
||||
def _merge_data(self, cr, uid, ids, oldest, fields, context=None):
|
||||
# prepare opportunity data into dictionary for merging
|
||||
"""
|
||||
Prepare lead/opp data into a dictionary for merging. Different types
|
||||
of fields are processed in different ways:
|
||||
- text: all the values are concatenated
|
||||
- m2m and o2m: those fields aren't processed
|
||||
- m2o: the first not null value prevails (the other are dropped)
|
||||
- any other type of field: same as m2o
|
||||
|
||||
:param list ids: list of ids of the leads to process
|
||||
:param list fields: list of leads' fields to process
|
||||
:return dict data: contains the merged values
|
||||
"""
|
||||
opportunities = self.browse(cr, uid, ids, context=context)
|
||||
|
||||
def _get_first_not_null(attr):
|
||||
if hasattr(oldest, attr):
|
||||
return getattr(oldest, attr)
|
||||
for opportunity in opportunities:
|
||||
if hasattr(opportunity, attr):
|
||||
return getattr(opportunity, attr)
|
||||
for opp in opportunities:
|
||||
if hasattr(opp, attr):
|
||||
return getattr(opp, attr)
|
||||
return False
|
||||
|
||||
def _get_first_not_null_id(attr):
|
||||
@@ -429,8 +486,9 @@ 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(opportunity, attr) or '' for opportunity in opportunities if hasattr(opportunity, attr)]))
|
||||
return ', '.join(filter(lambda x: x, [getattr(opp, attr) or '' for opp in opportunities if hasattr(opp, attr)]))
|
||||
|
||||
# Process the fields' values
|
||||
data = {}
|
||||
for field_name in fields:
|
||||
field_info = self._all_columns.get(field_name)
|
||||
@@ -445,24 +503,35 @@ class crm_lead(base_stage, format_address, osv.osv):
|
||||
data[field_name] = _concat_all(field_name) #not lost
|
||||
else:
|
||||
data[field_name] = _get_first_not_null(field_name) #not lost
|
||||
|
||||
# Define the resulting type ('lead' or 'opportunity')
|
||||
data['type'] = self._merge_get_result_type(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 = {}
|
||||
#TOCHECK: where pass 'convert' in context ?
|
||||
if context.get('convert'):
|
||||
ids = list(set(ids) - set(context.get('lead_ids', False)) )
|
||||
|
||||
#search opportunities order by create date
|
||||
opportunity_ids = self.search(cr, uid, [('id', 'in', ids)], order='create_date' , context=context)
|
||||
oldest_id = opportunity_ids[0]
|
||||
return self.browse(cr, uid, oldest_id, context=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]
|
||||
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:
|
||||
body.append("%s\n" % (title))
|
||||
|
||||
for field_name in fields:
|
||||
field_info = self._all_columns.get(field_name)
|
||||
if field_info is None:
|
||||
@@ -483,20 +552,25 @@ class crm_lead(base_stage, format_address, osv.osv):
|
||||
value = lead[field_name]
|
||||
|
||||
body.append("%s: %s" % (field.string, value or ''))
|
||||
|
||||
return "\n".join(body + ['---'])
|
||||
|
||||
def _merge_notification(self, cr, uid, opportunity_id, opportunities, context=None):
|
||||
def _merge_notify(self, cr, uid, opportunity_id, opportunities, context=None):
|
||||
"""
|
||||
Create a message gathering merged leads/opps information.
|
||||
"""
|
||||
#TOFIX: mail template should be used instead of fix body, subject text
|
||||
details = []
|
||||
merge_message = _('Merged opportunities')
|
||||
result_type = self._merge_get_result_type(cr, uid, opportunities, context)
|
||||
if result_type == 'lead':
|
||||
merge_message = _('Merged leads')
|
||||
else:
|
||||
merge_message = _('Merged opportunities')
|
||||
subject = [merge_message]
|
||||
fields = ['name', 'partner_id', 'stage_id', 'section_id', 'user_id', 'categ_ids', '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:
|
||||
subject.append(opportunity.name)
|
||||
title = "%s : %s" % (merge_message, opportunity.name)
|
||||
details.append(self._mail_body(cr, uid, opportunity, fields, title=title, context=context))
|
||||
details.append(self._mail_body(cr, uid, opportunity, CRM_LEAD_FIELDS_TO_MERGE, title=title, context=context))
|
||||
|
||||
# Chatter message's subject
|
||||
subject = subject[0] + ": " + ", ".join(subject[1:])
|
||||
@@ -540,42 +614,41 @@ class crm_lead(base_stage, format_address, osv.osv):
|
||||
|
||||
def merge_opportunity(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
To merge opportunities
|
||||
:param ids: list of opportunities ids to merge
|
||||
Different cases of merge:
|
||||
- merge leads together = 1 new lead
|
||||
- merge at least 1 opp with anything else (lead or opp) = 1 new opp
|
||||
|
||||
:param list ids: leads/opportunities ids to merge
|
||||
:return int id: id of the resulting lead/opp
|
||||
"""
|
||||
if context is None: context = {}
|
||||
|
||||
#TOCHECK: where pass lead_ids in context?
|
||||
lead_ids = context and context.get('lead_ids', []) or []
|
||||
|
||||
if len(ids) <= 1:
|
||||
raise osv.except_osv(_('Warning!'),_('Please select more than one opportunity from the list view.'))
|
||||
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))
|
||||
oldest = self._merge_find_oldest(cr, uid, ids, context=context)
|
||||
if ctx_opportunities :
|
||||
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:]
|
||||
|
||||
fields = ['partner_id', 'title', 'name', 'categ_ids', 'channel_id', 'city', 'company_id', 'contact_name', 'country_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)
|
||||
merged_data = self._merge_data(cr, uid, ids, oldest, 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)
|
||||
|
||||
# Merge notifications about loss of information
|
||||
self._merge_notification(cr, uid, first_opportunity, opportunities, context=context)
|
||||
self._merge_notify(cr, uid, first_opportunity, opportunities, context=context)
|
||||
# Write merged data into first opportunity
|
||||
self.write(cr, uid, [first_opportunity.id], data, context=context)
|
||||
self.write(cr, uid, [first_opportunity.id], merged_data, context=context)
|
||||
# Delete tail opportunities
|
||||
self.unlink(cr, uid, [x.id for x in tail_opportunities], context=context)
|
||||
|
||||
@@ -599,17 +672,17 @@ class crm_lead(base_stage, format_address, osv.osv):
|
||||
stage_id = stage_ids and stage_ids[0] or False
|
||||
|
||||
return {
|
||||
'planned_revenue': lead.planned_revenue,
|
||||
'probability': lead.probability,
|
||||
'name': lead.name,
|
||||
'partner_id': customer and customer.id or False,
|
||||
'user_id': (lead.user_id and lead.user_id.id),
|
||||
'type': 'opportunity',
|
||||
'stage_id': stage_id or False,
|
||||
'date_action': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'date_open': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
'email_from': customer and customer.email or lead.email_from,
|
||||
'phone': customer and customer.phone or lead.phone,
|
||||
'planned_revenue': lead.planned_revenue,
|
||||
'probability': lead.probability,
|
||||
'name': lead.name,
|
||||
'partner_id': customer and customer.id or False,
|
||||
'user_id': (lead.user_id and lead.user_id.id),
|
||||
'type': 'opportunity',
|
||||
'stage_id': stage_id or False,
|
||||
'date_action': fields.datetime.now(),
|
||||
'date_open': fields.datetime.now(),
|
||||
'email_from': customer and customer.email or lead.email_from,
|
||||
'phone': customer and customer.phone or lead.phone,
|
||||
}
|
||||
|
||||
def convert_opportunity(self, cr, uid, ids, partner_id, user_ids=False, section_id=False, context=None):
|
||||
@@ -668,40 +741,67 @@ class crm_lead(base_stage, format_address, osv.osv):
|
||||
return partner_id
|
||||
|
||||
def _lead_set_partner(self, cr, uid, lead, partner_id, context=None):
|
||||
"""
|
||||
Assign a partner to a lead.
|
||||
|
||||
:param object lead: browse record of the lead to process
|
||||
:param int partner_id: identifier of the partner to assign
|
||||
:return bool: True if the partner has properly been assigned
|
||||
"""
|
||||
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})
|
||||
contact_id = res_partner.address_get(cr, uid, [partner_id])['default']
|
||||
res = lead.write({'partner_id' : partner_id, }, context=context)
|
||||
res = lead.write({'partner_id': partner_id}, context=context)
|
||||
self._lead_set_partner_send_note(cr, uid, [lead.id], context)
|
||||
return res
|
||||
|
||||
def convert_partner(self, cr, uid, ids, action='create', partner_id=False, context=None):
|
||||
def handle_partner_assignation(self, cr, uid, ids, action='create', partner_id=False, context=None):
|
||||
"""
|
||||
Convert partner based on action.
|
||||
Handle partner assignation during a lead conversion.
|
||||
if action is 'create', create new partner with contact and assign lead to new partner_id.
|
||||
otherwise assign lead to specified partner_id
|
||||
otherwise assign lead to the specified partner_id
|
||||
|
||||
:param list ids: leads/opportunities ids to process
|
||||
:param string action: what has to be done regarding partners (create it, assign an existing one, or nothing)
|
||||
:param int partner_id: partner to assign if any
|
||||
:return dict: dictionary organized as followed: {lead_id: partner_assigned_id}
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
#TODO this is a duplication of the handle_partner_assignation method of crm_phonecall
|
||||
partner_ids = {}
|
||||
# If a partner_id is given, force this partner for all elements
|
||||
force_partner_id = partner_id
|
||||
for lead in self.browse(cr, uid, ids, context=context):
|
||||
# If the action is set to 'create' and no partner_id is set, create a new one
|
||||
if action == 'create':
|
||||
partner_id = force_partner_id or self._create_lead_partner(cr, uid, lead, context)
|
||||
self._lead_set_partner(cr, uid, lead, partner_id, context=context)
|
||||
partner_ids[lead.id] = partner_id
|
||||
return partner_ids
|
||||
|
||||
def allocate_salesman(self, cr, uid, ids, user_ids, team_id=False, context=None):
|
||||
def allocate_salesman(self, cr, uid, ids, user_ids=None, team_id=False, context=None):
|
||||
"""
|
||||
Assign salesmen and salesteam to a batch of leads. If there are more
|
||||
leads than salesmen, these salesmen will be assigned in round-robin.
|
||||
E.g.: 4 salesmen (S1, S2, S3, S4) for 6 leads (L1, L2, ... L6). They
|
||||
will be assigned as followed: L1 - S1, L2 - S2, L3 - S3, L4 - S4,
|
||||
L5 - S1, L6 - S2.
|
||||
|
||||
:param list ids: leads/opportunities ids to process
|
||||
:param list user_ids: salesmen to assign
|
||||
:param int team_id: salesteam to assign
|
||||
:return bool
|
||||
"""
|
||||
index = 0
|
||||
|
||||
for lead_id in ids:
|
||||
value = {}
|
||||
if team_id:
|
||||
value['section_id'] = team_id
|
||||
if user_ids:
|
||||
value['user_id'] = user_ids[index]
|
||||
# Cycle through user_ids
|
||||
index = (index + 1) % len(user_ids)
|
||||
if value:
|
||||
self.write(cr, uid, [lead_id], value, context=context)
|
||||
@@ -709,7 +809,7 @@ class crm_lead(base_stage, format_address, osv.osv):
|
||||
|
||||
def schedule_phonecall(self, cr, uid, ids, schedule_time, call_summary, desc, phone, contact_name, user_id=False, section_id=False, categ_id=False, action='schedule', context=None):
|
||||
"""
|
||||
action :('schedule','Schedule a call'), ('log','Log a call')
|
||||
:param string action: ('schedule','Schedule a call'), ('log','Log a call')
|
||||
"""
|
||||
phonecall = self.pool.get('crm.phonecall')
|
||||
model_data = self.pool.get('ir.model.data')
|
||||
@@ -724,17 +824,17 @@ class crm_lead(base_stage, format_address, osv.osv):
|
||||
if not user_id:
|
||||
user_id = lead.user_id and lead.user_id.id or False
|
||||
vals = {
|
||||
'name' : call_summary,
|
||||
'opportunity_id' : lead.id,
|
||||
'user_id' : user_id or False,
|
||||
'categ_id' : categ_id or False,
|
||||
'description' : desc or '',
|
||||
'date' : schedule_time,
|
||||
'section_id' : section_id or False,
|
||||
'partner_id': lead.partner_id and lead.partner_id.id or False,
|
||||
'partner_phone' : phone or lead.phone or (lead.partner_id and lead.partner_id.phone or False),
|
||||
'partner_mobile' : lead.partner_id and lead.partner_id.mobile or False,
|
||||
'priority': lead.priority,
|
||||
'name': call_summary,
|
||||
'opportunity_id': lead.id,
|
||||
'user_id': user_id or False,
|
||||
'categ_id': categ_id or False,
|
||||
'description': desc or '',
|
||||
'date': schedule_time,
|
||||
'section_id': section_id or False,
|
||||
'partner_id': lead.partner_id and lead.partner_id.id or False,
|
||||
'partner_phone': phone or lead.phone or (lead.partner_id and lead.partner_id.phone or False),
|
||||
'partner_mobile': lead.partner_id and lead.partner_id.mobile or False,
|
||||
'priority': lead.priority,
|
||||
}
|
||||
new_id = phonecall.create(cr, uid, vals, context=context)
|
||||
phonecall.case_open(cr, uid, [new_id], context=context)
|
||||
@@ -744,30 +844,50 @@ class crm_lead(base_stage, format_address, osv.osv):
|
||||
self.schedule_phonecall_send_note(cr, uid, [lead.id], new_id, action, context=context)
|
||||
return phonecall_dict
|
||||
|
||||
|
||||
def redirect_opportunity_view(self, cr, uid, opportunity_id, context=None):
|
||||
models_data = self.pool.get('ir.model.data')
|
||||
|
||||
# Get Opportunity views
|
||||
form_view = models_data.get_object_reference(cr, uid, 'crm', 'crm_case_form_view_oppor')
|
||||
tree_view = models_data.get_object_reference(cr, uid, 'crm', 'crm_case_tree_view_oppor')
|
||||
# Get opportunity views
|
||||
dummy, form_view = models_data.get_object_reference(cr, uid, 'crm', 'crm_case_form_view_oppor')
|
||||
dummy, tree_view = models_data.get_object_reference(cr, uid, 'crm', 'crm_case_tree_view_oppor')
|
||||
return {
|
||||
'name': _('Opportunity'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree, form',
|
||||
'res_model': 'crm.lead',
|
||||
'domain': [('type', '=', 'opportunity')],
|
||||
'res_id': int(opportunity_id),
|
||||
'view_id': False,
|
||||
'views': [(form_view and form_view[1] or False, 'form'),
|
||||
(tree_view and tree_view[1] or False, 'tree'),
|
||||
(False, 'calendar'), (False, 'graph')],
|
||||
'type': 'ir.actions.act_window',
|
||||
'name': _('Opportunity'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree, form',
|
||||
'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',
|
||||
}
|
||||
|
||||
def redirect_lead_view(self, cr, uid, lead_id, context=None):
|
||||
models_data = self.pool.get('ir.model.data')
|
||||
|
||||
# Get lead views
|
||||
dummy, form_view = models_data.get_object_reference(cr, uid, 'crm', 'crm_case_form_view_leads')
|
||||
dummy, tree_view = models_data.get_object_reference(cr, uid, 'crm', 'crm_case_tree_view_leads')
|
||||
return {
|
||||
'name': _('Lead'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree, form',
|
||||
'res_model': 'crm.lead',
|
||||
'domain': [('type', '=', 'lead')],
|
||||
'res_id': int(lead_id),
|
||||
'view_id': False,
|
||||
'views': [(form_view or False, 'form'),
|
||||
(tree_view or False, 'tree'),
|
||||
(False, 'calendar'), (False, 'graph')],
|
||||
'type': 'ir.actions.act_window',
|
||||
}
|
||||
|
||||
def action_makeMeeting(self, cr, uid, ids, context=None):
|
||||
""" This opens Meeting's calendar view to schedule meeting on current Opportunity
|
||||
@return : Dictionary value for created Meeting view
|
||||
"""
|
||||
Open meeting's calendar view to schedule meeting on current opportunity.
|
||||
:return dict: dictionary value for created Meeting view
|
||||
"""
|
||||
opportunity = self.browse(cr, uid, ids[0], context)
|
||||
res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid, 'base_calendar', 'action_crm_meeting', context)
|
||||
|
||||
@@ -247,7 +247,7 @@ Andrew</field>
|
||||
<field name="contact_name">Bojing Hú</field>
|
||||
<field name="partner_name">Incom Corporation</field>
|
||||
<field name="email_from">bhu.a100@gmail.com</field>
|
||||
<field name="partner_id" ref=""/>
|
||||
<field name="partner_id" ref="base.res_partner_1"/>
|
||||
<field name="country_id" ref="base.cn"/>
|
||||
<field name="city">Shenzhen</field>
|
||||
<field name="type_id" ref="type_lead3"/>
|
||||
@@ -548,6 +548,31 @@ Andrew</field>
|
||||
<field eval="1" name="active"/>
|
||||
</record>
|
||||
|
||||
<record id="crm_case_26" model="crm.lead">
|
||||
<field name="type">opportunity</field>
|
||||
<field name="name">Would appreciate more information about your products</field>
|
||||
<field eval="11000" name="planned_revenue"/>
|
||||
<field eval="45.0" name="probability"/>
|
||||
<field name="partner_name">Agrolait</field>
|
||||
<field name="email_from">info@agrolait.com</field>
|
||||
<field name="partner_id" ref="base.res_partner_2"/>
|
||||
<field name="street">69 rue de Chimay</field>
|
||||
<field name="country_id" ref="base.be"/>
|
||||
<field name="city">Wavre</field>
|
||||
<field name="zip">1300</field>
|
||||
<field name="type_id" ref="type_lead3"/>
|
||||
<field name="categ_ids" eval="[(6, 0, [categ_oppor2])]"/>
|
||||
<field name="channel_id" ref="crm_case_channel_website"/>
|
||||
<field name="priority">3</field>
|
||||
<field eval="time.strftime('%Y-%m-23')" name="date_deadline"/>
|
||||
<field eval="time.strftime('%Y-%m-10')" name="date_action"/>
|
||||
<field name="title_action">Send Catalogue by Email</field>
|
||||
<field name="section_id" ref="crm_case_section_4"/>
|
||||
<field name="user_id" ref="base.user_demo"/>
|
||||
<field name="stage_id" ref="crm.stage_lead3"/>
|
||||
<field eval="1" name="active"/>
|
||||
</record>
|
||||
|
||||
<!-- Unsubscribe Admin from case15, subscribe Demo -->
|
||||
<record id="crm_case_15" model="crm.lead">
|
||||
<field name="message_follower_ids" eval="[(3, ref('base.partner_root')), (4, ref('base.partner_demo'))]"/>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<field name="context">{'default_type':'lead', 'stage_type':'lead'}</field>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create an unqualified lead.
|
||||
Click to create an unqualified lead.
|
||||
</p><p>
|
||||
Use leads if you need a qualification step before creating an
|
||||
opportunity or a customer. It can be a business card you received,
|
||||
@@ -39,48 +39,48 @@
|
||||
<field name="act_window_id" ref="crm_case_category_act_leads_all"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="crm_case_category_act_oppor11">
|
||||
<field name="name">Opportunities</field>
|
||||
<field name="res_model">crm.lead</field>
|
||||
<field name="view_mode">kanban,tree,graph,form,calendar</field>
|
||||
<field name="domain">[('type','=','opportunity')]</field>
|
||||
<field name="context">{'stage_type': 'opportunity', 'default_type': 'opportunity'}</field>
|
||||
<field name="view_id" eval="False"/>
|
||||
<field name="search_view_id" ref="crm.view_crm_case_opportunities_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a new opportunity.
|
||||
</p><p>
|
||||
OpenERP helps you keep track of your sales pipeline to follow
|
||||
up potential sales and better forecast your future revenues.
|
||||
</p><p>
|
||||
You will be able to plan meetings and phone calls from
|
||||
opportunities, convert them into quotations, attach related
|
||||
documents, track all discussions, and much more.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
<record model="ir.actions.act_window" id="crm_case_category_act_oppor11">
|
||||
<field name="name">Opportunities</field>
|
||||
<field name="res_model">crm.lead</field>
|
||||
<field name="view_mode">kanban,tree,graph,form,calendar</field>
|
||||
<field name="domain">[('type','=','opportunity')]</field>
|
||||
<field name="context">{'stage_type': 'opportunity', 'default_type': 'opportunity', 'default_user_id': uid}</field>
|
||||
<field name="view_id" eval="False"/>
|
||||
<field name="search_view_id" ref="crm.view_crm_case_opportunities_filter"/>
|
||||
<field name="help" type="html">
|
||||
<p class="oe_view_nocontent_create">
|
||||
Click to create a new opportunity.
|
||||
</p><p>
|
||||
OpenERP helps you keep track of your sales pipeline to follow
|
||||
up potential sales and better forecast your future revenues.
|
||||
</p><p>
|
||||
You will be able to plan meetings and phone calls from
|
||||
opportunities, convert them into quotations, attach related
|
||||
documents, track all discussions, and much more.
|
||||
</p>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_crm_tag_kanban_view_oppor11">
|
||||
<field name="sequence" eval="0"/>
|
||||
<field name="view_mode">kanban</field>
|
||||
<field name="view_id" ref="crm_case_kanban_view_leads"/>
|
||||
<field name="act_window_id" ref="crm_case_category_act_oppor11"/>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="action_crm_tag_kanban_view_oppor11">
|
||||
<field name="sequence" eval="0"/>
|
||||
<field name="view_mode">kanban</field>
|
||||
<field name="view_id" ref="crm_case_kanban_view_leads"/>
|
||||
<field name="act_window_id" ref="crm_case_category_act_oppor11"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_crm_tag_tree_view_oppor11">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="crm_case_tree_view_oppor"/>
|
||||
<field name="act_window_id" ref="crm_case_category_act_oppor11"/>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="action_crm_tag_tree_view_oppor11">
|
||||
<field name="sequence" eval="1"/>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="view_id" ref="crm_case_tree_view_oppor"/>
|
||||
<field name="act_window_id" ref="crm_case_category_act_oppor11"/>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window.view" id="action_crm_tag_form_view_oppor11">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="crm_case_form_view_oppor"/>
|
||||
<field name="act_window_id" ref="crm_case_category_act_oppor11"/>
|
||||
</record>
|
||||
<record model="ir.actions.act_window.view" id="action_crm_tag_form_view_oppor11">
|
||||
<field name="sequence" eval="2"/>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="crm_case_form_view_oppor"/>
|
||||
<field name="act_window_id" ref="crm_case_category_act_oppor11"/>
|
||||
</record>
|
||||
|
||||
<menuitem name="Sales" id="base.menu_sales" parent="base.menu_base_partner" sequence="1" />
|
||||
<menuitem name="Leads" id="menu_crm_leads" parent="base.menu_sales" action="crm_case_category_act_leads_all" sequence="2" />
|
||||
|
||||
@@ -116,8 +116,11 @@
|
||||
<group>
|
||||
<group>
|
||||
<field name="partner_name" string="Company Name"/>
|
||||
<!-- Preload all the partner's information -->
|
||||
<field name="partner_id" string="Customer"
|
||||
on_change="on_change_partner(partner_id)" options='{"create_name_field": "name"}'/>
|
||||
on_change="on_change_partner(partner_id)"
|
||||
options='{"create_name_field": "name"}'
|
||||
context="{'default_name': contact_name, 'default_street': street, 'default_city': city, 'default_state_id': state_id, 'default_zip': zip, 'default_country_id': country_id, 'default_function': function, 'default_phone': phone, 'default_mobile': mobile, 'default_fax': fax, 'default_email': email_from, 'default_user_id': user_id, 'default_section_id': section_id}"/>
|
||||
<label for="street" string="Address"/>
|
||||
<div>
|
||||
<field name="street" placeholder="Street..."/>
|
||||
@@ -133,7 +136,7 @@
|
||||
<group>
|
||||
<label for="contact_name"/>
|
||||
<div>
|
||||
<field name="contact_name" class="oe_inline"/>,
|
||||
<field name="contact_name" class="oe_inline"/><span attrs="{'invisible': [('title', '=', '')]}">, </span>
|
||||
<field name="title" placeholder="Title" domain="[('domain', '=', 'contact')]" class="oe_inline" options='{"no_open": True}'/>
|
||||
</div>
|
||||
<field name="email_from" widget="email"/>
|
||||
@@ -206,7 +209,6 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- CRM Lead Tree View -->
|
||||
<record model="ir.ui.view" id="crm_case_tree_view_leads">
|
||||
<field name="name">Leads</field>
|
||||
|
||||
+28
-10
@@ -182,17 +182,23 @@ class crm_phonecall(base_state, osv.osv):
|
||||
'phone': phonecall.partner_phone,
|
||||
})
|
||||
|
||||
def convert_partner(self, cr, uid, ids, action='create', partner_id=False, context=None):
|
||||
def handle_partner_assignation(self, cr, uid, ids, action='create', partner_id=False, context=None):
|
||||
"""
|
||||
This function convert partner based on action.
|
||||
Handle partner assignation during a lead conversion.
|
||||
if action is 'create', create new partner with contact and assign lead to new partner_id.
|
||||
otherwise assign lead to specified partner_id
|
||||
|
||||
:param list ids: phonecalls ids to process
|
||||
:param string action: what has to be done regarding partners (create it, assign an existing one, or nothing)
|
||||
:param int partner_id: partner to assign if any
|
||||
:return dict: dictionary organized as followed: {lead_id: partner_assigned_id}
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
#TODO this is a duplication of the handle_partner_assignation method of crm_lead
|
||||
partner_ids = {}
|
||||
# If a partner_id is given, force this partner for all elements
|
||||
force_partner_id = partner_id
|
||||
for call in self.browse(cr, uid, ids, context=context):
|
||||
# If the action is set to 'create' and no partner_id is set, create a new one
|
||||
if action == 'create':
|
||||
partner_id = force_partner_id or self._call_create_partner(cr, uid, call, context=context)
|
||||
self._call_create_partner_address(cr, uid, call, partner_id, context=context)
|
||||
@@ -219,7 +225,6 @@ class crm_phonecall(base_state, osv.osv):
|
||||
}
|
||||
return value
|
||||
|
||||
|
||||
def convert_opportunity(self, cr, uid, ids, opportunity_summary=False, partner_id=False, planned_revenue=0.0, probability=0.0, context=None):
|
||||
partner = self.pool.get('res.partner')
|
||||
opportunity = self.pool.get('crm.lead')
|
||||
@@ -256,8 +261,9 @@ class crm_phonecall(base_state, osv.osv):
|
||||
return opportunity_dict
|
||||
|
||||
def action_make_meeting(self, cr, uid, ids, context=None):
|
||||
""" This opens Meeting's calendar view to schedule meeting on current Phonecall
|
||||
@return : Dictionary value for created Meeting view
|
||||
"""
|
||||
Open meeting's calendar view to schedule a meeting on current phonecall.
|
||||
:return dict: dictionary value for created meeting view
|
||||
"""
|
||||
phonecall = self.browse(cr, uid, ids[0], context)
|
||||
res = self.pool.get('ir.actions.act_window').for_xml_id(cr, uid, 'base_calendar', 'action_crm_meeting', context)
|
||||
@@ -270,14 +276,27 @@ class crm_phonecall(base_state, osv.osv):
|
||||
'default_name': phonecall.name,
|
||||
}
|
||||
return res
|
||||
|
||||
|
||||
def action_button_convert2opportunity(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Convert a phonecall into an opp and then redirect to the opp view.
|
||||
|
||||
:param list ids: list of calls ids to convert (typically contains a single id)
|
||||
:return dict: containing view information
|
||||
"""
|
||||
if len(ids) != 1:
|
||||
raise osv.except_osv(_('Warning!'),_('It\'s only possible to convert one phonecall at a time.'))
|
||||
|
||||
opportunity_dict = self.convert_opportunity(cr, uid, ids, context=context)
|
||||
return self.pool.get('crm.lead').redirect_opportunity_view(cr, uid, opportunity_dict[ids[0]], context)
|
||||
|
||||
# ----------------------------------------
|
||||
# OpenChatter
|
||||
# ----------------------------------------
|
||||
|
||||
def case_get_note_msg_prefix(self, cr, uid, id, context=None):
|
||||
return 'Phonecall'
|
||||
|
||||
|
||||
def case_reset_send_note(self, cr, uid, ids, context=None):
|
||||
message = _('Phonecall has been <b>reset and set as open</b>.')
|
||||
return self.message_post(cr, uid, ids, body=message, context=context)
|
||||
@@ -300,5 +319,4 @@ class crm_phonecall(base_state, osv.osv):
|
||||
def _call_set_partner_send_note(self, cr, uid, ids, context=None):
|
||||
return self.message_post(cr, uid, ids, body=_("Partner has been <b>created</b>."), context=context)
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<data>
|
||||
|
||||
|
||||
<!-- Phonecall Categories Form View -->
|
||||
<!-- Phonecall Categories Form View -->
|
||||
<record id="crm_phonecall_categ_action" model="ir.actions.act_window">
|
||||
<field name="name">Phonecall Categories</field>
|
||||
<field name="res_model">crm.case.categ</field>
|
||||
@@ -24,8 +24,7 @@
|
||||
<menuitem action="crm_phonecall_categ_action" name="Categories"
|
||||
id="menu_crm_case_phonecall-act" parent="menu_crm_config_phonecall" groups="base.group_no_one"/>
|
||||
|
||||
<!-- PhoneCalls Tree View -->
|
||||
|
||||
<!-- Phonecalls Tree View -->
|
||||
<record model="ir.ui.view" id="crm_case_phone_tree_view">
|
||||
<field name="name">CRM - Phone Calls Tree</field>
|
||||
<field name="model">crm.phonecall</field>
|
||||
@@ -35,13 +34,14 @@
|
||||
<field name="name"/>
|
||||
<field name="partner_id"/>
|
||||
<button string="Meeting"
|
||||
states="open,pending" icon="gtk-redo"
|
||||
name="action_make_meeting" type="object"/>
|
||||
<button string="Convert to Opportunity"
|
||||
name="%(phonecall2opportunity_act)d"
|
||||
states="open,pending"
|
||||
icon="gtk-index"
|
||||
type="action" attrs="{'invisible':[('opportunity_id','!=',False)]}"/>
|
||||
name="action_make_meeting"
|
||||
type="object"/>
|
||||
<button string="Convert to Opportunity"
|
||||
type="object"
|
||||
name="action_button_convert2opportunity"
|
||||
states="open,pending"
|
||||
attrs="{'invisible':[('opportunity_id','!=',False)]}"/>
|
||||
<field name="partner_phone"/>
|
||||
<field name="user_id"/>
|
||||
<field name="categ_id" invisible="1"/>
|
||||
@@ -60,27 +60,26 @@
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Phonecalls Form View -->
|
||||
|
||||
<!-- Phonecalls Form View -->
|
||||
<record model="ir.ui.view" id="crm_case_phone_form_view">
|
||||
<field name="name">CRM - Phone Call Form</field>
|
||||
<field name="model">crm.phonecall</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Phone Call" version="7.0">
|
||||
<header>
|
||||
<button name="case_close" string="Call Done" type="object" class="oe_highlight"
|
||||
states="open,pending"/>
|
||||
<button name="case_reset" string="Reset to Todo" type="object"
|
||||
states="cancel"/>
|
||||
<button name="case_cancel" string="Cancel" type="object"
|
||||
states="draft,open,pending"/>
|
||||
<field name="state" widget="statusbar" nolabel="1" statusbar_visible="open,done"/>
|
||||
</header>
|
||||
<header>
|
||||
<button name="case_close" string="Call Done" type="object" class="oe_highlight"
|
||||
states="open,pending"/>
|
||||
<button name="case_reset" string="Reset to Todo" type="object"
|
||||
states="cancel"/>
|
||||
<button name="case_cancel" string="Cancel" type="object"
|
||||
states="draft,open,pending"/>
|
||||
<field name="state" widget="statusbar" nolabel="1" statusbar_visible="open,done"/>
|
||||
</header>
|
||||
<sheet string="Phone Call">
|
||||
<div class="oe_right">
|
||||
<div class="oe_right">
|
||||
<button string="Convert to Opportunity"
|
||||
name="%(phonecall2opportunity_act)d"
|
||||
type="action"
|
||||
type="object"
|
||||
name="action_button_convert2opportunity"
|
||||
attrs="{'invisible':[ '|', ('opportunity_id','!=',False), ('state', 'not in', ('open', 'done'))]}"/>
|
||||
<button string="Schedule Other Call"
|
||||
name="%(phonecall_to_phonecall_act)d"
|
||||
@@ -97,7 +96,7 @@
|
||||
</div>
|
||||
<h2><field name="partner_phone"/></h2>
|
||||
</div>
|
||||
|
||||
|
||||
<group col="4">
|
||||
<field name="date"/>
|
||||
<field name="user_id"/>
|
||||
@@ -122,7 +121,6 @@
|
||||
</record>
|
||||
|
||||
<!--Logged Phonecalls Tree View -->
|
||||
|
||||
<record model="ir.ui.view" id="crm_case_inbound_phone_tree_view">
|
||||
<field name="name">CRM - Logged Phone Calls Tree</field>
|
||||
<field name="model">crm.phonecall</field>
|
||||
@@ -149,7 +147,7 @@
|
||||
icon="gtk-redo"
|
||||
name="action_make_meeting" type="object"/>
|
||||
<button string="Convert to Opportunity"
|
||||
name="%(phonecall2opportunity_act)d"
|
||||
name="action_button_convert2opportunity"
|
||||
states="open,pending"
|
||||
icon="gtk-index"
|
||||
type="action" attrs="{'invisible':[('opportunity_id','!=',False)]}"/>
|
||||
@@ -158,7 +156,6 @@
|
||||
</record>
|
||||
|
||||
<!-- Phonecalls Calendar View -->
|
||||
|
||||
<record model="ir.ui.view" id="crm_case_phone_calendar_view">
|
||||
<field name="name">CRM - Phone Calls Calendar</field>
|
||||
<field name="model">crm.phonecall</field>
|
||||
|
||||
@@ -293,7 +293,7 @@
|
||||
<field name="view_id" ref="crm_case_resource_type_tree"/>
|
||||
</record>
|
||||
|
||||
<menuitem action="crm_case_resource_type_act"
|
||||
<menuitem action="crm_case_resource_type_act"
|
||||
id="menu_crm_case_resource_type_act" sequence="4"
|
||||
groups="base.group_no_one"
|
||||
parent="base.menu_crm_config_lead"/>
|
||||
|
||||
@@ -33,20 +33,4 @@
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
lead_ids = self.search(cr, uid, [('email_from','=', 'Mr. John Right <info@customer.com>')])
|
||||
self.convert_partner(cr, uid, lead_ids, context=context)
|
||||
-
|
||||
I convert one phonecall request to a customer and put him into regular customer list.
|
||||
-
|
||||
!python {model: crm.phonecall2partner}: |
|
||||
context.update({'active_model': 'crm.phonecall', 'active_ids': [ref("crm.crm_phonecall_4")], 'active_id': ref("crm.crm_phonecall_4")})
|
||||
new_id = self.create(cr, uid, {}, context=context)
|
||||
self.make_partner(cr, uid, [new_id], context=context)
|
||||
-
|
||||
I check converted phonecall to partner.
|
||||
-
|
||||
!python {model: res.partner}: |
|
||||
partner_id = self.search(cr, uid, [('phonecall_ids', '=', ref('crm.crm_phonecall_4'))])
|
||||
assert partner_id, "Customer is not found in regular customer list."
|
||||
data = self.browse(cr, uid, partner_id, context=context)[0]
|
||||
assert data.user_id.id == ref("base.user_root"), "User not assigned properly"
|
||||
assert data.name == "Wanted information about pricing of laptops", "Bad partner name"
|
||||
self.handle_partner_assignation(cr, uid, lead_ids, context=context)
|
||||
|
||||
@@ -1,25 +1,15 @@
|
||||
-
|
||||
In order to test convert customer lead into opportunity,
|
||||
In order to test the conversion of a lead into a opportunity,
|
||||
-
|
||||
I open customer lead.
|
||||
I open a lead.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.case_open(cr, uid, [ref("crm_case_4")])
|
||||
-
|
||||
I check lead state is "Open".
|
||||
I check if the lead state is "Open".
|
||||
-
|
||||
!assert {model: crm.lead, id: crm.crm_case_4, string: Lead in open state}:
|
||||
!assert {model: crm.lead, id: crm.crm_case_4, string: Lead state is Open}:
|
||||
- state == "open"
|
||||
-
|
||||
I fill in a lead2partner wizard.
|
||||
-
|
||||
!record {model: crm.lead2partner, id: crm_lead2partner_id1, context: '{"active_model": "crm.lead", "active_ids": [ref("crm_case_4")]}'}:
|
||||
-
|
||||
I create a partner from the lead2partner wizard.
|
||||
-
|
||||
!python {model: crm.lead2partner}: |
|
||||
context.update({'active_model': 'crm.lead', 'active_ids': [ref('crm_case_4')], 'active_id': ref('crm_case_4')})
|
||||
self.make_partner(cr, uid ,[ref("crm_lead2partner_id1")], context=context)
|
||||
-
|
||||
I convert lead into opportunity for exiting customer.
|
||||
-
|
||||
@@ -76,7 +66,7 @@
|
||||
-
|
||||
!python {model: crm.lead2opportunity.partner.mass}: |
|
||||
context.update({'active_model': 'crm.lead', 'active_ids': [ref("crm_case_11"), ref("crm_case_2")], 'active_id': ref("crm_case_11")})
|
||||
id = self.create(cr, uid, {'user_ids': [ref('base.user_root')], 'section_id': ref('crm.section_sales_department')}, context=context)
|
||||
id = self.create(cr, uid, {'user_ids': [(6, 0, [ref('base.user_root')])], 'section_id': ref('crm.section_sales_department')}, context=context)
|
||||
self.mass_convert(cr, uid, [id], context=context)
|
||||
-
|
||||
Now I check first lead converted on opportunity.
|
||||
|
||||
@@ -0,0 +1,70 @@
|
||||
-
|
||||
During a lead to opp conversion, salesmen should be assigned to leads following the round-robin method. Start by creating 6 leads (1 to 6) and 4 salesmen (A to D).
|
||||
-
|
||||
!record {model: crm.lead, id: test_crm_lead_01}:
|
||||
type: 'lead'
|
||||
name: 'Test lead 1'
|
||||
stage_id: stage_lead1
|
||||
-
|
||||
!record {model: crm.lead, id: test_crm_lead_02}:
|
||||
type: 'lead'
|
||||
name: 'Test lead 2'
|
||||
stage_id: stage_lead1
|
||||
-
|
||||
!record {model: crm.lead, id: test_crm_lead_03}:
|
||||
type: 'lead'
|
||||
name: 'Test lead 3'
|
||||
stage_id: stage_lead1
|
||||
-
|
||||
!record {model: crm.lead, id: test_crm_lead_04}:
|
||||
type: 'lead'
|
||||
name: 'Test lead 4'
|
||||
stage_id: stage_lead1
|
||||
-
|
||||
!record {model: crm.lead, id: test_crm_lead_05}:
|
||||
type: 'lead'
|
||||
name: 'Test lead 5'
|
||||
stage_id: stage_lead1
|
||||
-
|
||||
!record {model: crm.lead, id: test_crm_lead_06}:
|
||||
type: 'lead'
|
||||
name: 'Test lead 6'
|
||||
stage_id: stage_lead1
|
||||
-
|
||||
!record {model: res.users, id: test_res_user_01}:
|
||||
name: 'Test user A'
|
||||
login: 'tua'
|
||||
new_password: 'tua'
|
||||
-
|
||||
!record {model: res.users, id: test_res_user_02}:
|
||||
name: 'Test user B'
|
||||
login: 'tub'
|
||||
new_password: 'tub'
|
||||
-
|
||||
!record {model: res.users, id: test_res_user_03}:
|
||||
name: 'Test user C'
|
||||
login: 'tuc'
|
||||
new_password: 'tuc'
|
||||
-
|
||||
!record {model: res.users, id: test_res_user_04}:
|
||||
name: 'Test user D'
|
||||
login: 'tud'
|
||||
new_password: 'tud'
|
||||
-
|
||||
I create a mass convert wizard and convert all the leads.
|
||||
-
|
||||
!python {model: crm.lead2opportunity.partner.mass}: |
|
||||
context.update({'active_model': 'crm.lead', 'active_ids': [ref("test_crm_lead_01"), ref("test_crm_lead_02"), ref("test_crm_lead_03"), ref("test_crm_lead_04"), ref("test_crm_lead_05"), ref("test_crm_lead_06")], 'active_id': ref("test_crm_lead_01")})
|
||||
id = self.create(cr, uid, {'user_ids': [(6, 0, [ref('test_res_user_01'), ref('test_res_user_02'), ref('test_res_user_03'), ref('test_res_user_04')])], 'section_id': ref('crm.section_sales_department')}, context=context)
|
||||
self.mass_convert(cr, uid, [id], context=context)
|
||||
-
|
||||
The leads should now be opps with a salesman and a salesteam. Also, salesmen should have been assigned following a round-robin method.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
opps = self.browse(cr, uid, [ref("test_crm_lead_01"), ref("test_crm_lead_02"), ref("test_crm_lead_03"), ref("test_crm_lead_04"), ref("test_crm_lead_05"), ref("test_crm_lead_06")], context)
|
||||
salesmen_ids = [ref('test_res_user_01'), ref('test_res_user_02'), ref('test_res_user_03'), ref('test_res_user_04')]
|
||||
i = 0
|
||||
for opp in opps:
|
||||
assert opp.type == 'opportunity', 'Type mismatch: this should be an opp, not a lead'
|
||||
assert opp.user_id.id == salesmen_ids[i], 'Salesman mismatch: expected salesman %r, got %r' % (salesmen_ids[i], opp.user_id.id)
|
||||
i = i+1 if (i < len(salesmen_ids) - 1) else 0
|
||||
@@ -1,34 +1,126 @@
|
||||
|
||||
-
|
||||
I make an opportunity from customer.
|
||||
During a mixed merge (involving leads and opps), data should be handled a certain way following their type (m2o, m2m, text, ...) Start by creating two leads and an opp.
|
||||
-
|
||||
!python {model: crm.partner2opportunity}: |
|
||||
context.update({'active_model': 'res.partner', 'active_ids': [ref("base.res_partner_9")]})
|
||||
res_id = self.create(cr, uid, {'name': "Enquête pour l'achat de services"}, context=context)
|
||||
self.make_opportunity(cr, uid, [res_id], context=context)
|
||||
!record {model: crm.lead, id: test_crm_lead_01}:
|
||||
type: 'lead'
|
||||
name: 'Test lead 1'
|
||||
partner_id: base.res_partner_1
|
||||
stage_id: stage_lead1
|
||||
description: This is the description of the test lead 1.
|
||||
-
|
||||
I make another opportunity from a phone call with the same customer.
|
||||
!record {model: crm.lead, id: test_crm_lead_02}:
|
||||
type: 'lead'
|
||||
name: 'Test lead 2'
|
||||
partner_id: base.res_partner_3
|
||||
stage_id: stage_lead1
|
||||
description: This is the description of the test lead 2.
|
||||
-
|
||||
!python {model: crm.phonecall2opportunity}: |
|
||||
context.update({'active_model': 'crm.phonecall', 'active_ids': [ref("crm.crm_phonecall_6")]})
|
||||
res_id = self.create(cr, uid, {'name': "À propos du prix de votre autre service", 'partner_id': ref("base.res_partner_9")}, context=context)
|
||||
self.make_opportunity(cr, uid, [res_id], context=context)
|
||||
-
|
||||
Now I merge these opportunities.
|
||||
!record {model: crm.lead, id: test_crm_opp_01}:
|
||||
type: 'opportunity'
|
||||
name: 'Test opportunity 1'
|
||||
partner_id: base.res_partner_5
|
||||
stage_id: stage_lead1
|
||||
description: This is the description of the test opp 1.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
opportunity_ids = self.search(cr, uid, [('partner_id','=', ref("base.res_partner_9"))])
|
||||
context.update({'active_model': 'crm.lead', 'active_ids': opportunity_ids, 'active_id': opportunity_ids[0]})
|
||||
lead_ids = [ref('test_crm_lead_01'), ref('test_crm_lead_02'), ref('test_crm_opp_01')]
|
||||
context.update({'active_model': 'crm.lead', 'active_ids': lead_ids, 'active_id': lead_ids[0]})
|
||||
-
|
||||
!record {model: crm.merge.opportunity, id: opportunity_merge_id }:
|
||||
I create a merge wizard and merge the leads and opp together in the first item of the list.
|
||||
-
|
||||
!record {model: crm.merge.opportunity, id: merge_opp_wizard_01}:
|
||||
-
|
||||
!python {model: crm.merge.opportunity}: |
|
||||
self.action_merge(cr, uid, [ref("opportunity_merge_id")], context=context)
|
||||
self.action_merge(cr, uid, [ref("merge_opp_wizard_01")], context=context)
|
||||
-
|
||||
I check for merged opportunities for customer.
|
||||
I check for the resulting merged opp (based on name and partner).
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
merge_id = self.search(cr, uid, [('partner_id','=', ref("base.res_partner_9"))])
|
||||
assert merge_id, 'Fail to create Merge opportunity'
|
||||
merge_data = self.browse(cr, uid, merge_id)[0]
|
||||
assert merge_data.type == 'opportunity', 'Merged opportunity type not change!'
|
||||
assert merge_data.partner_id.id == ref("base.res_partner_9"), 'Partner missmatch!'
|
||||
merge_id = self.search(cr, uid, [('name', '=', 'Test lead 1'), ('partner_id','=', ref("base.res_partner_1"))])
|
||||
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.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.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
tailing_lead = self.search(cr, uid, [('id', '=', ref('test_crm_lead_02'))])
|
||||
assert not tailing_lead, 'This tailing lead (id %s) should not exist anymore' % ref('test_crm_lead_02')
|
||||
|
||||
tailing_opp = self.search(cr, uid, [('id', '=', ref('test_crm_opp_01'))])
|
||||
assert not tailing_opp, 'This tailing opp (id %s) should not exist anymore' % ref('test_crm_opp_01')
|
||||
-
|
||||
I want to test leads merge. Start by creating two leads (with the same partner).
|
||||
-
|
||||
!record {model: crm.lead, id: test_crm_lead_03}:
|
||||
type: 'lead'
|
||||
name: 'Test lead 3'
|
||||
partner_id: base.res_partner_1
|
||||
stage_id: stage_lead1
|
||||
-
|
||||
!record {model: crm.lead, id: test_crm_lead_04}:
|
||||
type: 'lead'
|
||||
name: 'Test lead 4'
|
||||
partner_id: base.res_partner_1
|
||||
stage_id: stage_lead1
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
lead_ids = [ref('test_crm_lead_03'), ref('test_crm_lead_04')]
|
||||
context.update({'active_model': 'crm.lead', 'active_ids': lead_ids, 'active_id': lead_ids[0]})
|
||||
-
|
||||
I create a merge wizard and merge the leads together.
|
||||
-
|
||||
!record {model: crm.merge.opportunity, id: merge_opp_wizard_02}:
|
||||
-
|
||||
!python {model: crm.merge.opportunity}: |
|
||||
self.action_merge(cr, uid, [ref("merge_opp_wizard_02")], context=context)
|
||||
-
|
||||
I check for the resulting merged lead (based on name and partner).
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
merge_id = self.search(cr, uid, [('name', '=', 'Test lead 3'), ('partner_id','=', ref("base.res_partner_1"))])
|
||||
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'
|
||||
assert merge_result.type == 'lead', 'Type mismatch: when leads get merged together, the result should be a new lead (instead of %s)' % merge_result.type
|
||||
tailing_lead = self.search(cr, uid, [('id', '=', ref('test_crm_lead_04'))])
|
||||
assert not tailing_lead, 'This tailing lead (id %s) should not exist anymore' % ref('test_crm_lead_04')
|
||||
-
|
||||
I want to test opps merge. Start by creating two opportunities (with the same partner).
|
||||
-
|
||||
!record {model: crm.lead, id: test_crm_opp_02}:
|
||||
type: 'opportunity'
|
||||
name: 'Test opportunity 2'
|
||||
partner_id: base.res_partner_5
|
||||
stage_id: stage_lead1
|
||||
-
|
||||
!record {model: crm.lead, id: test_crm_opp_03}:
|
||||
type: 'opportunity'
|
||||
name: 'Test opportunity 3'
|
||||
partner_id: base.res_partner_5
|
||||
stage_id: stage_lead1
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
opp_ids = [ref('test_crm_opp_02'), ref('test_crm_opp_03')]
|
||||
context.update({'active_model': 'crm.lead', 'active_ids': opp_ids, 'active_id': opp_ids[0]})
|
||||
-
|
||||
I create a merge wizard and merge the opps together.
|
||||
-
|
||||
!record {model: crm.merge.opportunity, id: merge_opp_wizard_03}:
|
||||
-
|
||||
!python {model: crm.merge.opportunity}: |
|
||||
self.action_merge(cr, uid, [ref("merge_opp_wizard_03")], context=context)
|
||||
-
|
||||
I check for the resulting merged opp (based on name and partner).
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
merge_id = self.search(cr, uid, [('name', '=', 'Test opportunity 2'), ('partner_id','=', ref("base.res_partner_5"))])
|
||||
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_5"), 'Partner mismatch'
|
||||
assert merge_result.type == 'opportunity', 'Type mismatch: when opps get merged together, the result should be a new opp (instead of %s)' % merge_result.type
|
||||
tailing_opp = self.search(cr, uid, [('id', '=', ref('test_crm_opp_03'))])
|
||||
assert not tailing_opp, 'This tailing opp (id %s) should not exist anymore' % ref('test_crm_opp_03')
|
||||
@@ -1,5 +1,5 @@
|
||||
-
|
||||
I create lead record to call of partner onchange, stage onchange and Mailing opt-in onchange method.
|
||||
I create a lead record to call a partner onchange, stage onchange and mailing opt-in onchange method.
|
||||
-
|
||||
!record {model: crm.lead, id: crm_case_25}:
|
||||
name: 'Need more info about your pc2'
|
||||
@@ -8,7 +8,7 @@
|
||||
stage_id: crm.stage_lead1
|
||||
state: draft
|
||||
-
|
||||
I create lead record to call Mailing opt-out onchange method.
|
||||
I create a lead record to call a mailing opt-out onchange method.
|
||||
-
|
||||
!record {model: crm.lead, id: crm_case_18}:
|
||||
name: 'Need 20 Days of Consultancy'
|
||||
@@ -16,13 +16,13 @@
|
||||
state: draft
|
||||
opt_out: True
|
||||
-
|
||||
I create phonecall record to call partner onchange method.
|
||||
I create a phonecall record to call a partner onchange method.
|
||||
-
|
||||
!record {model: crm.phonecall, id: crm_phonecall_5}:
|
||||
name: 'Bad time'
|
||||
partner_id: base.res_partner_5
|
||||
-
|
||||
I setting next stage "New" for the lead.
|
||||
I set the next stage to "New" for the lead.
|
||||
-
|
||||
!python {model: crm.lead}: |
|
||||
self.stage_next(cr, uid, [ref("crm_case_4")], context={'stage_type': 'lead'})
|
||||
|
||||
@@ -19,16 +19,10 @@
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import crm_lead_to_partner
|
||||
import crm_lead_to_opportunity
|
||||
import crm_partner_binding
|
||||
import crm_phonecall_to_phonecall
|
||||
import crm_opportunity_to_phonecall
|
||||
import crm_phonecall_to_partner
|
||||
import crm_partner_to_opportunity
|
||||
import crm_phonecall_to_opportunity
|
||||
|
||||
import crm_lead_to_opportunity
|
||||
import crm_merge_opportunities
|
||||
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
|
||||
@@ -27,16 +27,13 @@ import re
|
||||
class crm_lead2opportunity_partner(osv.osv_memory):
|
||||
_name = 'crm.lead2opportunity.partner'
|
||||
_description = 'Lead To Opportunity Partner'
|
||||
_inherit = 'crm.lead2partner'
|
||||
_inherit = 'crm.partner.binding'
|
||||
|
||||
_columns = {
|
||||
'action': fields.selection([('exist', 'Link to an existing customer'), \
|
||||
('create', 'Create a new customer'), \
|
||||
('nothing', 'Do not link to a customer')], \
|
||||
'Related Customer', required=True),
|
||||
'name': fields.selection([('convert', 'Convert to opportunity'), \
|
||||
('merge', 'Merge with existing opportunities')], \
|
||||
'Conversion Action', required=True),
|
||||
'name': fields.selection([
|
||||
('convert', 'Convert to opportunity'),
|
||||
('merge', 'Merge with existing opportunities')
|
||||
], 'Conversion Action', required=True),
|
||||
'opportunity_ids': fields.many2many('crm.lead', string='Opportunities', domain=[('type', '=', 'opportunity')]),
|
||||
}
|
||||
|
||||
@@ -157,8 +154,8 @@ class crm_lead2opportunity_mass_convert(osv.osv_memory):
|
||||
_inherit = 'crm.lead2opportunity.partner'
|
||||
|
||||
_columns = {
|
||||
'user_ids': fields.many2many('res.users', string='Salesmen'),
|
||||
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
|
||||
'user_ids': fields.many2many('res.users', string='Salesmen'),
|
||||
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
|
||||
}
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<field name="model">crm.lead2opportunity.partner</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Convert to Opportunity" version="7.0">
|
||||
<group>
|
||||
<group name="name">
|
||||
<field name="name" class="oe_inline"/>
|
||||
<field name="opportunity_ids" attrs="{'invisible': [('name', '!=', 'merge')]}">
|
||||
<tree>
|
||||
@@ -18,7 +18,7 @@
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
<group attrs="{'invisible': [('name', '!=', 'convert')]}">
|
||||
<group name="action" attrs="{'invisible': [('name', '!=', 'convert')]}">
|
||||
<field name="action" class="oe_inline"/>
|
||||
<field name="partner_id"
|
||||
attrs="{'required': [('action', '=', 'exist')], 'invisible':[('action','!=','exist')]}"
|
||||
@@ -51,21 +51,17 @@
|
||||
<group string="Select Opportunities" attrs="{'invisible': [('name', '!=', 'merge')]}">
|
||||
<field name="opportunity_ids" colspan="4" nolabel="1" attrs="{'invisible': [('name', '=', 'convert')]}">
|
||||
<tree>
|
||||
<field name="name" />
|
||||
<field name="partner_id" />
|
||||
<field name="user_id" />
|
||||
<field name="section_id" />
|
||||
<field name="name"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="user_id"/>
|
||||
<field name="section_id"/>
|
||||
</tree>
|
||||
</field>
|
||||
</group>
|
||||
|
||||
<group string="Assign opportunities to" attrs="{'invisible': [('name', '=', '')]}">
|
||||
<field name="section_id" />
|
||||
<field name="user_ids" colspan="4">
|
||||
<tree>
|
||||
<field name="name" />
|
||||
</tree>
|
||||
</field>
|
||||
<field name="section_id"/>
|
||||
<field name="user_ids" widget="many2many_tags"/>
|
||||
</group>
|
||||
|
||||
<footer>
|
||||
|
||||
@@ -1,122 +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_lead2partner(osv.osv_memory):
|
||||
""" Converts lead to partner """
|
||||
_name = 'crm.lead2partner'
|
||||
_description = 'Lead to Partner'
|
||||
|
||||
_columns = {
|
||||
'action': fields.selection([('exist', 'Link to an existing customer'), \
|
||||
('create', 'Create a new customer')], \
|
||||
'Action', required=True),
|
||||
'partner_id': fields.many2one('res.partner', 'Customer'),
|
||||
}
|
||||
def view_init(self, cr, uid, fields, context=None):
|
||||
"""
|
||||
Check for precondition before wizard executes.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
model = context.get('active_model')
|
||||
model = self.pool.get(model)
|
||||
rec_ids = context and context.get('active_ids', [])
|
||||
for this in model.browse(cr, uid, rec_ids, context=context):
|
||||
if this.partner_id:
|
||||
raise osv.except_osv(_('Warning!'),
|
||||
_('A partner is already defined.'))
|
||||
|
||||
def _select_partner(self, cr, uid, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
if not context.get('active_model') == 'crm.lead' or not context.get('active_id'):
|
||||
return False
|
||||
partner = self.pool.get('res.partner')
|
||||
lead = self.pool.get('crm.lead')
|
||||
this = lead.browse(cr, uid, context.get('active_id'), context=context)
|
||||
if this.partner_id:
|
||||
return this.partner_id.id
|
||||
partner_id = False
|
||||
if this.email_from:
|
||||
partner_ids = partner.search(cr, uid, [('email', '=', this.email_from)], context=context)
|
||||
if partner_ids:
|
||||
partner_id = partner_ids[0]
|
||||
if not this.partner_id and this.partner_name:
|
||||
partner_ids = partner.search(cr, uid, [('name', '=', this.partner_name)], context=context)
|
||||
if partner_ids:
|
||||
partner_id = partner_ids[0]
|
||||
return partner_id
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
res = super(crm_lead2partner, self).default_get(cr, uid, fields, context=context)
|
||||
partner_id = self._select_partner(cr, uid, context=context)
|
||||
|
||||
if 'partner_id' in fields:
|
||||
res.update({'partner_id': partner_id})
|
||||
if 'action' in fields:
|
||||
res.update({'action': partner_id and 'exist' or 'create'})
|
||||
|
||||
return res
|
||||
|
||||
def open_create_partner(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Open form of create partner.
|
||||
"""
|
||||
view_obj = self.pool.get('ir.ui.view')
|
||||
view_id = view_obj.search(cr, uid, [('model', '=', self._name), \
|
||||
('name', '=', self._name+'.view')])
|
||||
return {
|
||||
'view_mode': 'form',
|
||||
'view_type': 'form',
|
||||
'view_id': view_id or False,
|
||||
'res_model': self._name,
|
||||
'context': context,
|
||||
'type': 'ir.actions.act_window',
|
||||
'target': 'new',
|
||||
}
|
||||
|
||||
def _create_partner(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Create partner based on action.
|
||||
"""
|
||||
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.convert_partner(cr, uid, lead_ids, data.action, partner_id, context=context)
|
||||
|
||||
def make_partner(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Make a partner based on action.
|
||||
Only called from form view, so only meant to convert one lead at a time.
|
||||
"""
|
||||
lead_id = context and context.get('active_id') or False
|
||||
partner_ids_map = self._create_partner(cr, uid, ids, context=context)
|
||||
return self.pool.get('res.partner').redirect_partner_form(cr, uid, partner_ids_map.get(lead_id, False), context=context)
|
||||
|
||||
crm_lead2partner()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
@@ -1,37 +0,0 @@
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Lead to Partner form view -->
|
||||
|
||||
<record id="view_crm_lead2partner" model="ir.ui.view">
|
||||
<field name="name">crm.lead2partner.view</field>
|
||||
<field name="model">crm.lead2partner</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Create a Partner" version="7.0">
|
||||
<group col="4">
|
||||
<separator string="Create a Partner"/>
|
||||
<field name="action"/>
|
||||
<field name="partner_id" attrs="{'required': [('action', '=', 'exist')], 'invisible':[('action','!=','exist')]}"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="make_partner" string="Continue" type="object" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
<!-- Lead to Partner wizard -->
|
||||
<record id="action_crm_lead2partner" model="ir.actions.act_window">
|
||||
<field name="name">Create a Partner</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">crm.lead2partner</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="view_crm_lead2partner"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -21,33 +21,51 @@ from osv import osv, fields
|
||||
from tools.translate import _
|
||||
|
||||
class crm_merge_opportunity(osv.osv_memory):
|
||||
"""Merge two Opportunities"""
|
||||
"""
|
||||
Merge opportunities together.
|
||||
If we're talking about opportunities, it's just because it makes more sense
|
||||
to merge opps than leads, because the leads are more ephemeral objects.
|
||||
But since opportunities are leads, it's also possible to merge leads
|
||||
together (resulting in a new lead), or leads and opps together (resulting
|
||||
in a new opp).
|
||||
"""
|
||||
|
||||
_name = 'crm.merge.opportunity'
|
||||
_description = 'Merge two Opportunities'
|
||||
|
||||
def action_merge(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
lead = self.pool.get('crm.lead')
|
||||
record = self.browse(cr, uid, ids[0], context=context)
|
||||
opportunities = record.opportunity_ids
|
||||
#TOFIX: why need to check lead_ids here
|
||||
lead_ids = [opportunities[0].id]
|
||||
self.write(cr, uid, ids, {'opportunity_ids' : [(6,0, lead_ids)]}, context=context)
|
||||
context['lead_ids'] = lead_ids
|
||||
merge_id = lead.merge_opportunity(cr, uid, [x.id for x in opportunities], context=context)
|
||||
return lead.redirect_opportunity_view(cr, uid, merge_id, context=context)
|
||||
|
||||
_description = 'Merge opportunities'
|
||||
_columns = {
|
||||
'opportunity_ids': fields.many2many('crm.lead', rel='merge_opportunity_rel', id1='merge_id', id2='opportunity_id', string='Leads/Opportunities'),
|
||||
}
|
||||
|
||||
def action_merge(self, cr, uid, ids, context=None):
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
lead_obj = self.pool.get('crm.lead')
|
||||
wizard = self.browse(cr, uid, ids[0], context=context)
|
||||
opportunity2merge_ids = wizard.opportunity_ids
|
||||
|
||||
#TODO: why is this passed through the context ?
|
||||
context['lead_ids'] = [opportunity2merge_ids[0].id]
|
||||
|
||||
merge_id = lead_obj.merge_opportunity(cr, uid, [x.id for x in opportunity2merge_ids], context=context)
|
||||
|
||||
# The newly created lead might be a lead or an opp: redirect toward the right view
|
||||
merge_result = lead_obj.browse(cr, uid, merge_id, context=context)
|
||||
|
||||
if merge_result.type == 'opportunity':
|
||||
return lead_obj.redirect_opportunity_view(cr, uid, merge_id, context=context)
|
||||
else:
|
||||
return lead_obj.redirect_lead_view(cr, uid, merge_id, context=context)
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
"""
|
||||
This function gets default values
|
||||
Use active_ids from the context to fetch the leads/opps to merge.
|
||||
In order to get merged, these leads/opps can't be in 'Done' or
|
||||
'Cancel' state.
|
||||
"""
|
||||
record_ids = context and context.get('active_ids', False) or False
|
||||
if context is None:
|
||||
context = {}
|
||||
record_ids = context.get('active_ids', False)
|
||||
res = super(crm_merge_opportunity, self).default_get(cr, uid, fields, context=context)
|
||||
|
||||
if record_ids:
|
||||
@@ -61,6 +79,4 @@ class crm_merge_opportunity(osv.osv_memory):
|
||||
|
||||
return res
|
||||
|
||||
crm_merge_opportunity()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -0,0 +1,115 @@
|
||||
# -*- 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_partner_binding(osv.osv_memory):
|
||||
"""
|
||||
Handle the partner binding or generation in any CRM wizard that requires
|
||||
such feature, like the lead2opportunity wizard, or the
|
||||
phonecall2opportunity wizard. Try to find a matching partner from the
|
||||
CRM model's information (name, email, phone number, etc) or create a new
|
||||
one on the fly.
|
||||
Use it like a mixin with the wizard of your choice.
|
||||
"""
|
||||
_name = 'crm.partner.binding'
|
||||
_description = 'Handle partner binding or generation in CRM wizards.'
|
||||
_columns = {
|
||||
'action': fields.selection([
|
||||
('exist', 'Link to an existing customer'),
|
||||
('create', 'Create a new customer'),
|
||||
('nothing', 'Do not link to a customer')
|
||||
], 'Related Customer', required=True),
|
||||
'partner_id': fields.many2one('res.partner', 'Customer'),
|
||||
}
|
||||
|
||||
def _find_matching_partner(self, cr, uid, context=None):
|
||||
"""
|
||||
Try to find a matching partner regarding the active model data, like
|
||||
the customer's name, email, phone number, etc.
|
||||
|
||||
:return int partner_id if any, False otherwise
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
partner_id = False
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
|
||||
# The active model has to be a lead or a phonecall
|
||||
if (context.get('active_model') == 'crm.lead') and context.get('active_id'):
|
||||
active_model = self.pool.get('crm.lead').browse(cr, uid, context.get('active_id'), context=context)
|
||||
elif (context.get('active_model') == 'crm.phonecall') and context.get('active_id'):
|
||||
active_model = self.pool.get('crm.phonecall').browse(cr, uid, context.get('active_id'), context=context)
|
||||
|
||||
# Find the best matching partner for the active model
|
||||
if (active_model):
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
|
||||
# A partner is set already
|
||||
if active_model.partner_id:
|
||||
partner_id = active_model.partner_id.id
|
||||
# Search through the existing partners based on the lead's email
|
||||
elif active_model.email_from:
|
||||
partner_ids = partner_obj.search(cr, uid, [('email', '=', active_model.email_from)], context=context)
|
||||
if partner_ids:
|
||||
partner_id = partner_ids[0]
|
||||
# Search through the existing partners based on the lead's partner or contact name
|
||||
elif active_model.partner_name:
|
||||
partner_ids = partner_obj.search(cr, uid, [('name', 'ilike', '%'+active_model.partner_name+'%')], context=context)
|
||||
if partner_ids:
|
||||
partner_id = partner_ids[0]
|
||||
elif active_model.contact_name:
|
||||
partner_ids = partner_obj.search(cr, uid, [
|
||||
('name', 'ilike', '%'+active_model.contact_name+'%')], context=context)
|
||||
if partner_ids:
|
||||
partner_id = partner_ids[0]
|
||||
|
||||
return partner_id
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
res = super(crm_partner_binding, self).default_get(cr, uid, fields, context=context)
|
||||
partner_id = self._find_matching_partner(cr, uid, context=context)
|
||||
|
||||
if 'action' in fields:
|
||||
res['action'] = partner_id and 'exist' or 'create'
|
||||
if 'partner_id' in fields:
|
||||
res['partner_id'] = partner_id
|
||||
|
||||
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:
|
||||
@@ -1,77 +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_partner2opportunity(osv.osv_memory):
|
||||
"""Converts Partner To Opportunity"""
|
||||
|
||||
_name = 'crm.partner2opportunity'
|
||||
_description = 'Partner To Opportunity'
|
||||
|
||||
_columns = {
|
||||
'name' : fields.char('Opportunity Name', size=64, required=True),
|
||||
'planned_revenue': fields.float('Expected Revenue', digits=(16,2)),
|
||||
'probability': fields.float('Success Probability', digits=(16,2)),
|
||||
'partner_id': fields.many2one('res.partner', 'Customer'),
|
||||
}
|
||||
|
||||
def action_cancel(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
Closes Partner 2 Opportunity
|
||||
"""
|
||||
return {'type':'ir.actions.act_window_close'}
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
"""
|
||||
This function gets default values
|
||||
"""
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
data = context and context.get('active_ids', []) or []
|
||||
res = super(crm_partner2opportunity, self).default_get(cr, uid, fields, context=context)
|
||||
|
||||
for partner in partner_obj.browse(cr, uid, data, []):
|
||||
if 'name' in fields:
|
||||
res.update({'name': partner.name})
|
||||
if 'partner_id' in fields:
|
||||
res.update({'partner_id': data and data[0] or False})
|
||||
return res
|
||||
|
||||
def make_opportunity(self, cr, uid, ids, context=None):
|
||||
partner_ids = context and context.get('active_ids', []) or []
|
||||
partner_id = partner_ids[0] if partner_ids else None
|
||||
partner = self.pool.get('res.partner')
|
||||
lead = self.pool.get('crm.lead')
|
||||
data = self.browse(cr, uid, ids, context=context)[0]
|
||||
opportunity_ids = partner.make_opportunity(cr, uid, partner_ids,
|
||||
data.name,
|
||||
data.planned_revenue,
|
||||
data.probability,
|
||||
partner_id,
|
||||
context=context,
|
||||
)
|
||||
opportunity_id = opportunity_ids[partner_ids[0]]
|
||||
return lead.redirect_opportunity_view(cr, uid, opportunity_id, context=context)
|
||||
|
||||
crm_partner2opportunity()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
@@ -1,27 +0,0 @@
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- partner To Opportunity form -->
|
||||
|
||||
<record id="view_crm_partner2opportunity" model="ir.ui.view">
|
||||
<field name="name">crm.crm.partner2opportunity</field>
|
||||
<field name="model">crm.partner2opportunity</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Create Opportunity" version="7.0">
|
||||
<group col="4">
|
||||
<field name="name"/>
|
||||
<field name="partner_id"/>
|
||||
<field name="planned_revenue"/>
|
||||
<field name="probability"/>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="make_opportunity" string="Create Opportunity" type="object" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,65 +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_phonecall2opportunity(osv.osv_memory):
|
||||
""" Converts Phonecall to Opportunity"""
|
||||
|
||||
_name = 'crm.phonecall2opportunity'
|
||||
_inherit = 'crm.partner2opportunity'
|
||||
_description = 'Phonecall To Opportunity'
|
||||
|
||||
def make_opportunity(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
This converts Phonecall to Opportunity and opens Phonecall view
|
||||
"""
|
||||
if not len(ids):
|
||||
return False
|
||||
call_ids = context and context.get('active_ids', False) or False
|
||||
this = self.browse(cr, uid, ids[0], context=context)
|
||||
if not call_ids:
|
||||
return {}
|
||||
opportunity = self.pool.get('crm.lead')
|
||||
phonecall = self.pool.get('crm.phonecall')
|
||||
opportunity_ids = phonecall.convert_opportunity(cr, uid, call_ids, this.name, this.partner_id and this.partner_id.id or False, \
|
||||
this.planned_revenue, this.probability, context=context)
|
||||
return opportunity.redirect_opportunity_view(cr, uid, opportunity_ids[call_ids[0]], context=context)
|
||||
|
||||
def default_get(self, cr, uid, fields, context=None):
|
||||
"""
|
||||
This function gets default values
|
||||
"""
|
||||
record_id = context and context.get('active_id', False) or False
|
||||
res = {}
|
||||
|
||||
if record_id:
|
||||
phonecall = self.pool.get('crm.phonecall').browse(cr, uid, record_id, context=context)
|
||||
if 'name' in fields:
|
||||
res.update({'name': phonecall.name})
|
||||
if 'partner_id' in fields:
|
||||
res.update({'partner_id': phonecall.partner_id and phonecall.partner_id.id or False})
|
||||
return res
|
||||
|
||||
crm_phonecall2opportunity()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
<?xml version="1.0"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Phonecall to Opportunity view -->
|
||||
|
||||
<record model="ir.ui.view" id="phonecall2opportunity_view">
|
||||
<field name="name">crm.phonecall2opportunity.form</field>
|
||||
<field name="model">crm.phonecall2opportunity</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Convert To Opportunity " version="7.0">
|
||||
<group>
|
||||
<field name="name"/>
|
||||
<field name="partner_id" />
|
||||
<label for="planned_revenue"/>
|
||||
<div>
|
||||
<field name="planned_revenue" class="oe_inline"/> at
|
||||
<field name="probability" class="oe_inline"/> %%
|
||||
</div>
|
||||
</group>
|
||||
<footer>
|
||||
<button name="make_opportunity" type="object" string="_Convert" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Phonecall to Opportunity action -->
|
||||
|
||||
<record model="ir.actions.act_window" id="phonecall2opportunity_act">
|
||||
<field name="name">Convert to opportunity</field>
|
||||
<field name="res_model">crm.phonecall2opportunity</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="phonecall2opportunity_view"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
@@ -1,67 +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_phonecall2partner(osv.osv_memory):
|
||||
""" Converts phonecall to partner """
|
||||
|
||||
_name = 'crm.phonecall2partner'
|
||||
_inherit = 'crm.lead2partner'
|
||||
_description = 'Phonecall to Partner'
|
||||
|
||||
def _select_partner(self, cr, uid, context=None):
|
||||
"""
|
||||
This function Searches for Partner from selected phonecall.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
|
||||
phonecall_obj = self.pool.get('crm.phonecall')
|
||||
partner_obj = self.pool.get('res.partner')
|
||||
rec_ids = context and context.get('active_ids', [])
|
||||
value = {}
|
||||
partner_id = False
|
||||
for phonecall in phonecall_obj.browse(cr, uid, rec_ids, context=context):
|
||||
partner_ids = partner_obj.search(cr, uid, [('name', '=', phonecall.name or phonecall.name)])
|
||||
if not partner_ids and (phonecall.partner_phone or phonecall.partner_mobile):
|
||||
partner_ids = partner_obj.search(cr, uid, ['|', ('phone', '=', phonecall.partner_phone), ('mobile','=',phonecall.partner_mobile)])
|
||||
|
||||
partner_id = partner_ids and partner_ids[0] or False
|
||||
return partner_id
|
||||
|
||||
|
||||
def _create_partner(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
This function Creates partner based on action.
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
phonecall = self.pool.get('crm.phonecall')
|
||||
data = self.browse(cr, uid, ids, context=context)[0]
|
||||
call_ids = context and context.get('active_ids') or []
|
||||
partner_id = data.partner_id and data.partner_id.id or False
|
||||
return phonecall.convert_partner(cr, uid, call_ids, data.action, partner_id, context=context)
|
||||
|
||||
crm_phonecall2partner()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
@@ -1,54 +0,0 @@
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Phonecall to partner confirmation form -->
|
||||
|
||||
<record id="view_crm_phonecall2partner_create" model="ir.ui.view">
|
||||
<field name="name">crm.phonecall2partner.view.create</field>
|
||||
<field name="model">crm.phonecall2partner</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Create a Partner" version="7.0">
|
||||
<label string="Are you sure you want to create a partner based on this Phonecall ?"/>
|
||||
<newline/>
|
||||
<label string="You may have to verify that this partner does not exist already."/>
|
||||
<footer>
|
||||
<button name="open_create_partner" string="Create Partner" type="object" groups="base.group_partner_manager" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Phonecall to partner form view -->
|
||||
|
||||
<record id="view_crm_phonecall2partner" model="ir.ui.view">
|
||||
<field name="name">crm.phonecall2partner.view</field>
|
||||
<field name="model">crm.phonecall2partner</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Create a Partner" version="7.0">
|
||||
<group>
|
||||
<field name="action"/>
|
||||
<field name="partner_id" attrs="{'required':[('action','=','exist')],'invisible':[('action','!=','exist')]}" />
|
||||
</group>
|
||||
<footer>
|
||||
<button name="make_partner" string="Continue" type="object" class="oe_highlight"/>
|
||||
or
|
||||
<button string="Cancel" class="oe_link" special="cancel" />
|
||||
</footer>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Phonecall to Partner wizard -->
|
||||
|
||||
<record id="action_crm_phonecall2partner" model="ir.actions.act_window">
|
||||
<field name="name">Create a Partner</field>
|
||||
<field name="type">ir.actions.act_window</field>
|
||||
<field name="res_model">crm.phonecall2partner</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_id" ref="view_crm_phonecall2partner_create"/>
|
||||
<field name="target">new</field>
|
||||
</record>
|
||||
</data>
|
||||
</openerp>
|
||||
Reference in New Issue
Block a user