[MERGE] crm improvement
bzr revid: tfr@openerp.com-20110407092730-bjm0pwq9mewpvzc0
This commit is contained in:
commit
1a45ff614d
|
@ -98,6 +98,27 @@ class crm_lead(crm_case, osv.osv):
|
|||
res[lead.id][field] = abs(int(duration))
|
||||
return res
|
||||
|
||||
def _history_search(self, cr, uid, obj, name, args, context=None):
|
||||
res = []
|
||||
msg_obj = self.pool.get('mailgate.message')
|
||||
message_ids = msg_obj.search(cr, uid, [('history','=',True), ('name', args[0][1], args[0][2])], context=context)
|
||||
lead_ids = self.search(cr, uid, [('message_ids', 'in', message_ids)], context=context)
|
||||
|
||||
if lead_ids:
|
||||
return [('id', 'in', lead_ids)]
|
||||
else:
|
||||
return [('id', '=', '0')]
|
||||
|
||||
def _get_email_subject(self, cr, uid, ids, fields, args, context=None):
|
||||
res = {}
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
res[obj.id] = ''
|
||||
for msg in obj.message_ids:
|
||||
if msg.history:
|
||||
res[obj.id] = msg.name
|
||||
break
|
||||
return res
|
||||
|
||||
_columns = {
|
||||
# Overridden from res.partner.address:
|
||||
'partner_id': fields.many2one('res.partner', 'Partner', ondelete='set null',
|
||||
|
@ -149,6 +170,7 @@ class crm_lead(crm_case, osv.osv):
|
|||
\nWhen the case is over, the state is set to \'Done\'.\
|
||||
\nIf the case needs to be reviewed then the state is set to \'Pending\'.'),
|
||||
'message_ids': fields.one2many('mailgate.message', 'res_id', 'Messages', domain=[('model','=',_name)]),
|
||||
'subjects': fields.function(_get_email_subject, fnct_search=_history_search, string='Subject of Email', method=True, type='char', size=64),
|
||||
}
|
||||
|
||||
|
||||
|
@ -289,17 +311,6 @@ class crm_lead(crm_case, osv.osv):
|
|||
self.log(cr, uid, case.id, message)
|
||||
return super(crm_lead,self).write(cr, uid, ids, vals, context)
|
||||
|
||||
def stage_historize(self, cr, uid, ids, stage, context=None):
|
||||
stage_obj = self.pool.get('crm.case.stage').browse(cr, uid, stage, context=context)
|
||||
self.history(cr, uid, ids, _('Stage'), details=stage_obj.name)
|
||||
for case in self.browse(cr, uid, ids, context=context):
|
||||
if case.type == 'lead':
|
||||
message = _("The stage of lead '%s' has been changed to '%s'.") % (case.name, stage_obj.name)
|
||||
elif case.type == 'opportunity':
|
||||
message = _("The stage of opportunity '%s' has been changed to '%s'.") % (case.name, stage_obj.name)
|
||||
self.log(cr, uid, case.id, message)
|
||||
return True
|
||||
|
||||
def stage_next(self, cr, uid, ids, context=None):
|
||||
stage = super(crm_lead, self).stage_next(cr, uid, ids, context=context)
|
||||
if stage:
|
||||
|
|
|
@ -183,7 +183,7 @@
|
|||
<field colspan="4" name="email_cc" widget="char" size="512"/>
|
||||
</group>
|
||||
<field name="message_ids" colspan="4" nolabel="1" mode="tree,form">
|
||||
<tree string="Communication history">
|
||||
<tree string="History">
|
||||
<field name="display_text" string="History Information"/>
|
||||
<field name="history" invisible="1"/>
|
||||
<button
|
||||
|
@ -192,34 +192,33 @@
|
|||
context="{'mail':'reply', 'model': 'crm.lead', 'include_original' : True}"
|
||||
icon="terp-mail-replied" type="action" />
|
||||
</tree>
|
||||
<form string="Communication history">
|
||||
<group col="4" colspan="4">
|
||||
<field name="email_from"/>
|
||||
<field name="date"/>
|
||||
<field name="email_to" widget="char" size="512"/>
|
||||
<field name="email_cc" widget="char" size="512"/>
|
||||
<field name="name" colspan="4" widget="char" size="512"/>
|
||||
<field name="history" invisible="1"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Details">
|
||||
<group attrs="{'invisible': [('history', '!=', True)]}">
|
||||
<field name="description" colspan="4" nolabel="1" height="250"/>
|
||||
<button colspan="4"
|
||||
string="Reply"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'crm.lead', 'include_original' : True}"
|
||||
icon="terp-mail-replied" type="action" />
|
||||
</group>
|
||||
<group attrs="{'invisible': [('history', '=', True)]}">
|
||||
<field name="display_text" colspan="4" nolabel="1" height="250"/>
|
||||
</group>
|
||||
</page>
|
||||
<page string="Attachments">
|
||||
<field name="attachment_ids" colspan="4" readonly="1" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
<form string="History">
|
||||
<group col="4" colspan="4">
|
||||
<field name="email_from"/>
|
||||
<field name="date"/>
|
||||
<field name="email_to" size="512"/>
|
||||
<field name="email_cc" size="512"/>
|
||||
<field name="name" colspan="4" widget="char" attrs="{'invisible': [('history', '=', False)]}" size="512"/>
|
||||
<field name="display_text" colspan="4" attrs="{'invisible': [('history', '=', True)]}"/>
|
||||
<field name="history" invisible="1"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
<page string="Details">
|
||||
<field name="description" colspan="4" nolabel="1"/>
|
||||
<group attrs="{'invisible': [('history', '!=', True)]}">
|
||||
<button colspan="4"
|
||||
string="Reply"
|
||||
name="%(crm.action_crm_send_mail)d"
|
||||
context="{'mail':'reply', 'model': 'crm.lead', 'include_original' : True}"
|
||||
icon="terp-mail-replied" type="action" />
|
||||
</group>
|
||||
|
||||
</page>
|
||||
<page string="Attachments">
|
||||
<field name="attachment_ids" colspan="4" readonly="1" nolabel="1"/>
|
||||
</page>
|
||||
</notebook>
|
||||
</form>
|
||||
</field>
|
||||
<button string="Add Internal Note"
|
||||
name="%(crm.action_crm_add_note)d"
|
||||
|
@ -255,6 +254,7 @@
|
|||
<field name="type_id" invisible="1"/>
|
||||
<field name="referred" invisible="1"/>
|
||||
<field name="channel_id" invisible="1"/>
|
||||
<field name="subjects" invisible="1"/>
|
||||
|
||||
<field name="stage_id"/>
|
||||
<button name="stage_previous" string="Previous Stage"
|
||||
|
@ -335,6 +335,7 @@
|
|||
domain="[('user_id','=', False)]"
|
||||
help="Unassigned Leads" />
|
||||
</field>
|
||||
<field name="subjects"/>
|
||||
<field name="section_id" widget="selection"
|
||||
context="{'invisible_section': False}">
|
||||
<filter icon="terp-personal+" groups="base.group_extended"
|
||||
|
|
|
@ -156,8 +156,8 @@
|
|||
<field name="date"/>
|
||||
<field name="email_to" size="512"/>
|
||||
<field name="email_cc" size="512"/>
|
||||
<field name="name" colspan="4" attrs="{'invisible': [('history', '=', True)]}"/>
|
||||
<field name="display_text" colspan="4" attrs="{'invisible': [('history', '=', False)]}"/>
|
||||
<field name="name" colspan="4" widget="char" attrs="{'invisible': [('history', '=', False)]}" size="512"/>
|
||||
<field name="display_text" colspan="4" attrs="{'invisible': [('history', '=', True)]}"/>
|
||||
<field name="history" invisible="1"/>
|
||||
</group>
|
||||
<notebook colspan="4">
|
||||
|
@ -230,6 +230,7 @@
|
|||
<field name="stage_id"/>
|
||||
<field name="channel_id" invisible="1"/>
|
||||
<field name="type_id" invisible="1"/>
|
||||
<field name="subjects" invisible="1"/>
|
||||
<button name="stage_previous" string="Previous Stage"
|
||||
states="open,pending" type="object" icon="gtk-go-back" />
|
||||
<button name="stage_next" string="Next Stage"
|
||||
|
@ -309,6 +310,7 @@
|
|||
domain="[]"
|
||||
help="Show Sales Team"/>
|
||||
</field>
|
||||
<field name="subjects"/>
|
||||
<newline/>
|
||||
<group expand="0" string="Extended Filters..." groups="base.group_extended">
|
||||
<field name="stage_id" widget="selection" domain="[('type', '=', 'opportunity')]"/>
|
||||
|
|
|
@ -21,6 +21,8 @@
|
|||
|
||||
from osv import osv, fields
|
||||
from tools.translate import _
|
||||
import tools
|
||||
import re
|
||||
|
||||
import time
|
||||
|
||||
|
@ -53,14 +55,29 @@ class crm_lead2opportunity_partner(osv.osv_memory):
|
|||
partner_id = False
|
||||
for lead in lead_obj.browse(cr, uid, opportunities, context=context):
|
||||
partner_id = lead.partner_id and lead.partner_id.id or False
|
||||
email = re.findall(r'([^ ,<@]+@[^> ,]+)', lead.email_from or '')
|
||||
email = map(lambda x: "'" + x + "'", email)
|
||||
|
||||
if not partner_id and res.get('partner_id'):
|
||||
partner_id = res.get('partner_id')
|
||||
|
||||
ids = []
|
||||
if partner_id:
|
||||
ids = lead_obj.search(cr, uid, [('partner_id', '=', partner_id), ('type', '=', 'opportunity')])
|
||||
opportunities += ids
|
||||
ids = lead_obj.search(cr, uid, [('partner_id', '=', partner_id), ('type', '=', 'opportunity'), '!', ('state', 'in', ['done', 'cancel'])])
|
||||
if ids:
|
||||
opportunities.append(ids[0])
|
||||
|
||||
|
||||
if not partner_id:
|
||||
label = False
|
||||
opp_ids = []
|
||||
if email:
|
||||
# Find email of existing opportunity matches the email_from of the lead
|
||||
cr.execute("""select id from crm_lead where type='opportunity' and
|
||||
substring(email_from from '([^ ,<@]+@[^> ,]+)') in (%s)""" % (','.join(email)))
|
||||
ids = map(lambda x:x[0], cr.fetchall())
|
||||
if ids:
|
||||
opportunities.append(ids[0])
|
||||
|
||||
if 'action' in fields:
|
||||
res.update({'action' : partner_id and 'exist' or 'create'})
|
||||
|
@ -82,7 +99,6 @@ class crm_lead2opportunity_partner(osv.osv_memory):
|
|||
@param uid: the current user’s ID for security checks,
|
||||
@param fields: List of fields for default value
|
||||
@param context: A standard dictionary for contextual values
|
||||
|
||||
"""
|
||||
if context is None:
|
||||
context = {}
|
||||
|
@ -90,13 +106,14 @@ class crm_lead2opportunity_partner(osv.osv_memory):
|
|||
|
||||
for lead in lead_obj.browse(cr, uid, context.get('active_ids', []), context=context):
|
||||
if lead.state in ['done', 'cancel']:
|
||||
raise osv.except_osv(_("Warning !"), _("Closed/Cancelled \
|
||||
Leads Could not convert into Opportunity"))
|
||||
raise osv.except_osv(_("Warning !"), _("Closed/Cancelled Leads Could not convert into Opportunity"))
|
||||
return False
|
||||
|
||||
def _convert(self, cr, uid, ids, lead, partner_id, stage_ids, context=None):
|
||||
leads = self.pool.get('crm.lead')
|
||||
address_id = self.pool.get('res.partner.address').search(cr, uid,
|
||||
address_id = False
|
||||
if partner_id:
|
||||
address_id = self.pool.get('res.partner.address').search(cr, uid,
|
||||
[('partner_id', '=', partner_id)],
|
||||
order='create_date desc',
|
||||
limit=1)
|
||||
|
@ -110,8 +127,10 @@ Leads Could not convert into Opportunity"))
|
|||
'stage_id': stage_ids and stage_ids[0] or False,
|
||||
'date_action': time.strftime('%Y-%m-%d %H:%M:%S'),
|
||||
}
|
||||
if address_id:
|
||||
if partner_id and address_id:
|
||||
vals['partner_address_id'] = address_id[0]
|
||||
else:
|
||||
vals['partner_address_id'] = False
|
||||
|
||||
lead.write(vals, context=context)
|
||||
leads.history(cr, uid, [lead], _('Converted to opportunity'), details='Converted to Opportunity', context=context)
|
||||
|
@ -122,6 +141,18 @@ Leads Could not convert into Opportunity"))
|
|||
}, context=context)
|
||||
leads.log(cr, uid, lead.id, _("Lead '%s' has been converted to an opportunity.") % lead.name)
|
||||
|
||||
def send_mail_to_salesman(self, lead):
|
||||
email_to = lead.user_id and lead.user_id.user_email
|
||||
if not email_to:
|
||||
return
|
||||
email_from = lead.section_id and lead.section_id.user_id and lead.section_id.user_id.user_email or email_to
|
||||
partner = lead.partner_id and lead.partner_id.name or lead.partner_name
|
||||
subject = "lead %s converted into opportunity" % lead.name
|
||||
body = "Info \n Id : %s \n Subject: %s \n Partner: %s \n Description : %s " % (lead.id, lead.name, lead.partner_id.name, lead.description)
|
||||
try :
|
||||
tools.email_send(email_from, email_to, subject, body)
|
||||
except:
|
||||
pass
|
||||
|
||||
def action_apply(self, cr, uid, ids, context=None):
|
||||
"""
|
||||
|
@ -130,6 +161,9 @@ Leads Could not convert into Opportunity"))
|
|||
|
||||
@return : View dictionary opening the Opportunity form view
|
||||
"""
|
||||
if not context:
|
||||
context = {}
|
||||
|
||||
record_id = context and context.get('active_ids') or False
|
||||
if not record_id:
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
@ -154,19 +188,27 @@ Leads Could not convert into Opportunity"))
|
|||
cr, uid, opportunity_view_tree, context=context).res_id
|
||||
|
||||
for lead in leads.browse(cr, uid, record_id, context=context):
|
||||
if(lead.section_id):
|
||||
if lead.section_id:
|
||||
stage_ids = self.pool.get('crm.case.stage').search(cr, uid, [('type','=','opportunity'),('sequence','>=',1), ('section_ids','=', lead.section_id.id)])
|
||||
else:
|
||||
stage_ids = self.pool.get('crm.case.stage').search(cr, uid, [('type','=','opportunity'),('sequence','>=',1)])
|
||||
|
||||
data = self.browse(cr, uid, ids[0], context=context)
|
||||
partner_ids = []
|
||||
if data.action == 'create':
|
||||
partner_ids = self._create_partner(cr, uid, ids, context=context)
|
||||
|
||||
partner_id = partner_ids and partner_ids[0] or data.partner_id.id
|
||||
|
||||
if data.action == 'create':
|
||||
partner_ids = []
|
||||
partner_ids = self._create_partner(cr, uid, ids, context=context)
|
||||
partner_id = partner_ids and partner_ids[0]
|
||||
elif data.action == 'exist':
|
||||
partner_id = data.partner_id and data.partner_id.id
|
||||
else:
|
||||
partner_id = False
|
||||
|
||||
self._convert(cr, uid, ids, lead, partner_id, stage_ids, context=context)
|
||||
if data.name == 'merge':
|
||||
self.send_mail_to_salesman(lead)
|
||||
#If we convert in mass, don't merge if there is no other opportunity but no warning
|
||||
if data.name == 'merge' and (len(data.opportunity_ids) > 1 or not context.get('mass_convert') ):
|
||||
merge_obj = self.pool.get('crm.merge.opportunity')
|
||||
self.write(cr, uid, ids, {'opportunity_ids' : [(6,0, [data.opportunity_ids[0].id])]}, context=context)
|
||||
context.update({'lead_ids' : record_id})
|
||||
|
@ -189,4 +231,66 @@ Leads Could not convert into Opportunity"))
|
|||
|
||||
crm_lead2opportunity_partner()
|
||||
|
||||
class crm_lead2opportunity_mass_convert(osv.osv_memory):
|
||||
_name = 'crm.lead2opportunity.partner.mass'
|
||||
_description = 'Mass Lead To Opportunity Partner'
|
||||
_inherit = 'crm.lead2opportunity.partner'
|
||||
|
||||
|
||||
_columns = {
|
||||
'user_ids': fields.many2many('res.users', 'mass_convert_rel', 'user_id', 'wizard_id', 'Salesmans'),
|
||||
'section_id': fields.many2one('crm.case.section', 'Sales Team'),
|
||||
|
||||
}
|
||||
|
||||
def mass_convert(self, cr, uid, ids, context=None):
|
||||
lead_obj = self.pool.get('crm.lead')
|
||||
if not context:
|
||||
context = {}
|
||||
|
||||
active_ids = context.get('active_ids')
|
||||
data = self.browse(cr, uid, ids, context=context)[0]
|
||||
|
||||
salesteam = data.section_id and data.section_id.id
|
||||
if data.user_ids:
|
||||
salesmans = map(lambda x : x.id, data.user_ids)
|
||||
index = 0
|
||||
else:
|
||||
salesmans = False
|
||||
|
||||
for lead_id in active_ids:
|
||||
value = {}
|
||||
if salesteam:
|
||||
value['section_id'] = salesteam
|
||||
if salesmans:
|
||||
value['user_id'] = salesmans[index]
|
||||
index += 1
|
||||
index = index < len(salesmans) and index or 0
|
||||
if value:
|
||||
lead_obj.write(cr, uid, [lead_id], value, context=context)
|
||||
|
||||
context['active_ids'] = [lead_id]
|
||||
value = self.default_get(cr, uid, ['partner_id', 'opportunity_ids'], context=context)
|
||||
value['opportunity_ids'] = [(6, 0, value['opportunity_ids'])]
|
||||
self.write(cr, uid, ids, value, context=context)
|
||||
|
||||
self.action_apply(cr, uid, ids, context=context)
|
||||
|
||||
|
||||
|
||||
models_data = self.pool.get('ir.model.data')
|
||||
result = models_data._get_id(cr, uid, 'crm', 'view_crm_case_opportunities_filter')
|
||||
opportunity_view_search = models_data.browse(cr, uid, result, context=context).res_id
|
||||
|
||||
return {
|
||||
'name': _('Opportunity'),
|
||||
'view_type': 'form',
|
||||
'view_mode': 'tree,form',
|
||||
'res_model': 'crm.lead',
|
||||
'domain': [('type', '=', 'opportunity'), ('id', 'in', active_ids)],
|
||||
'type': 'ir.actions.act_window',
|
||||
'search_view_id': opportunity_view_search,
|
||||
}
|
||||
|
||||
crm_lead2opportunity_mass_convert()
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -36,5 +36,42 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record id="view_crm_lead2opportunity_partner_mass" model="ir.ui.view">
|
||||
<field name="name">crm.lead2opportunity.partner.mass.form</field>
|
||||
<field name="model">crm.lead2opportunity.partner.mass</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Convert to Opportunity">
|
||||
|
||||
<field name="action"/>
|
||||
<field name="name" colspan="4"/>
|
||||
|
||||
<separator string="Assigned opportunities to" colspan="4" />
|
||||
<field name="section_id" />
|
||||
<group col="4" colspan="4">
|
||||
<separator string="Select Salesman" colspan="4" />
|
||||
</group>
|
||||
<field name="user_ids" nolabel="1" colspan="4">
|
||||
<tree>
|
||||
<field name="name" />
|
||||
</tree>
|
||||
</field>
|
||||
<separator string="" colspan="4" />
|
||||
<group col="4" colspan="4">
|
||||
<button special="cancel" string="Cancel" icon="gtk-cancel"/>
|
||||
<button name="mass_convert" string="Convert into Opportunities" type="object" icon="gtk-ok"/>
|
||||
</group>
|
||||
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<act_window id="action_crm_send_mass_convert"
|
||||
multi="True"
|
||||
key2="client_action_multi" name="Convert opportunities"
|
||||
res_model="crm.lead2opportunity.partner.mass" src_model="crm.lead"
|
||||
view_mode="form" target="new" view_type="form"
|
||||
context="{'mass_convert' : True}"
|
||||
view_id="view_crm_lead2opportunity_partner_mass"/>
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -71,7 +71,7 @@ class crm_lead2partner(osv.osv_memory):
|
|||
contact_obj = self.pool.get('res.partner.address')
|
||||
partner_id = False
|
||||
|
||||
data = context and context.get('active_ids', []) or []
|
||||
data = list(context and context.get('active_ids', []) or [])
|
||||
res = super(crm_lead2partner, self).default_get(cr, uid, fields, context=context)
|
||||
|
||||
for lead in lead_obj.browse(cr, uid, data, context=context):
|
||||
|
@ -85,17 +85,15 @@ class crm_lead2partner(osv.osv_memory):
|
|||
substring(email from '([^ ,<@]+@[^> ,]+)') in (%s)""" % (','.join(email)))
|
||||
address_ids = map(lambda x: x[0], cr.fetchall())
|
||||
if address_ids:
|
||||
addresses = contact_obj.browse(cr, uid, address_ids)
|
||||
partner_ids = addresses and [addresses[0].partner_id.id] or False
|
||||
|
||||
partner_ids = partner_obj.search(cr, uid, [('address', 'in', address_ids)], context=context)
|
||||
|
||||
# Find partner name that matches the name of the lead
|
||||
if not partner_ids and lead.partner_name:
|
||||
partner_ids = partner_obj.search(cr, uid, [('name', '=', lead.partner_name)], context=context)
|
||||
if not partner_ids:
|
||||
cr.execute("""SELECT p.id from res_partner p
|
||||
where regexp_replace(lower(p.name), '[^a-z]*', '', 'g') = regexp_replace(%s, '[^a-z]*', '', 'g')""", (lead.name.lower(), ))
|
||||
partner_ids = map(lambda x: x[0], cr.fetchall())
|
||||
|
||||
partner_id = partner_ids and partner_ids[0] or False
|
||||
|
||||
|
||||
|
||||
if 'partner_id' in fields:
|
||||
res.update({'partner_id': partner_id})
|
||||
|
|
|
@ -27,13 +27,19 @@ class crm_merge_opportunity(osv.osv_memory):
|
|||
_name = 'crm.merge.opportunity'
|
||||
_description = 'Merge two Opportunities'
|
||||
|
||||
def _get_first_not_null_id(self, attr, ops):
|
||||
def _get_first_not_null_id(self, attr, ops, oldest):
|
||||
if hasattr(oldest, attr) and getattr(oldest, attr):
|
||||
return getattr(oldest, attr).id
|
||||
|
||||
for op in ops:
|
||||
if hasattr(op, attr) and getattr(op, attr):
|
||||
return getattr(op, attr).id
|
||||
return False
|
||||
|
||||
def _get_first_not_null(self, attr, ops):
|
||||
def _get_first_not_null(self, attr, ops, oldest):
|
||||
if hasattr(oldest, attr) and getattr(oldest, attr):
|
||||
return getattr(oldest, attr)
|
||||
|
||||
for op in ops:
|
||||
if hasattr(op, attr) and getattr(op, attr):
|
||||
return getattr(op, attr)
|
||||
|
@ -54,6 +60,12 @@ class crm_merge_opportunity(osv.osv_memory):
|
|||
attach_obj.write(cr, uid, attach_ids, {'res_id' : op_id})
|
||||
|
||||
|
||||
def find_oldest(self, cr, uid, op_ids, context=None):
|
||||
ids = [op_id.id for op_id in op_ids]
|
||||
lead_obj = self.pool.get('crm.lead')
|
||||
op_id = lead_obj.search(cr, uid, [('id', 'in', ids)], order='create_date' , context=context)
|
||||
opps = lead_obj.browse(cr, uid, [op_id[0]], context=context)
|
||||
return opps[0]
|
||||
|
||||
def merge(self, cr, uid, op_ids, context=None):
|
||||
"""
|
||||
|
@ -64,59 +76,66 @@ class crm_merge_opportunity(osv.osv_memory):
|
|||
|
||||
lead_ids = context and context.pop('lead_ids', []) or []
|
||||
|
||||
|
||||
if len(op_ids) <= 1:
|
||||
raise osv.except_osv(_('Warning !'),_('Please select more than one opportunities.'))
|
||||
|
||||
opportunities = opp_obj.browse(cr, uid, lead_ids, context=context)
|
||||
opportunities_list = list(set(op_ids) - set(opportunities))
|
||||
|
||||
oldest_opp = self.find_oldest(cr, uid, op_ids, context=context)
|
||||
if opportunities :
|
||||
first_opportunity = opportunities[0]
|
||||
tail_opportunities = opportunities_list
|
||||
else:
|
||||
first_opportunity = opportunities_list[0]
|
||||
tail_opportunities = opportunities_list[1:]
|
||||
|
||||
|
||||
|
||||
data = {
|
||||
'partner_id': self._get_first_not_null_id('partner_id', op_ids), # !!
|
||||
'title': self._get_first_not_null_id('title', op_ids),
|
||||
'name' : self._concat_all('name', op_ids), #not lost
|
||||
'categ_id' : self._get_first_not_null_id('categ_id', op_ids), # !!
|
||||
'channel_id' : self._get_first_not_null_id('channel_id', op_ids), # !!
|
||||
'city' : self._get_first_not_null('city', op_ids), # !!
|
||||
'company_id' : self._get_first_not_null_id('company_id', op_ids), #!!
|
||||
'contact_name' : self._concat_all('contact_name', op_ids), #not lost
|
||||
'country_id' : self._get_first_not_null_id('country_id', op_ids), #!!
|
||||
'partner_address_id' : self._get_first_not_null_id('partner_address_id', op_ids), #!!
|
||||
'partner_assigned_id' : hasattr(opp_obj,'partner_assigned_id') and self._get_first_not_null_id('partner_assigned_id', op_ids), #!!
|
||||
'type_id' : self._get_first_not_null_id('type_id', op_ids), #!!
|
||||
'user_id' : self._get_first_not_null_id('user_id', op_ids), #!!
|
||||
'section_id' : self._get_first_not_null_id('section_id', op_ids), #!!
|
||||
'state_id' : self._get_first_not_null_id('state_id', op_ids),
|
||||
'partner_id': self._get_first_not_null_id('partner_id', op_ids, oldest_opp), # !!
|
||||
'title': self._get_first_not_null_id('title', op_ids, oldest_opp),
|
||||
'name' : self._get_first_not_null('name', op_ids, oldest_opp), #not lost
|
||||
'categ_id' : self._get_first_not_null_id('categ_id', op_ids, oldest_opp), # !!
|
||||
'channel_id' : self._get_first_not_null_id('channel_id', op_ids, oldest_opp), # !!
|
||||
'city' : self._get_first_not_null('city', op_ids, oldest_opp), # !!
|
||||
'company_id' : self._get_first_not_null_id('company_id', op_ids, oldest_opp), #!!
|
||||
'contact_name' : self._get_first_not_null('contact_name', op_ids, oldest_opp), #not lost
|
||||
'country_id' : self._get_first_not_null_id('country_id', op_ids, oldest_opp), #!!
|
||||
'partner_address_id' : self._get_first_not_null_id('partner_address_id', op_ids, oldest_opp), #!!
|
||||
'partner_assigned_id' : hasattr(opp_obj,'partner_assigned_id') and self._get_first_not_null_id('partner_assigned_id', op_ids, oldest_opp), #!!
|
||||
'type_id' : self._get_first_not_null_id('type_id', op_ids, oldest_opp), #!!
|
||||
'user_id' : self._get_first_not_null_id('user_id', op_ids, oldest_opp), #!!
|
||||
'section_id' : self._get_first_not_null_id('section_id', op_ids, oldest_opp), #!!
|
||||
'state_id' : self._get_first_not_null_id('state_id', op_ids, oldest_opp),
|
||||
'description' : self._concat_all('description', op_ids), #not lost
|
||||
'email' : self._get_first_not_null('email', op_ids), # !!
|
||||
'fax' : self._get_first_not_null('fax', op_ids),
|
||||
'mobile' : self._get_first_not_null('mobile', op_ids),
|
||||
'partner_latitude' : hasattr(opp_obj,'partner_latitude') and self._get_first_not_null('partner_latitude', op_ids),
|
||||
'partner_longitude' : hasattr(opp_obj,'partner_longitude') and self._get_first_not_null('partner_longitude', op_ids),
|
||||
'partner_name' : self._get_first_not_null('partner_name', op_ids),
|
||||
'phone' : self._get_first_not_null('phone', op_ids),
|
||||
'probability' : self._get_first_not_null('probability', op_ids),
|
||||
'planned_revenue' : self._get_first_not_null('planned_revenue', op_ids),
|
||||
'street' : self._get_first_not_null('street', op_ids),
|
||||
'street2' : self._get_first_not_null('street2', op_ids),
|
||||
'zip' : self._get_first_not_null('zip', op_ids),
|
||||
'email' : self._get_first_not_null('email', op_ids, oldest_opp), # !!
|
||||
'fax' : self._get_first_not_null('fax', op_ids, oldest_opp),
|
||||
'mobile' : self._get_first_not_null('mobile', op_ids, oldest_opp),
|
||||
'partner_latitude' : hasattr(opp_obj,'partner_latitude') and self._get_first_not_null('partner_latitude', op_ids, oldest_opp),
|
||||
'partner_longitude' : hasattr(opp_obj,'partner_longitude') and self._get_first_not_null('partner_longitude', op_ids, oldest_opp),
|
||||
'partner_name' : self._get_first_not_null('partner_name', op_ids, oldest_opp),
|
||||
'phone' : self._get_first_not_null('phone', op_ids, oldest_opp),
|
||||
'probability' : self._get_first_not_null('probability', op_ids, oldest_opp),
|
||||
'planned_revenue' : self._get_first_not_null('planned_revenue', op_ids, oldest_opp),
|
||||
'street' : self._get_first_not_null('street', op_ids, oldest_opp),
|
||||
'street2' : self._get_first_not_null('street2', op_ids, oldest_opp),
|
||||
'zip' : self._get_first_not_null('zip', op_ids, oldest_opp),
|
||||
'state' : 'open',
|
||||
'create_date' : self._get_first_not_null('create_date', op_ids, oldest_opp),
|
||||
'date_action_last': self._get_first_not_null('date_action_last', op_ids, oldest_opp),
|
||||
'date_action_next': self._get_first_not_null('date_action_nexte', op_ids, oldest_opp),
|
||||
'email_from' : self._get_first_not_null('email_from', op_ids, oldest_opp),
|
||||
'email_cc' : self._get_first_not_null('email_cc', op_ids, oldest_opp),
|
||||
'partner_name' : self._get_first_not_null('partner_name', op_ids, oldest_opp),
|
||||
|
||||
}
|
||||
|
||||
|
||||
#copy message into the first opportunity + merge attachement
|
||||
for opp in tail_opportunities:
|
||||
|
||||
for opp in tail_opportunities + [first_opportunity]:
|
||||
attach_ids = self.get_attachments(cr, uid, opp, context=context)
|
||||
self.set_attachements_res_id(cr, uid, first_opportunity.id, attach_ids)
|
||||
for history in opp.message_ids:
|
||||
new_history = message_obj.copy(cr, uid, history.id, default={'res_id': opp.id})
|
||||
new_history = message_obj.write(cr, uid, history.id, {'res_id': first_opportunity.id, 'name' : _("From %s : %s") % (opp.name, history.name) }, context=context)
|
||||
|
||||
#Notification about loss of information
|
||||
details = []
|
||||
|
@ -214,8 +233,13 @@ class crm_merge_opportunity(osv.osv_memory):
|
|||
res = super(crm_merge_opportunity, self).default_get(cr, uid, fields, context=context)
|
||||
|
||||
if record_ids:
|
||||
opp_ids = []
|
||||
opps = self.pool.get('crm.lead').browse(cr, uid, record_ids, context=context)
|
||||
for opp in opps:
|
||||
if opp.state not in ('done', 'cancel'):
|
||||
opp_ids.append(opp.id)
|
||||
if 'opportunity_ids' in fields:
|
||||
res.update({'opportunity_ids': record_ids})
|
||||
res.update({'opportunity_ids': opp_ids})
|
||||
|
||||
return res
|
||||
|
||||
|
|
|
@ -57,9 +57,25 @@ class crm_send_new_email(osv.osv_memory):
|
|||
'body': fields.text('Message Body', required=True),
|
||||
'state': fields.selection(AVAILABLE_STATES, string='Set New State To', required=True),
|
||||
'attachment_ids' : fields.one2many('crm.send.mail.attachment', 'wizard_id', 'Attachment'),
|
||||
'html': fields.boolean('HTML formatting?', help="Select this if you want to send email with HTML formatting."),
|
||||
'html': fields.boolean('HTML formatting?', help="Select this if you want to send email with HTML formatting."),
|
||||
}
|
||||
|
||||
def action_mass_send(self, cr, uid, ids, context=None):
|
||||
|
||||
if not context:
|
||||
context = {}
|
||||
|
||||
context.update({'mail' : 'new'})
|
||||
actives_ids = context.get('active_ids')
|
||||
print "mass_mail", context.get('mass_mail')
|
||||
model = context.get('active_model')
|
||||
case_pool = self.pool.get(model)
|
||||
for id in actives_ids:
|
||||
context.update({'active_id' : id})
|
||||
self.action_send(cr, uid, ids, context=context)
|
||||
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
def action_send(self, cr, uid, ids, context=None):
|
||||
""" This sends an email to ALL the addresses of the selected partners.
|
||||
"""
|
||||
|
@ -75,6 +91,8 @@ class crm_send_new_email(osv.osv_memory):
|
|||
case_pool = self.pool.get(model)
|
||||
res_id = context and context.get('active_id', False) or False
|
||||
|
||||
|
||||
|
||||
for obj in self.browse(cr, uid, ids, context=context):
|
||||
attach = [
|
||||
(x.name, base64.decodestring(x.binary)) for x in obj.attachment_ids
|
||||
|
@ -110,8 +128,15 @@ class crm_send_new_email(osv.osv_memory):
|
|||
res_id = hist.res_id
|
||||
ref_id = hist.ref_id
|
||||
case = case_pool.browse(cr, uid, res_id, context=context)
|
||||
emails = re.findall(r'([^ ,<@]+@[^> ,]+)', obj.email_to or '')
|
||||
|
||||
if context.get('mass_mail'):
|
||||
email_temp = case.email_from and tools.ustr(case.email_from) or ''
|
||||
emails = re.findall(r'([^ ,<@]+@[^> ,]+)', email_temp)
|
||||
else:
|
||||
emails = re.findall(r'([^ ,<@]+@[^> ,]+)', obj.email_to or '')
|
||||
|
||||
email_cc = re.findall(r'([^ ,<@]+@[^> ,]+)', obj.email_cc or '')
|
||||
|
||||
emails = filter(None, emails)
|
||||
body = obj.body
|
||||
|
||||
|
@ -180,10 +205,11 @@ class crm_send_new_email(osv.osv_memory):
|
|||
|
||||
user_obj = self.pool.get('res.users')
|
||||
user_mail_from = user_obj._get_email_from(cr, uid, [uid], context=context)[uid]
|
||||
|
||||
for case in mod_obj.browse(cr, uid, res_id, context=context):
|
||||
if 'email_to' in fields:
|
||||
res.update({'email_to': case.email_from and tools.ustr(case.email_from) or ''})
|
||||
if context.get('mass_mail'):
|
||||
res.update({'email_to': ''})
|
||||
if 'email_from' in fields:
|
||||
res.update({'email_from': user_mail_from and tools.ustr(user_mail_from) or ''})
|
||||
if 'reply_to' in fields:
|
||||
|
@ -191,8 +217,12 @@ class crm_send_new_email(osv.osv_memory):
|
|||
res.update({'reply_to': case.section_id and case.section_id.reply_to or False})
|
||||
if 'subject' in fields:
|
||||
res.update({'subject': tools.ustr(context.get('subject', case.name) or '')})
|
||||
if context.get('mass_mail'):
|
||||
res.update({'subject': ''})
|
||||
if 'email_cc' in fields:
|
||||
res.update({'email_cc': tools.ustr(case.email_cc or '')})
|
||||
if context.get('mass_mail'):
|
||||
res.update({'email_cc': ''})
|
||||
if 'body' in fields:
|
||||
res.update({'body': u'\n'+(tools.ustr(case.user_id.signature or ''))})
|
||||
if 'state' in fields:
|
||||
|
|
|
@ -44,6 +44,45 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.ui.view" id="crm_send_new_mass_mail_view">
|
||||
<field name="name">crm.new.send.mass.mail.form</field>
|
||||
<field name="model">crm.send.mail</field>
|
||||
<field name="type">form</field>
|
||||
<field name="arch" type="xml">
|
||||
<form string="Send Mail" col="4">
|
||||
<group colspan="4" col="2">
|
||||
<field name="email_from"/>
|
||||
<field name="reply_to"/>
|
||||
<field name="email_cc"/>
|
||||
<field name="subject" />
|
||||
<field name="html"/>
|
||||
</group>
|
||||
<notebook colspan="6">
|
||||
<page string="Message">
|
||||
<field name="body" nolabel="1" colspan="4" default_focus="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_send" type="object" string="_Send to All" icon="gtk-go-forward" />
|
||||
</group>
|
||||
</form>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Send New Mail action -->
|
||||
|
||||
<record model="ir.actions.act_window" id="action_crm_send_mail">
|
||||
|
@ -56,6 +95,14 @@
|
|||
</record>
|
||||
|
||||
|
||||
<act_window id="action_crm_send_mass_mail"
|
||||
multi="True"
|
||||
key2="client_action_multi" name="Send emails"
|
||||
res_model="crm.send.mail" src_model="crm.lead"
|
||||
view_mode="form" target="new" view_type="form"
|
||||
context="{'mass_mail' : True}"
|
||||
view_id="crm_send_new_mass_mail_view"/>
|
||||
|
||||
<!-- Reply to Mail view -->
|
||||
|
||||
<record model="ir.ui.view" id="crm_reply_mail_view">
|
||||
|
@ -89,6 +136,9 @@
|
|||
</field>
|
||||
</record>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Reply to Mail action -->
|
||||
|
||||
<record model="ir.actions.act_window" id="action_crm_reply_mail">
|
||||
|
|
|
@ -43,6 +43,7 @@ You can also use the geolocalization without using the GPS coordinates.
|
|||
'wizard/crm_forward_to_partner_view.xml',
|
||||
'crm_lead_view.xml',
|
||||
'report/crm_lead_report_view.xml',
|
||||
'report/crm_partner_report_view.xml',
|
||||
],
|
||||
'test': ['test/test_crm_partner_assign.yml'],
|
||||
'installable': True,
|
||||
|
|
|
@ -142,21 +142,6 @@ class crm_lead(osv.osv):
|
|||
('country', '=', part.country_id.id),
|
||||
], context=context)
|
||||
|
||||
# 3. third way: other countries, small area
|
||||
if not part_ids:
|
||||
part_ids = self.pool.get('res.partner').search(cr, uid, [
|
||||
('partner_weight','>',0),
|
||||
('partner_latitude','>',result[0]-2), ('partner_latitude','<',result[0]+2),
|
||||
('partner_longitude','>',result[1]-1.5), ('partner_longitude','<',result[1]+1.5)
|
||||
], context=context)
|
||||
|
||||
# 4. fourth way: other countries, big area
|
||||
if not part_ids:
|
||||
part_ids = self.pool.get('res.partner').search(cr, uid, [
|
||||
('partner_weight','>',0),
|
||||
('partner_latitude','>',result[0]-4), ('partner_latitude','<',result[0]+4),
|
||||
('partner_longitude','>',result[1]-3), ('partner_longitude','<',result[1]+3)
|
||||
], context=context)
|
||||
|
||||
# 5. fifth way: anywhere in same country
|
||||
if not part_ids:
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
##############################################################################
|
||||
#
|
||||
#
|
||||
# OpenERP, Open Source Management Solution
|
||||
# Copyright (C) 2004-2010 Tiny SPRL (<http://tiny.be>).
|
||||
#
|
||||
|
@ -15,9 +15,10 @@
|
|||
# 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/>.
|
||||
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
##############################################################################
|
||||
|
||||
import crm_lead_report
|
||||
import crm_partner_report
|
||||
|
||||
|
|
|
@ -37,7 +37,7 @@ class crm_lead_report_assign(osv.osv):
|
|||
_auto = False
|
||||
_description = "CRM Lead Report"
|
||||
_columns = {
|
||||
'name': fields.char('Year', size=64, required=False, readonly=True),
|
||||
'year': fields.char('Year', size=64, required=False, readonly=True),
|
||||
'partner_assigned_id':fields.many2one('res.partner', 'Partner', readonly=True),
|
||||
'grade_id':fields.many2one('res.partner.grade', 'Grade', readonly=True),
|
||||
'user_id':fields.many2one('res.users', 'User', readonly=True),
|
||||
|
@ -51,7 +51,7 @@ class crm_lead_report_assign(osv.osv):
|
|||
('09', 'September'), ('10', 'October'),\
|
||||
('11', 'November'), ('12', 'December')], 'Month', readonly=True),
|
||||
'company_id': fields.many2one('res.company', 'Company', readonly=True),
|
||||
'partner_date': fields.date('Partner Date', readonly=True),
|
||||
'date_assign': fields.date('Partner Date', readonly=True),
|
||||
'create_date': fields.datetime('Create Date', readonly=True),
|
||||
'day': fields.char('Day', size=128, readonly=True),
|
||||
'delay_open': fields.float('Delay to Open',digits=(16,2),readonly=True, group_operator="avg",help="Number of Days to open the case"),
|
||||
|
@ -82,18 +82,20 @@ class crm_lead_report_assign(osv.osv):
|
|||
CRM Lead Report
|
||||
@param cr: the current row, from the database cursor
|
||||
"""
|
||||
print "WHATTT "
|
||||
tools.drop_view_if_exists(cr, 'crm_lead_report_assign')
|
||||
cr.execute("""
|
||||
CREATE OR REPLACE VIEW crm_lead_report_assign AS (
|
||||
SELECT
|
||||
c.id,
|
||||
to_char(c.create_date, 'YYYY') as name,
|
||||
to_char(c.create_date, 'MM') as month,
|
||||
to_char(c.create_date, 'YYYY-MM-DD') as day,
|
||||
to_char(c.date_assign, 'YYYY') as year,
|
||||
to_char(c.date_assign, 'MM') as month,
|
||||
to_char(c.date_assign, 'YYYY-MM-DD') as day,
|
||||
to_char(c.create_date, 'YYYY-MM-DD') as creation_date,
|
||||
to_char(c.date_open, 'YYYY-MM-DD') as opening_date,
|
||||
to_char(c.date_closed, 'YYYY-mm-dd') as date_closed,
|
||||
c.state,
|
||||
c.date_assign,
|
||||
c.user_id,
|
||||
c.probability,
|
||||
c.probability as probability_max,
|
||||
|
|
|
@ -69,17 +69,17 @@
|
|||
domain="[]"
|
||||
context="{'group_by':'company_id'}" />
|
||||
<separator orientation="vertical" />
|
||||
<filter string="Partner Date" icon="terp-go-today"
|
||||
<filter string="Assign Date" icon="terp-go-today"
|
||||
domain="[]"
|
||||
name="group_partner_date"
|
||||
context="{'group_by':'partner_date'}"/>
|
||||
context="{'group_by':'date_assign'}"/>
|
||||
<separator orientation="vertical"/>
|
||||
<filter string="Day" icon="terp-go-today"
|
||||
domain="[]" context="{'group_by':'day'}"/>
|
||||
<filter string="Month" icon="terp-go-month"
|
||||
domain="[]" context="{'group_by':'month'}" />
|
||||
<filter string="Year" icon="terp-go-year"
|
||||
domain="[]" context="{'group_by':'name'}" />
|
||||
domain="[]" context="{'group_by':'year'}" />
|
||||
</group>
|
||||
|
||||
</search>
|
||||
|
@ -107,9 +107,9 @@
|
|||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Opportunities Assignment Analysis">
|
||||
<field name="name" invisible="1"/>
|
||||
<field name="year" invisible="1"/>
|
||||
<field name="month" invisible="1"/>
|
||||
<field name="partner_date" invisible="1"/>
|
||||
<field name="date_assign" invisible="1"/>
|
||||
<field name="section_id" invisible="1" groups="base.group_extended"/>
|
||||
<field name="user_id" invisible="1"/>
|
||||
<field name="grade_id" invisible="1" widget="selection"/>
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
# -*- 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 fields,osv
|
||||
import tools
|
||||
|
||||
|
||||
class crm_partner_report_assign(osv.osv):
|
||||
""" CRM Lead Report """
|
||||
_name = "crm.partner.report.assign"
|
||||
_auto = False
|
||||
_description = "CRM Partner Report"
|
||||
_columns = {
|
||||
'name': fields.char('Partner name', size=64, required=False, readonly=True),
|
||||
'grade_id':fields.many2one('res.partner.grade', 'Grade', readonly=True),
|
||||
'user_id':fields.many2one('res.users', 'User', readonly=True),
|
||||
'country_id':fields.many2one('res.country', 'Country', readonly=True),
|
||||
'section_id':fields.many2one('crm.case.section', 'Sales Team', readonly=True),
|
||||
'nbr': fields.integer('# of Partner', readonly=True),
|
||||
'opp': fields.integer('# of Opportunity', readonly=True),
|
||||
}
|
||||
|
||||
def init(self, cr):
|
||||
|
||||
"""
|
||||
CRM Lead Report
|
||||
@param cr: the current row, from the database cursor
|
||||
"""
|
||||
tools.drop_view_if_exists(cr, 'crm_partner_report_assign')
|
||||
cr.execute("""
|
||||
CREATE OR REPLACE VIEW crm_partner_report_assign AS (
|
||||
SELECT
|
||||
p.id,
|
||||
p.name,
|
||||
(SELECT country_id FROM res_partner_address a WHERE a.partner_id=p.id AND country_id is not null limit 1) as country_id,
|
||||
p.grade_id,
|
||||
p.user_id,
|
||||
p.section_id,
|
||||
1 as nbr,
|
||||
(SELECT count(id) FROM crm_lead WHERE partner_assigned_id=p.id) AS opp
|
||||
FROM
|
||||
res_partner p
|
||||
|
||||
)""")
|
||||
|
||||
crm_partner_report_assign()
|
|
@ -0,0 +1,71 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<openerp>
|
||||
<data>
|
||||
|
||||
<!-- Opportunity tree view -->
|
||||
<record id="view_report_crm_partner_assign_filter" model="ir.ui.view">
|
||||
<field name="name">crm.partner.report.assign.select</field>
|
||||
<field name="model">crm.partner.report.assign</field>
|
||||
<field name="type">search</field>
|
||||
<field name="arch" type="xml">
|
||||
<search string="Partner assigned Analysis">
|
||||
<group col="20" colspan="8">
|
||||
<field name="country_id" />
|
||||
<field name="grade_id"/>
|
||||
<field name="user_id"/>
|
||||
<field name="section_id"/>
|
||||
</group>
|
||||
<newline/>
|
||||
<group expand="1" string="Group By...">
|
||||
<filter string="Salesman" name="user" icon="terp-personal"
|
||||
domain="[]" context="{'group_by':'user_id'}" />
|
||||
<filter string="Country" icon="terp-go-home" name="group_country" context="{'group_by':'country_id'}" />
|
||||
<separator orientation="vertical" />
|
||||
<filter string="Section" icon="terp-personal+"
|
||||
domain="[]"
|
||||
context="{'group_by':'section_id'}" />
|
||||
<filter string="Grade" name="group_grade" icon="terp-stock_symbol-selection"
|
||||
domain="[]" context="{'group_by':'grade_id'}" />
|
||||
<filter string="Name" name="" icon="terp-stock_symbol-selection"
|
||||
domain="[]" context="{'group_by':'name'}" />
|
||||
<separator orientation="vertical" />
|
||||
</group>
|
||||
</search>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Crm Lead Assign report Graph View -->
|
||||
|
||||
<record id="view_report_crm_partner_assign_tree" model="ir.ui.view">
|
||||
<field name="name">crm.partner.assign.report.tree</field>
|
||||
<field name="model">crm.partner.report.assign</field>
|
||||
<field name="type">tree</field>
|
||||
<field name="arch" type="xml">
|
||||
<tree string="Opportunities Assignment Analysis">
|
||||
<field name="name" invisible="1"/>
|
||||
<field name="country_id" invisible="1"/>
|
||||
<field name="grade_id" invisible="1"/>
|
||||
<field name="section_id" invisible="1" groups="base.group_extended"/>
|
||||
<field name="user_id" invisible="1"/>
|
||||
<field name="nbr" string="#Partner" sum="#Partner"/>
|
||||
<field name="opp"/>
|
||||
</tree>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<!-- Leads by user and section Action -->
|
||||
|
||||
<record id="action_report_crm_partner_assign" model="ir.actions.act_window">
|
||||
<field name="name">Partnership Analysis</field>
|
||||
<field name="res_model">crm.partner.report.assign</field>
|
||||
<field name="context">{'search_default_group_country': 1, 'search_default_group_grade': 1, 'group_by_no_leaf':1,'group_by':[]}</field>
|
||||
<field name="view_mode">tree</field>
|
||||
<field name="domain">[('grade_id', '!=', False)]</field>
|
||||
</record>
|
||||
|
||||
<menuitem id="menu_report_crm_partner_assign_tree"
|
||||
groups="base.group_extended"
|
||||
parent="base.next_id_64" action="action_report_crm_partner_assign" sequence="5"/>
|
||||
|
||||
</data>
|
||||
</openerp>
|
|
@ -1,5 +1,6 @@
|
|||
"id","name","model_id:id","group_id:id","perm_read","perm_write","perm_create","perm_unlink"
|
||||
"access_ crm_lead_report_assign"," crm.lead.report.assign","model_crm_lead_report_assign","base.group_sale_salesman",1,1,1,0
|
||||
"access_ crm_lead_report_assign","crm.lead.report.assign","model_crm_lead_report_assign","base.group_sale_salesman",1,1,1,0
|
||||
"access_ crm_lead_report_assign_all","crm.lead.report.assign.all","model_crm_lead_report_assign","base.group_user",1,0,0,0
|
||||
"access_crm_partner_report","crm.partner.report.assign.all","model_crm_partner_report_assign","base.group_sale_salesman",1,0,0,0
|
||||
"access_res_partner_grade","res.partner.grade","model_res_partner_grade","base.group_sale_salesman",1,1,1,0
|
||||
"access_res_partner_grade_manager","res.partner.grade.manager","model_res_partner_grade","base.group_sale_manager",1,1,1,1
|
||||
|
|
|
|
@ -44,9 +44,10 @@ class crm_lead_forward_to_partner(osv.osv_memory):
|
|||
_defaults = {
|
||||
'name' : 'email',
|
||||
'history': 'latest',
|
||||
'email_from': lambda self, cr, uid, *a: self.pool.get('res.users')._get_email_from(cr, uid, uid)[uid]
|
||||
'email_from': lambda self, cr, uid, *a: self.pool.get('res.users')._get_email_from(cr, uid, uid)[uid],
|
||||
}
|
||||
|
||||
|
||||
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
|
||||
|
@ -87,7 +88,7 @@ class crm_lead_forward_to_partner(osv.osv_memory):
|
|||
@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
|
||||
@param partner: Changed Partner id
|
||||
"""
|
||||
if not user:
|
||||
return {'value': {'email_to': False}}
|
||||
|
@ -146,7 +147,7 @@ class crm_lead_forward_to_partner(osv.osv_memory):
|
|||
@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
|
||||
@param partner: Changed Partner id
|
||||
"""
|
||||
if not partner_id:
|
||||
return {'value' : {'email_to' : False, 'address_id': False}}
|
||||
|
@ -155,13 +156,13 @@ class crm_lead_forward_to_partner(osv.osv_memory):
|
|||
addr = partner_obj.address_get(cr, uid, [partner_id], ['contact'])
|
||||
data = {'address_id': addr['contact']}
|
||||
data.update(self.on_change_address(cr, uid, ids, addr['contact'])['value'])
|
||||
|
||||
|
||||
partner = partner_obj.browse(cr, uid, [partner_id])
|
||||
user_id = partner and partner[0].user_id or False
|
||||
email = user_id and user_id.user_email or ''
|
||||
data.update({'email_cc' : email})
|
||||
return {
|
||||
'value' : data,
|
||||
'value' : data,
|
||||
'domain' : {'address_id' : partner_id and "[('partner_id', '=', partner_id)]" or "[]"}
|
||||
}
|
||||
|
||||
|
@ -236,23 +237,23 @@ class crm_lead_forward_to_partner(osv.osv_memory):
|
|||
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 ''),
|
||||
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 + ['---'])
|
||||
|
||||
|
@ -260,26 +261,66 @@ class crm_lead_forward_to_partner(osv.osv_memory):
|
|||
"""
|
||||
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' % (_('Fwd'), lead.name),
|
||||
'subject' : '%s: %s - %s' % (_('Fwd'), 'Openerp lead forward', lead.name),
|
||||
'body' : body,
|
||||
'email_cc' : ''
|
||||
'email_cc' : email_cc,
|
||||
'email_to' : email or 'dummy@dummy.ly'
|
||||
})
|
||||
return defaults
|
||||
|
||||
crm_lead_forward_to_partner()
|
||||
|
||||
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', 'email_to', 'email_cc', 'subject', 'history'], context=context)
|
||||
self.write(cr, uid, ids, value, context=context)
|
||||
self.action_forward(cr,uid, ids, context=context)
|
||||
|
||||
return {'type': 'ir.actions.act_window_close'}
|
||||
|
||||
|
||||
crm_lead_mass_forward_to_partner()
|
||||
|
||||
# vim:expandtab:smartindent:tabstop=4:softtabstop=4:shiftwidth=4:
|
||||
|
|
|
@ -38,14 +38,70 @@
|
|||
</button>
|
||||
</field>
|
||||
</record>
|
||||
|
||||
<record model="ir.actions.act_window" id="crm_lead_forward_to_partner_act">
|
||||
<field name="name">Forward to Partner</field>
|
||||
<field name="res_model">crm.lead.forward.to.partner</field>
|
||||
<field name="view_type">form</field>
|
||||
<field name="view_mode">form</field>
|
||||
<field name="view_id" ref="crm_lead_forward_to_partner_form1"/>
|
||||
<field name="view_id" ref="crm_lead_forward_to_partner_form"/>
|
||||
<field name="target">new</field>
|
||||
</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" 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"
|
||||
multi="True"
|
||||
key2="client_action_multi" name="Mass forward to partner"
|
||||
res_model="crm.lead.mass.forward.to.partner" src_model="crm.lead"
|
||||
view_mode="form" target="new" view_type="form"
|
||||
context="{'mass_forward' : True}"
|
||||
view_id="crm_forward_mass_mail_view"
|
||||
/>
|
||||
|
||||
|
||||
|
||||
</data>
|
||||
</openerp>
|
||||
|
|
|
@ -151,7 +151,7 @@ class hr_employee(osv.osv):
|
|||
'work_email': fields.char('Work E-mail', size=240),
|
||||
'work_location': fields.char('Office Location', size=32),
|
||||
'notes': fields.text('Notes'),
|
||||
'parent_id': fields.many2one('hr.employee', 'Manager'),
|
||||
'parent_id': fields.many2one('hr.employee', 'Manager'),
|
||||
'category_ids': fields.many2many('hr.employee.category', 'employee_category_rel', 'emp_id', 'category_id', 'Category'),
|
||||
'child_ids': fields.one2many('hr.employee', 'parent_id', 'Subordinates'),
|
||||
'resource_id': fields.many2one('resource.resource', 'Resource', ondelete='cascade', required=True),
|
||||
|
@ -240,7 +240,7 @@ class res_users(osv.osv):
|
|||
except:
|
||||
# Tolerate a missing shortcut. See product/product.py for similar code.
|
||||
logging.getLogger('orm').debug('Skipped meetings shortcut for user "%s"', data.get('name','<new'))
|
||||
|
||||
|
||||
return user_id
|
||||
|
||||
res_users()
|
||||
|
|
|
@ -251,7 +251,7 @@ class mailgate_message(osv.osv):
|
|||
for message in self.browse(cr, uid, ids, context=context):
|
||||
msg_txt = ''
|
||||
if message.history:
|
||||
msg_txt += _('%s wrote on %s:\n\t') % (message.email_from or '/', format_date_tz(message.date, tz))
|
||||
msg_txt += _('%s wrote on %s: \n Subject: %s \n\t') % (message.email_from or '/', format_date_tz(message.date, tz), message.name)
|
||||
if message.description:
|
||||
msg_txt += self.truncate_data(cr, uid, message.description, context=context)
|
||||
else:
|
||||
|
|
|
@ -21,6 +21,7 @@
|
|||
|
||||
import time
|
||||
import base64
|
||||
import itertools
|
||||
from datetime import datetime
|
||||
from dateutil.relativedelta import relativedelta
|
||||
from operator import itemgetter
|
||||
|
|
Loading…
Reference in New Issue